Comparar commits
22 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| b80ae36681 | |||
| 3367b007a2 | |||
| feb7e26211 | |||
| 5a5b42f2a7 | |||
| f82a3d148f | |||
| 21051534f3 | |||
| f4bc3c12b5 | |||
| c1112b74fe | |||
| f77bcc95d0 | |||
| cb3d709237 | |||
| d9a0a4503c | |||
| 3ef88f8b80 | |||
| 80c6c16a2f | |||
| e12ca69306 | |||
| d8ba649549 | |||
| 0490728321 | |||
| dd1f2b5c25 | |||
| 47a307b773 | |||
| 050f23d913 | |||
| b027603a6a | |||
| a2f5430a5d | |||
| acd775f551 |
@@ -23,3 +23,5 @@ sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
addons:
|
||||
firefox: latest
|
||||
|
||||
@@ -6,6 +6,31 @@ _(none)_
|
||||
|
||||
--------------------
|
||||
|
||||
## 5.8.2 (2016-03-09)
|
||||
* @gkatsev fixed chapters menu. Fixes #3062 ([view](https://github.com/videojs/video.js/pull/3163))
|
||||
|
||||
## 5.8.1 (2016-03-07)
|
||||
* @gkatsev updated videojs badges in the README ([view](https://github.com/videojs/video.js/pull/3134))
|
||||
* @BrandonOCasey converted remaining text-track modules to ES6 ([view](https://github.com/videojs/video.js/pull/3130))
|
||||
* @gkatsev cleared waiting/spinner on timeupdate. Fixes #3124 ([view](https://github.com/videojs/video.js/pull/3138))
|
||||
* @BrandonOCasey updated text track unit tests to use full es6 syntax ([view](https://github.com/videojs/video.js/pull/3148))
|
||||
* @defli added missing var to sandbox index.html example ([view](https://github.com/videojs/video.js/pull/3155))
|
||||
* @defli fixed typo and updated Turkish translations ([view](https://github.com/videojs/video.js/pull/3156))
|
||||
* @OwenEdwards fixed menu closing on ios, specifically ipad ([view](https://github.com/videojs/video.js/pull/3158))
|
||||
|
||||
## 5.8.0 (2016-02-19)
|
||||
* @gkatsev added issue and PR templates for github ([view](https://github.com/videojs/video.js/pull/3117))
|
||||
* @Nipoto added fa.json (farsi/persian lang file) ([view](https://github.com/videojs/video.js/pull/3116))
|
||||
* @forbesjo updated travis to use latest firefox ([view](https://github.com/videojs/video.js/pull/3112))
|
||||
* @Naouak updated time display to not change if values do not change ([view](https://github.com/videojs/video.js/pull/3101))
|
||||
* @forbesjo updated track settings to not fail restoring settings when localStorage is not available ([view](https://github.com/videojs/video.js/pull/3120))
|
||||
* @mister-ben Added en.json as localization template ([view](https://github.com/videojs/video.js/pull/3096))
|
||||
* @misteroneill added alt css as video-js-cdn.css ([view](https://github.com/videojs/video.js/pull/3118))
|
||||
|
||||
## 5.7.1 (2016-02-11)
|
||||
* @alex-phillips fixed reference to videojs-vtt.js dependency ([view](https://github.com/videojs/video.js/pull/3080))
|
||||
* @gkatsev fixed minified videojs in IE8. Fixes #3064 and #3070 ([view](https://github.com/videojs/video.js/pull/3104))
|
||||
|
||||
## 5.7.0 (2016-02-04)
|
||||
* @forbesjo updated emulated tracks to have listeners removed when they are removed ([view](https://github.com/videojs/video.js/pull/3046))
|
||||
* @incompl improved the UX of time tooltips ([view](https://github.com/videojs/video.js/pull/3060))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
## Description
|
||||
Briefly describe the issue.
|
||||
Include a [reduced test case](https://css-tricks.com/reduced-test-cases/), we have a [starter template](http://jsbin.com/axedog/edit?html,output) on JSBin you can use.
|
||||
|
||||
## Steps to reproduce
|
||||
Explain in detail the exact steps necessary to reproduce the issue.
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## Results
|
||||
### Expected
|
||||
Please describe what you expected to see.
|
||||
|
||||
### Actual
|
||||
Please describe what actually happened.
|
||||
|
||||
### Error output
|
||||
If there are any errors at all, please include them here.
|
||||
|
||||
## Additional Information
|
||||
Please include any additional information necessary here. Including the following:
|
||||
### versions
|
||||
#### videojs
|
||||
what version of videojs does this occur with?
|
||||
#### browsers
|
||||
what browser are affected?
|
||||
#### OSes
|
||||
what platforms (operating systems and devices) are affected?
|
||||
### plugins
|
||||
are any videojs plugins being used on the page? If so, please list them below.
|
||||
@@ -0,0 +1,16 @@
|
||||
## Description
|
||||
Please describe the change as necessary.
|
||||
If it's a feature or enhancement please be as detailed as possible.
|
||||
If it's a bug fix, please link the issue that it fixes or describe the bug in as much detail.
|
||||
|
||||
|
||||
## Specific Changes proposed
|
||||
Please list the specific changes involved in this pull request.
|
||||
|
||||
## Requirements Checklist
|
||||
- [ ] Feature implemented / Bug fixed
|
||||
- [ ] If necessary, more likely in a feature request than a bug fix
|
||||
- [ ] Unit Tests updated or fixed
|
||||
- [ ] Docs/guides updated
|
||||
- [ ] Example created ([starter template on JSBin](http://jsbin.com/axedog/edit?html,output))
|
||||
- [ ] Reviewed by Two Core Contributors
|
||||
+5
-1
@@ -1,6 +1,10 @@
|
||||

|
||||
|
||||
# [Video.js - HTML5 Video Player](http://videojs.com) [](https://travis-ci.org/videojs/video.js)
|
||||
# [Video.js - HTML5 Video Player](http://videojs.com)
|
||||
[](https://travis-ci.org/videojs/video.js)
|
||||
[](https://coveralls.io/github/videojs/video.js?branch=master)
|
||||
|
||||
[](https://nodei.co/npm/video.js/)
|
||||
|
||||
> Video.js is a web video player built from the ground up for an HTML5 world. It supports HTML5 and Flash video, as well as YouTube and Vimeo (through [plugins](https://github.com/videojs/video.js/wiki/Plugins)). It supports video playback on desktops and mobile devices. This project was started mid 2010, and the player is now used on over ~~50,000~~ ~~100,000~~ 200,000 websites.
|
||||
|
||||
|
||||
+8
-3
@@ -149,6 +149,10 @@ module.exports = function(grunt) {
|
||||
},
|
||||
dist: {},
|
||||
watch: {
|
||||
minify: {
|
||||
files: ['build/temp/video.js'],
|
||||
tasks: ['uglify']
|
||||
},
|
||||
skin: {
|
||||
files: ['src/css/**/*'],
|
||||
tasks: ['sass', 'wrapcodepoints']
|
||||
@@ -188,7 +192,7 @@ module.exports = function(grunt) {
|
||||
minify: {
|
||||
expand: true,
|
||||
cwd: 'build/temp/',
|
||||
src: ['video-js.css'],
|
||||
src: ['video-js.css', 'alt/video-js-cdn.css'],
|
||||
dest: 'build/temp/',
|
||||
ext: '.min.css'
|
||||
}
|
||||
@@ -196,7 +200,8 @@ module.exports = function(grunt) {
|
||||
sass: {
|
||||
build: {
|
||||
files: {
|
||||
'build/temp/video-js.css': 'src/css/vjs.scss'
|
||||
'build/temp/video-js.css': 'src/css/vjs.scss',
|
||||
'build/temp/alt/video-js-cdn.css': 'src/css/vjs-cdn.scss'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -396,7 +401,7 @@ module.exports = function(grunt) {
|
||||
options: {
|
||||
separator: '\n',
|
||||
},
|
||||
src: ['build/temp/video.js', 'node_modules/vtt.js/dist/vtt.js'],
|
||||
src: ['build/temp/video.js', 'node_modules/videojs-vtt.js/dist/vtt.js'],
|
||||
dest: 'build/temp/video.js',
|
||||
},
|
||||
},
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"description": "An HTML5 and Flash video player with a common API and skin for both.",
|
||||
"version": "5.7.0",
|
||||
"version": "5.8.2",
|
||||
"keywords": [
|
||||
"videojs",
|
||||
"html5",
|
||||
|
||||
externo
+1235
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+543
-429
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+8
-7
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+9
-1
@@ -22,5 +22,13 @@ videojs.addLanguage("de",{
|
||||
"A network error caused the media download to fail part-way.": "Der Videodownload ist aufgrund eines Netzwerkfehlers fehlgeschlagen.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Das Video konnte nicht geladen werden, da entweder ein Server- oder Netzwerkfehler auftrat oder das Format nicht unterstützt wird.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "Die Videowiedergabe wurde entweder wegen eines Problems mit einem beschädigten Video oder wegen verwendeten Funktionen, die vom Browser nicht unterstützt werden, abgebrochen.",
|
||||
"No compatible source was found for this media.": "Für dieses Video wurde keine kompatible Quelle gefunden."
|
||||
"No compatible source was found for this media.": "Für dieses Video wurde keine kompatible Quelle gefunden.",
|
||||
"Play video": "Video abspielen",
|
||||
"Close": "Schließen",
|
||||
"Modal Window": "Modales Fenster",
|
||||
"This is a modal window": "Dies ist ein modales Fenster",
|
||||
"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)"
|
||||
});
|
||||
externo
+34
@@ -0,0 +1,34 @@
|
||||
videojs.addLanguage("en",{
|
||||
"Play": "Play",
|
||||
"Pause": "Pause",
|
||||
"Current Time": "Current Time",
|
||||
"Duration Time": "Duration Time",
|
||||
"Remaining Time": "Remaining Time",
|
||||
"Stream Type": "Stream Type",
|
||||
"LIVE": "LIVE",
|
||||
"Loaded": "Loaded",
|
||||
"Progress": "Progress",
|
||||
"Fullscreen": "Fullscreen",
|
||||
"Non-Fullscreen": "Non-Fullscreen",
|
||||
"Mute": "Mute",
|
||||
"Unmute": "Unmute",
|
||||
"Playback Rate": "Playback Rate",
|
||||
"Subtitles": "Subtitles",
|
||||
"subtitles off": "subtitles off",
|
||||
"Captions": "Captions",
|
||||
"captions off": "captions off",
|
||||
"Chapters": "Chapters",
|
||||
"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.",
|
||||
"Play video": "Play video",
|
||||
"Close": "Close",
|
||||
"Modal Window": "Modal Window",
|
||||
"This is a modal window": "This is a modal window",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "This modal can be closed by pressing the Escape key or activating the close button.",
|
||||
", opens captions settings dialog": ", opens captions settings dialog",
|
||||
", opens subtitles settings dialog": ", opens subtitles settings dialog",
|
||||
", selected": ", selected"
|
||||
});
|
||||
externo
+26
@@ -0,0 +1,26 @@
|
||||
videojs.addLanguage("fa",{
|
||||
"Play": "پخش",
|
||||
"Pause": "وقفه",
|
||||
"Current Time": "زمان کنونی",
|
||||
"Duration Time": "مدت زمان",
|
||||
"Remaining Time": "زمان باقیمانده",
|
||||
"Stream Type": "نوع استریم",
|
||||
"LIVE": "زنده",
|
||||
"Loaded": "فراخوانی شده",
|
||||
"Progress": "پیشرفت",
|
||||
"Fullscreen": "تمام صفحه",
|
||||
"Non-Fullscreen": "نمایش عادی",
|
||||
"Mute": "بی صدا",
|
||||
"Unmute": "بهمراه صدا",
|
||||
"Playback Rate": "سرعت پخش",
|
||||
"Subtitles": "زیرنویس",
|
||||
"subtitles off": "بدون زیرنویس",
|
||||
"Captions": "عنوان",
|
||||
"captions off": "بدون عنوان",
|
||||
"Chapters": "فصل",
|
||||
"You aborted the media playback": "شما پخش را متوقف کردید.",
|
||||
"A network error caused the media download to fail part-way.": "مشکل در دریافت ویدئو ...",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "فرمت پشتیبانی نمیشود یا خطایی روی داده است.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "مشکل در دریافت ویدئو ...",
|
||||
"No compatible source was found for this media.": "هیچ ورودی ای برای این رسانه شناسایی نشد."
|
||||
});
|
||||
externo
+10
-2
@@ -14,7 +14,7 @@ videojs.addLanguage("tr",{
|
||||
"Unmute": "Ses Aç",
|
||||
"Playback Rate": "Oynatma Hızı",
|
||||
"Subtitles": "Altyazı",
|
||||
"subtitles off": "Altyazı Kapat",
|
||||
"subtitles off": "Altyazı Kapalı",
|
||||
"Captions": "Ek Açıklamalar",
|
||||
"captions off": "Ek Açıklamalar Kapalı",
|
||||
"Chapters": "Bölümler",
|
||||
@@ -22,5 +22,13 @@ videojs.addLanguage("tr",{
|
||||
"A network error caused the media download to fail part-way.": "Video indirilirken bağlantı sorunu oluştu.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Video oynatılamadı, ağ ya da sunucu hatası veya belirtilen format desteklenmiyor.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "Tarayıcınız desteklemediği için videoda hata oluştu.",
|
||||
"No compatible source was found for this media.": "Video için kaynak bulunamadı."
|
||||
"No compatible source was found for this media.": "Video için kaynak bulunamadı.",
|
||||
"Play video": "Videoyu Oynat",
|
||||
"Close": "Kapat",
|
||||
"Modal Window": "Modal Penceresi",
|
||||
"This is a modal window": "Bu bir modal penceresidir",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "Bu modal ESC tuşuna basarak ya da kapata tıklanarak kapatılabilir.",
|
||||
", opens captions settings dialog": ", ek açıklama ayarları menüsünü açar",
|
||||
", opens subtitles settings dialog": ", altyazı ayarları menüsünü açar",
|
||||
", selected": ", seçildi"
|
||||
});
|
||||
Arquivo binário não exibido.
externo
+1
-5
@@ -475,7 +475,7 @@ body.vjs-full-window {
|
||||
bottom: 1.5em;
|
||||
max-height: 15em; }
|
||||
|
||||
.vjs-menu-button-popup:hover .vjs-menu,
|
||||
.vjs-workinghover .vjs-menu-button-popup:hover .vjs-menu,
|
||||
.vjs-menu-button-popup .vjs-menu.vjs-lock-showing {
|
||||
display: block; }
|
||||
|
||||
@@ -1128,10 +1128,6 @@ video::-webkit-media-text-track-display {
|
||||
100% {
|
||||
border-top-color: #73859f; } }
|
||||
|
||||
.vjs-chapters-button .vjs-menu {
|
||||
left: -10em;
|
||||
width: 0; }
|
||||
|
||||
.vjs-chapters-button .vjs-menu ul {
|
||||
width: 24em; }
|
||||
|
||||
|
||||
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+543
-429
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+12
-12
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+9
-8
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+1
-1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -5,7 +5,11 @@ Multiple language support allows for users of non-English locales to natively in
|
||||
|
||||
Creating the Language File
|
||||
--------------------------
|
||||
Video.js uses key/value object dictionaries in JSON form. A sample dictionary for Spanish `['es']` would look as follows;
|
||||
Video.js uses key/value object dictionaries in JSON form.
|
||||
|
||||
An English lang file is at [/lang/en.json](https://github.com/videojs/video.js/tree/master/lang/en.json) which should be used as a template for new files. This will be kept up to date with strings in the core player that need localizations.
|
||||
|
||||
A sample dictionary for Spanish `['es']` would look as follows:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -38,7 +42,7 @@ Video.js uses key/value object dictionaries in JSON form. A sample dictionary fo
|
||||
|
||||
Notes:
|
||||
|
||||
- The file name should always be in the format `XX.json`, where `XX` is the two letter value of the language reported to the browser (for options see the bottom of this document).
|
||||
- The file name should always be in the format `XX.json`, where `XX` is the language code. This should be a two letter code (for options see the bottom of this document) except for cases where a more specific code with sub-code is appropriate, e.g. `zh-CN.lang`.
|
||||
- For automatic inclusion at build time, add your language file to the `/lang` directory (see 'Adding Languages to Video.js below').
|
||||
|
||||
Adding Languages to Video.js
|
||||
|
||||
+9
-1
@@ -22,5 +22,13 @@
|
||||
"A network error caused the media download to fail part-way.": "Der Videodownload ist aufgrund eines Netzwerkfehlers fehlgeschlagen.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Das Video konnte nicht geladen werden, da entweder ein Server- oder Netzwerkfehler auftrat oder das Format nicht unterstützt wird.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "Die Videowiedergabe wurde entweder wegen eines Problems mit einem beschädigten Video oder wegen verwendeten Funktionen, die vom Browser nicht unterstützt werden, abgebrochen.",
|
||||
"No compatible source was found for this media.": "Für dieses Video wurde keine kompatible Quelle gefunden."
|
||||
"No compatible source was found for this media.": "Für dieses Video wurde keine kompatible Quelle gefunden.",
|
||||
"Play video": "Video abspielen",
|
||||
"Close": "Schließen",
|
||||
"Modal Window": "Modales Fenster",
|
||||
"This is a modal window": "Dies ist ein modales Fenster",
|
||||
"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)"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"Play": "Play",
|
||||
"Pause": "Pause",
|
||||
"Current Time": "Current Time",
|
||||
"Duration Time": "Duration Time",
|
||||
"Remaining Time": "Remaining Time",
|
||||
"Stream Type": "Stream Type",
|
||||
"LIVE": "LIVE",
|
||||
"Loaded": "Loaded",
|
||||
"Progress": "Progress",
|
||||
"Fullscreen": "Fullscreen",
|
||||
"Non-Fullscreen": "Non-Fullscreen",
|
||||
"Mute": "Mute",
|
||||
"Unmute": "Unmute",
|
||||
"Playback Rate": "Playback Rate",
|
||||
"Subtitles": "Subtitles",
|
||||
"subtitles off": "subtitles off",
|
||||
"Captions": "Captions",
|
||||
"captions off": "captions off",
|
||||
"Chapters": "Chapters",
|
||||
"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.",
|
||||
"Play video": "Play video",
|
||||
"Close": "Close",
|
||||
"Modal Window": "Modal Window",
|
||||
"This is a modal window": "This is a modal window",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "This modal can be closed by pressing the Escape key or activating the close button.",
|
||||
", opens captions settings dialog": ", opens captions settings dialog",
|
||||
", opens subtitles settings dialog": ", opens subtitles settings dialog",
|
||||
", selected": ", selected"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"Play": "پخش",
|
||||
"Pause": "وقفه",
|
||||
"Current Time": "زمان کنونی",
|
||||
"Duration Time": "مدت زمان",
|
||||
"Remaining Time": "زمان باقیمانده",
|
||||
"Stream Type": "نوع استریم",
|
||||
"LIVE": "زنده",
|
||||
"Loaded": "فراخوانی شده",
|
||||
"Progress": "پیشرفت",
|
||||
"Fullscreen": "تمام صفحه",
|
||||
"Non-Fullscreen": "نمایش عادی",
|
||||
"Mute": "بی صدا",
|
||||
"Unmute": "بهمراه صدا",
|
||||
"Playback Rate": "سرعت پخش",
|
||||
"Subtitles": "زیرنویس",
|
||||
"subtitles off": "بدون زیرنویس",
|
||||
"Captions": "عنوان",
|
||||
"captions off": "بدون عنوان",
|
||||
"Chapters": "فصل",
|
||||
"You aborted the media playback": "شما پخش را متوقف کردید.",
|
||||
"A network error caused the media download to fail part-way.": "مشکل در دریافت ویدئو ...",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "فرمت پشتیبانی نمیشود یا خطایی روی داده است.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "مشکل در دریافت ویدئو ...",
|
||||
"No compatible source was found for this media.": "هیچ ورودی ای برای این رسانه شناسایی نشد."
|
||||
}
|
||||
+10
-2
@@ -14,7 +14,7 @@
|
||||
"Unmute": "Ses Aç",
|
||||
"Playback Rate": "Oynatma Hızı",
|
||||
"Subtitles": "Altyazı",
|
||||
"subtitles off": "Altyazı Kapat",
|
||||
"subtitles off": "Altyazı Kapalı",
|
||||
"Captions": "Ek Açıklamalar",
|
||||
"captions off": "Ek Açıklamalar Kapalı",
|
||||
"Chapters": "Bölümler",
|
||||
@@ -22,5 +22,13 @@
|
||||
"A network error caused the media download to fail part-way.": "Video indirilirken bağlantı sorunu oluştu.",
|
||||
"The media could not be loaded, either because the server or network failed or because the format is not supported.": "Video oynatılamadı, ağ ya da sunucu hatası veya belirtilen format desteklenmiyor.",
|
||||
"The media playback was aborted due to a corruption problem or because the media used features your browser did not support.": "Tarayıcınız desteklemediği için videoda hata oluştu.",
|
||||
"No compatible source was found for this media.": "Video için kaynak bulunamadı."
|
||||
"No compatible source was found for this media.": "Video için kaynak bulunamadı.",
|
||||
"Play video": "Videoyu Oynat",
|
||||
"Close": "Kapat",
|
||||
"Modal Window": "Modal Penceresi",
|
||||
"This is a modal window": "Bu bir modal penceresidir",
|
||||
"This modal can be closed by pressing the Escape key or activating the close button.": "Bu modal ESC tuşuna basarak ya da kapata tıklanarak kapatılabilir.",
|
||||
", opens captions settings dialog": ", ek açıklama ayarları menüsünü açar",
|
||||
", opens subtitles settings dialog": ", altyazı ayarları menüsünü açar",
|
||||
", selected": ", seçildi"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"description": "An HTML5 and Flash video player with a common API and skin for both.",
|
||||
"version": "5.7.0",
|
||||
"version": "5.8.2",
|
||||
"copyright": "Copyright Brightcove, Inc. <https://www.brightcove.com/>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</video>
|
||||
|
||||
<script>
|
||||
vid = document.getElementById("vid1");
|
||||
var vid = document.getElementById("vid1");
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
@extend .vjs-icon-chapters;
|
||||
}
|
||||
|
||||
.vjs-chapters-button .vjs-menu {
|
||||
left: -10em; // (Width of vjs-menu - width of vjs-control) / 2
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.vjs-chapters-button .vjs-menu ul {
|
||||
width: 24em;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
max-height: 15em;
|
||||
}
|
||||
|
||||
.vjs-menu-button-popup:hover .vjs-menu,
|
||||
.vjs-workinghover .vjs-menu-button-popup:hover .vjs-menu,
|
||||
.vjs-menu-button-popup .vjs-menu.vjs-lock-showing {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
$icon-font-path: '//vjs.zencdn.net/font/1.5.1';
|
||||
|
||||
@import 'video-js';
|
||||
@@ -90,11 +90,13 @@ class ChaptersButton extends TextTrackButton {
|
||||
let menu = this.menu;
|
||||
if (menu === undefined) {
|
||||
menu = new Menu(this.player_);
|
||||
menu.contentEl().appendChild(Dom.createEl('li', {
|
||||
let title = Dom.createEl('li', {
|
||||
className: 'vjs-menu-title',
|
||||
innerHTML: toTitleCase(this.kind_),
|
||||
tabIndex: -1
|
||||
}));
|
||||
});
|
||||
menu.children_.unshift(title);
|
||||
Dom.insertElFirst(title, menu.contentEl());
|
||||
}
|
||||
|
||||
if (chaptersTrack && chaptersTrack.cues == null) {
|
||||
|
||||
@@ -55,7 +55,10 @@ class CurrentTimeDisplay extends Component {
|
||||
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());
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> ${formattedTime}`;
|
||||
if (formattedTime !== this.formattedTime_) {
|
||||
this.formattedTime_ = formattedTime;
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> ${formattedTime}`;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ class DurationDisplay extends Component {
|
||||
*/
|
||||
updateContent() {
|
||||
let duration = this.player_.duration();
|
||||
if (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
|
||||
|
||||
@@ -54,7 +54,10 @@ class RemainingTimeDisplay extends Component {
|
||||
if (this.player_.duration()) {
|
||||
const localizedText = this.localize('Remaining Time');
|
||||
const formattedTime = formatTime(this.player_.remainingTime());
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> -${formattedTime}`;
|
||||
if (formattedTime !== this.formattedTime_) {
|
||||
this.formattedTime_ = formattedTime;
|
||||
this.contentEl_.innerHTML = `<span class="vjs-control-text">${localizedText}</span> -${formattedTime}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
|
||||
@@ -70,11 +70,13 @@ class MenuButton extends ClickableComponent {
|
||||
|
||||
// Add a title list item to the top
|
||||
if (this.options_.title) {
|
||||
menu.contentEl().appendChild(Dom.createEl('li', {
|
||||
let 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']();
|
||||
|
||||
@@ -196,6 +196,11 @@ class Player extends Component {
|
||||
// this.addClass('vjs-touch-enabled');
|
||||
// }
|
||||
|
||||
// iOS Safari has broken hover handling
|
||||
if (!browser.IS_IOS) {
|
||||
this.addClass('vjs-workinghover');
|
||||
}
|
||||
|
||||
// Make player easily findable by ID
|
||||
Player.players[this.id_] = this;
|
||||
|
||||
@@ -812,6 +817,7 @@ class Player extends Component {
|
||||
handleTechWaiting_() {
|
||||
this.addClass('vjs-waiting');
|
||||
this.trigger('waiting');
|
||||
this.one('timeupdate', () => this.removeClass('vjs-waiting'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
import * as browser from '../utils/browser.js';
|
||||
import document from 'global/document';
|
||||
|
||||
/*
|
||||
/**
|
||||
* A List of text track cues as defined in:
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist
|
||||
*
|
||||
* interface TextTrackCueList {
|
||||
@@ -12,72 +13,93 @@ import document from 'global/document';
|
||||
* getter TextTrackCue (unsigned long index);
|
||||
* TextTrackCue? getCueById(DOMString id);
|
||||
* };
|
||||
*
|
||||
* @param {Array} cues A list of cues to be initialized with
|
||||
* @class TextTrackCueList
|
||||
*/
|
||||
|
||||
let TextTrackCueList = function(cues) {
|
||||
let list = this;
|
||||
class TextTrackCueList {
|
||||
constructor(cues) {
|
||||
let list = this;
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
list = document.createElement('custom');
|
||||
if (browser.IS_IE8) {
|
||||
list = document.createElement('custom');
|
||||
|
||||
for (let prop in TextTrackCueList.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
list[prop] = TextTrackCueList.prototype[prop];
|
||||
for (let prop in TextTrackCueList.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
list[prop] = TextTrackCueList.prototype[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextTrackCueList.prototype.setCues_.call(list, cues);
|
||||
|
||||
Object.defineProperty(list, 'length', {
|
||||
get() {
|
||||
return this.length_;
|
||||
}
|
||||
});
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for cues in this list
|
||||
*
|
||||
* @param {Array} cues an array of cues
|
||||
* @method setCues_
|
||||
* @private
|
||||
*/
|
||||
setCues_(cues) {
|
||||
let oldLength = this.length || 0;
|
||||
let i = 0;
|
||||
let l = cues.length;
|
||||
|
||||
this.cues_ = cues;
|
||||
this.length_ = cues.length;
|
||||
|
||||
let defineProp = function(index) {
|
||||
if (!('' + index in this)) {
|
||||
Object.defineProperty(this, '' + index, {
|
||||
get() {
|
||||
return this.cues_[index];
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (oldLength < l) {
|
||||
i = oldLength;
|
||||
|
||||
for (; i < l; i++) {
|
||||
defineProp.call(this, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextTrackCueList.prototype.setCues_.call(list, cues);
|
||||
/**
|
||||
* Get a cue that is currently in the Cue list by id
|
||||
*
|
||||
* @param {String} id
|
||||
* @method getCueById
|
||||
* @return {Object} a single cue
|
||||
*/
|
||||
getCueById(id) {
|
||||
let result = null;
|
||||
|
||||
Object.defineProperty(list, 'length', {
|
||||
get: function() {
|
||||
return this.length_;
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
let cue = this[i];
|
||||
|
||||
if (cue.id === id) {
|
||||
result = cue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
return list;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
TextTrackCueList.prototype.setCues_ = function(cues) {
|
||||
let oldLength = this.length || 0;
|
||||
let i = 0;
|
||||
let l = cues.length;
|
||||
|
||||
this.cues_ = cues;
|
||||
this.length_ = cues.length;
|
||||
|
||||
let defineProp = function(i) {
|
||||
if (!(''+i in this)) {
|
||||
Object.defineProperty(this, '' + i, {
|
||||
get: function() {
|
||||
return this.cues_[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (oldLength < l) {
|
||||
i = oldLength;
|
||||
|
||||
for(; i < l; i++) {
|
||||
defineProp.call(this, i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TextTrackCueList.prototype.getCueById = function(id) {
|
||||
let result = null;
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
let cue = this[i];
|
||||
if (cue.id === id) {
|
||||
result = cue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export default TextTrackCueList;
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
/**
|
||||
* @file text-track-enums.js
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode
|
||||
*
|
||||
* enum TextTrackMode { "disabled", "hidden", "showing" };
|
||||
*/
|
||||
var TextTrackMode = {
|
||||
'disabled': 'disabled',
|
||||
'hidden': 'hidden',
|
||||
'showing': 'showing'
|
||||
const TextTrackMode = {
|
||||
disabled: 'disabled',
|
||||
hidden: 'hidden',
|
||||
showing: 'showing'
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackkind
|
||||
*
|
||||
* enum TextTrackKind { "subtitles", "captions", "descriptions", "chapters", "metadata" };
|
||||
* enum TextTrackKind {
|
||||
* "subtitles",
|
||||
* "captions",
|
||||
* "descriptions",
|
||||
* "chapters",
|
||||
* "metadata"
|
||||
* };
|
||||
*/
|
||||
var TextTrackKind = {
|
||||
'subtitles': 'subtitles',
|
||||
'captions': 'captions',
|
||||
'descriptions': 'descriptions',
|
||||
'chapters': 'chapters',
|
||||
'metadata': 'metadata'
|
||||
const TextTrackKind = {
|
||||
subtitles: 'subtitles',
|
||||
captions: 'captions',
|
||||
descriptions: 'descriptions',
|
||||
chapters: 'chapters',
|
||||
metadata: 'metadata'
|
||||
};
|
||||
|
||||
/* jshint ignore:start */
|
||||
// we ignore jshint here because it does not see
|
||||
// TextTrackMode or TextTrackKind as defined here somehow...
|
||||
export { TextTrackMode, TextTrackKind };
|
||||
/* jshint ignore:end */
|
||||
|
||||
+117
-102
@@ -6,7 +6,8 @@ import * as Fn from '../utils/fn.js';
|
||||
import * as browser from '../utils/browser.js';
|
||||
import document from 'global/document';
|
||||
|
||||
/*
|
||||
/**
|
||||
* A text track list as defined in:
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist
|
||||
*
|
||||
* interface TextTrackList : EventTarget {
|
||||
@@ -18,50 +19,140 @@ import document from 'global/document';
|
||||
* attribute EventHandler onaddtrack;
|
||||
* attribute EventHandler onremovetrack;
|
||||
* };
|
||||
*
|
||||
* @param {Track[]} tracks A list of tracks to initialize the list with
|
||||
* @extends EventTarget
|
||||
* @class TextTrackList
|
||||
*/
|
||||
let TextTrackList = function(tracks) {
|
||||
let list = this;
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
list = document.createElement('custom');
|
||||
class TextTrackList extends EventTarget {
|
||||
constructor(tracks = []) {
|
||||
super();
|
||||
let list = this;
|
||||
|
||||
for (let prop in TextTrackList.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
list[prop] = TextTrackList.prototype[prop];
|
||||
if (browser.IS_IE8) {
|
||||
list = document.createElement('custom');
|
||||
|
||||
for (let prop in TextTrackList.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
list[prop] = TextTrackList.prototype[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tracks = tracks || [];
|
||||
list.tracks_ = [];
|
||||
list.tracks_ = [];
|
||||
|
||||
Object.defineProperty(list, 'length', {
|
||||
get: function() {
|
||||
return this.tracks_.length;
|
||||
Object.defineProperty(list, 'length', {
|
||||
get() {
|
||||
return this.tracks_.length;
|
||||
}
|
||||
});
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
list.addTrack_(tracks[i]);
|
||||
}
|
||||
});
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
list.addTrack_(tracks[i]);
|
||||
if (browser.IS_IE8) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
return list;
|
||||
/**
|
||||
* Add TextTrack from TextTrackList
|
||||
*
|
||||
* @param {TextTrack} track
|
||||
* @method addTrack_
|
||||
* @private
|
||||
*/
|
||||
addTrack_(track) {
|
||||
let index = this.tracks_.length;
|
||||
|
||||
if (!('' + index in this)) {
|
||||
Object.defineProperty(this, index, {
|
||||
get() {
|
||||
return this.tracks_[index];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
track.addEventListener('modechange', Fn.bind(this, function() {
|
||||
this.trigger('change');
|
||||
}));
|
||||
this.tracks_.push(track);
|
||||
|
||||
this.trigger({
|
||||
track,
|
||||
type: 'addtrack'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
TextTrackList.prototype = Object.create(EventTarget.prototype);
|
||||
TextTrackList.prototype.constructor = TextTrackList;
|
||||
/**
|
||||
* Remove TextTrack from TextTrackList
|
||||
* NOTE: Be mindful of what is passed in as it may be a HTMLTrackElement
|
||||
*
|
||||
* @param {TextTrack} rtrack
|
||||
* @method removeTrack_
|
||||
* @private
|
||||
*/
|
||||
removeTrack_(rtrack) {
|
||||
let track;
|
||||
|
||||
/*
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === rtrack) {
|
||||
track = this[i];
|
||||
if (track.off) {
|
||||
track.off();
|
||||
}
|
||||
|
||||
this.tracks_.splice(i, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.trigger({
|
||||
track,
|
||||
type: 'removetrack'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a TextTrack from TextTrackList by a tracks id
|
||||
*
|
||||
* @param {String} id - the id of the track to get
|
||||
* @method getTrackById
|
||||
* @return {TextTrack}
|
||||
* @private
|
||||
*/
|
||||
getTrackById(id) {
|
||||
let result = null;
|
||||
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
let track = this[i];
|
||||
|
||||
if (track.id === id) {
|
||||
result = track;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* change - One or more tracks in the track list have been enabled or disabled.
|
||||
* addtrack - A track has been added to the track list.
|
||||
* removetrack - A track has been removed from the track list.
|
||||
*/
|
||||
TextTrackList.prototype.allowedEvents_ = {
|
||||
'change': 'change',
|
||||
'addtrack': 'addtrack',
|
||||
'removetrack': 'removetrack'
|
||||
change: 'change',
|
||||
addtrack: 'addtrack',
|
||||
removetrack: 'removetrack'
|
||||
};
|
||||
|
||||
// emulate attribute EventHandler support to allow for feature detection
|
||||
@@ -69,80 +160,4 @@ for (let event in TextTrackList.prototype.allowedEvents_) {
|
||||
TextTrackList.prototype['on' + event] = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add TextTrack from TextTrackList
|
||||
*
|
||||
* @param {TextTrack} track
|
||||
* @method addTrack_
|
||||
* @private
|
||||
*/
|
||||
TextTrackList.prototype.addTrack_ = function(track) {
|
||||
let index = this.tracks_.length;
|
||||
if (!(''+index in this)) {
|
||||
Object.defineProperty(this, index, {
|
||||
get: function() {
|
||||
return this.tracks_[index];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
track.addEventListener('modechange', Fn.bind(this, function() {
|
||||
this.trigger('change');
|
||||
}));
|
||||
this.tracks_.push(track);
|
||||
|
||||
this.trigger({
|
||||
type: 'addtrack',
|
||||
track: track
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove TextTrack from TextTrackList
|
||||
* NOTE: Be mindful of what is passed in as it may be a HTMLTrackElement
|
||||
*
|
||||
* @param {TextTrack} rtrack
|
||||
* @method removeTrack_
|
||||
* @private
|
||||
*/
|
||||
TextTrackList.prototype.removeTrack_ = function(rtrack) {
|
||||
let track;
|
||||
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === rtrack) {
|
||||
track = this[i];
|
||||
if (track.off) {
|
||||
track.off();
|
||||
}
|
||||
|
||||
this.tracks_.splice(i, 1);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.trigger({
|
||||
type: 'removetrack',
|
||||
track: track
|
||||
});
|
||||
};
|
||||
|
||||
TextTrackList.prototype.getTrackById = function(id) {
|
||||
let result = null;
|
||||
|
||||
for (let i = 0, l = this.length; i < l; i++) {
|
||||
let track = this[i];
|
||||
if (track.id === id) {
|
||||
result = track;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export default TextTrackList;
|
||||
|
||||
@@ -158,10 +158,16 @@ class TextTrackSettings extends Component {
|
||||
* @method restoreSettings
|
||||
*/
|
||||
restoreSettings() {
|
||||
let [err, values] = safeParseTuple(window.localStorage.getItem('vjs-text-track-settings'));
|
||||
let err, values;
|
||||
|
||||
if (err) {
|
||||
log.error(err);
|
||||
try {
|
||||
[err, values] = safeParseTuple(window.localStorage.getItem('vjs-text-track-settings'));
|
||||
|
||||
if (err) {
|
||||
log.error(err);
|
||||
}
|
||||
} catch (e) {
|
||||
log.warn(e);
|
||||
}
|
||||
|
||||
if (values) {
|
||||
@@ -186,7 +192,9 @@ class TextTrackSettings extends Component {
|
||||
} else {
|
||||
window.localStorage.removeItem('vjs-text-track-settings');
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+255
-254
@@ -13,229 +13,16 @@ import window from 'global/window';
|
||||
import { isCrossOrigin } from '../utils/url.js';
|
||||
import XHR from 'xhr';
|
||||
|
||||
/*
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack
|
||||
/**
|
||||
* takes a webvtt file contents and parses it into cues
|
||||
*
|
||||
* interface TextTrack : EventTarget {
|
||||
* readonly attribute TextTrackKind kind;
|
||||
* readonly attribute DOMString label;
|
||||
* readonly attribute DOMString language;
|
||||
*
|
||||
* readonly attribute DOMString id;
|
||||
* readonly attribute DOMString inBandMetadataTrackDispatchType;
|
||||
*
|
||||
* attribute TextTrackMode mode;
|
||||
*
|
||||
* readonly attribute TextTrackCueList? cues;
|
||||
* readonly attribute TextTrackCueList? activeCues;
|
||||
*
|
||||
* void addCue(TextTrackCue cue);
|
||||
* void removeCue(TextTrackCue cue);
|
||||
*
|
||||
* attribute EventHandler oncuechange;
|
||||
* };
|
||||
* @param {String} srcContent webVTT file contents
|
||||
* @param {Track} track track to addcues to
|
||||
*/
|
||||
let TextTrack = function(options={}) {
|
||||
if (!options.tech) {
|
||||
throw new Error('A tech was not provided.');
|
||||
}
|
||||
|
||||
let tt = this;
|
||||
if (browser.IS_IE8) {
|
||||
tt = document.createElement('custom');
|
||||
|
||||
for (let prop in TextTrack.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
tt[prop] = TextTrack.prototype[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tt.tech_ = options.tech;
|
||||
|
||||
let mode = TextTrackEnum.TextTrackMode[options['mode']] || 'disabled';
|
||||
let kind = TextTrackEnum.TextTrackKind[options['kind']] || 'subtitles';
|
||||
let label = options['label'] || '';
|
||||
let language = options['language'] || options['srclang'] || '';
|
||||
let id = options['id'] || 'vjs_text_track_' + Guid.newGUID();
|
||||
|
||||
if (kind === 'metadata' || kind === 'chapters') {
|
||||
mode = 'hidden';
|
||||
}
|
||||
|
||||
tt.cues_ = [];
|
||||
tt.activeCues_ = [];
|
||||
|
||||
let cues = new TextTrackCueList(tt.cues_);
|
||||
let activeCues = new TextTrackCueList(tt.activeCues_);
|
||||
|
||||
let changed = false;
|
||||
let timeupdateHandler = Fn.bind(tt, function() {
|
||||
this['activeCues'];
|
||||
if (changed) {
|
||||
this['trigger']('cuechange');
|
||||
changed = false;
|
||||
}
|
||||
});
|
||||
if (mode !== 'disabled') {
|
||||
tt.tech_.on('timeupdate', timeupdateHandler);
|
||||
}
|
||||
|
||||
Object.defineProperty(tt, 'kind', {
|
||||
get: function() {
|
||||
return kind;
|
||||
},
|
||||
set: Function.prototype
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'label', {
|
||||
get: function() {
|
||||
return label;
|
||||
},
|
||||
set: Function.prototype
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'language', {
|
||||
get: function() {
|
||||
return language;
|
||||
},
|
||||
set: Function.prototype
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'id', {
|
||||
get: function() {
|
||||
return id;
|
||||
},
|
||||
set: Function.prototype
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'mode', {
|
||||
get: function() {
|
||||
return mode;
|
||||
},
|
||||
set: function(newMode) {
|
||||
if (!TextTrackEnum.TextTrackMode[newMode]) {
|
||||
return;
|
||||
}
|
||||
mode = newMode;
|
||||
if (mode === 'showing') {
|
||||
this.tech_.on('timeupdate', timeupdateHandler);
|
||||
}
|
||||
this.trigger('modechange');
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'cues', {
|
||||
get: function() {
|
||||
if (!this.loaded_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return cues;
|
||||
},
|
||||
set: Function.prototype
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'activeCues', {
|
||||
get: function() {
|
||||
if (!this.loaded_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this['cues'].length === 0) {
|
||||
return activeCues; // nothing to do
|
||||
}
|
||||
|
||||
let ct = this.tech_.currentTime();
|
||||
let active = [];
|
||||
|
||||
for (let i = 0, l = this['cues'].length; i < l; i++) {
|
||||
let cue = this['cues'][i];
|
||||
if (cue['startTime'] <= ct && cue['endTime'] >= ct) {
|
||||
active.push(cue);
|
||||
} else if (cue['startTime'] === cue['endTime'] && cue['startTime'] <= ct && cue['startTime'] + 0.5 >= ct) {
|
||||
active.push(cue);
|
||||
}
|
||||
}
|
||||
|
||||
changed = false;
|
||||
|
||||
if (active.length !== this.activeCues_.length) {
|
||||
changed = true;
|
||||
} else {
|
||||
for (let i = 0; i < active.length; i++) {
|
||||
if (indexOf.call(this.activeCues_, active[i]) === -1) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.activeCues_ = active;
|
||||
activeCues.setCues_(this.activeCues_);
|
||||
|
||||
return activeCues;
|
||||
},
|
||||
set: Function.prototype
|
||||
});
|
||||
|
||||
if (options.src) {
|
||||
tt.src = options.src;
|
||||
loadTrack(options.src, tt);
|
||||
} else {
|
||||
tt.loaded_ = true;
|
||||
}
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
return tt;
|
||||
}
|
||||
};
|
||||
|
||||
TextTrack.prototype = Object.create(EventTarget.prototype);
|
||||
TextTrack.prototype.constructor = TextTrack;
|
||||
|
||||
/*
|
||||
* cuechange - One or more cues in the track have become active or stopped being active.
|
||||
*/
|
||||
TextTrack.prototype.allowedEvents_ = {
|
||||
'cuechange': 'cuechange'
|
||||
};
|
||||
|
||||
TextTrack.prototype.addCue = function(cue) {
|
||||
let tracks = this.tech_.textTracks();
|
||||
|
||||
if (tracks) {
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
if (tracks[i] !== this) {
|
||||
tracks[i].removeCue(cue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.cues_.push(cue);
|
||||
this['cues'].setCues_(this.cues_);
|
||||
};
|
||||
|
||||
TextTrack.prototype.removeCue = function(removeCue) {
|
||||
let removed = false;
|
||||
|
||||
for (let i = 0, l = this.cues_.length; i < l; i++) {
|
||||
let cue = this.cues_[i];
|
||||
if (cue === removeCue) {
|
||||
this.cues_.splice(i, 1);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
this.cues.setCues_(this.cues_);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Downloading stuff happens below this point
|
||||
*/
|
||||
var parseCues = function(srcContent, track) {
|
||||
let parser = new window.WebVTT.Parser(window, window.vttjs, window.WebVTT.StringDecoder());
|
||||
const parseCues = function(srcContent, track) {
|
||||
let parser = new window.WebVTT.Parser(window,
|
||||
window.vttjs,
|
||||
window.WebVTT.StringDecoder());
|
||||
|
||||
parser.oncue = function(cue) {
|
||||
track.addCue(cue);
|
||||
@@ -256,17 +43,24 @@ var parseCues = function(srcContent, track) {
|
||||
parser.flush();
|
||||
};
|
||||
|
||||
var loadTrack = function(src, track) {
|
||||
|
||||
/**
|
||||
* load a track from a specifed url
|
||||
*
|
||||
* @param {String} src url to load track from
|
||||
* @param {Track} track track to addcues to
|
||||
*/
|
||||
const loadTrack = function(src, track) {
|
||||
let opts = {
|
||||
uri: src
|
||||
};
|
||||
|
||||
let crossOrigin = isCrossOrigin(src);
|
||||
|
||||
if (crossOrigin) {
|
||||
opts.cors = crossOrigin;
|
||||
}
|
||||
|
||||
XHR(opts, Fn.bind(this, function(err, response, responseBody){
|
||||
XHR(opts, Fn.bind(this, function(err, response, responseBody) {
|
||||
if (err) {
|
||||
return log.error(err, response);
|
||||
}
|
||||
@@ -284,38 +78,245 @@ var loadTrack = function(src, track) {
|
||||
}));
|
||||
};
|
||||
|
||||
var indexOf = function(searchElement, fromIndex) {
|
||||
if (this == null) {
|
||||
throw new TypeError('"this" is null or not defined');
|
||||
}
|
||||
|
||||
let O = Object(this);
|
||||
|
||||
let len = O.length >>> 0;
|
||||
|
||||
if (len === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let n = +fromIndex || 0;
|
||||
|
||||
if (Math.abs(n) === Infinity) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
if (n >= len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
|
||||
|
||||
while (k < len) {
|
||||
if (k in O && O[k] === searchElement) {
|
||||
return k;
|
||||
/**
|
||||
* A single text track as defined in:
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack
|
||||
*
|
||||
* interface TextTrack : EventTarget {
|
||||
* readonly attribute TextTrackKind kind;
|
||||
* readonly attribute DOMString label;
|
||||
* readonly attribute DOMString language;
|
||||
*
|
||||
* readonly attribute DOMString id;
|
||||
* readonly attribute DOMString inBandMetadataTrackDispatchType;
|
||||
*
|
||||
* attribute TextTrackMode mode;
|
||||
*
|
||||
* readonly attribute TextTrackCueList? cues;
|
||||
* readonly attribute TextTrackCueList? activeCues;
|
||||
*
|
||||
* void addCue(TextTrackCue cue);
|
||||
* void removeCue(TextTrackCue cue);
|
||||
*
|
||||
* attribute EventHandler oncuechange;
|
||||
* };
|
||||
*
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @extends EventTarget
|
||||
* @class TextTrack
|
||||
*/
|
||||
class TextTrack extends EventTarget {
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
if (!options.tech) {
|
||||
throw new Error('A tech was not provided.');
|
||||
}
|
||||
|
||||
let tt = this;
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
tt = document.createElement('custom');
|
||||
|
||||
for (let prop in TextTrack.prototype) {
|
||||
if (prop !== 'constructor') {
|
||||
tt[prop] = TextTrack.prototype[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tt.tech_ = options.tech;
|
||||
|
||||
let mode = TextTrackEnum.TextTrackMode[options.mode] || 'disabled';
|
||||
let kind = TextTrackEnum.TextTrackKind[options.kind] || 'subtitles';
|
||||
let label = options.label || '';
|
||||
let language = options.language || options.srclang || '';
|
||||
let id = options.id || 'vjs_text_track_' + Guid.newGUID();
|
||||
|
||||
if (kind === 'metadata' || kind === 'chapters') {
|
||||
mode = 'hidden';
|
||||
}
|
||||
|
||||
tt.cues_ = [];
|
||||
tt.activeCues_ = [];
|
||||
|
||||
let cues = new TextTrackCueList(tt.cues_);
|
||||
let activeCues = new TextTrackCueList(tt.activeCues_);
|
||||
let changed = false;
|
||||
let timeupdateHandler = Fn.bind(tt, function() {
|
||||
this.activeCues;
|
||||
if (changed) {
|
||||
this.trigger('cuechange');
|
||||
changed = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (mode !== 'disabled') {
|
||||
tt.tech_.on('timeupdate', timeupdateHandler);
|
||||
}
|
||||
|
||||
Object.defineProperty(tt, 'kind', {
|
||||
get() {
|
||||
return kind;
|
||||
},
|
||||
set() {}
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'label', {
|
||||
get() {
|
||||
return label;
|
||||
},
|
||||
set() {}
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'language', {
|
||||
get() {
|
||||
return language;
|
||||
},
|
||||
set() {}
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'id', {
|
||||
get() {
|
||||
return id;
|
||||
},
|
||||
set() {}
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'mode', {
|
||||
get() {
|
||||
return mode;
|
||||
},
|
||||
set(newMode) {
|
||||
if (!TextTrackEnum.TextTrackMode[newMode]) {
|
||||
return;
|
||||
}
|
||||
mode = newMode;
|
||||
if (mode === 'showing') {
|
||||
this.tech_.on('timeupdate', timeupdateHandler);
|
||||
}
|
||||
this.trigger('modechange');
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'cues', {
|
||||
get() {
|
||||
if (!this.loaded_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return cues;
|
||||
},
|
||||
set() {}
|
||||
});
|
||||
|
||||
Object.defineProperty(tt, 'activeCues', {
|
||||
get() {
|
||||
if (!this.loaded_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// nothing to do
|
||||
if (this.cues.length === 0) {
|
||||
return activeCues;
|
||||
}
|
||||
|
||||
let ct = this.tech_.currentTime();
|
||||
let active = [];
|
||||
|
||||
for (let i = 0, l = this.cues.length; i < l; i++) {
|
||||
let cue = this.cues[i];
|
||||
|
||||
if (cue.startTime <= ct && cue.endTime >= ct) {
|
||||
active.push(cue);
|
||||
} else if (cue.startTime === cue.endTime &&
|
||||
cue.startTime <= ct &&
|
||||
cue.startTime + 0.5 >= ct) {
|
||||
active.push(cue);
|
||||
}
|
||||
}
|
||||
|
||||
changed = false;
|
||||
|
||||
if (active.length !== this.activeCues_.length) {
|
||||
changed = true;
|
||||
} else {
|
||||
for (let i = 0; i < active.length; i++) {
|
||||
if (this.activeCues_.indexOf(active[i]) === -1) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.activeCues_ = active;
|
||||
activeCues.setCues_(this.activeCues_);
|
||||
|
||||
return activeCues;
|
||||
},
|
||||
set() {}
|
||||
});
|
||||
|
||||
if (options.src) {
|
||||
tt.src = options.src;
|
||||
loadTrack(options.src, tt);
|
||||
} else {
|
||||
tt.loaded_ = true;
|
||||
}
|
||||
|
||||
if (browser.IS_IE8) {
|
||||
return tt;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
return -1;
|
||||
|
||||
/**
|
||||
* add a cue to the internal list of cues
|
||||
*
|
||||
* @param {Object} cue the cue to add to our internal list
|
||||
* @method addCue
|
||||
*/
|
||||
addCue(cue) {
|
||||
let tracks = this.tech_.textTracks();
|
||||
|
||||
if (tracks) {
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
if (tracks[i] !== this) {
|
||||
tracks[i].removeCue(cue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.cues_.push(cue);
|
||||
this.cues.setCues_(this.cues_);
|
||||
}
|
||||
|
||||
/**
|
||||
* remvoe a cue from our internal list
|
||||
*
|
||||
* @param {Object} removeCue the cue to remove from our internal list
|
||||
* @method removeCue
|
||||
*/
|
||||
removeCue(removeCue) {
|
||||
let removed = false;
|
||||
|
||||
for (let i = 0, l = this.cues_.length; i < l; i++) {
|
||||
let cue = this.cues_[i];
|
||||
|
||||
if (cue === removeCue) {
|
||||
this.cues_.splice(i, 1);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
this.cues.setCues_(this.cues_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cuechange - One or more cues in the track have become active or stopped being active.
|
||||
*/
|
||||
TextTrack.prototype.allowedEvents_ = {
|
||||
cuechange: 'cuechange'
|
||||
};
|
||||
|
||||
export default TextTrack;
|
||||
|
||||
@@ -943,3 +943,11 @@ test('player#reset loads the first item in the techOrder and then techCalls rese
|
||||
equal(loadedSource, null, 'with a null source');
|
||||
equal(techCallMethod, 'reset', 'we then reset the tech');
|
||||
});
|
||||
|
||||
test('Remove waiting class on timeupdate after tech waiting', function() {
|
||||
let player = TestHelpers.makePlayer();
|
||||
player.tech_.trigger('waiting');
|
||||
ok(/vjs-waiting/.test(player.el().className), 'vjs-waiting is added to the player el on tech waiting');
|
||||
player.trigger('timeupdate');
|
||||
ok(!/vjs-waiting/.test(player.el().className), 'vjs-waiting is removed from the player el on timeupdate');
|
||||
});
|
||||
|
||||
@@ -2,30 +2,29 @@ import HTMLTrackElement from '../../../src/js/tracks/html-track-element.js';
|
||||
import HTMLTrackElementList from '../../../src/js/tracks/html-track-element-list.js';
|
||||
import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
|
||||
let noop = Function.prototype;
|
||||
let defaultTech = {
|
||||
textTracks: noop,
|
||||
on: noop,
|
||||
off: noop,
|
||||
currentTime: noop
|
||||
const defaultTech = {
|
||||
textTracks() {},
|
||||
on() {},
|
||||
off() {},
|
||||
currentTime() {}
|
||||
};
|
||||
|
||||
let track1 = new TextTrack({
|
||||
const track1 = new TextTrack({
|
||||
id: 1,
|
||||
tech: defaultTech
|
||||
});
|
||||
let track2 = new TextTrack({
|
||||
const track2 = new TextTrack({
|
||||
id: 2,
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
var genericHtmlTrackElements = [{
|
||||
const genericHtmlTrackElements = [{
|
||||
tech() {},
|
||||
kind: 'captions',
|
||||
tech: noop,
|
||||
track: track1
|
||||
}, {
|
||||
tech() {},
|
||||
kind: 'chapters',
|
||||
tech: noop,
|
||||
track: track2
|
||||
}];
|
||||
|
||||
@@ -47,9 +46,9 @@ test('can get html track element by track', function() {
|
||||
test('length is updated when new tracks are added or removed', function() {
|
||||
let htmlTrackElementList = new HTMLTrackElementList(genericHtmlTrackElements);
|
||||
|
||||
htmlTrackElementList.addTrackElement_({tech: noop});
|
||||
htmlTrackElementList.addTrackElement_({tech() {}});
|
||||
equal(htmlTrackElementList.length, genericHtmlTrackElements.length + 1, `the length is ${genericHtmlTrackElements.length + 1}`);
|
||||
htmlTrackElementList.addTrackElement_({tech: noop});
|
||||
htmlTrackElementList.addTrackElement_({tech() {}});
|
||||
equal(htmlTrackElementList.length, genericHtmlTrackElements.length + 2, `the length is ${genericHtmlTrackElements.length + 2}`);
|
||||
|
||||
htmlTrackElementList.removeTrackElement_(htmlTrackElementList.getTrackElementByTrack_(track1));
|
||||
|
||||
@@ -2,12 +2,11 @@ import HTMLTrackElement from '../../../src/js/tracks/html-track-element.js';
|
||||
import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import window from 'global/window';
|
||||
|
||||
let noop = Function.prototype;
|
||||
let defaultTech = {
|
||||
textTracks: noop,
|
||||
on: noop,
|
||||
off: noop,
|
||||
currentTime: noop
|
||||
const defaultTech = {
|
||||
textTracks() {},
|
||||
on() {},
|
||||
off() {},
|
||||
currentTime() {}
|
||||
};
|
||||
|
||||
q.module('HTML Track Element');
|
||||
@@ -23,12 +22,12 @@ test('html track element requires a tech', function() {
|
||||
});
|
||||
|
||||
test('can create a html track element with various properties', function() {
|
||||
let kind = 'chapters',
|
||||
label = 'English',
|
||||
language = 'en',
|
||||
src = 'http://www.example.com';
|
||||
let kind = 'chapters';
|
||||
let label = 'English';
|
||||
let language = 'en';
|
||||
let src = 'http://www.example.com';
|
||||
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
kind,
|
||||
label,
|
||||
language,
|
||||
@@ -36,7 +35,7 @@ test('can create a html track element with various properties', function() {
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
equal(htmlTrackElement.default, undefined, 'we have a default');
|
||||
equal(typeof htmlTrackElement.default, 'undefined', 'we have a default');
|
||||
equal(htmlTrackElement.kind, kind, 'we have a kind');
|
||||
equal(htmlTrackElement.label, label, 'we have a label');
|
||||
equal(htmlTrackElement.readyState, 0, 'we have a readyState');
|
||||
@@ -46,29 +45,29 @@ test('can create a html track element with various properties', function() {
|
||||
});
|
||||
|
||||
test('defaults when items not provided', function() {
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
equal(htmlTrackElement.default, undefined, 'we have a default');
|
||||
equal(typeof htmlTrackElement.default, 'undefined', 'we have a default');
|
||||
equal(htmlTrackElement.kind, 'subtitles', 'we have a kind');
|
||||
equal(htmlTrackElement.label, '', 'we have a label');
|
||||
equal(htmlTrackElement.readyState, 0, 'we have a readyState');
|
||||
equal(htmlTrackElement.src, undefined, 'we have a src');
|
||||
equal(typeof htmlTrackElement.src, 'undefined', 'we have a src');
|
||||
equal(htmlTrackElement.srclang, '', 'we have a srclang');
|
||||
equal(htmlTrackElement.track.cues.length, 0, 'we have a track');
|
||||
});
|
||||
|
||||
test('fires loadeddata when track cues become populated', function() {
|
||||
let changes = 0,
|
||||
loadHandler;
|
||||
let changes = 0;
|
||||
let loadHandler;
|
||||
|
||||
loadHandler = function() {
|
||||
changes++;
|
||||
};
|
||||
|
||||
let htmlTrackElement = new HTMLTrackElement({
|
||||
tech: noop
|
||||
tech() {}
|
||||
});
|
||||
|
||||
htmlTrackElement.addEventListener('load', loadHandler);
|
||||
|
||||
@@ -3,15 +3,15 @@ import TestHelpers from '../test-helpers.js';
|
||||
import * as browser from '../../../src/js/utils/browser.js';
|
||||
|
||||
q.module('Text Track Controls', {
|
||||
'setup': function() {
|
||||
setup() {
|
||||
this.clock = sinon.useFakeTimers();
|
||||
},
|
||||
'teardown': function() {
|
||||
teardown() {
|
||||
this.clock.restore();
|
||||
}
|
||||
});
|
||||
|
||||
var track = {
|
||||
const track = {
|
||||
kind: 'captions',
|
||||
label: 'test'
|
||||
};
|
||||
@@ -30,7 +30,7 @@ test('should be displayed when text tracks list is not empty', function() {
|
||||
});
|
||||
|
||||
test('should be displayed when a text track is added to an empty track list', function() {
|
||||
var player = TestHelpers.makePlayer();
|
||||
let player = TestHelpers.makePlayer();
|
||||
|
||||
player.addRemoteTextTrack(track);
|
||||
|
||||
@@ -41,7 +41,7 @@ test('should be displayed when a text track is added to an empty track list', fu
|
||||
});
|
||||
|
||||
test('should not be displayed when text tracks list is empty', function() {
|
||||
var player = TestHelpers.makePlayer();
|
||||
let player = TestHelpers.makePlayer();
|
||||
|
||||
ok(player.controlBar.captionsButton.hasClass('vjs-hidden'), 'control is not displayed');
|
||||
equal(player.textTracks().length, 0, 'textTracks is empty');
|
||||
@@ -50,7 +50,7 @@ test('should not be displayed when text tracks list is empty', function() {
|
||||
});
|
||||
|
||||
test('should not be displayed when last text track is removed', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks: [track]
|
||||
});
|
||||
|
||||
@@ -63,10 +63,10 @@ test('should not be displayed when last text track is removed', function() {
|
||||
});
|
||||
|
||||
test('menu should contain "Settings", "Off" and one track', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
tracks: [track]
|
||||
}),
|
||||
menuItems;
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks: [track]
|
||||
});
|
||||
let menuItems;
|
||||
|
||||
this.clock.tick(1000);
|
||||
|
||||
@@ -81,7 +81,7 @@ test('menu should contain "Settings", "Off" and one track', function() {
|
||||
});
|
||||
|
||||
test('menu should update with addRemoteTextTrack', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks: [track]
|
||||
});
|
||||
|
||||
@@ -96,7 +96,7 @@ test('menu should update with addRemoteTextTrack', function() {
|
||||
});
|
||||
|
||||
test('menu should update with removeRemoteTextTrack', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks: [track, track]
|
||||
});
|
||||
|
||||
@@ -115,15 +115,15 @@ if (!browser.IS_IE8) {
|
||||
// However, this test tests a specific with iOS7 where the TextTrackList doesn't report track mode changes.
|
||||
// TODO: figure out why this test doens't work on IE8. https://github.com/videojs/video.js/issues/1861
|
||||
test('menu items should polyfill mode change events', function() {
|
||||
var player = TestHelpers.makePlayer({}),
|
||||
changes,
|
||||
trackMenuItem;
|
||||
let player = TestHelpers.makePlayer({});
|
||||
let changes;
|
||||
let trackMenuItem;
|
||||
|
||||
// emulate a TextTrackList that doesn't report track mode changes,
|
||||
// like iOS7
|
||||
player.textTracks().onchange = undefined;
|
||||
trackMenuItem = new TextTrackMenuItem(player, {
|
||||
track: track
|
||||
track
|
||||
});
|
||||
|
||||
player.textTracks().on('change', function() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import TextTrackCueList from '../../../src/js/tracks/text-track-cue-list.js';
|
||||
|
||||
let genericTracks = [
|
||||
const genericTracks = [
|
||||
{
|
||||
id: '1'
|
||||
}, {
|
||||
@@ -13,13 +13,13 @@ let genericTracks = [
|
||||
q.module('Text Track Cue List');
|
||||
|
||||
test('TextTrackCueList\'s length is set correctly', function() {
|
||||
var ttcl = new TextTrackCueList(genericTracks);
|
||||
let ttcl = new TextTrackCueList(genericTracks);
|
||||
|
||||
equal(ttcl.length, genericTracks.length, 'the length is ' + genericTracks.length);
|
||||
});
|
||||
|
||||
test('can get cues by id', function() {
|
||||
var ttcl = new TextTrackCueList(genericTracks);
|
||||
let ttcl = new TextTrackCueList(genericTracks);
|
||||
|
||||
equal(ttcl.getCueById('1').id, 1, 'id "1" has id of "1"');
|
||||
equal(ttcl.getCueById('2').id, 2, 'id "2" has id of "2"');
|
||||
@@ -28,7 +28,7 @@ test('can get cues by id', function() {
|
||||
});
|
||||
|
||||
test('length is updated when new tracks are added or removed', function() {
|
||||
var ttcl = new TextTrackCueList(genericTracks);
|
||||
let ttcl = new TextTrackCueList(genericTracks);
|
||||
|
||||
ttcl.setCues_(genericTracks.concat([{id: '100'}]));
|
||||
equal(ttcl.length, genericTracks.length + 1, 'the length is ' + (genericTracks.length + 1));
|
||||
@@ -42,9 +42,9 @@ test('length is updated when new tracks are added or removed', function() {
|
||||
});
|
||||
|
||||
test('can access items by index', function() {
|
||||
var ttcl = new TextTrackCueList(genericTracks),
|
||||
i = 0,
|
||||
length = ttcl.length;
|
||||
let ttcl = new TextTrackCueList(genericTracks);
|
||||
let i = 0;
|
||||
let length = ttcl.length;
|
||||
|
||||
expect(length);
|
||||
|
||||
@@ -54,7 +54,7 @@ test('can access items by index', function() {
|
||||
});
|
||||
|
||||
test('can access new items by index', function() {
|
||||
var ttcl = new TextTrackCueList(genericTracks);
|
||||
let ttcl = new TextTrackCueList(genericTracks);
|
||||
|
||||
ttcl.setCues_(genericTracks.concat([{id: '100'}]));
|
||||
|
||||
@@ -64,7 +64,7 @@ test('can access new items by index', function() {
|
||||
});
|
||||
|
||||
test('cannot access removed items by index', function() {
|
||||
var ttcl = new TextTrackCueList(genericTracks);
|
||||
let ttcl = new TextTrackCueList(genericTracks);
|
||||
|
||||
ttcl.setCues_(genericTracks.concat([{id: '100'}, {id: '101'}]));
|
||||
equal(ttcl[3].id, '100', 'id of item at index 3 is 100');
|
||||
@@ -77,7 +77,7 @@ test('cannot access removed items by index', function() {
|
||||
});
|
||||
|
||||
test('new item available at old index', function() {
|
||||
var ttcl = new TextTrackCueList(genericTracks);
|
||||
let ttcl = new TextTrackCueList(genericTracks);
|
||||
|
||||
ttcl.setCues_(genericTracks.concat([{id: '100'}]));
|
||||
equal(ttcl[3].id, '100', 'id of item at index 3 is 100');
|
||||
|
||||
@@ -3,7 +3,6 @@ import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import TextTrackList from '../../../src/js/tracks/text-track-list.js';
|
||||
import Html5 from '../../../src/js/tech/html5.js';
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
|
||||
q.module('Text Track List Converter', {});
|
||||
|
||||
@@ -26,6 +25,7 @@ let cleanup = (item) => {
|
||||
if (Html5.supportsNativeTextTracks()) {
|
||||
q.test('trackToJson_ produces correct representation for native track object', function(a) {
|
||||
let track = document.createElement('track');
|
||||
|
||||
track.src = 'example.com/english.vtt';
|
||||
track.kind = 'captions';
|
||||
track.srclang = 'en';
|
||||
@@ -48,11 +48,13 @@ if (Html5.supportsNativeTextTracks()) {
|
||||
});
|
||||
|
||||
let nativeTrack = document.createElement('track');
|
||||
|
||||
nativeTrack.kind = 'captions';
|
||||
nativeTrack.srclang = 'es';
|
||||
nativeTrack.label = 'Spanish';
|
||||
|
||||
let tt = new TextTrackList();
|
||||
|
||||
tt.addTrack_(nativeTrack.track);
|
||||
tt.addTrack_(emulatedTrack);
|
||||
|
||||
@@ -96,12 +98,14 @@ if (Html5.supportsNativeTextTracks()) {
|
||||
});
|
||||
|
||||
let nativeTrack = document.createElement('track');
|
||||
|
||||
nativeTrack.src = 'example.com/spanish.vtt';
|
||||
nativeTrack.kind = 'captions';
|
||||
nativeTrack.srclang = 'es';
|
||||
nativeTrack.label = 'Spanish';
|
||||
|
||||
let tt = new TextTrackList();
|
||||
|
||||
tt.addTrack_(nativeTrack.track);
|
||||
tt.addTrack_(emulatedTrack);
|
||||
|
||||
@@ -171,6 +175,7 @@ q.test('textTracksToJson produces good json output for emulated only', function(
|
||||
});
|
||||
|
||||
let tt = new TextTrackList();
|
||||
|
||||
tt.addTrack_(anotherTrack);
|
||||
tt.addTrack_(emulatedTrack);
|
||||
|
||||
@@ -224,6 +229,7 @@ q.test('jsonToTextTracks calls addRemoteTextTrack on the tech with emulated trac
|
||||
});
|
||||
|
||||
let tt = new TextTrackList();
|
||||
|
||||
tt.addTrack_(anotherTrack);
|
||||
tt.addTrack_(emulatedTrack);
|
||||
|
||||
|
||||
@@ -2,33 +2,32 @@ import TextTrackList from '../../../src/js/tracks/text-track-list.js';
|
||||
import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import EventTarget from '../../../src/js/event-target.js';
|
||||
|
||||
var noop = Function.prototype;
|
||||
var genericTracks = [
|
||||
const genericTracks = [
|
||||
{
|
||||
id: '1',
|
||||
addEventListener: noop,
|
||||
off: noop
|
||||
addEventListener() {},
|
||||
off() {}
|
||||
}, {
|
||||
id: '2',
|
||||
addEventListener: noop,
|
||||
off: noop
|
||||
addEventListener() {},
|
||||
off() {}
|
||||
}, {
|
||||
id: '3',
|
||||
addEventListener: noop,
|
||||
off: noop
|
||||
addEventListener() {},
|
||||
off() {}
|
||||
}
|
||||
];
|
||||
|
||||
q.module('Text Track List');
|
||||
|
||||
test('TextTrackList\'s length is set correctly', function() {
|
||||
var ttl = new TextTrackList(genericTracks);
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
|
||||
equal(ttl.length, genericTracks.length, 'the length is ' + genericTracks.length);
|
||||
});
|
||||
|
||||
test('can get text tracks by id', function() {
|
||||
var ttl = new TextTrackList(genericTracks);
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
|
||||
equal(ttl.getTrackById('1').id, 1, 'id "1" has id of "1"');
|
||||
equal(ttl.getTrackById('2').id, 2, 'id "2" has id of "2"');
|
||||
@@ -37,11 +36,11 @@ test('can get text tracks by id', function() {
|
||||
});
|
||||
|
||||
test('length is updated when new tracks are added or removed', function() {
|
||||
var ttl = new TextTrackList(genericTracks);
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
|
||||
ttl.addTrack_({id: '100', addEventListener: noop, off: noop});
|
||||
ttl.addTrack_({id: '100', addEventListener() {}, off() {}});
|
||||
equal(ttl.length, genericTracks.length + 1, 'the length is ' + (genericTracks.length + 1));
|
||||
ttl.addTrack_({id: '101', addEventListener: noop, off: noop});
|
||||
ttl.addTrack_({id: '101', addEventListener() {}, off() {}});
|
||||
equal(ttl.length, genericTracks.length + 2, 'the length is ' + (genericTracks.length + 2));
|
||||
|
||||
ttl.removeTrack_(ttl.getTrackById('101'));
|
||||
@@ -51,9 +50,9 @@ test('length is updated when new tracks are added or removed', function() {
|
||||
});
|
||||
|
||||
test('can access items by index', function() {
|
||||
var ttl = new TextTrackList(genericTracks),
|
||||
i = 0,
|
||||
length = ttl.length;
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
let i = 0;
|
||||
let length = ttl.length;
|
||||
|
||||
expect(length);
|
||||
|
||||
@@ -63,19 +62,19 @@ test('can access items by index', function() {
|
||||
});
|
||||
|
||||
test('can access new items by index', function() {
|
||||
var ttl = new TextTrackList(genericTracks);
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
|
||||
ttl.addTrack_({id: '100', addEventListener: noop});
|
||||
ttl.addTrack_({id: '100', addEventListener() {}});
|
||||
equal(ttl[3].id, '100', 'id of item at index 3 is 100');
|
||||
ttl.addTrack_({id: '101', addEventListener: noop});
|
||||
ttl.addTrack_({id: '101', addEventListener() {}});
|
||||
equal(ttl[4].id, '101', 'id of item at index 4 is 101');
|
||||
});
|
||||
|
||||
test('cannot access removed items by index', function() {
|
||||
var ttl = new TextTrackList(genericTracks);
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
|
||||
ttl.addTrack_({id: '100', addEventListener: noop, off: noop});
|
||||
ttl.addTrack_({id: '101', addEventListener: noop, off: noop});
|
||||
ttl.addTrack_({id: '100', addEventListener() {}, off() {}});
|
||||
ttl.addTrack_({id: '101', addEventListener() {}, off() {}});
|
||||
equal(ttl[3].id, '100', 'id of item at index 3 is 100');
|
||||
equal(ttl[4].id, '101', 'id of item at index 4 is 101');
|
||||
|
||||
@@ -87,51 +86,55 @@ test('cannot access removed items by index', function() {
|
||||
});
|
||||
|
||||
test('new item available at old index', function() {
|
||||
var ttl = new TextTrackList(genericTracks);
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
|
||||
ttl.addTrack_({id: '100', addEventListener: noop, off: noop});
|
||||
ttl.addTrack_({id: '100', addEventListener() {}, off() {}});
|
||||
equal(ttl[3].id, '100', 'id of item at index 3 is 100');
|
||||
|
||||
ttl.removeTrack_(ttl.getTrackById('100'));
|
||||
ok(!ttl[3], 'nothing at index 3');
|
||||
|
||||
ttl.addTrack_({id: '101', addEventListener: noop});
|
||||
ttl.addTrack_({id: '101', addEventListener() {}});
|
||||
equal(ttl[3].id, '101', 'id of new item at index 3 is now 101');
|
||||
});
|
||||
|
||||
test('a "addtrack" event is triggered when new tracks are added', function() {
|
||||
var ttl = new TextTrackList(genericTracks),
|
||||
tracks = 0,
|
||||
adds = 0,
|
||||
addHandler = function(e) {
|
||||
e.track && tracks++;
|
||||
adds++;
|
||||
};
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
let tracks = 0;
|
||||
let adds = 0;
|
||||
let addHandler = function(e) {
|
||||
if (e.track) {
|
||||
tracks++;
|
||||
}
|
||||
adds++;
|
||||
};
|
||||
|
||||
ttl.on('addtrack', addHandler);
|
||||
|
||||
ttl.addTrack_({id: '100', addEventListener: noop});
|
||||
ttl.addTrack_({id: '101', addEventListener: noop});
|
||||
ttl.addTrack_({id: '100', addEventListener() {}});
|
||||
ttl.addTrack_({id: '101', addEventListener() {}});
|
||||
|
||||
ttl.off('addtrack', addHandler);
|
||||
|
||||
ttl.onaddtrack = addHandler;
|
||||
|
||||
ttl.addTrack_({id: '102', addEventListener: noop});
|
||||
ttl.addTrack_({id: '103', addEventListener: noop});
|
||||
ttl.addTrack_({id: '102', addEventListener() {}});
|
||||
ttl.addTrack_({id: '103', addEventListener() {}});
|
||||
|
||||
equal(adds, 4, 'we got ' + adds + ' "addtrack" events');
|
||||
equal(tracks, 4, 'we got a track with every event');
|
||||
});
|
||||
|
||||
test('a "removetrack" event is triggered when tracks are removed', function() {
|
||||
var ttl = new TextTrackList(genericTracks),
|
||||
tracks = 0,
|
||||
rms = 0,
|
||||
rmHandler = function(e) {
|
||||
e.track && tracks++;
|
||||
rms++;
|
||||
};
|
||||
let ttl = new TextTrackList(genericTracks);
|
||||
let tracks = 0;
|
||||
let rms = 0;
|
||||
let rmHandler = function(e) {
|
||||
if (e.track) {
|
||||
tracks++;
|
||||
}
|
||||
rms++;
|
||||
};
|
||||
|
||||
ttl.on('removetrack', rmHandler);
|
||||
|
||||
@@ -149,12 +152,12 @@ test('a "removetrack" event is triggered when tracks are removed', function() {
|
||||
});
|
||||
|
||||
test('trigger "change" event when "modechange" is fired on a track', function() {
|
||||
var tt = new EventTarget(),
|
||||
ttl = new TextTrackList([tt]),
|
||||
changes = 0,
|
||||
changeHandler = function() {
|
||||
changes++;
|
||||
};
|
||||
let tt = new EventTarget();
|
||||
let ttl = new TextTrackList([tt]);
|
||||
let changes = 0;
|
||||
let changeHandler = function() {
|
||||
changes++;
|
||||
};
|
||||
|
||||
ttl.on('change', changeHandler);
|
||||
|
||||
@@ -170,16 +173,16 @@ test('trigger "change" event when "modechange" is fired on a track', function()
|
||||
});
|
||||
|
||||
test('trigger "change" event when mode changes on a TextTrack', function() {
|
||||
var tt = new TextTrack({
|
||||
tech: {
|
||||
on: noop
|
||||
}
|
||||
}),
|
||||
ttl = new TextTrackList([tt]),
|
||||
changes = 0,
|
||||
changeHandler = function() {
|
||||
changes++;
|
||||
};
|
||||
let tt = new TextTrack({
|
||||
tech: {
|
||||
on() {}
|
||||
}
|
||||
});
|
||||
let ttl = new TextTrackList([tt]);
|
||||
let changes = 0;
|
||||
let changeHandler = function() {
|
||||
changes++;
|
||||
};
|
||||
|
||||
ttl.on('change', changeHandler);
|
||||
|
||||
|
||||
@@ -4,33 +4,33 @@ import * as Events from '../../../src/js/utils/events.js';
|
||||
import safeParseTuple from 'safe-json-parse/tuple';
|
||||
import window from 'global/window';
|
||||
|
||||
var tracks = [{
|
||||
const tracks = [{
|
||||
kind: 'captions',
|
||||
label: 'test'
|
||||
}];
|
||||
|
||||
q.module('Text Track Settings', {
|
||||
beforeEach: function() {
|
||||
beforeEach() {
|
||||
window.localStorage.clear();
|
||||
}
|
||||
});
|
||||
|
||||
test('should update settings', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
tracks: tracks,
|
||||
persistTextTrackSettings: true
|
||||
}),
|
||||
newSettings = {
|
||||
'backgroundOpacity': '1',
|
||||
'textOpacity': '1',
|
||||
'windowOpacity': '1',
|
||||
'edgeStyle': 'raised',
|
||||
'fontFamily': 'monospaceSerif',
|
||||
'color': '#FFF',
|
||||
'backgroundColor': '#FFF',
|
||||
'windowColor': '#FFF',
|
||||
'fontPercent': 1.25
|
||||
};
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks,
|
||||
persistTextTrackSettings: true
|
||||
});
|
||||
let newSettings = {
|
||||
backgroundOpacity: '1',
|
||||
textOpacity: '1',
|
||||
windowOpacity: '1',
|
||||
edgeStyle: 'raised',
|
||||
fontFamily: 'monospaceSerif',
|
||||
color: '#FFF',
|
||||
backgroundColor: '#FFF',
|
||||
windowColor: '#FFF',
|
||||
fontPercent: 1.25
|
||||
};
|
||||
|
||||
player.textTrackSettings.setValues(newSettings);
|
||||
deepEqual(player.textTrackSettings.getValues(), newSettings, 'values are updated');
|
||||
@@ -52,8 +52,8 @@ test('should update settings', function() {
|
||||
});
|
||||
|
||||
test('should restore default settings', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
tracks: tracks,
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks,
|
||||
persistTextTrackSettings: true
|
||||
});
|
||||
|
||||
@@ -88,9 +88,10 @@ test('should restore default settings', function() {
|
||||
});
|
||||
|
||||
test('should open on click', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
tracks: tracks
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks
|
||||
});
|
||||
|
||||
Events.trigger(player.$('.vjs-texttrack-settings'), 'click');
|
||||
ok(!player.textTrackSettings.hasClass('vjs-hidden'), 'settings open');
|
||||
|
||||
@@ -98,9 +99,10 @@ test('should open on click', function() {
|
||||
});
|
||||
|
||||
test('should close on done click', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
tracks: tracks
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks
|
||||
});
|
||||
|
||||
Events.trigger(player.$('.vjs-texttrack-settings'), 'click');
|
||||
Events.trigger(player.$('.vjs-done-button'), 'click');
|
||||
ok(player.textTrackSettings.hasClass('vjs-hidden'), 'settings closed');
|
||||
@@ -109,16 +111,16 @@ test('should close on done click', function() {
|
||||
});
|
||||
|
||||
test('if persist option is set, restore settings on init', function() {
|
||||
var player,
|
||||
oldRestoreSettings = TextTrackSettings.prototype.restoreSettings,
|
||||
restore = 0;
|
||||
let player;
|
||||
let oldRestoreSettings = TextTrackSettings.prototype.restoreSettings;
|
||||
let restore = 0;
|
||||
|
||||
TextTrackSettings.prototype.restoreSettings = function() {
|
||||
restore++;
|
||||
};
|
||||
|
||||
player = TestHelpers.makePlayer({
|
||||
tracks: tracks,
|
||||
tracks,
|
||||
persistTextTrackSettings: true
|
||||
});
|
||||
|
||||
@@ -130,12 +132,12 @@ test('if persist option is set, restore settings on init', function() {
|
||||
});
|
||||
|
||||
test('if persist option is set, save settings when "done"', function() {
|
||||
var player = TestHelpers.makePlayer({
|
||||
tracks: tracks,
|
||||
persistTextTrackSettings: true
|
||||
}),
|
||||
oldSaveSettings = TextTrackSettings.prototype.saveSettings,
|
||||
save = 0;
|
||||
let player = TestHelpers.makePlayer({
|
||||
tracks,
|
||||
persistTextTrackSettings: true
|
||||
});
|
||||
let oldSaveSettings = TextTrackSettings.prototype.saveSettings;
|
||||
let save = 0;
|
||||
|
||||
TextTrackSettings.prototype.saveSettings = function() {
|
||||
save++;
|
||||
@@ -151,11 +153,11 @@ test('if persist option is set, save settings when "done"', function() {
|
||||
});
|
||||
|
||||
test('do not try to restore or save settings if persist option is not set', function() {
|
||||
var player,
|
||||
oldRestoreSettings = TextTrackSettings.prototype.restoreSettings,
|
||||
oldSaveSettings = TextTrackSettings.prototype.saveSettings,
|
||||
save = 0,
|
||||
restore = 0;
|
||||
let player;
|
||||
let oldRestoreSettings = TextTrackSettings.prototype.restoreSettings;
|
||||
let oldSaveSettings = TextTrackSettings.prototype.saveSettings;
|
||||
let save = 0;
|
||||
let restore = 0;
|
||||
|
||||
TextTrackSettings.prototype.restoreSettings = function() {
|
||||
restore++;
|
||||
@@ -165,7 +167,7 @@ test('do not try to restore or save settings if persist option is not set', func
|
||||
};
|
||||
|
||||
player = TestHelpers.makePlayer({
|
||||
tracks: tracks,
|
||||
tracks,
|
||||
persistTextTrackSettings: false
|
||||
});
|
||||
|
||||
@@ -183,23 +185,23 @@ test('do not try to restore or save settings if persist option is not set', func
|
||||
});
|
||||
|
||||
test('should restore saved settings', function() {
|
||||
var player,
|
||||
newSettings = {
|
||||
'backgroundOpacity': '1',
|
||||
'textOpacity': '1',
|
||||
'windowOpacity': '1',
|
||||
'edgeStyle': 'raised',
|
||||
'fontFamily': 'monospaceSerif',
|
||||
'color': '#FFF',
|
||||
'backgroundColor': '#FFF',
|
||||
'windowColor': '#FFF',
|
||||
'fontPercent': 1.25
|
||||
};
|
||||
let player;
|
||||
let newSettings = {
|
||||
backgroundOpacity: '1',
|
||||
textOpacity: '1',
|
||||
windowOpacity: '1',
|
||||
edgeStyle: 'raised',
|
||||
fontFamily: 'monospaceSerif',
|
||||
color: '#FFF',
|
||||
backgroundColor: '#FFF',
|
||||
windowColor: '#FFF',
|
||||
fontPercent: 1.25
|
||||
};
|
||||
|
||||
window.localStorage.setItem('vjs-text-track-settings', JSON.stringify(newSettings));
|
||||
|
||||
player = TestHelpers.makePlayer({
|
||||
tracks: tracks,
|
||||
tracks,
|
||||
persistTextTrackSettings: true
|
||||
});
|
||||
|
||||
@@ -209,23 +211,23 @@ test('should restore saved settings', function() {
|
||||
});
|
||||
|
||||
test('should not restore saved settings', function() {
|
||||
var player,
|
||||
newSettings = {
|
||||
'backgroundOpacity': '1',
|
||||
'textOpacity': '1',
|
||||
'windowOpacity': '1',
|
||||
'edgeStyle': 'raised',
|
||||
'fontFamily': 'monospaceSerif',
|
||||
'color': '#FFF',
|
||||
'backgroundColor': '#FFF',
|
||||
'windowColor': '#FFF',
|
||||
'fontPercent': 1.25
|
||||
};
|
||||
let player;
|
||||
let newSettings = {
|
||||
backgroundOpacity: '1',
|
||||
textOpacity: '1',
|
||||
windowOpacity: '1',
|
||||
edgeStyle: 'raised',
|
||||
fontFamily: 'monospaceSerif',
|
||||
color: '#FFF',
|
||||
backgroundColor: '#FFF',
|
||||
windowColor: '#FFF',
|
||||
fontPercent: 1.25
|
||||
};
|
||||
|
||||
window.localStorage.setItem('vjs-text-track-settings', JSON.stringify(newSettings));
|
||||
|
||||
player = TestHelpers.makePlayer({
|
||||
tracks: tracks,
|
||||
tracks,
|
||||
persistTextTrackSettings: false
|
||||
});
|
||||
|
||||
|
||||
@@ -1,39 +1,35 @@
|
||||
import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import window from 'global/window';
|
||||
import TestHelpers from '../test-helpers.js';
|
||||
|
||||
var noop = Function.prototype;
|
||||
var defaultTech = {
|
||||
textTracks: noop,
|
||||
on: noop,
|
||||
off: noop,
|
||||
currentTime: noop
|
||||
const defaultTech = {
|
||||
textTracks() {},
|
||||
on() {},
|
||||
off() {},
|
||||
currentTime() {}
|
||||
};
|
||||
|
||||
q.module('Text Track');
|
||||
|
||||
test('text-track requires a tech', function() {
|
||||
window.throws(function() {
|
||||
new TextTrack();
|
||||
},
|
||||
new Error('A tech was not provided.'),
|
||||
'a tech is required for text track');
|
||||
let error = new Error('A tech was not provided.');
|
||||
|
||||
q.throws(() => new TextTrack(), error, 'a tech is required for text track');
|
||||
});
|
||||
|
||||
test('can create a TextTrack with various properties', function() {
|
||||
var kind = 'captions',
|
||||
label = 'English',
|
||||
language = 'en',
|
||||
id = '1',
|
||||
mode = 'disabled',
|
||||
tt = new TextTrack({
|
||||
tech: defaultTech,
|
||||
kind: kind,
|
||||
label: label,
|
||||
language: language,
|
||||
id: id,
|
||||
mode: mode
|
||||
});
|
||||
let kind = 'captions';
|
||||
let label = 'English';
|
||||
let language = 'en';
|
||||
let id = '1';
|
||||
let mode = 'disabled';
|
||||
let tt = new TextTrack({
|
||||
kind,
|
||||
label,
|
||||
language,
|
||||
id,
|
||||
mode,
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
equal(tt.kind, kind, 'we have a kind');
|
||||
equal(tt.label, label, 'we have a label');
|
||||
@@ -43,7 +39,7 @@ test('can create a TextTrack with various properties', function() {
|
||||
});
|
||||
|
||||
test('defaults when items not provided', function() {
|
||||
var tt = new TextTrack({
|
||||
let tt = new TextTrack({
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
@@ -54,7 +50,7 @@ test('defaults when items not provided', function() {
|
||||
});
|
||||
|
||||
test('kind can only be one of several options, defaults to subtitles', function() {
|
||||
var tt = new TextTrack({
|
||||
let tt = new TextTrack({
|
||||
tech: defaultTech,
|
||||
kind: 'foo'
|
||||
});
|
||||
@@ -99,7 +95,7 @@ test('kind can only be one of several options, defaults to subtitles', function(
|
||||
});
|
||||
|
||||
test('mode can only be one of several options, defaults to disabled', function() {
|
||||
var tt = new TextTrack({
|
||||
let tt = new TextTrack({
|
||||
tech: defaultTech,
|
||||
mode: 'foo'
|
||||
});
|
||||
@@ -130,19 +126,19 @@ test('mode can only be one of several options, defaults to disabled', function()
|
||||
});
|
||||
|
||||
test('kind, label, language, id, cue, and activeCues are read only', function() {
|
||||
var kind = 'captions',
|
||||
label = 'English',
|
||||
language = 'en',
|
||||
id = '1',
|
||||
mode = 'disabled',
|
||||
tt = new TextTrack({
|
||||
tech: defaultTech,
|
||||
kind: kind,
|
||||
label: label,
|
||||
language: language,
|
||||
id: id,
|
||||
mode: mode
|
||||
});
|
||||
let kind = 'captions';
|
||||
let label = 'English';
|
||||
let language = 'en';
|
||||
let id = '1';
|
||||
let mode = 'disabled';
|
||||
let tt = new TextTrack({
|
||||
kind,
|
||||
label,
|
||||
language,
|
||||
id,
|
||||
mode,
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
tt.kind = 'subtitles';
|
||||
tt.label = 'Spanish';
|
||||
@@ -160,8 +156,8 @@ test('kind, label, language, id, cue, and activeCues are read only', function()
|
||||
});
|
||||
|
||||
test('mode can only be set to a few options', function() {
|
||||
var tt = new TextTrack({
|
||||
tech: defaultTech,
|
||||
let tt = new TextTrack({
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
tt.mode = 'foo';
|
||||
@@ -185,8 +181,8 @@ test('mode can only be set to a few options', function() {
|
||||
});
|
||||
|
||||
test('cues and activeCues return a TextTrackCueList', function() {
|
||||
var tt = new TextTrack({
|
||||
tech: defaultTech,
|
||||
let tt = new TextTrack({
|
||||
tech: defaultTech
|
||||
});
|
||||
|
||||
ok(tt.cues.getCueById, 'cues are a TextTrackCueList');
|
||||
@@ -194,14 +190,13 @@ test('cues and activeCues return a TextTrackCueList', function() {
|
||||
});
|
||||
|
||||
test('cues can be added and removed from a TextTrack', function() {
|
||||
var tt = new TextTrack({
|
||||
tech: defaultTech,
|
||||
}),
|
||||
cues;
|
||||
let tt = new TextTrack({
|
||||
tech: defaultTech
|
||||
});
|
||||
let cues;
|
||||
|
||||
cues = tt.cues;
|
||||
|
||||
|
||||
equal(cues.length, 0, 'start with zero cues');
|
||||
|
||||
tt.addCue({id: '1'});
|
||||
@@ -220,13 +215,13 @@ test('cues can be added and removed from a TextTrack', function() {
|
||||
});
|
||||
|
||||
test('fires cuechange when cues become active and inactive', function() {
|
||||
var player = TestHelpers.makePlayer(),
|
||||
changes = 0,
|
||||
cuechangeHandler,
|
||||
tt = new TextTrack({
|
||||
tech: player.tech_,
|
||||
mode: 'showing'
|
||||
});
|
||||
let player = TestHelpers.makePlayer();
|
||||
let changes = 0;
|
||||
let cuechangeHandler;
|
||||
let tt = new TextTrack({
|
||||
tech: player.tech_,
|
||||
mode: 'showing'
|
||||
});
|
||||
|
||||
cuechangeHandler = function() {
|
||||
changes++;
|
||||
|
||||
@@ -5,34 +5,32 @@ import CaptionsButton from '../../../src/js/control-bar/text-track-controls/capt
|
||||
import TextTrack from '../../../src/js/tracks/text-track.js';
|
||||
import TextTrackDisplay from '../../../src/js/tracks/text-track-display.js';
|
||||
import Html5 from '../../../src/js/tech/html5.js';
|
||||
import Flash from '../../../src/js/tech/flash.js';
|
||||
import Tech from '../../../src/js/tech/tech.js';
|
||||
import Component from '../../../src/js/component.js';
|
||||
|
||||
import * as browser from '../../../src/js/utils/browser.js';
|
||||
import TestHelpers from '../test-helpers.js';
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
import TechFaker from '../tech/tech-faker.js';
|
||||
|
||||
q.module('Tracks', {
|
||||
'setup': function() {
|
||||
setup() {
|
||||
this.clock = sinon.useFakeTimers();
|
||||
},
|
||||
'teardown': function() {
|
||||
teardown() {
|
||||
this.clock.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test('should place title list item into ul', function() {
|
||||
var player, chaptersButton;
|
||||
let player;
|
||||
let chaptersButton;
|
||||
|
||||
player = TestHelpers.makePlayer();
|
||||
|
||||
chaptersButton = new ChaptersButton(player);
|
||||
|
||||
var menuContentElement = chaptersButton.el().getElementsByTagName('UL')[0];
|
||||
var titleElement = menuContentElement.children[0];
|
||||
let menuContentElement = chaptersButton.el().getElementsByTagName('UL')[0];
|
||||
let titleElement = menuContentElement.children[0];
|
||||
|
||||
ok(titleElement.innerHTML === 'Chapters', 'title element placed in ul');
|
||||
|
||||
@@ -40,8 +38,8 @@ test('should place title list item into ul', function() {
|
||||
});
|
||||
|
||||
test('Player track methods call the tech', function() {
|
||||
var player,
|
||||
calls = 0;
|
||||
let player;
|
||||
let calls = 0;
|
||||
|
||||
player = TestHelpers.makePlayer();
|
||||
|
||||
@@ -61,35 +59,34 @@ test('Player track methods call the tech', function() {
|
||||
});
|
||||
|
||||
test('TextTrackDisplay initializes tracks on player ready', function() {
|
||||
var calls = 0,
|
||||
ttd = new TextTrackDisplay({
|
||||
on: Function.prototype,
|
||||
addTextTracks: function() {
|
||||
calls--;
|
||||
},
|
||||
getChild: function() {
|
||||
calls--;
|
||||
},
|
||||
ready: function() {
|
||||
calls++;
|
||||
}
|
||||
}, {});
|
||||
let calls = 0;
|
||||
let ttd = new TextTrackDisplay({
|
||||
on() {},
|
||||
addTextTracks() {
|
||||
calls--;
|
||||
},
|
||||
getChild() {
|
||||
calls--;
|
||||
},
|
||||
ready() {
|
||||
calls++;
|
||||
}
|
||||
}, {});
|
||||
|
||||
equal(calls, 1, 'only a player.ready call was made');
|
||||
});
|
||||
|
||||
test('listen to remove and add track events in native text tracks', function() {
|
||||
var oldTestVid = Html5.TEST_VID,
|
||||
player,
|
||||
options,
|
||||
oldTextTracks,
|
||||
events = {},
|
||||
html;
|
||||
let oldTestVid = Html5.TEST_VID;
|
||||
let player;
|
||||
let options;
|
||||
let oldTextTracks = Html5.prototype.textTracks;
|
||||
let events = {};
|
||||
let html;
|
||||
|
||||
oldTextTracks = Html5.prototype.textTracks;
|
||||
Html5.prototype.textTracks = function() {
|
||||
return {
|
||||
addEventListener: function(type, handler) {
|
||||
addEventListener(type, handler) {
|
||||
events[type] = true;
|
||||
}
|
||||
};
|
||||
@@ -101,17 +98,17 @@ test('listen to remove and add track events in native text tracks', function() {
|
||||
|
||||
player = {
|
||||
// Function.prototype is a built-in no-op function.
|
||||
controls: Function.prototype,
|
||||
ready: Function.prototype,
|
||||
options: function() {
|
||||
controls() {},
|
||||
ready() {},
|
||||
options() {
|
||||
return {};
|
||||
},
|
||||
addChild: Function.prototype,
|
||||
id: Function.prototype,
|
||||
el: function() {
|
||||
addChild() {},
|
||||
id() {},
|
||||
el() {
|
||||
return {
|
||||
insertBefore: Function.prototype,
|
||||
appendChild: Function.prototype
|
||||
insertBefore() {},
|
||||
appendChild() {}
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -120,24 +117,24 @@ test('listen to remove and add track events in native text tracks', function() {
|
||||
|
||||
html = new Html5(options);
|
||||
|
||||
ok(events['removetrack'], 'removetrack listener was added');
|
||||
ok(events['addtrack'], 'addtrack listener was added');
|
||||
ok(events.removetrack, 'removetrack listener was added');
|
||||
ok(events.addtrack, 'addtrack listener was added');
|
||||
|
||||
Html5.TEST_VID = oldTestVid;
|
||||
Html5.prototype.textTracks = oldTextTracks;
|
||||
});
|
||||
|
||||
test('update texttrack buttons on removetrack or addtrack', function() {
|
||||
var update = 0,
|
||||
i,
|
||||
player,
|
||||
tag,
|
||||
track,
|
||||
oldTextTracks,
|
||||
events = {},
|
||||
oldCaptionsUpdate,
|
||||
oldSubsUpdate,
|
||||
oldChaptersUpdate;
|
||||
let update = 0;
|
||||
let i;
|
||||
let player;
|
||||
let tag;
|
||||
let track;
|
||||
let oldTextTracks;
|
||||
let events = {};
|
||||
let oldCaptionsUpdate;
|
||||
let oldSubsUpdate;
|
||||
let oldChaptersUpdate;
|
||||
|
||||
oldCaptionsUpdate = CaptionsButton.prototype.update;
|
||||
oldSubsUpdate = SubtitlesButton.prototype.update;
|
||||
@@ -155,19 +152,19 @@ test('update texttrack buttons on removetrack or addtrack', function() {
|
||||
oldChaptersUpdate.call(this);
|
||||
};
|
||||
|
||||
Tech.prototype['featuresNativeTextTracks'] = true;
|
||||
Tech.prototype.featuresNativeTextTracks = true;
|
||||
oldTextTracks = Tech.prototype.textTracks;
|
||||
Tech.prototype.textTracks = function() {
|
||||
return {
|
||||
length: 0,
|
||||
addEventListener: function(type, handler) {
|
||||
addEventListener(type, handler) {
|
||||
if (!events[type]) {
|
||||
events[type] = [];
|
||||
}
|
||||
events[type].push(handler);
|
||||
},
|
||||
// Requrired in player.dispose()
|
||||
removeEventListener: function(){}
|
||||
removeEventListener() {}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -185,26 +182,26 @@ test('update texttrack buttons on removetrack or addtrack', function() {
|
||||
track.src = '#es.vtt';
|
||||
tag.appendChild(track);
|
||||
|
||||
player = TestHelpers.makePlayer({}, tag);
|
||||
player = TestHelpers.makePlayer({}, tag);
|
||||
|
||||
player.player_ = player;
|
||||
|
||||
equal(update, 3, 'update was called on the three buttons during init');
|
||||
|
||||
for (i = 0; i < events['removetrack'].length; i++) {
|
||||
events['removetrack'][i]();
|
||||
for (i = 0; i < events.removetrack.length; i++) {
|
||||
events.removetrack[i]();
|
||||
}
|
||||
|
||||
equal(update, 6, 'update was called on the three buttons for remove track');
|
||||
|
||||
for (i = 0; i < events['addtrack'].length; i++) {
|
||||
events['addtrack'][i]();
|
||||
for (i = 0; i < events.addtrack.length; i++) {
|
||||
events.addtrack[i]();
|
||||
}
|
||||
|
||||
equal(update, 9, 'update was called on the three buttons for remove track');
|
||||
|
||||
Tech.prototype.textTracks = oldTextTracks;
|
||||
Tech.prototype['featuresNativeTextTracks'] = false;
|
||||
Tech.prototype.featuresNativeTextTracks = false;
|
||||
CaptionsButton.prototype.update = oldCaptionsUpdate;
|
||||
SubtitlesButton.prototype.update = oldSubsUpdate;
|
||||
ChaptersButton.prototype.update = oldChaptersUpdate;
|
||||
@@ -213,15 +210,13 @@ test('update texttrack buttons on removetrack or addtrack', function() {
|
||||
});
|
||||
|
||||
test('if native text tracks are not supported, create a texttrackdisplay', function() {
|
||||
var oldTestVid = Html5.TEST_VID,
|
||||
oldIsFirefox = browser.IS_FIREFOX,
|
||||
oldTextTrackDisplay = Component.getComponent('TextTrackDisplay'),
|
||||
called = false,
|
||||
player,
|
||||
tag,
|
||||
track,
|
||||
options,
|
||||
html;
|
||||
let oldTestVid = Html5.TEST_VID;
|
||||
let oldIsFirefox = browser.IS_FIREFOX;
|
||||
let oldTextTrackDisplay = Component.getComponent('TextTrackDisplay');
|
||||
let called = false;
|
||||
let player;
|
||||
let tag;
|
||||
let track;
|
||||
|
||||
tag = document.createElement('video');
|
||||
track = document.createElement('track');
|
||||
@@ -258,7 +253,7 @@ test('if native text tracks are not supported, create a texttrackdisplay', funct
|
||||
});
|
||||
|
||||
test('html5 tech supports native text tracks if the video supports it, unless mode is a number', function() {
|
||||
var oldTestVid = Html5.TEST_VID;
|
||||
let oldTestVid = Html5.TEST_VID;
|
||||
|
||||
Html5.TEST_VID = {
|
||||
textTracks: [{
|
||||
@@ -272,8 +267,8 @@ test('html5 tech supports native text tracks if the video supports it, unless mo
|
||||
});
|
||||
|
||||
test('html5 tech supports native text tracks if the video supports it, unless it is firefox', function() {
|
||||
var oldTestVid = Html5.TEST_VID,
|
||||
oldIsFirefox = browser.IS_FIREFOX;
|
||||
let oldTestVid = Html5.TEST_VID;
|
||||
let oldIsFirefox = browser.IS_FIREFOX;
|
||||
|
||||
Html5.TEST_VID = {
|
||||
textTracks: []
|
||||
@@ -308,6 +303,7 @@ if (Html5.supportsNativeTextTracks()) {
|
||||
let tt = el.textTracks;
|
||||
let emulatedTt = html.textTracks();
|
||||
let track = document.createElement('track');
|
||||
|
||||
el.appendChild(track);
|
||||
|
||||
let addtrack = function() {
|
||||
@@ -317,6 +313,7 @@ if (Html5.supportsNativeTextTracks()) {
|
||||
emulatedTt.off('addtrack', addtrack);
|
||||
el.removeChild(track);
|
||||
};
|
||||
|
||||
emulatedTt.on('addtrack', addtrack);
|
||||
emulatedTt.on('removetrack', function() {
|
||||
equal(emulatedTt.length, tt.length, 'we have matching tracks length');
|
||||
@@ -333,6 +330,7 @@ if (Html5.supportsNativeTextTracks()) {
|
||||
let tt = el.textTracks;
|
||||
let emulatedTt = html.textTracks();
|
||||
let track = document.createElement('track');
|
||||
|
||||
el.appendChild(track);
|
||||
|
||||
let addtrack = function() {
|
||||
@@ -347,6 +345,7 @@ if (Html5.supportsNativeTextTracks()) {
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
emulatedTt.on('addtrack', addtrack);
|
||||
});
|
||||
}
|
||||
@@ -354,6 +353,7 @@ if (Html5.supportsNativeTextTracks()) {
|
||||
test('should check for text track changes when emulating text tracks', function() {
|
||||
let tech = new Tech();
|
||||
let numTextTrackChanges = 0;
|
||||
|
||||
tech.on('texttrackchange', function() {
|
||||
numTextTrackChanges++;
|
||||
});
|
||||
@@ -367,6 +367,7 @@ test('removes cuechange event when text track is hidden for emulated tracks', fu
|
||||
tech: player.tech_,
|
||||
mode: 'showing'
|
||||
});
|
||||
|
||||
tt.addCue({
|
||||
id: '1',
|
||||
startTime: 2,
|
||||
@@ -376,6 +377,7 @@ test('removes cuechange event when text track is hidden for emulated tracks', fu
|
||||
player.tech_.emulateTextTracks();
|
||||
|
||||
let numTextTrackChanges = 0;
|
||||
|
||||
player.tech_.on('texttrackchange', function() {
|
||||
numTextTrackChanges++;
|
||||
});
|
||||
@@ -406,19 +408,18 @@ test('removes cuechange event when text track is hidden for emulated tracks', fu
|
||||
'texttrackchange should be not be called since mode is hidden');
|
||||
});
|
||||
|
||||
test('should return correct remote text track values', function () {
|
||||
test('should return correct remote text track values', function() {
|
||||
let fixture = document.getElementById('qunit-fixture');
|
||||
|
||||
let html = '<video id="example_1" class="video-js" autoplay preload="none">';
|
||||
html += '<source src="http://google.com" type="video/mp4">';
|
||||
html += '<source src="http://google.com" type="video/webm">';
|
||||
html += '<track kind="captions" label="label">';
|
||||
html += '</video>';
|
||||
let html = `
|
||||
<video id="example_1" class="video-js" autoplay preload="none">
|
||||
<source src="http://google.com" type="video/mp4">
|
||||
<source src="http://google.com" type="video/webm">
|
||||
<track kind="captions" label="label">
|
||||
</video>
|
||||
`;
|
||||
|
||||
fixture.innerHTML += html;
|
||||
|
||||
let tag = document.getElementById('example_1');
|
||||
|
||||
let player = TestHelpers.makePlayer({}, tag);
|
||||
|
||||
this.clock.tick(1);
|
||||
@@ -442,9 +443,8 @@ test('should return correct remote text track values', function () {
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
test('should uniformly create html track element when adding text track', function () {
|
||||
test('should uniformly create html track element when adding text track', function() {
|
||||
let player = TestHelpers.makePlayer();
|
||||
|
||||
let track = {
|
||||
kind: 'kind',
|
||||
src: 'src',
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário