mirror of
https://github.com/videojs/video.js.git
synced 2024-11-24 08:42:25 +02:00
feat: add skip forward/backward buttons (#8147)
* remove duplicate icons from icon example * create initial forward and back button classes * add logic for back/forward buttons on click * change icon used based on option passed into player * move logic from forward and back buttons into one component * add jsdoc comments for clarity * create initial test file * refactor button logic into separate files * update skip button example and add test files * test both the forward and backward buttons * test handleClick fns for both forward and backward btns * update skip buttons example * update jsdocs for skip backward and forward buttons * make control text accessible and use seekableEnd/Start when skipping forward/back * update font version to use updated icons * set control text only if config is valid * add link to sandbox page & use localization * update translations needed
This commit is contained in:
parent
0022867a2a
commit
8f3f32cb2b
@ -16,8 +16,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
|
||||
| Language file | Missing translations |
|
||||
| ----------------------- | ----------------------------------------------------------------------------------- |
|
||||
| ar.json (Complete) | |
|
||||
| ba.json (missing 68) | Audio Player |
|
||||
| ar.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| ba.json (missing 70) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -85,7 +86,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| bg.json (missing 68) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| bg.json (missing 70) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -153,12 +156,16 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| bn.json (missing 5) | Exit Fullscreen |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| bn.json (missing 7) | Exit Fullscreen |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| ca.json (missing 68) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| ca.json (missing 70) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -226,7 +233,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| cs.json (missing 9) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| cs.json (missing 11) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
@ -235,7 +244,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| cy.json (missing 9) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| cy.json (missing 11) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
@ -244,7 +255,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| da.json (missing 68) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| da.json (missing 70) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -312,8 +325,11 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| de.json (Complete) | |
|
||||
| el.json (missing 54) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| de.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| el.json (missing 56) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -367,24 +383,33 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| en-GB.json (has 1) | Needs manual checking. Can safely use most default strings.
|
||||
| es.json (Complete) | |
|
||||
| et.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| en-GB.json (has 1) | Needs manual checking. Can safely use most default strings. |
|
||||
| es.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| et.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| eu.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| eu.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| fa.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| fa.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| fi.json (missing 68) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| fi.json (missing 70) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -452,22 +477,29 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| fr.json (Complete) | |
|
||||
| gd.json (missing 7) | Exit Picture-in-Picture |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| fr.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| gd.json (missing 9) | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
| | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| gl.json (missing 7) | Exit Picture-in-Picture |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| gl.json (missing 9) | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
| | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| he.json (missing 10) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| he.json (missing 12) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | {1} is loading. |
|
||||
| | Exit Picture-in-Picture |
|
||||
@ -477,12 +509,16 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| hi.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| hi.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| hr.json (missing 68) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| hr.json (missing 70) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -550,33 +586,45 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| hu.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| hu.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| it.json (missing 7) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| it.json (missing 9) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | Raised |
|
||||
| | Depressed |
|
||||
| | Casual |
|
||||
| | Script |
|
||||
| | No content |
|
||||
| ja.json (Complete) | |
|
||||
| ko.json (Complete) | |
|
||||
| lv.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| ja.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| ko.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| lv.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| nb.json (missing 7) | Exit Picture-in-Picture |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| nb.json (missing 9) | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
| | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| nl.json (missing 10) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| nl.json (missing 12) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | {1} is loading. |
|
||||
| | Exit Picture-in-Picture |
|
||||
@ -586,29 +634,39 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| nn.json (missing 7) | Exit Picture-in-Picture |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| nn.json (missing 9) | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
| | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| oc.json (missing 4) | Color |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| oc.json (missing 6) | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| pl.json (missing 4) | Color |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| pl.json (missing 6) | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| pt-BR.json (missing 7) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| pt-BR.json (missing 9) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| pt-PT.json (missing 53) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| pt-PT.json (missing 55) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
@ -661,17 +719,23 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| ro.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| ro.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| ru.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| ru.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| sk.json (missing 9) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| sk.json (missing 11) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
@ -680,7 +744,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| sl.json (missing 11) | Proportional Sans-Serif |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| sl.json (missing 13) | Proportional Sans-Serif |
|
||||
| | Monospace Sans-Serif |
|
||||
| | Proportional Serif |
|
||||
| | Monospace Serif |
|
||||
@ -691,7 +757,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| sr.json (missing 68) | Audio Player |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| sr.json (missing 70) | Audio Player |
|
||||
| | Video Player |
|
||||
| | Replay |
|
||||
| | Seek to live, currently behind live |
|
||||
@ -759,28 +827,38 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| sv.json (missing 7) | Exit Picture-in-Picture |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| sv.json (missing 9) | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
| | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| te.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| te.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| th.json (missing 5) | No content |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| th.json (missing 7) | No content |
|
||||
| | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| tr.json (missing 4) | Color |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| tr.json (missing 6) | Color |
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| uk.json (missing 9) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| uk.json (missing 11) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | Exit Picture-in-Picture |
|
||||
| | Picture-in-Picture |
|
||||
@ -789,7 +867,9 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| vi.json (missing 10) | Seek to live, currently behind live |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| vi.json (missing 12) | Seek to live, currently behind live |
|
||||
| | Seek to live, currently playing live |
|
||||
| | {1} is loading. |
|
||||
| | Exit Picture-in-Picture |
|
||||
@ -799,7 +879,11 @@ This default value is hardcoded as a default to the localize method in the SeekB
|
||||
| | Opacity |
|
||||
| | Text Background |
|
||||
| | Caption Area Background |
|
||||
| zh-CN.json (Complete) | |
|
||||
| zh-TW.json (Complete) | |
|
||||
| | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| zh-CN.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
| zh-TW.json (missing 2) | Skip backward {1} seconds |
|
||||
| | Skip forward {1} seconds |
|
||||
|
||||
<!-- END langtable -->
|
||||
|
@ -27,6 +27,7 @@
|
||||
<li><a href="sandbox/quality-levels.html">QualityLevels Demo</a></li>
|
||||
<li><a href="sandbox/autoplay-tests.html">Autoplay Tests</a></li>
|
||||
<li><a href="sandbox/noUITitleAttributes.html">noUITitleAttributes Demo</a></li>
|
||||
<li><a href="sandbox/skip-buttons.html">Skip Buttons demo</a></li>
|
||||
<li><a href="sandbox/debug.html">Videojs debug build test page</a></li>
|
||||
</ul>
|
||||
|
||||
|
@ -90,5 +90,7 @@
|
||||
"Color": "Color",
|
||||
"Opacity": "Opacity",
|
||||
"Text Background": "Text Background",
|
||||
"Caption Area Background": "Caption Area Background"
|
||||
"Caption Area Background": "Caption Area Background",
|
||||
"Skip backward {1} seconds": "Skip backward {1} seconds",
|
||||
"Skip forward {1} seconds": "Skip forward {1} seconds"
|
||||
}
|
||||
|
121
package-lock.json
generated
121
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "video.js",
|
||||
"version": "8.1.1",
|
||||
"version": "8.0.4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -1664,9 +1664,9 @@
|
||||
}
|
||||
},
|
||||
"@videojs/http-streaming": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.0.2.tgz",
|
||||
"integrity": "sha512-iSZkwTLGg3Rx78ypCCq/GsMME89ElNvU02xj7reCE2PlITMQjyYsER1w5AsySvT1A694u5yuSzEzLLGF1cL4pg==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.0.0.tgz",
|
||||
"integrity": "sha512-AdKmY/W2dyeJP0uALgMRmhLa4pbHMvE4OMlg6yQvufnqsz6jDFo1DYnZRv2ENDYrmVdnPH58Ehgu59053+OIhQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "4.0.0",
|
||||
@ -1674,19 +1674,8 @@
|
||||
"global": "^4.4.0",
|
||||
"m3u8-parser": "^6.0.0",
|
||||
"mpd-parser": "^1.0.1",
|
||||
"mux.js": "6.3.0",
|
||||
"mux.js": "6.2.0",
|
||||
"video.js": "^7 || ^8"
|
||||
},
|
||||
"dependencies": {
|
||||
"mux.js": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-6.3.0.tgz",
|
||||
"integrity": "sha512-/QTkbSAP2+w1nxV+qTcumSDN5PA98P0tjrADijIzQHe85oBK3Akhy9AHlH0ne/GombLMz1rLyvVsmrgRxoPDrQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@videojs/vhs-utils": {
|
||||
@ -15201,39 +15190,89 @@
|
||||
"dev": true
|
||||
},
|
||||
"video.js": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-8.0.4.tgz",
|
||||
"integrity": "sha512-fvvWauPanrKDps1HQGGL+9CIAK8G0YVwlNme0hvY0k3moXQryaRcJSLHIlPKV2j9ZFTHl32VbN43jL3TaUllfg==",
|
||||
"version": "7.21.1",
|
||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-7.21.1.tgz",
|
||||
"integrity": "sha512-AvHfr14ePDHCfW5Lx35BvXk7oIonxF6VGhSxocmTyqotkQpxwYdmt4tnQSV7MYzNrYHb0GI8tJMt20NDkCQrxg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/http-streaming": "3.0.0",
|
||||
"@videojs/vhs-utils": "^4.0.0",
|
||||
"@videojs/http-streaming": "2.15.1",
|
||||
"@videojs/vhs-utils": "^3.0.4",
|
||||
"@videojs/xhr": "2.6.0",
|
||||
"aes-decrypter": "^4.0.1",
|
||||
"global": "4.4.0",
|
||||
"keycode": "2.2.0",
|
||||
"m3u8-parser": "^6.0.0",
|
||||
"mpd-parser": "^1.0.1",
|
||||
"mux.js": "^6.2.0",
|
||||
"aes-decrypter": "3.1.3",
|
||||
"global": "^4.4.0",
|
||||
"keycode": "^2.2.0",
|
||||
"m3u8-parser": "4.8.0",
|
||||
"mpd-parser": "0.22.1",
|
||||
"mux.js": "6.0.1",
|
||||
"safe-json-parse": "4.0.0",
|
||||
"videojs-contrib-quality-levels": "3.0.0",
|
||||
"videojs-font": "3.2.0",
|
||||
"videojs-vtt.js": "0.15.4"
|
||||
"videojs-vtt.js": "^0.15.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@videojs/http-streaming": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.0.0.tgz",
|
||||
"integrity": "sha512-AdKmY/W2dyeJP0uALgMRmhLa4pbHMvE4OMlg6yQvufnqsz6jDFo1DYnZRv2ENDYrmVdnPH58Ehgu59053+OIhQ==",
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.15.1.tgz",
|
||||
"integrity": "sha512-/uuN3bVkEeJAdrhu5Hyb19JoUo3CMys7yf2C1vUjeL1wQaZ4Oe8JrZzRrnWZ0rjvPgKfNLPXQomsRtgrMoRMJQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "4.0.0",
|
||||
"aes-decrypter": "4.0.1",
|
||||
"@videojs/vhs-utils": "3.0.5",
|
||||
"aes-decrypter": "3.1.3",
|
||||
"global": "^4.4.0",
|
||||
"m3u8-parser": "^6.0.0",
|
||||
"mpd-parser": "^1.0.1",
|
||||
"mux.js": "6.2.0",
|
||||
"video.js": "^7 || ^8"
|
||||
"m3u8-parser": "4.8.0",
|
||||
"mpd-parser": "^0.22.1",
|
||||
"mux.js": "6.0.1",
|
||||
"video.js": "^6 || ^7"
|
||||
}
|
||||
},
|
||||
"@videojs/vhs-utils": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz",
|
||||
"integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"global": "^4.4.0",
|
||||
"url-toolkit": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"aes-decrypter": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.3.tgz",
|
||||
"integrity": "sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"global": "^4.4.0",
|
||||
"pkcs7": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"m3u8-parser": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.8.0.tgz",
|
||||
"integrity": "sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"mpd-parser": {
|
||||
"version": "0.22.1",
|
||||
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.22.1.tgz",
|
||||
"integrity": "sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"@xmldom/xmldom": "^0.8.3",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"mux.js": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-6.0.1.tgz",
|
||||
"integrity": "sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"videojs-font": {
|
||||
@ -15252,9 +15291,9 @@
|
||||
}
|
||||
},
|
||||
"videojs-font": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.0.0.tgz",
|
||||
"integrity": "sha512-sRXrizXF0zBMatXjg2vGpn63G26uH3XqwyZ9PjU2H9xqGm7fRSVYuxOJCUME6us/1rFl9yxkRKk31WTQ7XZkww=="
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.1.0.tgz",
|
||||
"integrity": "sha512-X1LuPfLZPisPLrANIAKCknZbZu5obVM/ylfd1CN+SsCmPZQ3UMDPcvLTpPBJxcBuTpHQq2MO1QCFt7p8spnZ/w=="
|
||||
},
|
||||
"videojs-generate-karma-config": {
|
||||
"version": "8.0.1",
|
||||
|
@ -97,7 +97,7 @@
|
||||
"mux.js": "^6.2.0",
|
||||
"safe-json-parse": "4.0.0",
|
||||
"videojs-contrib-quality-levels": "3.0.0",
|
||||
"videojs-font": "4.0.0",
|
||||
"videojs-font": "4.1.0",
|
||||
"videojs-vtt.js": "0.15.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -48,9 +48,6 @@
|
||||
<li><span class="vjs-icon-forward-5"></span> <code>.vjs-icon-forward-5</code></li>
|
||||
<li><span class="vjs-icon-forward-10"></span> <code>.vjs-icon-forward-10</code></li>
|
||||
<li><span class="vjs-icon-forward-30"></span> <code>.vjs-icon-forward-30</code></li>
|
||||
<li><span class="vjs-icon-forward-30"></span> <code>.vjs-icon-forward-30</code></li>
|
||||
<li><span class="vjs-icon-forward-30"></span> <code>.vjs-icon-forward-30</code></li>
|
||||
<li><span class="vjs-icon-forward-30"></span> <code>.vjs-icon-forward-30</code></li>
|
||||
<li><span class="vjs-icon-audio"></span> <code>.vjs-icon-audio</code></li>
|
||||
<li><span class="vjs-icon-next-item"></span> <code>.vjs-next-item</code></li>
|
||||
<li><span class="vjs-icon-previous-item"></span> <code>.vjs-icon-previous-item</code></li>
|
||||
|
114
sandbox/skip-buttons.html.example
Normal file
114
sandbox/skip-buttons.html.example
Normal file
@ -0,0 +1,114 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Video.js Sandbox</title>
|
||||
<link href="../dist/video-js.css" rel="stylesheet" type="text/css" />
|
||||
<script src="../dist/video.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h2>Forward: 5, Backward: 10</h2>
|
||||
<video-js
|
||||
id="vid1"
|
||||
controls
|
||||
preload="auto"
|
||||
width="640"
|
||||
height="264"
|
||||
poster="https://vjs.zencdn.net/v/oceans.png"
|
||||
>
|
||||
<source src="https://vjs.zencdn.net/v/oceans.mp4" type="video/mp4" />
|
||||
<source src="https://vjs.zencdn.net/v/oceans.webm" type="video/webm" />
|
||||
<source src="https://vjs.zencdn.net/v/oceans.ogv" type="video/ogg" />
|
||||
<track
|
||||
kind="captions"
|
||||
src="../docs/examples/shared/example-captions.vtt"
|
||||
srclang="en"
|
||||
label="English"
|
||||
/>
|
||||
<p class="vjs-no-js">
|
||||
To view this video please enable JavaScript, and consider upgrading to
|
||||
a web browser that
|
||||
<a href="https://videojs.com/html5-video-support/" target="_blank"
|
||||
>supports HTML5 video</a
|
||||
>
|
||||
</p>
|
||||
</video-js>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Forward: 10, Backward: 30</h2>
|
||||
<video-js
|
||||
id="vid2"
|
||||
controls
|
||||
preload="auto"
|
||||
width="640"
|
||||
height="264"
|
||||
poster="https://vjs.zencdn.net/v/oceans.png"
|
||||
>
|
||||
<source src="https://vjs.zencdn.net/v/oceans.mp4" type="video/mp4" />
|
||||
<source src="https://vjs.zencdn.net/v/oceans.webm" type="video/webm" />
|
||||
<source src="https://vjs.zencdn.net/v/oceans.ogv" type="video/ogg" />
|
||||
<track
|
||||
kind="captions"
|
||||
src="../docs/examples/shared/example-captions.vtt"
|
||||
srclang="en"
|
||||
label="English"
|
||||
/>
|
||||
<p class="vjs-no-js">
|
||||
To view this video please enable JavaScript, and consider upgrading to
|
||||
a web browser that
|
||||
<a href="https://videojs.com/html5-video-support/" target="_blank"
|
||||
>supports HTML5 video</a
|
||||
>
|
||||
</p>
|
||||
</video-js>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Forward: 10</h2>
|
||||
<video-js
|
||||
id="vid3"
|
||||
controls
|
||||
preload="auto"
|
||||
width="640"
|
||||
height="264"
|
||||
poster="https://vjs.zencdn.net/v/oceans.png"
|
||||
>
|
||||
<source src="https://vjs.zencdn.net/v/oceans.mp4" type="video/mp4" />
|
||||
<source src="https://vjs.zencdn.net/v/oceans.webm" type="video/webm" />
|
||||
<source src="https://vjs.zencdn.net/v/oceans.ogv" type="video/ogg" />
|
||||
<track
|
||||
kind="captions"
|
||||
src="../docs/examples/shared/example-captions.vtt"
|
||||
srclang="en"
|
||||
label="English"
|
||||
/>
|
||||
<p class="vjs-no-js">
|
||||
To view this video please enable JavaScript, and consider upgrading to
|
||||
a web browser that
|
||||
<a href="https://videojs.com/html5-video-support/" target="_blank"
|
||||
>supports HTML5 video</a
|
||||
>
|
||||
</p>
|
||||
</video-js>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var vid1 = document.getElementById("vid1");
|
||||
var options = {
|
||||
muted: true,
|
||||
controlBar: { skipButtons: { forward: 5, backward: 10 } },
|
||||
};
|
||||
videojs(vid1, options);
|
||||
|
||||
var vid2 = document.getElementById("vid2");
|
||||
options.controlBar.skipButtons = { forward: 10, backward: 30 };
|
||||
videojs(vid2, options);
|
||||
|
||||
var vid3 = document.getElementById("vid3");
|
||||
options.controlBar.skipButtons = {forward: 10}
|
||||
videojs(vid3, options);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
40
src/css/components/_skip-buttons.scss
Normal file
40
src/css/components/_skip-buttons.scss
Normal file
@ -0,0 +1,40 @@
|
||||
.video-js .vjs-skip-forward-5 {
|
||||
cursor: pointer;
|
||||
& .vjs-icon-placeholder {
|
||||
@extend .vjs-icon-forward-5;
|
||||
}
|
||||
}
|
||||
|
||||
.video-js .vjs-skip-forward-10 {
|
||||
cursor: pointer;
|
||||
& .vjs-icon-placeholder {
|
||||
@extend .vjs-icon-forward-10;
|
||||
}
|
||||
}
|
||||
.video-js .vjs-skip-forward-30 {
|
||||
cursor: pointer;
|
||||
& .vjs-icon-placeholder {
|
||||
@extend .vjs-icon-forward-30;
|
||||
}
|
||||
}
|
||||
|
||||
.video-js .vjs-skip-backward-5 {
|
||||
cursor: pointer;
|
||||
& .vjs-icon-placeholder {
|
||||
@extend .vjs-icon-replay-5;
|
||||
}
|
||||
}
|
||||
|
||||
.video-js .vjs-skip-backward-10 {
|
||||
cursor: pointer;
|
||||
& .vjs-icon-placeholder {
|
||||
@extend .vjs-icon-replay-10;
|
||||
}
|
||||
}
|
||||
|
||||
.video-js .vjs-skip-backward-30 {
|
||||
cursor: pointer;
|
||||
& .vjs-icon-placeholder {
|
||||
@extend .vjs-icon-replay-30;
|
||||
}
|
||||
}
|
@ -42,6 +42,7 @@
|
||||
@import "components/adaptive";
|
||||
@import "components/captions-settings";
|
||||
@import "components/title-bar";
|
||||
@import "components/skip-buttons";
|
||||
|
||||
@import "print";
|
||||
|
||||
|
@ -16,6 +16,8 @@ import './progress-control/progress-control.js';
|
||||
import './picture-in-picture-toggle.js';
|
||||
import './fullscreen-toggle.js';
|
||||
import './volume-panel.js';
|
||||
import './skip-buttons/skip-forward.js';
|
||||
import './skip-buttons/skip-backward.js';
|
||||
import './text-track-controls/chapters-button.js';
|
||||
import './text-track-controls/descriptions-button.js';
|
||||
import './text-track-controls/subtitles-button.js';
|
||||
@ -55,6 +57,8 @@ class ControlBar extends Component {
|
||||
ControlBar.prototype.options_ = {
|
||||
children: [
|
||||
'playToggle',
|
||||
'skipBackward',
|
||||
'skipForward',
|
||||
'volumePanel',
|
||||
'currentTimeDisplay',
|
||||
'timeDivider',
|
||||
|
69
src/js/control-bar/skip-buttons/skip-backward.js
Normal file
69
src/js/control-bar/skip-buttons/skip-backward.js
Normal file
@ -0,0 +1,69 @@
|
||||
import Button from '../../button';
|
||||
import Component from '../../component';
|
||||
|
||||
/**
|
||||
* Button to skip backward a configurable amount of time
|
||||
* through a video. Renders in the control bar.
|
||||
*
|
||||
* * e.g. options: {controlBar: {skipButtons: backward: 5}}
|
||||
*
|
||||
* @extends Button
|
||||
*/
|
||||
class SkipBackward extends Button {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.validOptions = [5, 10, 30];
|
||||
this.skipTime = this.getSkipBackwardTime();
|
||||
|
||||
if (this.skipTime && this.validOptions.includes(this.skipTime)) {
|
||||
this.controlText(this.localize('Skip backward {1} seconds', [this.skipTime]));
|
||||
this.show();
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
getSkipBackwardTime() {
|
||||
const playerOptions = this.options_.playerOptions;
|
||||
|
||||
return playerOptions.controlBar && playerOptions.controlBar.skipButtons && playerOptions.controlBar.skipButtons.backward;
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-skip-backward-${this.getSkipBackwardTime()} ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* On click, skips backward in the video by a configurable amount of seconds.
|
||||
* If the current time in the video is less than the configured 'skip backward' time,
|
||||
* skips to beginning of video or seekable range.
|
||||
*
|
||||
* Handle a click on a `SkipBackward` button
|
||||
*
|
||||
* @param {EventTarget~Event} event
|
||||
* The `click` event that caused this function
|
||||
* to be called
|
||||
*/
|
||||
handleClick(event) {
|
||||
const currentVideoTime = this.player_.currentTime();
|
||||
const liveTracker = this.player_.liveTracker;
|
||||
const seekableStart = liveTracker && liveTracker.isLive() && liveTracker.seekableStart();
|
||||
let newTime;
|
||||
|
||||
if (seekableStart && (currentVideoTime - this.skipTime <= seekableStart)) {
|
||||
newTime = seekableStart;
|
||||
} else if (currentVideoTime >= this.skipTime) {
|
||||
newTime = currentVideoTime - this.skipTime;
|
||||
} else {
|
||||
newTime = 0;
|
||||
}
|
||||
this.player_.currentTime(newTime);
|
||||
}
|
||||
}
|
||||
|
||||
SkipBackward.prototype.controlText_ = 'Skip Backward';
|
||||
|
||||
Component.registerComponent('SkipBackward', SkipBackward);
|
||||
|
||||
export default SkipBackward;
|
66
src/js/control-bar/skip-buttons/skip-forward.js
Normal file
66
src/js/control-bar/skip-buttons/skip-forward.js
Normal file
@ -0,0 +1,66 @@
|
||||
import Button from '../../button';
|
||||
import Component from '../../component';
|
||||
|
||||
/**
|
||||
* Button to skip forward a configurable amount of time
|
||||
* through a video. Renders in the control bar.
|
||||
*
|
||||
* e.g. options: {controlBar: {skipButtons: forward: 5}}
|
||||
*
|
||||
* @extends Button
|
||||
*/
|
||||
class SkipForward extends Button {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
this.validOptions = [5, 10, 30];
|
||||
this.skipTime = this.getSkipForwardTime();
|
||||
|
||||
if (this.skipTime && this.validOptions.includes(this.skipTime)) {
|
||||
this.controlText(this.localize('Skip forward {1} seconds', [this.skipTime]));
|
||||
this.show();
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
getSkipForwardTime() {
|
||||
const playerOptions = this.options_.playerOptions;
|
||||
|
||||
return playerOptions.controlBar && playerOptions.controlBar.skipButtons && playerOptions.controlBar.skipButtons.forward;
|
||||
}
|
||||
|
||||
buildCSSClass() {
|
||||
return `vjs-skip-forward-${this.getSkipForwardTime()} ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* On click, skips forward in the duration/seekable range by a configurable amount of seconds.
|
||||
* If the time left in the duration/seekable range is less than the configured 'skip forward' time,
|
||||
* skips to end of duration/seekable range.
|
||||
*
|
||||
* Handle a click on a `SkipForward` button
|
||||
*
|
||||
* @param {EventTarget~Event} event
|
||||
* The `click` event that caused this function
|
||||
* to be called
|
||||
*/
|
||||
handleClick(event) {
|
||||
const currentVideoTime = this.player_.currentTime();
|
||||
const liveTracker = this.player_.liveTracker;
|
||||
const duration = (liveTracker && liveTracker.isLive()) ? liveTracker.seekableEnd() : this.player_.duration();
|
||||
let newTime;
|
||||
|
||||
if (currentVideoTime + this.skipTime <= duration) {
|
||||
newTime = currentVideoTime + this.skipTime;
|
||||
} else {
|
||||
newTime = duration;
|
||||
}
|
||||
|
||||
this.player_.currentTime(newTime);
|
||||
}
|
||||
}
|
||||
|
||||
Component.registerComponent('SkipForward', SkipForward);
|
||||
|
||||
export default SkipForward;
|
@ -0,0 +1,98 @@
|
||||
/* eslint-env qunit */
|
||||
import TestHelpers from '../../test-helpers';
|
||||
import sinon from 'sinon';
|
||||
import { createTimeRange } from '../../../../src/js/utils/time';
|
||||
|
||||
QUnit.module('SkipBackwardButton');
|
||||
|
||||
QUnit.test('is not visible if option is not set', function(assert) {
|
||||
const player = TestHelpers.makePlayer({});
|
||||
const button = player.controlBar.skipBackward;
|
||||
|
||||
assert.expect(1);
|
||||
assert.ok(button.hasClass('vjs-hidden'), 'has the vjs-hidden class');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('is not visible if option is set with an invalid config', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {backward: 4}}});
|
||||
const button = player.controlBar.skipBackward;
|
||||
|
||||
assert.expect(1);
|
||||
assert.ok(button.hasClass('vjs-hidden'), 'has the vjs-hidden class');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('is visible if option is set with a valid config', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {backward: 5}}});
|
||||
const button = player.controlBar.skipBackward;
|
||||
|
||||
assert.expect(2);
|
||||
assert.notOk(button.hasClass('vjs-hidden'), 'button is not hidden');
|
||||
assert.ok(button.hasClass('vjs-skip-backward-5'), 'button shows correct icon');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('control text should specify amount seconds that can be skipped backward', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {backward: 10}}});
|
||||
const button = player.controlBar.skipBackward;
|
||||
|
||||
assert.expect(1);
|
||||
assert.strictEqual(button.controlText_, 'Skip backward 10 seconds', 'control text specifies number of seconds backward');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('skip to beginning of seekable range in live video if current time - seekableStart is less than skip bacward time', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {backward: 30}}});
|
||||
const button = player.controlBar.skipBackward;
|
||||
|
||||
player.options_.liveui = true;
|
||||
player.seekable = () => createTimeRange(20, 40);
|
||||
player.duration(Infinity);
|
||||
player.currentTime(22);
|
||||
|
||||
const curTimeSpy = sinon.spy(player, 'currentTime');
|
||||
|
||||
button.trigger('click');
|
||||
|
||||
assert.expect(1);
|
||||
assert.equal(curTimeSpy.getCall(1).args[0], 20, 'player set to start of seekable range');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('skips to beginning of video if current time is less than configured skip backward time', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {backward: 30}}});
|
||||
const button = player.controlBar.skipBackward;
|
||||
|
||||
player.currentTime(25);
|
||||
|
||||
const curTimeSpy = sinon.spy(player, 'currentTime');
|
||||
|
||||
button.trigger('click');
|
||||
|
||||
assert.expect(1);
|
||||
assert.equal(curTimeSpy.getCall(1).args[0], 0, 'player current time is set to start of video');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('skip backward in video by configured skip backward time amount', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {backward: 30}}});
|
||||
const button = player.controlBar.skipBackward;
|
||||
|
||||
player.currentTime(31);
|
||||
|
||||
const curTimeSpy = sinon.spy(player, 'currentTime');
|
||||
|
||||
button.trigger('click');
|
||||
|
||||
assert.expect(1);
|
||||
assert.equal(curTimeSpy.getCall(1).args[0], 1, 'player current time set 30 seconds back on button click');
|
||||
|
||||
player.dispose();
|
||||
});
|
117
test/unit/control-bar/skip-buttons/skip-forward-button.test.js
Normal file
117
test/unit/control-bar/skip-buttons/skip-forward-button.test.js
Normal file
@ -0,0 +1,117 @@
|
||||
/* eslint-env qunit */
|
||||
import TestHelpers from '../../test-helpers';
|
||||
import sinon from 'sinon';
|
||||
import { createTimeRange } from '../../../../src/js/utils/time';
|
||||
|
||||
QUnit.module('SkipForwardButton');
|
||||
|
||||
QUnit.test('is not visible if option is not set', function(assert) {
|
||||
const player = TestHelpers.makePlayer({});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
assert.expect(1);
|
||||
assert.ok(button.hasClass('vjs-hidden'), 'has the vjs-hidden class');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('is not visible if option is set with an invalid config', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {forward: 4}}});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
assert.expect(1);
|
||||
assert.ok(button.hasClass('vjs-hidden'), 'has the vjs-hidden class');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('is visible if option is set with a valid config', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {forward: 5}}});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
assert.expect(2);
|
||||
assert.notOk(button.hasClass('vjs-hidden'), 'button is not hidden');
|
||||
assert.ok(button.hasClass('vjs-skip-forward-5'), 'button shows correct icon');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('control text should specify how many seconds forward can be skipped', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {forward: 5}}});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
assert.expect(1);
|
||||
assert.strictEqual(button.controlText_, 'Skip forward 5 seconds', 'control text specifies seconds forward');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('skips to end of video if time remaining is less than configured skip forward time', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {forward: 30}}});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
player.currentTime(25);
|
||||
player.duration(30);
|
||||
|
||||
const curTimeSpy = sinon.spy(player, 'currentTime');
|
||||
|
||||
button.trigger('click');
|
||||
|
||||
assert.expect(1);
|
||||
assert.equal(curTimeSpy.getCall(1).args[0], 30, 'player current time is set to end of video');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('skips to end of seekable range in live video if time remaining is less than configured skip forward time', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {forward: 30}}});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
player.options_.liveui = true;
|
||||
player.seekable = () => createTimeRange(0, 20);
|
||||
player.duration(Infinity);
|
||||
|
||||
const curTimeSpy = sinon.spy(player, 'currentTime');
|
||||
|
||||
button.trigger('click');
|
||||
|
||||
assert.expect(1);
|
||||
assert.equal(curTimeSpy.getCall(1).args[0], 20, 'player current time is set to end of seekable range in live video');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('skips forward in live video by configured skip forward time amount', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {forward: 10}}});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
player.options_.liveui = true;
|
||||
player.seekable = () => createTimeRange(0, 45);
|
||||
player.duration(Infinity);
|
||||
|
||||
const curTimeSpy = sinon.spy(player, 'currentTime');
|
||||
|
||||
button.trigger('click');
|
||||
|
||||
assert.expect(1);
|
||||
assert.equal(curTimeSpy.getCall(1).args[0], 10, 'player current time is set 10 seconds forward in live video');
|
||||
|
||||
player.dispose();
|
||||
});
|
||||
|
||||
QUnit.test('skips forward in video by configured skip forward time amount', function(assert) {
|
||||
const player = TestHelpers.makePlayer({controlBar: {skipButtons: {forward: 30}}});
|
||||
const button = player.controlBar.skipForward;
|
||||
|
||||
player.currentTime(0);
|
||||
player.duration(50);
|
||||
|
||||
const curTimeSpy = sinon.spy(player, 'currentTime');
|
||||
|
||||
button.trigger('click');
|
||||
|
||||
assert.expect(1);
|
||||
assert.equal(curTimeSpy.getCall(1).args[0], 30, 'player current time set 30 seconds forward after button click');
|
||||
|
||||
player.dispose();
|
||||
});
|
Loading…
Reference in New Issue
Block a user