fcad-core-dragon 2.0.0-beta.0 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{.eslintrc.js → .eslintrc.cjs} +13 -18
- package/README.md +1 -1
- package/bk.scss +117 -0
- package/package.json +22 -40
- package/src/$locales/en.json +57 -19
- package/src/$locales/fr.json +66 -28
- package/src/components/AppBase.vue +790 -376
- package/src/components/AppBaseButton.vue +33 -5
- package/src/components/AppBaseErrorDisplay.vue +62 -25
- package/src/components/AppBaseModule.vue +831 -754
- package/src/components/AppBasePage.vue +60 -74
- package/src/components/AppCompAudio.vue +266 -0
- package/src/components/AppCompBranchButtons.vue +79 -89
- package/src/components/AppCompButtonProgress.vue +35 -61
- package/src/components/AppCompCarousel.vue +160 -249
- package/src/components/AppCompInputCheckBox.vue +9 -3
- package/src/components/AppCompInputDropdown.vue +2 -4
- package/src/components/AppCompInputRadio.vue +8 -15
- package/src/components/AppCompInputTextTable.vue +15 -12
- package/src/components/AppCompInputTextToFillDropdown.vue +16 -14
- package/src/components/AppCompInputTextToFillText.vue +2 -2
- package/src/components/AppCompJauge.vue +14 -3
- package/src/components/AppCompMenu.vue +284 -85
- package/src/components/AppCompMenuItem.vue +67 -92
- package/src/components/AppCompNavigation.vue +945 -0
- package/src/components/AppCompNoteCall.vue +141 -0
- package/src/components/AppCompNoteCredit.vue +267 -0
- package/src/components/AppCompPlayBar.vue +1122 -1391
- package/src/components/AppCompPlayBarProgress.vue +73 -0
- package/src/components/AppCompPopUp.vue +195 -135
- package/src/components/AppCompPopover.vue +27 -0
- package/src/components/AppCompQuiz.vue +90 -113
- package/src/components/AppCompQuizRecall.vue +277 -0
- package/src/components/AppCompSVG.vue +335 -0
- package/src/components/AppCompSettingsMenu.vue +7 -8
- package/src/components/AppCompTableOfContent.vue +264 -88
- package/src/components/AppCompTranscript.vue +19 -0
- package/src/components/AppCompVideoPlayer.vue +380 -0
- package/src/components/BaseModule.vue +37 -114
- package/src/main.js +130 -85
- package/src/mixins/$mediaMixins.js +827 -0
- package/src/mixins/$pageMixins.js +149 -115
- package/src/mixins/$quizMixins.js +12 -26
- package/src/mixins/timerMixin.js +39 -16
- package/src/module/store.js +218 -78
- package/src/module/xapi/ADL.js +90 -53
- package/src/module/xapi/Crypto/Hasher.js +8 -8
- package/src/module/xapi/Crypto/WordArray.js +6 -6
- package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +4 -4
- package/src/module/xapi/Crypto/algorithms/C_algo.js +14 -18
- package/src/module/xapi/Crypto/algorithms/HMAC.js +1 -1
- package/src/module/xapi/Crypto/algorithms/SHA1.js +1 -1
- package/src/module/xapi/Crypto/encoders/Base.js +7 -7
- package/src/module/xapi/Crypto/encoders/Base64.js +3 -3
- package/src/module/xapi/Crypto/encoders/Hex.js +4 -3
- package/src/module/xapi/Crypto/encoders/Latin1.js +3 -3
- package/src/module/xapi/Crypto/encoders/Utf8.js +3 -3
- package/src/module/xapi/Statement/index.js +1 -1
- package/src/module/xapi/launch.js +10 -10
- package/src/module/xapi/utils.js +17 -17
- package/src/module/xapi/wrapper.js +127 -54
- package/src/module/xapi/xapiStatement.js +29 -29
- package/src/plugins/gsap.js +4 -1
- package/src/plugins/helper.js +58 -24
- package/src/plugins/i18n.js +23 -10
- package/src/plugins/idb.js +1 -0
- package/src/plugins/scorm.js +14 -14
- package/src/public/index.html +1 -1
- package/src/router/index.js +40 -0
- package/src/router/routes.js +317 -0
- package/src/shared/generalfuncs.js +91 -9
- package/src/shared/validators.js +959 -0
- package/.prettierrc.js +0 -5
- package/babel.config.js +0 -3
- package/src/components/AppBaseDragChoice.vue +0 -91
- package/src/components/AppBaseDropZone.vue +0 -112
- package/src/components/AppCompDragAndDrop.vue +0 -339
- package/src/components/AppCompInputAssociation.vue +0 -332
- package/src/components/AppCompMediaPlayer.vue +0 -365
- package/src/components/AppCompNavigationFull.vue +0 -1791
- package/src/components/AppCompToolTip.vue +0 -94
- package/src/plugins/timeManager.js +0 -77
- package/src/routes.js +0 -734
- package/vue.config.js +0 -83
|
@@ -1,1540 +1,1271 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<!--@ Description: This component is used to display the playbar associate with the videoPlayer
|
|
2
|
+
@ What it does: The component is used to interacted with the videoPlayer or audioPlayer via buttons.
|
|
3
|
+
mediaMixins is used for all the methods/data shared between audio and video. In the appCompPlayBar component, there is also all the methods/data specific to video-->
|
|
3
4
|
<template>
|
|
4
5
|
<div
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
ref="$pb-container"
|
|
7
|
+
class="pb-container"
|
|
8
|
+
:class="{ video: mediaToPlay.mType === 'video' }"
|
|
8
9
|
>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<output>{{ displayVol }} %</output>
|
|
10
|
+
<!--------------------------------- Btn Play Principal (video only) -------------------------------------->
|
|
11
|
+
<app-base-button
|
|
12
|
+
v-if="mediaToPlay.mType === 'video'"
|
|
13
|
+
ref="$btn-play-playback"
|
|
14
|
+
class="playback-button"
|
|
15
|
+
:class="{
|
|
16
|
+
initial: !playClicked,
|
|
17
|
+
'playback-animation': playBackAnim && playClicked
|
|
18
|
+
}"
|
|
19
|
+
:aria-label="playLabel + ' principal'"
|
|
20
|
+
:data-title="`${playLabel}`"
|
|
21
|
+
@click="
|
|
22
|
+
() => {
|
|
23
|
+
mediaToPlay.mType === 'video'
|
|
24
|
+
? handlePlayVideo('playBackAnim')
|
|
25
|
+
: togglePlay()
|
|
26
|
+
}
|
|
27
|
+
"
|
|
28
|
+
>
|
|
29
|
+
<div
|
|
30
|
+
v-show="(!playClicked && !canReplay) || (!canReplay && isPlaying)"
|
|
31
|
+
class="playback-wrapper"
|
|
32
|
+
>
|
|
33
|
+
<svg class="app-icons-svg play-icon">
|
|
34
|
+
<use href="#play-icon" />
|
|
35
|
+
</svg>
|
|
36
|
+
</div>
|
|
37
|
+
<div
|
|
38
|
+
v-show="playClicked && !isPlaying && !canReplay"
|
|
39
|
+
class="playback-wrapper"
|
|
40
|
+
>
|
|
41
|
+
<svg class="app-icons-svg pause-icon">
|
|
42
|
+
<use href="#pause-icon" />
|
|
43
|
+
</svg>
|
|
44
|
+
</div>
|
|
45
|
+
<div v-show="!playClicked && canReplay" class="playback-wrapper">
|
|
46
|
+
<svg class="app-icons-svg replay-icon">
|
|
47
|
+
<use href="#replay-icon" />
|
|
48
|
+
</svg>
|
|
49
|
+
</div>
|
|
50
|
+
</app-base-button>
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
<div
|
|
53
|
+
v-if="mediaToPlay"
|
|
54
|
+
class="pb-wrapper"
|
|
55
|
+
:class="{
|
|
56
|
+
'show-controls': showControlsValue || mediaToPlay.mType === 'audio',
|
|
57
|
+
audio: mediaToPlay.mType === 'audio',
|
|
58
|
+
video: mediaToPlay.mType === 'video'
|
|
59
|
+
}"
|
|
60
|
+
>
|
|
61
|
+
<!--------------------------------- PLAY-BAR Progress (video only) -------------------------------------->
|
|
62
|
+
<div
|
|
63
|
+
v-if="mediaToPlay.mType === 'video'"
|
|
64
|
+
ref="$playbar-timeline"
|
|
65
|
+
class="pb-timeline"
|
|
66
|
+
>
|
|
67
|
+
<div ref="$progress-area" class="progress-area">
|
|
68
|
+
<div
|
|
69
|
+
ref="$progress-bar"
|
|
70
|
+
draggable="false"
|
|
71
|
+
tabindex="0"
|
|
72
|
+
class="pb-progress-bar"
|
|
73
|
+
role="slider"
|
|
74
|
+
aria-valuemin="0"
|
|
75
|
+
:aria-label="mediaA11Y.label"
|
|
76
|
+
:aria-valuenow="mediaA11Y.valNow"
|
|
77
|
+
:aria-valuemax="mediaA11Y.valMax"
|
|
78
|
+
:aria-valuetext="mediaA11Y.valueText"
|
|
79
|
+
@focus="changeFocusState('progressBar', true)"
|
|
80
|
+
@blur="changeFocusState('progressBar', false)"
|
|
81
|
+
>
|
|
82
|
+
<!--Class progress-animation is apply when we are not using the thumb to change the progression-->
|
|
83
|
+
<div
|
|
84
|
+
ref="$progress-indicator"
|
|
85
|
+
draggable="false"
|
|
86
|
+
class="progress-indicator"
|
|
87
|
+
:class="{ 'progress-animation': !progressThumbDown }"
|
|
88
|
+
:style="{ width: progressBarPercentage + '%' }"
|
|
89
|
+
>
|
|
90
|
+
<!--Mousedown validate if the thumb is cliqued (if yes, the mouse is follow to modify the progress)
|
|
91
|
+
MouseOver/MouseOut deactivate click event on progressBar if the mouse hovered the thumb-->
|
|
92
|
+
<div
|
|
93
|
+
ref="$progress-thumb"
|
|
94
|
+
draggable="false"
|
|
95
|
+
class="progress-thumb"
|
|
96
|
+
style="z-index: 9"
|
|
97
|
+
@mousedown="
|
|
98
|
+
savedIsPlaying = isPlaying
|
|
99
|
+
progressThumbDown = true
|
|
100
|
+
"
|
|
101
|
+
@mouseover="progressThumbHover = true"
|
|
102
|
+
@mouseleave="progressThumbHover = false"
|
|
103
|
+
></div>
|
|
54
104
|
</div>
|
|
55
105
|
</div>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
viewBox="0 0 24 24"
|
|
106
|
+
<!--------------------------------- PLAY-BAR ToolTip (video only) ----------------------------------->
|
|
107
|
+
<div
|
|
108
|
+
v-if="mediaToPlay.mType === 'video'"
|
|
109
|
+
ref="$seek-tooltip"
|
|
110
|
+
aria-hidden="true"
|
|
111
|
+
class="seek-tooltip"
|
|
63
112
|
>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
data-name="Path 3896"
|
|
67
|
-
d="M0,0H24V24H0Z"
|
|
68
|
-
fill="none"
|
|
69
|
-
/>
|
|
70
|
-
<path
|
|
71
|
-
id="Path_3897"
|
|
72
|
-
data-name="Path 3897"
|
|
73
|
-
d="M3,9v6H7l5,5V4L7,9Zm13.5,3A4.5,4.5,0,0,0,14,7.97v8.05A4.474,4.474,0,0,0,16.5,12ZM14,3.23V5.29a7,7,0,0,1,0,13.42v2.06A8.994,8.994,0,0,0,14,3.23Z"
|
|
74
|
-
/>
|
|
75
|
-
</svg>
|
|
76
|
-
<svg
|
|
77
|
-
v-if="volDefault <= 0"
|
|
78
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
79
|
-
width="18"
|
|
80
|
-
height="18"
|
|
81
|
-
viewBox="0 0 18 18"
|
|
82
|
-
>
|
|
83
|
-
<path
|
|
84
|
-
id="Path_3893"
|
|
85
|
-
data-name="Path 3893"
|
|
86
|
-
d="M16.5,12A4.5,4.5,0,0,0,14,7.97v2.21l2.45,2.45A4.232,4.232,0,0,0,16.5,12ZM19,12a6.843,6.843,0,0,1-.54,2.64l1.51,1.51A8.8,8.8,0,0,0,21,12a9,9,0,0,0-7-8.77V5.29A7.005,7.005,0,0,1,19,12ZM4.27,3,3,4.27,7.73,9H3v6H7l5,5V13.27l4.25,4.25A6.924,6.924,0,0,1,14,18.7v2.06a8.99,8.99,0,0,0,3.69-1.81L19.73,21,21,19.73l-9-9ZM12,4,9.91,6.09,12,8.18Z"
|
|
87
|
-
transform="translate(-3 -3)"
|
|
88
|
-
/>
|
|
89
|
-
</svg>
|
|
113
|
+
{{ tooTipTimeCode }}
|
|
114
|
+
</div>
|
|
90
115
|
</div>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
d="M6,19h4V5H6ZM14,5V19h4V5Z"
|
|
113
|
-
transform="translate(-6 -5)"
|
|
114
|
-
/>
|
|
115
|
-
</svg>
|
|
116
|
-
<!--------------------------------Replay SVG------------------------------------>
|
|
117
|
-
<svg
|
|
118
|
-
v-if="canReplay && !isPlaying"
|
|
119
|
-
id="replay-icon"
|
|
120
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
121
|
-
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
122
|
-
width="24"
|
|
123
|
-
height="24"
|
|
124
|
-
viewBox="0 0 16 20"
|
|
125
|
-
xml:space="preserve"
|
|
126
|
-
>
|
|
127
|
-
<path
|
|
128
|
-
class="st0"
|
|
129
|
-
d="M8,4V0L3,5l5,5V6c3.3,0,6,2.7,6,6s-2.7,6-6,6s-6-2.7-6-6H0c0,4.4,3.6,8,8,8s8-3.6,8-8 S12.4,4,8,4z"
|
|
130
|
-
/>
|
|
131
|
-
</svg>
|
|
132
|
-
<!--------------------------------- Play SVG ----------------------------------->
|
|
133
|
-
<svg
|
|
134
|
-
v-if="!isPlaying && !canReplay"
|
|
135
|
-
id="play-icon"
|
|
136
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
137
|
-
width="15.278"
|
|
138
|
-
height="19.444"
|
|
139
|
-
viewBox="0 0 15.278 19.444"
|
|
140
|
-
>
|
|
141
|
-
<path
|
|
142
|
-
id="Path_3858"
|
|
143
|
-
data-name="Path 3858"
|
|
144
|
-
d="M8,5V24.444l15.278-9.722Z"
|
|
145
|
-
transform="translate(-8 -5)"
|
|
146
|
-
/>
|
|
147
|
-
</svg>
|
|
148
|
-
</app-base-button>
|
|
149
|
-
<app-base-button
|
|
150
|
-
id="acessMenu"
|
|
151
|
-
ref="subButton"
|
|
152
|
-
class="playbar-btn"
|
|
153
|
-
:aria-label="$t('button.accessibility')"
|
|
154
|
-
:title="$t('button.accessibility')"
|
|
155
|
-
@click="toggleSubtitleMenu"
|
|
156
|
-
@focus="playbarFocus"
|
|
157
|
-
>
|
|
158
|
-
<svg
|
|
159
|
-
v-if="!subtitleMenuOpen"
|
|
160
|
-
id="Component_86_3"
|
|
161
|
-
data-name="Component 86 – 3"
|
|
162
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
163
|
-
width="21.642"
|
|
164
|
-
height="16"
|
|
165
|
-
viewBox="0 0 21.642 16"
|
|
166
|
-
>
|
|
167
|
-
<path
|
|
168
|
-
id="Path_3989"
|
|
169
|
-
data-name="Path 3989"
|
|
170
|
-
d="M690,385a4.991,4.991,0,0,1-4.578-7H673a2.006,2.006,0,0,0-2,2v12a2.006,2.006,0,0,0,2,2h16a2.006,2.006,0,0,0,2-2v-7.1A4.987,4.987,0,0,1,690,385Zm-17,1h4v2h-4Zm10,6H673v-2h10Zm6,0h-4v-2h4Zm0-4H679v-2h10Z"
|
|
171
|
-
transform="translate(-671 -378)"
|
|
172
|
-
/>
|
|
173
|
-
<path
|
|
174
|
-
id="Path_3902"
|
|
175
|
-
data-name="Path 3902"
|
|
176
|
-
d="M688.061,379l-.609.61,2.595,2.6,2.6-2.6-.61-.61-1.985,1.981Z"
|
|
177
|
-
transform="translate(-671 -378)"
|
|
178
|
-
/>
|
|
179
|
-
</svg>
|
|
180
|
-
|
|
181
|
-
<svg
|
|
182
|
-
v-if="subtitleMenuOpen"
|
|
183
|
-
id="Component_86_5"
|
|
184
|
-
data-name="Component 86 – 5"
|
|
185
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
186
|
-
width="21.642"
|
|
187
|
-
height="16"
|
|
188
|
-
viewBox="0 0 21.642 16"
|
|
116
|
+
</div>
|
|
117
|
+
<div class="pb-controls">
|
|
118
|
+
<div class="pb-areas left">
|
|
119
|
+
<!--------------------------------- PLAY-BAR Play ------------------------------------>
|
|
120
|
+
<app-base-button
|
|
121
|
+
ref="$btn-play"
|
|
122
|
+
class="playbar-btn playbar-play"
|
|
123
|
+
:class="{ displayLabel: btnsLabelDisplay['playbar-play'] === true }"
|
|
124
|
+
:aria-label="
|
|
125
|
+
playLabel + (mediaToPlay.mType === 'video' ? ' secondaire' : '')
|
|
126
|
+
"
|
|
127
|
+
:data-title="`${playLabel} (k)`"
|
|
128
|
+
@click="
|
|
129
|
+
() => {
|
|
130
|
+
mediaToPlay.mType === 'video' ? handlePlayVideo() : togglePlay()
|
|
131
|
+
}
|
|
132
|
+
"
|
|
133
|
+
@mouseenter="activateLabel($event)"
|
|
134
|
+
@mouseleave="deactivateLabel($event)"
|
|
135
|
+
@focus="activateLabel($event)"
|
|
136
|
+
@blur="deactivateLabel($event)"
|
|
189
137
|
>
|
|
190
|
-
<
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
d="M690,385a4.991,4.991,0,0,1-4.578-7H673a2.006,2.006,0,0,0-2,2v12a2.006,2.006,0,0,0,2,2h16a2.006,2.006,0,0,0,2-2v-7.1A4.987,4.987,0,0,1,690,385Zm-17,1h4v2h-4Zm10,6H673v-2h10Zm6,0h-4v-2h4Zm0-4H679v-2h10Z"
|
|
194
|
-
transform="translate(-671 -378)"
|
|
195
|
-
/>
|
|
196
|
-
<path
|
|
197
|
-
id="Path_3902"
|
|
198
|
-
data-name="Path 3902"
|
|
199
|
-
d="M688.061,379l-.609.61,2.595,2.6,2.6-2.6-.61-.61-1.985,1.981Z"
|
|
200
|
-
transform="translate(709.094 383.205) rotate(180)"
|
|
201
|
-
/>
|
|
202
|
-
</svg>
|
|
203
|
-
</app-base-button>
|
|
204
|
-
<div id="playbar-cc" :class="{ submenu_active: subtitleMenuOpen }">
|
|
205
|
-
<div v-show="subtitleMenuOpen" id="subtitleMenuWrapper">
|
|
206
|
-
<app-base-button
|
|
207
|
-
id="btn-transcript"
|
|
208
|
-
class="subtitleBtns"
|
|
209
|
-
:aria-label="$t('button.download_transcript')"
|
|
210
|
-
:title="$t('button.download_transcript')"
|
|
211
|
-
:disabled="!hasTranscript"
|
|
212
|
-
:class="{ md_disabled: !hasTranscript }"
|
|
213
|
-
@click="downloadTranscript"
|
|
214
|
-
@focus="playbarFocus"
|
|
138
|
+
<svg
|
|
139
|
+
v-show="!canReplay && !isPlaying"
|
|
140
|
+
class="app-icons-svg play-icon"
|
|
215
141
|
>
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
>
|
|
222
|
-
<path
|
|
223
|
-
id="Path_3846"
|
|
224
|
-
data-name="Path 3846"
|
|
225
|
-
d="M19,12v7H5V12H3v7a2.006,2.006,0,0,0,2,2H19a2.006,2.006,0,0,0,2-2V12Zm-6,.67,2.59-2.58L17,11.5l-5,5-5-5,1.41-1.41L11,12.67V3h2Z"
|
|
226
|
-
transform="translate(-3 -3)"
|
|
227
|
-
/>
|
|
228
|
-
</svg>
|
|
229
|
-
<span>{{ $t('button.download_transcript') }}</span>
|
|
230
|
-
</app-base-button>
|
|
231
|
-
<app-base-button
|
|
232
|
-
v-if="!subtitlesEnabled"
|
|
233
|
-
id="btn-subtitles"
|
|
234
|
-
class="btn subtitleBtns"
|
|
235
|
-
:aria-label="$t('button.show_subtitle')"
|
|
236
|
-
:title="$t('button.show_subtitle')"
|
|
237
|
-
:disabled="!hasSubtitle"
|
|
238
|
-
:class="{ md_disabled: !hasSubtitle }"
|
|
239
|
-
@click="showSubtitles"
|
|
240
|
-
@focus="playbarFocus"
|
|
142
|
+
<use href="#play-icon" />
|
|
143
|
+
</svg>
|
|
144
|
+
<svg
|
|
145
|
+
v-show="isPlaying && !canReplay"
|
|
146
|
+
class="app-icons-svg pause-icon"
|
|
241
147
|
>
|
|
242
|
-
<
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
</svg>
|
|
255
|
-
<span>{{ $t('button.show_subtitle') }}</span>
|
|
256
|
-
</app-base-button>
|
|
257
|
-
<app-base-button
|
|
258
|
-
v-if="subtitlesEnabled"
|
|
259
|
-
id="btn-hide-subtitles"
|
|
260
|
-
class="subtitleBtns"
|
|
261
|
-
:aria-label="$t('button.hide_subtitle')"
|
|
262
|
-
:title="$t('button.hide_subtitle')"
|
|
263
|
-
@click="hideSubtitles"
|
|
148
|
+
<use href="#pause-icon" />
|
|
149
|
+
</svg>
|
|
150
|
+
<svg v-show="canReplay" class="app-icons-svg replay-icon">
|
|
151
|
+
<use href="#replay-icon" />
|
|
152
|
+
</svg>
|
|
153
|
+
</app-base-button>
|
|
154
|
+
<!--------------------------------- PLAY-BAR Timer ------------------------------------>
|
|
155
|
+
<div class="pb-timer">
|
|
156
|
+
<span
|
|
157
|
+
aria-hidden="true"
|
|
158
|
+
style="-webkit-user-select: none"
|
|
159
|
+
draggable="false"
|
|
264
160
|
>
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
161
|
+
{{ timecode }} / {{ mediaDurationTime }}
|
|
162
|
+
</span>
|
|
163
|
+
</div>
|
|
164
|
+
<!--------------------------------- PLAY-BAR Progress (audio only) -------------------------------------->
|
|
165
|
+
<div
|
|
166
|
+
v-if="mediaToPlay.mType === 'audio'"
|
|
167
|
+
ref="$playbar-timeline"
|
|
168
|
+
class="pb-timeline"
|
|
169
|
+
>
|
|
170
|
+
<div ref="$progress-area" class="progress-area">
|
|
171
|
+
<div
|
|
172
|
+
id="progress-bar"
|
|
173
|
+
ref="$progress-bar"
|
|
174
|
+
draggable="false"
|
|
175
|
+
tabindex="0"
|
|
176
|
+
class="pb-progress-bar"
|
|
177
|
+
role="slider"
|
|
178
|
+
aria-valuemin="0"
|
|
179
|
+
:aria-label="mediaA11Y.label"
|
|
180
|
+
:aria-valuenow="mediaA11Y.valNow"
|
|
181
|
+
:aria-valuemax="mediaA11Y.valMax"
|
|
182
|
+
:aria-valuetext="mediaA11Y.valueText"
|
|
183
|
+
@focus="changeFocusState('progressBar', true)"
|
|
184
|
+
@blur="changeFocusState('progressBar', false)"
|
|
271
185
|
>
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
186
|
+
<!--Class progress-animation is apply when we are not using the thumb to change the progression-->
|
|
187
|
+
<div
|
|
188
|
+
id="progress-indicator"
|
|
189
|
+
ref="$progress-indicator"
|
|
190
|
+
draggable="false"
|
|
191
|
+
class="progress-indicator"
|
|
192
|
+
:class="{ 'progress-animation': !progressThumbDown }"
|
|
193
|
+
:style="{ width: progressBarPercentage + '%' }"
|
|
276
194
|
>
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
195
|
+
<!--Mousedown validate if the thumb is cliqued (if yes, the mouse is follow to modify the progress)
|
|
196
|
+
MouseOver/MouseOut deactivate click event on progressBar if the mouse hovered the thumb-->
|
|
197
|
+
<div
|
|
198
|
+
ref="$progress-thumb"
|
|
199
|
+
draggable="false"
|
|
200
|
+
class="progress-thumb"
|
|
201
|
+
style="z-index: 9"
|
|
202
|
+
@mousedown="
|
|
203
|
+
savedIsPlaying = isPlaying
|
|
204
|
+
progressThumbDown = true
|
|
205
|
+
"
|
|
206
|
+
@mouseover="progressThumbHover = true"
|
|
207
|
+
@mouseleave="progressThumbHover = false"
|
|
208
|
+
></div>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
<!--------------------------------- PLAY-BAR Volume -------------------------------------->
|
|
214
|
+
<app-base-button
|
|
215
|
+
id="playbar-volume"
|
|
216
|
+
ref="$btn-volume"
|
|
217
|
+
class="volume-btn"
|
|
218
|
+
:class="{
|
|
219
|
+
displayLabel: btnsLabelDisplay['playbar-volume'] === true
|
|
220
|
+
}"
|
|
221
|
+
tabindex="0"
|
|
222
|
+
:aria-label="volumeLabel"
|
|
223
|
+
:data-title="`${volumeLabel} (m)`"
|
|
224
|
+
@click="toggleMute"
|
|
225
|
+
@mouseenter="activateLabel($event)"
|
|
226
|
+
@mouseleave="deactivateLabel($event)"
|
|
227
|
+
@focus="activateLabel($event)"
|
|
228
|
+
@blur="deactivateLabel($event)"
|
|
229
|
+
>
|
|
230
|
+
<svg v-show="volumeState == 'muted'" class="app-icons-svg">
|
|
231
|
+
<use href="#volume-mute-icon" />
|
|
232
|
+
</svg>
|
|
233
|
+
<svg v-show="volumeState == 'high'" class="app-icons-svg">
|
|
234
|
+
<use href="#volume-high-icon" />
|
|
235
|
+
</svg>
|
|
236
|
+
<svg
|
|
237
|
+
v-show="volumeState == 'low'"
|
|
238
|
+
class="app-icons-svg volume-low-icon"
|
|
239
|
+
>
|
|
240
|
+
<use href="#volume-low-icon" />
|
|
241
|
+
</svg>
|
|
242
|
+
</app-base-button>
|
|
243
|
+
<div ref="zone-volume" class="volume-controls">
|
|
244
|
+
<input
|
|
245
|
+
ref="$volume-slider"
|
|
246
|
+
class="volume-slider"
|
|
247
|
+
:class="{
|
|
248
|
+
displayLabel: btnsLabelDisplay['volume-slider'] === true
|
|
249
|
+
}"
|
|
250
|
+
:value="currentVolume"
|
|
251
|
+
:aria-valuetext="volumeLevelA11Y"
|
|
252
|
+
type="range"
|
|
253
|
+
max="1"
|
|
254
|
+
min="0"
|
|
255
|
+
step="0.01"
|
|
256
|
+
tabindex="0"
|
|
257
|
+
:aria-label="`${$t('button.volume')}`"
|
|
258
|
+
@click="updateVolumeLevel"
|
|
259
|
+
@mouseenter="activateLabel($event.currentTarget)"
|
|
260
|
+
@mouseleave="deactivateLabel($event.currentTarget)"
|
|
261
|
+
@focus="
|
|
262
|
+
activateLabel($event.currentTarget),
|
|
263
|
+
changeFocusState('volumeSlider', true)
|
|
264
|
+
"
|
|
265
|
+
@blur="
|
|
266
|
+
deactivateLabel($event.currentTarget),
|
|
267
|
+
changeFocusState('volumeSlider', false)
|
|
268
|
+
"
|
|
269
|
+
/>
|
|
270
|
+
<span class="volume-label" aria-hidden="true">
|
|
271
|
+
{{ $t('button.volume') }}
|
|
272
|
+
</span>
|
|
273
|
+
<!--using span because ::before on input is not supported by firefox-->
|
|
274
|
+
<span
|
|
275
|
+
ref="$volume-progress"
|
|
276
|
+
class="volume-progress"
|
|
277
|
+
:style="{
|
|
278
|
+
'--background-size-vs': `calc(${volumeSliderBackground} - 2px)`
|
|
279
|
+
}"
|
|
280
|
+
></span>
|
|
293
281
|
</div>
|
|
294
282
|
</div>
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
283
|
+
<!--------------------------------- PLAY-BAR CC (video only) ------------------------------------------>
|
|
284
|
+
<div v-if="mediaToPlay.mType === 'video'" class="pb-areas right">
|
|
285
|
+
<app-base-button
|
|
286
|
+
id="btn-subtitles"
|
|
287
|
+
ref="$btn-subtitle"
|
|
288
|
+
class="btn subtitleBtns"
|
|
289
|
+
:aria-label="ccLabel"
|
|
290
|
+
:data-title="`${ccLabel} (c)`"
|
|
291
|
+
:disabled="!hasSubtitle"
|
|
292
|
+
:class="{
|
|
293
|
+
md_disabled: !hasSubtitle,
|
|
294
|
+
displayLabel: btnsLabelDisplay['btn-subtitles'] === true
|
|
295
|
+
}"
|
|
296
|
+
@click="toggleViewSubtitle()"
|
|
297
|
+
@mouseenter="activateLabel($event)"
|
|
298
|
+
@mouseleave="deactivateLabel($event)"
|
|
299
|
+
@focus="activateLabel($event)"
|
|
300
|
+
@blur="deactivateLabel($event)"
|
|
301
|
+
>
|
|
302
|
+
<svg
|
|
303
|
+
v-show="(hasSubtitle && !subtitlesEnabled) || !hasSubtitle"
|
|
304
|
+
class="app-icons-svg"
|
|
305
|
+
>
|
|
306
|
+
<use href="#subtitle-off-icon" />
|
|
307
|
+
</svg>
|
|
308
|
+
<svg v-show="hasSubtitle && subtitlesEnabled" class="app-icons-svg">
|
|
309
|
+
<use href="#subtitle-on-icon" />
|
|
310
|
+
</svg>
|
|
311
|
+
</app-base-button>
|
|
312
|
+
<!--------------------------------- PLAY-BAR Transcript ----------------------------------->
|
|
313
|
+
<app-base-button
|
|
314
|
+
id="btn-transcript"
|
|
315
|
+
ref="$btn-transcript"
|
|
316
|
+
class="btn-transcript"
|
|
317
|
+
:aria-label="transcriptLabel"
|
|
318
|
+
:data-title="`${transcriptLabel} (t)`"
|
|
319
|
+
:disabled="!hasTranscript || fullscreenOn"
|
|
320
|
+
:class="{
|
|
321
|
+
md_disabled: !hasTranscript || fullscreenOn,
|
|
322
|
+
displayLabel: btnsLabelDisplay['btn-transcript'] === true
|
|
323
|
+
}"
|
|
324
|
+
@click="toggleViewTranscript()"
|
|
325
|
+
@mouseenter="activateLabel($event)"
|
|
326
|
+
@mouseleave="deactivateLabel($event)"
|
|
327
|
+
@focus="activateLabel($event)"
|
|
328
|
+
@blur="deactivateLabel($event)"
|
|
329
|
+
>
|
|
330
|
+
<svg
|
|
331
|
+
v-show="(hasTranscript && !transcriptEnabled) || !hasTranscript"
|
|
332
|
+
class="app-icons-svg"
|
|
333
|
+
>
|
|
334
|
+
<use href="#transcript-off-icon" />
|
|
335
|
+
</svg>
|
|
336
|
+
<svg
|
|
337
|
+
v-show="hasTranscript && transcriptEnabled"
|
|
338
|
+
class="app-icons-svg"
|
|
339
|
+
>
|
|
340
|
+
<use href="#transcript-on-icon" />
|
|
341
|
+
</svg>
|
|
342
|
+
</app-base-button>
|
|
343
|
+
<!--------------------------------- PLAY-BAR FullScreen ----------------------------------->
|
|
344
|
+
<app-base-button
|
|
345
|
+
id="btn-fullscreen"
|
|
346
|
+
ref="$btn-fullscreen"
|
|
347
|
+
class="fullscreenBtns"
|
|
348
|
+
:aria-label="fullscreenLabel"
|
|
349
|
+
:disabled="transcriptEnabled"
|
|
350
|
+
:class="{
|
|
351
|
+
md_disabled: transcriptEnabled,
|
|
352
|
+
displayLabel: btnsLabelDisplay['btn-fullscreen'] === true
|
|
353
|
+
}"
|
|
354
|
+
:data-title="`${fullscreenLabel} (f)`"
|
|
355
|
+
@click="toggleFullScreen()"
|
|
356
|
+
@mouseenter="activateLabel($event)"
|
|
357
|
+
@mouseleave="deactivateLabel($event)"
|
|
358
|
+
@focus="activateLabel($event)"
|
|
359
|
+
@blur="deactivateLabel($event)"
|
|
360
|
+
>
|
|
361
|
+
<svg v-show="!fullscreenOn" class="app-icons-svg">
|
|
362
|
+
<use href="#fullscreen-icon" />
|
|
363
|
+
</svg>
|
|
364
|
+
<svg v-show="fullscreenOn" class="app-icons-svg">
|
|
365
|
+
<use href="#fullscreen-exit-icon" />
|
|
366
|
+
</svg>
|
|
367
|
+
</app-base-button>
|
|
301
368
|
</div>
|
|
302
369
|
</div>
|
|
303
370
|
</div>
|
|
304
|
-
<div
|
|
305
|
-
id="playbar-progress"
|
|
306
|
-
ref="playbar-progress"
|
|
307
|
-
role="progressbar"
|
|
308
|
-
aria-valuemin="0"
|
|
309
|
-
:aria-label="mediaA11Y.label"
|
|
310
|
-
:aria-valuenow="mediaA11Y.valNow"
|
|
311
|
-
:aria-valuemax="mediaA11Y.valMax"
|
|
312
|
-
:aria-valuetext="mediaA11Y.valueText"
|
|
313
|
-
@mouseover="progressOver"
|
|
314
|
-
@mouseleave="progressLeave"
|
|
315
|
-
@mousemove="progressMove"
|
|
316
|
-
@click="progressClick"
|
|
317
|
-
>
|
|
318
|
-
<div id="playbar-buffer" ref="playbar-buffer"></div>
|
|
319
|
-
<div id="playbar-playback" ref="playbar-playback">
|
|
320
|
-
<div
|
|
321
|
-
id="playbar-cursor"
|
|
322
|
-
tabindex="0"
|
|
323
|
-
@mousedown="cursorDown"
|
|
324
|
-
@focus="playbarFocus"
|
|
325
|
-
></div>
|
|
326
|
-
</div>
|
|
327
|
-
</div>
|
|
328
371
|
</div>
|
|
329
372
|
</template>
|
|
330
373
|
|
|
331
374
|
<script>
|
|
375
|
+
import $extendsMedia from '../mixins/$mediaMixins'
|
|
332
376
|
import { mapGetters } from 'vuex'
|
|
333
377
|
|
|
334
378
|
export default {
|
|
379
|
+
mixins: [$extendsMedia],
|
|
335
380
|
props: {
|
|
336
|
-
|
|
337
|
-
mediaToShow: { type: [Object, Boolean], default: false }
|
|
381
|
+
mediaToPlay: { type: [Object, Boolean], default: false }
|
|
338
382
|
},
|
|
339
383
|
|
|
340
384
|
data() {
|
|
341
385
|
return {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
progressTime: null,
|
|
353
|
-
mediaDuration: '--:--',
|
|
354
|
-
navigation: {},
|
|
355
|
-
currentPath: null,
|
|
356
|
-
isBranching: false,
|
|
357
|
-
//bCounter: null,
|
|
358
|
-
index: 0,
|
|
359
|
-
navigationRoutes: null,
|
|
360
|
-
hasMedia: false,
|
|
361
|
-
hasSound: false,
|
|
362
|
-
media: null,
|
|
363
|
-
nextActivity: null,
|
|
364
|
-
previousActivity: null,
|
|
365
|
-
cursorDragged: false,
|
|
366
|
-
bufferDomElem: '',
|
|
367
|
-
playbackDomElem: '',
|
|
368
|
-
isPlaying: false,
|
|
369
|
-
mediaHandlersSet: false,
|
|
370
|
-
duration: '',
|
|
371
|
-
timecode: '',
|
|
372
|
-
subtitlesEnabled: false,
|
|
373
|
-
volumeSliderOpen: false,
|
|
374
|
-
volumeBtn: null,
|
|
375
|
-
volDefault: 1,
|
|
376
|
-
hover: false,
|
|
377
|
-
lastVolume: '',
|
|
378
|
-
muted: false,
|
|
379
|
-
isAnimation: false,
|
|
380
|
-
subtitleMenuOpen: false,
|
|
381
|
-
hasTranscript: false,
|
|
382
|
-
hasSubtitle: false,
|
|
383
|
-
canReplay: false,
|
|
386
|
+
id: `plyr_${this.mediaToPlay.id}`,
|
|
387
|
+
//Playback animation
|
|
388
|
+
playClicked: false,
|
|
389
|
+
playBackAnim: true,
|
|
390
|
+
//ProgressSeek
|
|
391
|
+
progressSeek: null,
|
|
392
|
+
//Tooltip
|
|
393
|
+
seekTooltip: null,
|
|
394
|
+
tooTipTimeCode: '00:00',
|
|
395
|
+
//Hiding playbar animation
|
|
384
396
|
focusTimeout: null,
|
|
385
|
-
delayUntilHide:
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
timeCode: 0,
|
|
393
|
-
duration: 0
|
|
394
|
-
}
|
|
397
|
+
delayUntilHide: 5000,
|
|
398
|
+
hideTimer: null,
|
|
399
|
+
//Transcript
|
|
400
|
+
transcriptEnabled: false,
|
|
401
|
+
transcriptToShow: null,
|
|
402
|
+
//Fullscreen
|
|
403
|
+
fullscreenOn: false
|
|
395
404
|
}
|
|
396
405
|
},
|
|
397
406
|
computed: {
|
|
398
407
|
...mapGetters([
|
|
399
|
-
'getCurrentPage',
|
|
400
|
-
'getModuleChildren',
|
|
401
|
-
'hasMediaElOrTimeline',
|
|
402
|
-
'getCurrentMediaDuration',
|
|
403
|
-
'
|
|
404
|
-
'
|
|
405
|
-
'
|
|
406
|
-
'
|
|
407
|
-
'
|
|
408
|
-
'getMediaSubtitles',
|
|
409
|
-
'getUserInteraction'
|
|
408
|
+
// 'getCurrentPage',
|
|
409
|
+
// 'getModuleChildren',
|
|
410
|
+
//'hasMediaElOrTimeline',
|
|
411
|
+
//'getCurrentMediaDuration',
|
|
412
|
+
//'getCurrentBrowser',
|
|
413
|
+
// 'getAutoplayEnabled',
|
|
414
|
+
//'getModuleInfo',
|
|
415
|
+
//'getMediaSubtitles',
|
|
416
|
+
//'getUserInteraction'
|
|
410
417
|
]),
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
let viewed = false
|
|
416
|
-
if (
|
|
417
|
-
userData &&
|
|
418
|
-
userData[activityId] &&
|
|
419
|
-
userData[activityId][pageId] &&
|
|
420
|
-
userData[activityId][pageId].userInteraction &&
|
|
421
|
-
userData[activityId][pageId].userInteraction.mediaIsViewed
|
|
422
|
-
) {
|
|
423
|
-
viewed = true
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
return viewed
|
|
418
|
+
//Transcript
|
|
419
|
+
hasTranscript() {
|
|
420
|
+
if (!this.mediaToPlay) return
|
|
421
|
+
return this.mediaToPlay.mTranscript || false
|
|
427
422
|
},
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if (!this.
|
|
431
|
-
|
|
432
|
-
} else {
|
|
433
|
-
//si la vidéo joue, minimiser seulement si la souris ne la survole pas.
|
|
434
|
-
return !this.hover
|
|
435
|
-
}
|
|
423
|
+
//Subtitle
|
|
424
|
+
hasSubtitle() {
|
|
425
|
+
if (!this.mediaToPlay) return
|
|
426
|
+
return this.mediaToPlay.mSubtitles || false
|
|
436
427
|
},
|
|
437
|
-
|
|
438
|
-
return
|
|
439
|
-
|
|
440
|
-
this.volDefault +
|
|
441
|
-
'; --text-value:"' +
|
|
442
|
-
this.volDefault +
|
|
443
|
-
'";'
|
|
444
|
-
)
|
|
428
|
+
subtitlesEnabled() {
|
|
429
|
+
if (!this.hasSubtitle) return false
|
|
430
|
+
else return this.getMediaSubtitles
|
|
445
431
|
},
|
|
446
|
-
|
|
432
|
+
//mediaContainer (only used for video)
|
|
433
|
+
mediaContainer() {
|
|
434
|
+
if (!this.mediaToPlay) return
|
|
435
|
+
return this.mediaToPlay.mMediaContainer
|
|
436
|
+
},
|
|
437
|
+
|
|
438
|
+
//MediaDuration :Number (used for tooltip)
|
|
439
|
+
mediaDuration() {
|
|
440
|
+
return this.mediaToPlay.mElement.duration
|
|
441
|
+
? this.mediaToPlay.mElement.duration
|
|
442
|
+
: 0
|
|
443
|
+
},
|
|
444
|
+
//Labels
|
|
445
|
+
fullscreenLabel() {
|
|
447
446
|
let label = null
|
|
448
|
-
if (this.
|
|
449
|
-
|
|
450
|
-
} else {
|
|
451
|
-
label = `${this.$t('button.play')}`
|
|
452
|
-
}
|
|
447
|
+
if (this.fullscreenOn) label = `${this.$t('button.full_screen_off')}`
|
|
448
|
+
else label = `${this.$t('button.full_screen_on')}`
|
|
453
449
|
return label
|
|
454
450
|
},
|
|
455
|
-
|
|
451
|
+
transcriptLabel() {
|
|
456
452
|
let label = null
|
|
457
|
-
if (this.
|
|
458
|
-
|
|
459
|
-
} else {
|
|
460
|
-
label = `${this.$t('button.mute')}`
|
|
461
|
-
}
|
|
453
|
+
if (this.transcriptEnabled) label = `${this.$t('button.transcript_off')}`
|
|
454
|
+
else label = `${this.$t('button.transcript_on')}`
|
|
462
455
|
return label
|
|
463
456
|
},
|
|
464
|
-
|
|
465
|
-
let
|
|
466
|
-
|
|
457
|
+
ccLabel() {
|
|
458
|
+
let label = null
|
|
459
|
+
if (this.subtitlesEnabled) label = `${this.$t('button.subtitle_off')}`
|
|
460
|
+
else label = `${this.$t('button.subtitle_on')}`
|
|
461
|
+
return label
|
|
467
462
|
}
|
|
468
463
|
},
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
if (this.mediaHandlersSet === false && this.hasMedia) {
|
|
491
|
-
if (this.getAutoplayEnabled) {
|
|
492
|
-
this.playClick()
|
|
493
|
-
}
|
|
494
|
-
//animation was viewed previously
|
|
495
|
-
if (this.isViewed) {
|
|
496
|
-
//set animation timeline at the end
|
|
497
|
-
this.setMediaTime(this.mediaToShow.timeline.totalDuration())
|
|
498
|
-
this.canReplay = true
|
|
499
|
-
}
|
|
500
|
-
this.setMediaHandlers()
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
this.updateTimecodeDisplay()
|
|
504
|
-
|
|
505
|
-
break
|
|
506
|
-
|
|
507
|
-
case 'pg_media':
|
|
508
|
-
if (mElement) {
|
|
509
|
-
this.setMedia()
|
|
510
|
-
this.updateDurationDisplay()
|
|
511
|
-
this.setMediaA11Y()
|
|
512
|
-
if (this.mediaHandlersSet === false && this.hasMedia) {
|
|
513
|
-
this.setVolume()
|
|
514
|
-
if (this.subtitlesEnabled) {
|
|
515
|
-
this.showSubtitles()
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
this.updateTimecodeDisplay()
|
|
519
|
-
|
|
520
|
-
if (this.getAutoplayEnabled) {
|
|
521
|
-
this.playClick()
|
|
522
|
-
}
|
|
523
|
-
//video was viewed previously
|
|
524
|
-
if (this.isViewed) {
|
|
525
|
-
//set video timecode at the end
|
|
526
|
-
this.setMediaTime(this.media.mElement.duration)
|
|
527
|
-
this.canReplay = true
|
|
528
|
-
}
|
|
529
|
-
this.setMediaHandlers()
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
break
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
},
|
|
536
|
-
immediate: true
|
|
537
|
-
},
|
|
538
|
-
|
|
539
|
-
$route() {
|
|
540
|
-
setTimeout(() => {
|
|
541
|
-
this.$scorm.getDataValues()
|
|
542
|
-
}, 200)
|
|
543
|
-
},
|
|
544
|
-
/*
|
|
545
|
-
* In some cases (when the page has media ) the media metadata is not ready and total duration is not available.
|
|
546
|
-
* Watching getCurrentMediaDuration allow to track changes in the value of the duration and call updateDurationDisplay()
|
|
547
|
-
*/
|
|
548
|
-
getCurrentMediaDuration() {
|
|
549
|
-
this.updateDurationDisplay()
|
|
550
|
-
}
|
|
464
|
+
mounted() {
|
|
465
|
+
//initialize media $refs
|
|
466
|
+
this.initializeMediaElm()
|
|
467
|
+
//initialize video $refs
|
|
468
|
+
if (this.mediaToPlay.mType === 'video') this.initializeVideoElm()
|
|
469
|
+
|
|
470
|
+
//Set eventlistener for media
|
|
471
|
+
this.setMediaHandlers()
|
|
472
|
+
//Set eventlistener for video
|
|
473
|
+
if (this.mediaToPlay.mType === 'video') this.setVideoHandlers()
|
|
474
|
+
|
|
475
|
+
//Set label for ProgressBar
|
|
476
|
+
this.setProgressBarA11Y()
|
|
477
|
+
//Set initial volume and duration
|
|
478
|
+
this.updateVolumeLevel()
|
|
479
|
+
|
|
480
|
+
//update the the information of the media element linked to this play bar. playbar instance will be added to the media info
|
|
481
|
+
this.$store.dispatch('updateCurrentMediaElements', {
|
|
482
|
+
id: this.mediaToPlay.id,
|
|
483
|
+
...this.$parent.$refs
|
|
484
|
+
})
|
|
551
485
|
},
|
|
552
|
-
|
|
553
|
-
this.saveToLrs()
|
|
486
|
+
beforeUnmount() {
|
|
554
487
|
if (this.isPlaying) {
|
|
555
|
-
this.
|
|
556
|
-
}
|
|
557
|
-
this.cancelTimeout()
|
|
558
|
-
if (this.mediaHandlersSet) {
|
|
559
|
-
this.removeMediaHandlers()
|
|
488
|
+
this.togglePlay()
|
|
560
489
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
mounted() {
|
|
564
|
-
this.volumeBtn = this.$refs['volume-range']
|
|
565
|
-
this.bufferDomElem = this.$refs['playbar-buffer']
|
|
566
|
-
this.playbackDomElem = this.$refs['playbar-playback']
|
|
567
|
-
//get volume from the store
|
|
568
|
-
this.volDefault = this.getMediaVolume
|
|
569
|
-
this.subtitlesEnabled = this.getMediaSubtitles
|
|
490
|
+
this.removeMediaHandlers()
|
|
570
491
|
|
|
571
|
-
|
|
492
|
+
if (this.mediaToPlay.mType === 'video') this.removeVideoHandlers()
|
|
572
493
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
//
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
// var key = e.key || e.keyCode
|
|
580
|
-
// if (key === 'ArrowUp' || key === 38) {
|
|
581
|
-
// // console.log('VolumeUP')
|
|
582
|
-
// }
|
|
583
|
-
|
|
584
|
-
// if (key === 'ArrowDown' || key === 40) {
|
|
585
|
-
// //console.log('VolumeDOWN')
|
|
586
|
-
// }
|
|
587
|
-
// })
|
|
588
|
-
// })
|
|
494
|
+
if (this.firefoxTrack) {
|
|
495
|
+
this.firefoxTrack.removeEventListener('cuechange', this.fireFoxMoveCC)
|
|
496
|
+
}
|
|
497
|
+
//this.$bus.$off('play-media', this.handleMediaControls)
|
|
498
|
+
this.$bus.$off('transcript-hidden', this.resetTranscript)
|
|
499
|
+
return this.$bus.$off('close-sidebar', 'ctxTranscript')
|
|
589
500
|
},
|
|
590
501
|
methods: {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
let activityId = this.getCurrentPage.activityRef
|
|
594
|
-
let pageId = this.getCurrentPage.id
|
|
595
|
-
|
|
596
|
-
this.$set(
|
|
597
|
-
userData[activityId][pageId].userInteraction,
|
|
598
|
-
'mediaIsViewed',
|
|
599
|
-
true
|
|
600
|
-
)
|
|
601
|
-
},
|
|
602
|
-
saveToLrs() {
|
|
603
|
-
let text
|
|
604
|
-
//Defining the text to display for stmt description and definition
|
|
605
|
-
switch (this.$i18n.locale) {
|
|
606
|
-
case 'fr':
|
|
607
|
-
if (this.getModuleInfo.courseID)
|
|
608
|
-
text = `Le ${this.getModuleInfo.id} de ${this.getModuleInfo.courseID}`
|
|
609
|
-
else text = `Le ${this.getModuleInfo.id}`
|
|
610
|
-
break
|
|
611
|
-
case 'en':
|
|
612
|
-
if (this.getModuleInfo.courseID)
|
|
613
|
-
text = `The ${this.getModuleInfo.id} of ${this.getModuleInfo.courseID}`
|
|
614
|
-
else text = `The ${this.getModuleInfo.id}`
|
|
615
|
-
break
|
|
616
|
-
}
|
|
617
|
-
//Creating custom statement
|
|
618
|
-
const stmt = {
|
|
619
|
-
id: (() => {
|
|
620
|
-
if (this.getModuleInfo.courseID) return this.getModuleInfo.courseID
|
|
621
|
-
else return null
|
|
622
|
-
})(),
|
|
623
|
-
verb: 'played',
|
|
624
|
-
definition: text,
|
|
625
|
-
description: text,
|
|
626
|
-
extension: [
|
|
627
|
-
{
|
|
628
|
-
id: 'playbar-values',
|
|
629
|
-
content: {
|
|
630
|
-
volume: this.volDefault,
|
|
631
|
-
subtitlesEnabled: this.subtitlesEnabled
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
]
|
|
635
|
-
}
|
|
636
|
-
setTimeout(() => {
|
|
637
|
-
this.$bus.$emit('send-xapi-statement', stmt) //send xapi statement
|
|
638
|
-
}, 1000)
|
|
639
|
-
},
|
|
640
|
-
|
|
641
|
-
/*TODO: Need to refactor the control key mecanique to take in account Arrow Keys UP/DOWN
|
|
642
|
-
* ISSUE: Not possible to controle volume with Arrow keys UP/DOWN
|
|
502
|
+
/**
|
|
503
|
+
* @description - Set the DOM elements specific for video
|
|
643
504
|
*/
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
)
|
|
651
|
-
return
|
|
652
|
-
|
|
653
|
-
//when focus is on the video element, spacebar = play/pause
|
|
654
|
-
if (key === ' ' || key === 'Esc' || key === 32) this.playClick()
|
|
655
|
-
|
|
656
|
-
//left and right arrows to seek video
|
|
657
|
-
if (key === 'ArrowLeft' || key === 37) {
|
|
658
|
-
this.cursorLeft()
|
|
659
|
-
}
|
|
660
|
-
if (key === 'ArrowRight' || key === 39) {
|
|
661
|
-
this.cursorRight()
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
// if (key === 'ArrowUp' || key === 38) {
|
|
665
|
-
// // this.cursorRight()
|
|
666
|
-
// console.log('VolumeUP')
|
|
667
|
-
// }
|
|
668
|
-
|
|
669
|
-
// if (key === 'ArrowDown' || key === 40) {
|
|
670
|
-
// console.log('VolumeDOWN')
|
|
671
|
-
// //this.cursorRight()
|
|
672
|
-
// }
|
|
673
|
-
},
|
|
674
|
-
getCurrentTime() {
|
|
675
|
-
return this.isAnimation
|
|
676
|
-
? this.media.timeline.time()
|
|
677
|
-
: this.media.mElement.currentTime
|
|
678
|
-
},
|
|
679
|
-
cursorLeft() {
|
|
680
|
-
this.playbarFocus()
|
|
681
|
-
this.setMediaTime(this.getCurrentTime() - 10)
|
|
682
|
-
},
|
|
683
|
-
cursorRight() {
|
|
684
|
-
this.playbarFocus()
|
|
685
|
-
this.setMediaTime(this.getCurrentTime() + 10)
|
|
686
|
-
},
|
|
687
|
-
playbarFocus() {
|
|
688
|
-
this.playbarOver()
|
|
689
|
-
},
|
|
690
|
-
startTimeout() {
|
|
691
|
-
this.focusTimeout = setTimeout(this.playbarLeave, this.delayUntilHide)
|
|
692
|
-
},
|
|
693
|
-
cancelTimeout() {
|
|
694
|
-
if (this.focusTimeout) {
|
|
695
|
-
clearTimeout(this.focusTimeout)
|
|
696
|
-
}
|
|
697
|
-
},
|
|
698
|
-
playbarOver() {
|
|
699
|
-
this.hover = true
|
|
700
|
-
this.cancelTimeout()
|
|
701
|
-
this.startTimeout()
|
|
702
|
-
},
|
|
703
|
-
playbarLeave() {
|
|
704
|
-
this.hover = this.cursorDragged ? true : false
|
|
705
|
-
this.volumeLeave()
|
|
706
|
-
if (this.subtitleMenuOpen) {
|
|
707
|
-
this.toggleSubtitleMenu()
|
|
708
|
-
}
|
|
709
|
-
},
|
|
710
|
-
volumeOver() {
|
|
711
|
-
this.volumeSliderOpen = true
|
|
505
|
+
initializeVideoElm() {
|
|
506
|
+
//SeekTooltip
|
|
507
|
+
this.seekTooltip = this.$refs['$seek-tooltip']
|
|
508
|
+
//Transcript
|
|
509
|
+
this.$bus.$on('transcript-hidden', this.resetTranscript)
|
|
510
|
+
this.setTranscript()
|
|
712
511
|
},
|
|
713
|
-
volumeLeave() {
|
|
714
|
-
this.volumeSliderOpen = false
|
|
715
|
-
},
|
|
716
|
-
volumeClick(ev) {
|
|
717
|
-
if (ev.target.id !== 'playbar-volume') {
|
|
718
|
-
return false
|
|
719
|
-
}
|
|
720
512
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
} else {
|
|
745
|
-
this.duration = Number.isNaN(this.media.mElement.duration)
|
|
746
|
-
? '--:--'
|
|
747
|
-
: this.$helper.formatTime(this.media.mElement.duration)
|
|
513
|
+
/** "@description -update the information of the seek tooltip*/
|
|
514
|
+
updateSeekTooltip(evt) {
|
|
515
|
+
//Elm progress Bar
|
|
516
|
+
const progressBar = this.progressBar
|
|
517
|
+
//progressBar position on the page
|
|
518
|
+
const left = progressBar.getBoundingClientRect().left
|
|
519
|
+
//Mouse position versus progressBar
|
|
520
|
+
const hoverPos = evt.clientX - left
|
|
521
|
+
//Get progressBar offsetWidth
|
|
522
|
+
const width = progressBar.offsetWidth
|
|
523
|
+
|
|
524
|
+
//Define the value of the skip tooltip position
|
|
525
|
+
let offsetX = null
|
|
526
|
+
|
|
527
|
+
switch (true) {
|
|
528
|
+
case hoverPos < 15:
|
|
529
|
+
offsetX = 20
|
|
530
|
+
break
|
|
531
|
+
case hoverPos > width - 55:
|
|
532
|
+
offsetX = width - 55
|
|
533
|
+
break
|
|
534
|
+
default:
|
|
535
|
+
offsetX = hoverPos
|
|
748
536
|
}
|
|
749
|
-
},
|
|
750
|
-
updateTimecodeDisplay() {
|
|
751
|
-
this.timecode = this.isAnimation
|
|
752
|
-
? this.$helper.formatTime(this.media.timeline.time())
|
|
753
|
-
: this.$helper.formatTime(this.media.mElement.currentTime)
|
|
754
|
-
},
|
|
755
537
|
|
|
756
|
-
|
|
757
|
-
const currentTime = this.isAnimation
|
|
758
|
-
? this.media.timeline.time()
|
|
759
|
-
: this.media.mElement.currentTime
|
|
760
|
-
const duration = this.isAnimation
|
|
761
|
-
? this.mediaToShow.timeline.totalDuration()
|
|
762
|
-
: this.media.mElement.duration
|
|
763
|
-
const cursorPos = this.getCursorPosFromTime(currentTime, duration)
|
|
764
|
-
this.setCursorPosition(cursorPos)
|
|
765
|
-
},
|
|
766
|
-
setMediaHandlers() {
|
|
767
|
-
if (this.media && (this.media.mElement || this.media.timeline)) {
|
|
768
|
-
//window handlers for playbar progress
|
|
769
|
-
window.addEventListener('mousemove', this.windowMove)
|
|
770
|
-
window.addEventListener('mouseup', this.windowUp)
|
|
771
|
-
window.addEventListener('resize', this.updateCursorPosition)
|
|
772
|
-
window.addEventListener('keydown', this.windowKeydown)
|
|
773
|
-
if (this.isAnimation) {
|
|
774
|
-
this.media.timeline.eventCallback('onUpdate', this.mediaTimeupdate)
|
|
775
|
-
this.media.timeline.eventCallback('onComplete', this.mediaEnded)
|
|
776
|
-
} else {
|
|
777
|
-
this.media.mElement.addEventListener(
|
|
778
|
-
'timeupdate',
|
|
779
|
-
this.mediaTimeupdate
|
|
780
|
-
)
|
|
781
|
-
this.media.mElement.addEventListener('ended', this.mediaEnded)
|
|
782
|
-
/// hide the this.playbar()
|
|
538
|
+
this.seekTooltip.style.left = `${offsetX}px` // update visual position of tooltip
|
|
783
539
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
this.media.mElement.focus()
|
|
791
|
-
//There is a timeline animation link to media set the callback event for timeline
|
|
792
|
-
if (this.media.timeline) {
|
|
793
|
-
this.media.timeline.eventCallback('onUpdate', this.mediaTimeupdate)
|
|
794
|
-
this.media.timeline.eventCallback('onComplete', this.mediaEnded)
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
this.mediaHandlersSet = true
|
|
799
|
-
},
|
|
800
|
-
removeMediaHandlers() {
|
|
801
|
-
if (this.isAnimation || this.media.timeline) {
|
|
802
|
-
this.media.timeline.eventCallback('onUpdate', null)
|
|
803
|
-
this.media.timeline.eventCallback('onComplete', null)
|
|
804
|
-
this.media.timeline.kill()
|
|
805
|
-
}
|
|
806
|
-
if (this.media.mElement) {
|
|
807
|
-
this.media.mElement.removeEventListener(
|
|
808
|
-
'timeupdate',
|
|
809
|
-
this.mediaTimeupdate
|
|
810
|
-
)
|
|
811
|
-
this.media.mElement.removeEventListener('ended', this.mediaEnded)
|
|
540
|
+
//Get % of the cursor hover position/progressBar width
|
|
541
|
+
let percentage = 0
|
|
542
|
+
if (hoverPos > width) percentage = 100
|
|
543
|
+
if (hoverPos < 0) percentage = 0
|
|
544
|
+
else {
|
|
545
|
+
percentage = hoverPos / width
|
|
812
546
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
window.removeEventListener('resize', this.updateCursorPosition)
|
|
817
|
-
window.removeEventListener('keydown', this.windowKeydown)
|
|
818
|
-
|
|
819
|
-
this.mediaHandlersSet = false
|
|
547
|
+
let skipTo = percentage * this.mediaDuration
|
|
548
|
+
//Update the Tooltip time
|
|
549
|
+
this.tooTipTimeCode = this.$helper.formatTime(skipTo)
|
|
820
550
|
},
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
this.
|
|
834
|
-
this.playbarFocus()
|
|
551
|
+
/**
|
|
552
|
+
* @description - handle all the listeners for videos
|
|
553
|
+
*/
|
|
554
|
+
setVideoHandlers() {
|
|
555
|
+
//Tooltip
|
|
556
|
+
this.progressArea.addEventListener('mousemove', this.updateSeekTooltip)
|
|
557
|
+
//Fullscreen
|
|
558
|
+
this.mediaContainer.addEventListener(
|
|
559
|
+
'fullscreenchange',
|
|
560
|
+
this.updateFullScreenState
|
|
561
|
+
)
|
|
562
|
+
//Show controls
|
|
563
|
+
this.mediaContainer.addEventListener('mousemove', this.showControls)
|
|
835
564
|
},
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
565
|
+
/**
|
|
566
|
+
* @description - Unset all the listeners (video)
|
|
567
|
+
*/
|
|
568
|
+
removeVideoHandlers() {
|
|
569
|
+
//Tooltip
|
|
570
|
+
this.progressArea.removeEventListener('mousemove', this.updateSeekTooltip)
|
|
571
|
+
//Fullscreen
|
|
572
|
+
this.mediaContainer.removeEventListener(
|
|
573
|
+
'fullscreenchange',
|
|
574
|
+
this.updateFullScreenState
|
|
575
|
+
)
|
|
576
|
+
//Show controls
|
|
577
|
+
this.mediaContainer.removeEventListener('mousemove', this.showControls)
|
|
843
578
|
},
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
579
|
+
/**
|
|
580
|
+
/* @description - handle the play /pause of the media and the playback video animation
|
|
581
|
+
*/
|
|
582
|
+
handlePlayVideo(type = null) {
|
|
583
|
+
//Play/pause
|
|
584
|
+
this.togglePlay()
|
|
585
|
+
//Playbar animation (show/hide)
|
|
586
|
+
this.isPlaying ? this.hideControls() : this.showControls()
|
|
587
|
+
|
|
588
|
+
//Playback animation (only the first play click)
|
|
589
|
+
if (this.playClicked && !type) {
|
|
590
|
+
this.playBackAnim = false
|
|
591
|
+
return
|
|
852
592
|
}
|
|
593
|
+
//this.runPlaybackAnimation()
|
|
594
|
+
this.playBackAnim = true
|
|
595
|
+
this.playClicked = true
|
|
596
|
+
// Should indicate with media is playing and set it in the store
|
|
853
597
|
},
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
598
|
+
/**
|
|
599
|
+
* @description - Toggle the state of the screen
|
|
600
|
+
* Set or unset the media in full screen
|
|
601
|
+
*/
|
|
602
|
+
toggleFullScreen() {
|
|
603
|
+
const fullscreenElement = this.mediaContainer
|
|
604
|
+
if (document.fullscreenElement) {
|
|
605
|
+
// exitFullscreen is only available on the Document object.
|
|
606
|
+
document.exitFullscreen()
|
|
860
607
|
} else {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
}
|
|
864
|
-
},
|
|
865
|
-
mediaTimeupdate() {
|
|
866
|
-
if (!this.cursorDragged) {
|
|
867
|
-
this.updateCursorPosition()
|
|
608
|
+
//fullscreen is available on Element.
|
|
609
|
+
fullscreenElement.requestFullscreen()
|
|
868
610
|
}
|
|
869
|
-
this.updateTimecodeDisplay()
|
|
870
|
-
this.setMediaA11Y()
|
|
871
611
|
},
|
|
872
|
-
|
|
873
612
|
/**
|
|
874
|
-
* @
|
|
613
|
+
* @description update the value of fulls screen state
|
|
875
614
|
*/
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
this.media.timeline.pause()
|
|
879
|
-
this.media.timeline.paused(true)
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
this.isPlaying = false
|
|
883
|
-
this.canReplay = true
|
|
884
|
-
this.$bus.$emit('mediaPlaybackEnded')
|
|
885
|
-
//save the viewed status in userInteraction
|
|
886
|
-
if (this.isViewed === false) {
|
|
887
|
-
this.setIsViewed()
|
|
888
|
-
}
|
|
889
|
-
},
|
|
890
|
-
windowMove(ev) {
|
|
891
|
-
if (this.cursorDragged) {
|
|
892
|
-
this.setCursorPosition(ev.clientX)
|
|
893
|
-
}
|
|
894
|
-
},
|
|
895
|
-
windowUp(ev) {
|
|
896
|
-
if (this.cursorDragged) {
|
|
897
|
-
this.setCursorDragging(false)
|
|
898
|
-
const timeToSet = this.getTimeFromClickPos(ev)
|
|
899
|
-
this.setMediaTime(timeToSet)
|
|
900
|
-
}
|
|
901
|
-
},
|
|
902
|
-
setCursorDragging(bool) {
|
|
903
|
-
this.cursorDragged = bool
|
|
904
|
-
},
|
|
905
|
-
cursorDown() {
|
|
906
|
-
this.setCursorDragging(true)
|
|
907
|
-
},
|
|
908
|
-
progressOver() {
|
|
909
|
-
this.bufferDomElem.style.opacity = '1'
|
|
910
|
-
},
|
|
911
|
-
progressLeave() {
|
|
912
|
-
this.bufferDomElem.style.opacity = '0'
|
|
913
|
-
},
|
|
914
|
-
progressMove(ev) {
|
|
915
|
-
this.bufferDomElem.style.width = ev.clientX + 'px'
|
|
916
|
-
},
|
|
917
|
-
progressClick(ev) {
|
|
918
|
-
if (!this.cursorDragged) {
|
|
919
|
-
this.bufferDomElem.style.width = ev.clientX + 'px'
|
|
920
|
-
const timeToSet = this.getTimeFromClickPos(ev)
|
|
921
|
-
this.setMediaTime(timeToSet)
|
|
922
|
-
}
|
|
923
|
-
},
|
|
924
|
-
getCursorPosFromTime(currentTime, totalTime) {
|
|
925
|
-
let cursorPosition = 0
|
|
926
|
-
const domElem = this.$refs['playbar-progress']
|
|
927
|
-
const width = domElem.offsetWidth
|
|
928
|
-
const percentageTime = currentTime / totalTime
|
|
929
|
-
cursorPosition = width * percentageTime
|
|
930
|
-
return cursorPosition
|
|
931
|
-
},
|
|
932
|
-
getTimeFromClickPos(ev) {
|
|
933
|
-
let timeToSet = 0
|
|
934
|
-
const domElem = this.$refs['playbar-progress']
|
|
935
|
-
const clickPos = ev.clientX
|
|
936
|
-
const width = domElem.offsetWidth
|
|
937
|
-
const percentage = (clickPos / width) * 100
|
|
938
|
-
if (this.media && (this.media.timeline || this.media.mElement))
|
|
939
|
-
timeToSet = this.isAnimation
|
|
940
|
-
? (this.media.timeline.totalDuration() / 100) * percentage
|
|
941
|
-
: (this.media.mElement.duration / 100) * percentage
|
|
942
|
-
else console.warn('media undefined')
|
|
943
|
-
return Math.floor(timeToSet)
|
|
615
|
+
updateFullScreenState() {
|
|
616
|
+
this.fullscreenOn = !this.fullscreenOn
|
|
944
617
|
},
|
|
945
618
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
this.media.mElement.volume = this.volDefault = this.volumeBtn.value
|
|
950
|
-
this.$store.dispatch('setMediaVolume', this.volumeBtn.value)
|
|
619
|
+
fireFoxMoveCC() {
|
|
620
|
+
if (this.firefoxTrack.activeCues[0]) {
|
|
621
|
+
this.firefoxTrack.activeCues[0].line = 12
|
|
951
622
|
}
|
|
952
623
|
},
|
|
953
|
-
|
|
954
|
-
toggleSubtitleMenu() {
|
|
955
|
-
this.subtitleMenuOpen = !this.subtitleMenuOpen
|
|
956
|
-
},
|
|
957
624
|
/**
|
|
958
|
-
* @description
|
|
959
|
-
* @summary Create a tag with downloadable link and download the element to user PC. remove a element after download
|
|
625
|
+
* @description show the subtitle
|
|
960
626
|
*/
|
|
961
|
-
async downloadTranscript() {
|
|
962
|
-
try {
|
|
963
|
-
const tFile = this.media.mTranscript
|
|
964
|
-
const fileUrl = `./${tFile}`
|
|
965
|
-
let atype = tFile.split('.')[1]
|
|
966
|
-
|
|
967
|
-
const res = await this.axios.get(fileUrl, { responseType: 'blob' })
|
|
968
|
-
const blob = new Blob([res.data], {
|
|
969
|
-
type: this.$helper.mimeTypeFor(atype)
|
|
970
|
-
})
|
|
971
|
-
const alink = document.createElement('a') //create a element
|
|
972
|
-
|
|
973
|
-
alink.href = URL.createObjectURL(blob) //create url reference for the object
|
|
974
|
-
alink.download = `${tFile}` // set download name
|
|
975
|
-
alink.click() //symulate click event to download the object
|
|
976
|
-
URL.revokeObjectURL(alink.href) //release the url referrence of the object
|
|
977
|
-
} catch (err) {
|
|
978
|
-
console.warn(this.$t('err_download_transcript'))
|
|
979
|
-
}
|
|
980
|
-
},
|
|
981
627
|
showSubtitles() {
|
|
982
|
-
this.
|
|
983
|
-
this.subtitlesEnabled = true
|
|
628
|
+
this.mediaElement.textTracks[0].mode = 'showing'
|
|
984
629
|
this.$store.dispatch('setMediaSubtitles', true)
|
|
985
630
|
if (this.getCurrentBrowser == 'Firefox') {
|
|
986
631
|
let video = document.getElementsByTagName('video')[0]
|
|
987
632
|
let tracks = video.textTracks
|
|
988
|
-
|
|
633
|
+
this.firefoxTrack = tracks[0]
|
|
989
634
|
|
|
990
|
-
|
|
991
|
-
if (track.activeCues[0]) {
|
|
992
|
-
track.activeCues[0].line = 12
|
|
993
|
-
}
|
|
994
|
-
})
|
|
635
|
+
this.firefoxTrack.addEventListener('cuechange', this.fireFoxMoveCC)
|
|
995
636
|
}
|
|
996
637
|
},
|
|
638
|
+
|
|
997
639
|
hideSubtitles() {
|
|
998
|
-
this.
|
|
999
|
-
this.subtitlesEnabled = false
|
|
640
|
+
this.mediaElement.textTracks[0].mode = 'hidden' // value can be 'disabled' also.
|
|
1000
641
|
this.$store.dispatch('setMediaSubtitles', false)
|
|
1001
642
|
},
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
this
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
this.hasSubtitle = false
|
|
1027
|
-
}
|
|
1028
|
-
}, // END setMedia
|
|
1029
|
-
|
|
1030
|
-
/** @description - methode to set A11Y support for screen reader on media element (video/audio/animation) */
|
|
1031
|
-
setMediaA11Y() {
|
|
1032
|
-
if (!this.hasMedia) return
|
|
1033
|
-
|
|
1034
|
-
const w = this.$i18n.locale === 'en' ? 'at' : 'à'
|
|
1035
|
-
const dm =
|
|
1036
|
-
this.$i18n.locale === 'en'
|
|
1037
|
-
? `${this.media.mType} duration`
|
|
1038
|
-
: `durée ${this.media.mType}`
|
|
1039
|
-
|
|
1040
|
-
this.mediaA11Y.valMax = this.isAnimation
|
|
1041
|
-
? Math.round(this.media.timeline.totalDuration())
|
|
1042
|
-
: Math.round(this.media.mElement.duration) // media duration in floating-point
|
|
1043
|
-
|
|
1044
|
-
//get media Current time
|
|
1045
|
-
this.mediaA11Y.valNow = this.isAnimation
|
|
1046
|
-
? Math.round(this.media.timeline.time())
|
|
1047
|
-
: Math.round(this.media.mElement.currentTime)
|
|
1048
|
-
|
|
1049
|
-
//format text output for screen reader
|
|
1050
|
-
let currentTime = this.timecode.split(':')
|
|
1051
|
-
let fullTime = this.duration.split(':')
|
|
1052
|
-
let hrsTxt, mnTxt, ssTxt, HRSTxt, MNTxt, SSTxt, fTimeTxt, cTimeTxt
|
|
1053
|
-
|
|
1054
|
-
const mediaTitle = this.media.mTitle || this.media.mType
|
|
1055
|
-
|
|
1056
|
-
this.mediaA11Y.label = this.$t('a11y_sr.seek_slider')
|
|
1057
|
-
|
|
1058
|
-
//format string to remove leading 0 digit for time
|
|
1059
|
-
const formatNum = (n) => {
|
|
1060
|
-
return n[0] == '0' ? n.substring(1).trim() : n.trim()
|
|
643
|
+
toggleViewSubtitle() {
|
|
644
|
+
if (this.subtitlesEnabled) return this.hideSubtitles()
|
|
645
|
+
if (!this.subtitlesEnabled) return this.showSubtitles()
|
|
646
|
+
},
|
|
647
|
+
/**
|
|
648
|
+
* @description method to show or hide the transcipt.
|
|
649
|
+
* @summary get toggle the value of transcriptEnabled and get content from the transcript file
|
|
650
|
+
* and transfer it to Module for display.
|
|
651
|
+
* @fires 'open-sidebar' to AppBaseModule
|
|
652
|
+
* @fires 'close-sidebar' to AppBaseModule
|
|
653
|
+
*/
|
|
654
|
+
toggleViewTranscript() {
|
|
655
|
+
this.transcriptEnabled = !this.transcriptEnabled
|
|
656
|
+
|
|
657
|
+
if (this.transcriptEnabled && this.transcriptToShow) {
|
|
658
|
+
//this.$bus.$emit('resize-media', 'sm')
|
|
659
|
+
//Resize video container
|
|
660
|
+
this.$emit('resize-video', 'sm')
|
|
661
|
+
//Open sidebar with the transcript
|
|
662
|
+
return this.$bus.$emit('open-sidebar', {
|
|
663
|
+
ctx: 'ctxTranscript',
|
|
664
|
+
e: this.transcriptToShow,
|
|
665
|
+
w: this.pbContainer
|
|
666
|
+
})
|
|
1061
667
|
}
|
|
1062
668
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
669
|
+
// Send close signal for the side bar when transcipt state is not enabled
|
|
670
|
+
if (!this.transcriptEnabled) {
|
|
671
|
+
//this.$bus.$emit('resize-media', 'lg')
|
|
672
|
+
//Resize video container
|
|
673
|
+
this.$emit('resize-video', 'lg')
|
|
674
|
+
//Open sidebar with the transcript
|
|
675
|
+
return this.$bus.$emit('close-sidebar', 'ctxTranscript')
|
|
1069
676
|
}
|
|
677
|
+
},
|
|
678
|
+
/**
|
|
679
|
+
* @description Fetching method for transcript
|
|
680
|
+
* @summary Fetch a transcript from HTML file to display. File URL is defined in the media data
|
|
681
|
+
* and return its content for display
|
|
682
|
+
* @return {String} HTML string
|
|
683
|
+
*/
|
|
684
|
+
async fetchTranscript() {
|
|
685
|
+
try {
|
|
686
|
+
// const tFile = 'exemple_transcript2.html'
|
|
687
|
+
const { mTranscript } = this.mediaToPlay
|
|
688
|
+
const tFile = mTranscript
|
|
1070
689
|
|
|
1071
|
-
|
|
1072
|
-
case 3:
|
|
1073
|
-
if (!currentTime.length) return
|
|
1074
|
-
|
|
1075
|
-
//format current hours text text with plurialization apply
|
|
1076
|
-
hrsTxt =
|
|
1077
|
-
currentTime.length == 3 && parseInt(currentTime[0]) > 0
|
|
1078
|
-
? `${formatNum(currentTime[0])} ${this.$tc(
|
|
1079
|
-
'a11y_sr.time.hours',
|
|
1080
|
-
formatNum(currentTime[0])
|
|
1081
|
-
)}`
|
|
1082
|
-
: ''
|
|
1083
|
-
|
|
1084
|
-
//format minutes text text with plurialization apply
|
|
1085
|
-
mnTxt =
|
|
1086
|
-
parseInt(currentTime[1]) > 0
|
|
1087
|
-
? `${formatNum(currentTime[1])} ${this.$tc(
|
|
1088
|
-
'a11y_sr.time.minute',
|
|
1089
|
-
formatNum(currentTime[1])
|
|
1090
|
-
)}`
|
|
1091
|
-
: ''
|
|
1092
|
-
|
|
1093
|
-
//format seconds text with plurialization apply
|
|
1094
|
-
ssTxt =
|
|
1095
|
-
parseInt(currentTime[2]) > 0
|
|
1096
|
-
? `${formatNum(currentTime[2])} ${this.$tc(
|
|
1097
|
-
'a11y_sr.time.second',
|
|
1098
|
-
formatNum(currentTime[2])
|
|
1099
|
-
)}`
|
|
1100
|
-
: `0 ${this.$tc('a11y_sr.time.second')}`
|
|
1101
|
-
|
|
1102
|
-
HRSTxt =
|
|
1103
|
-
parseInt(fullTime[0]) > 0
|
|
1104
|
-
? `${formatNum(fullTime[0])} ${this.$tc(
|
|
1105
|
-
'a11y_sr.time.hours',
|
|
1106
|
-
formatNum(fullTime[0])
|
|
1107
|
-
)}`
|
|
1108
|
-
: ''
|
|
1109
|
-
|
|
1110
|
-
MNTxt =
|
|
1111
|
-
parseInt(fullTime[1]) > 0
|
|
1112
|
-
? `${formatNum(fullTime[1])} ${this.$tc(
|
|
1113
|
-
'a11y_sr.time.minute',
|
|
1114
|
-
formatNum(fullTime[1])
|
|
1115
|
-
)}`
|
|
1116
|
-
: ''
|
|
1117
|
-
|
|
1118
|
-
SSTxt =
|
|
1119
|
-
parseInt(fullTime[2]) > 0
|
|
1120
|
-
? `${formatNum(fullTime[2])} ${this.$tc(
|
|
1121
|
-
'a11y_sr.time.second',
|
|
1122
|
-
formatNum(fullTime[2])
|
|
1123
|
-
)}`
|
|
1124
|
-
: ''
|
|
1125
|
-
|
|
1126
|
-
cTimeTxt = `${hrsTxt} ${mnTxt} ${ssTxt}`
|
|
1127
|
-
fTimeTxt = `${HRSTxt} ${MNTxt} ${SSTxt}`
|
|
690
|
+
if (!tFile) throw new Error('Missing transcript File!')
|
|
1128
691
|
|
|
1129
|
-
|
|
1130
|
-
|
|
692
|
+
// validate file types. Only .html are allowed
|
|
693
|
+
if (!tFile.endsWith('.html'))
|
|
694
|
+
throw new Error(
|
|
695
|
+
'Invalid valid transcript file. \n Expecting .html file'
|
|
696
|
+
)
|
|
1131
697
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
this.mediaA11Y.valueText = `${mediaTitle} ${formatMsg(
|
|
1136
|
-
cTimeTxt,
|
|
1137
|
-
fTimeTxt
|
|
1138
|
-
)}`
|
|
698
|
+
const fileUrl = `./${tFile}`
|
|
699
|
+
const res = await this.axios.get(fileUrl, { responseType: 'blob' })
|
|
700
|
+
const content = await res.data.text()
|
|
1139
701
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
702
|
+
return content
|
|
703
|
+
} catch (err) {
|
|
704
|
+
console.warn("YOU'VE GOT AN ERROR!\n", err)
|
|
705
|
+
}
|
|
706
|
+
},
|
|
707
|
+
/** ******************* Rendering Methods****************************** */
|
|
1143
708
|
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
formatNum(currentTime[0])
|
|
1150
|
-
)}`
|
|
1151
|
-
: ''
|
|
1152
|
-
ssTxt =
|
|
1153
|
-
parseInt(currentTime[1]) > 0
|
|
1154
|
-
? `${formatNum(currentTime[1])} ${this.$tc(
|
|
1155
|
-
'a11y_sr.time.second',
|
|
1156
|
-
formatNum(currentTime[1])
|
|
1157
|
-
)}`
|
|
1158
|
-
: `0 ${this.$tc('a11y_sr.time.second')}`
|
|
709
|
+
/**
|
|
710
|
+
* @Description Method to set the transcription that need to be displayed
|
|
711
|
+
*/
|
|
712
|
+
async setTranscript() {
|
|
713
|
+
if (!this.hasTranscript) return (this.transcriptToShow = null)
|
|
1159
714
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
parseInt(fullTime[0]) > 0
|
|
1163
|
-
? `${formatNum(fullTime[0])} ${this.$tc(
|
|
1164
|
-
'a11y_sr.time.minute',
|
|
1165
|
-
formatNum(fullTime[0])
|
|
1166
|
-
)}`
|
|
1167
|
-
: ''
|
|
1168
|
-
SSTxt =
|
|
1169
|
-
parseInt(fullTime[1]) > 0
|
|
1170
|
-
? `${formatNum(fullTime[1])} ${this.$tc(
|
|
1171
|
-
'a11y_sr.time.second',
|
|
1172
|
-
formatNum(fullTime[1])
|
|
1173
|
-
)}`
|
|
1174
|
-
: ''
|
|
715
|
+
this.transcriptToShow = await this.fetchTranscript()
|
|
716
|
+
},
|
|
1175
717
|
|
|
1176
|
-
|
|
1177
|
-
|
|
718
|
+
/**
|
|
719
|
+
* @description Method to reset the transcript state
|
|
720
|
+
*/
|
|
721
|
+
resetTranscript(content) {
|
|
722
|
+
this.transcriptEnabled = false
|
|
723
|
+
},
|
|
1178
724
|
|
|
1179
|
-
|
|
1180
|
-
|
|
725
|
+
/**
|
|
726
|
+
* @description Show the media controler */
|
|
727
|
+
showControls() {
|
|
728
|
+
this.showControlsValue = true
|
|
729
|
+
if (this.hideTimer) clearTimeout(this.hideTimer) //cancel existing timer
|
|
1181
730
|
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
731
|
+
this.hideControls()
|
|
732
|
+
},
|
|
733
|
+
/**
|
|
734
|
+
* @description Hide the media after the video start playing
|
|
735
|
+
*/
|
|
1185
736
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
fTimeTxt
|
|
1189
|
-
)}`
|
|
737
|
+
hideControls() {
|
|
738
|
+
if (this.mediaElement.paused) return
|
|
1190
739
|
|
|
1191
|
-
|
|
1192
|
-
|
|
740
|
+
this.hideTimer = setTimeout(() => {
|
|
741
|
+
this.showControlsValue = false
|
|
742
|
+
}, this.delayUntilHide)
|
|
1193
743
|
}
|
|
1194
744
|
}
|
|
1195
745
|
}
|
|
1196
746
|
</script>
|
|
1197
|
-
<style lang="scss">
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
#
|
|
747
|
+
<style lang="scss" scoped>
|
|
748
|
+
.pb-container {
|
|
749
|
+
//colors
|
|
750
|
+
--primary100: #deeff8;
|
|
751
|
+
--primary600: #006fab;
|
|
752
|
+
--primary700: #005c8d;
|
|
753
|
+
--primary800: #004870;
|
|
754
|
+
--primary900: #003552;
|
|
755
|
+
}
|
|
756
|
+
.pb-container.video {
|
|
757
|
+
position: absolute;
|
|
758
|
+
height: 100%;
|
|
1202
759
|
width: 100%;
|
|
760
|
+
justify-content: center;
|
|
761
|
+
display: flex;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
.playback-button {
|
|
1203
765
|
position: absolute;
|
|
766
|
+
top: 0;
|
|
1204
767
|
left: 0;
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
768
|
+
width: 100%;
|
|
769
|
+
height: 100%;
|
|
770
|
+
display: flex;
|
|
771
|
+
flex-flow: column wrap;
|
|
772
|
+
justify-content: center;
|
|
773
|
+
align-items: center;
|
|
774
|
+
background-color: transparent;
|
|
775
|
+
.playback-wrapper {
|
|
776
|
+
height: 64px;
|
|
777
|
+
width: 64px;
|
|
778
|
+
display: flex;
|
|
779
|
+
justify-content: center;
|
|
780
|
+
align-items: center;
|
|
781
|
+
background-color: var(--primary700);
|
|
782
|
+
border-radius: 50%;
|
|
783
|
+
&:hover {
|
|
784
|
+
background-color: var(--primary600);
|
|
785
|
+
}
|
|
786
|
+
svg {
|
|
787
|
+
fill: var(--primary100);
|
|
788
|
+
height: 32px;
|
|
789
|
+
width: 26.29px;
|
|
790
|
+
&.play-icon {
|
|
791
|
+
margin-left: 11%;
|
|
1224
792
|
}
|
|
1225
793
|
}
|
|
1226
794
|
}
|
|
795
|
+
}
|
|
796
|
+
//Wrapper
|
|
797
|
+
.pb-wrapper {
|
|
798
|
+
width: 100%;
|
|
799
|
+
display: flex;
|
|
800
|
+
flex-direction: column;
|
|
801
|
+
position: absolute;
|
|
802
|
+
bottom: 0;
|
|
803
|
+
opacity: 0;
|
|
804
|
+
z-index: 2;
|
|
805
|
+
background-color: var(--primary100);
|
|
806
|
+
&.show-controls {
|
|
807
|
+
opacity: 1;
|
|
808
|
+
transition: opacity 0.35s ease-in-out;
|
|
809
|
+
}
|
|
1227
810
|
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
811
|
+
//Wrapper timeline
|
|
812
|
+
.pb-timeline {
|
|
813
|
+
--progress-bar-height: 6px;
|
|
814
|
+
position: relative;
|
|
815
|
+
width: 100%;
|
|
816
|
+
height: var(--progress-bar-height);
|
|
817
|
+
.progress-area {
|
|
818
|
+
width: 100%;
|
|
819
|
+
height: 400%; //Add contact surface of click on progressBar
|
|
820
|
+
position: relative;
|
|
821
|
+
top: -150%;
|
|
1236
822
|
display: flex;
|
|
1237
|
-
|
|
1238
|
-
justify-content: space-around;
|
|
823
|
+
cursor: pointer;
|
|
1239
824
|
align-items: center;
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
825
|
+
z-index: 8; //z-index on top of the video elm
|
|
826
|
+
&:hover {
|
|
827
|
+
.seek-tooltip {
|
|
828
|
+
opacity: 1;
|
|
829
|
+
}
|
|
1244
830
|
}
|
|
1245
831
|
|
|
1246
|
-
|
|
832
|
+
//Progress bar
|
|
833
|
+
.pb-progress-bar {
|
|
834
|
+
--progress-bar-border-height: 1px;
|
|
1247
835
|
cursor: pointer;
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
836
|
+
width: 100%;
|
|
837
|
+
height: var(--progress-bar-height);
|
|
838
|
+
background-color: transparent;
|
|
839
|
+
border: var(--progress-bar-border-height) var(--primary700) solid;
|
|
840
|
+
overflow: visible;
|
|
841
|
+
&:focus {
|
|
842
|
+
.progress-thumb {
|
|
843
|
+
}
|
|
1256
844
|
}
|
|
845
|
+
}
|
|
1257
846
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
var(--min),
|
|
1282
|
-
var(--value, 0),
|
|
1283
|
-
var(--max)
|
|
1284
|
-
); // default value ("--value" is used in single-range markup)
|
|
1285
|
-
--value-b: var(--value, 0); // default value
|
|
1286
|
-
|
|
1287
|
-
--completed-a: calc(
|
|
1288
|
-
(var(--value-a) - var(--min)) / (var(--max) - var(--min)) *
|
|
1289
|
-
100
|
|
1290
|
-
);
|
|
1291
|
-
--completed-b: calc(
|
|
1292
|
-
(var(--value-b) - var(--min)) / (var(--max) - var(--min)) *
|
|
1293
|
-
100
|
|
1294
|
-
);
|
|
1295
|
-
--ca: Min(var(--completed-a), var(--completed-b));
|
|
1296
|
-
--cb: Max(var(--completed-a), var(--completed-b));
|
|
1297
|
-
|
|
1298
|
-
// breakdown of the below super-complex brain-breaking CSS math:
|
|
1299
|
-
// "clamp" is used to ensure either "-1" or "1"
|
|
1300
|
-
// "calc" is used to inflat the outcome into a huge number, to get rid of any value between -1 & 1
|
|
1301
|
-
// if absolute diff of both completed % is above "5" (%)
|
|
1302
|
-
// ".001" bumps the value just a bit, to avoid a scenario where calc resulted in "0" (then clamp will also be "0")
|
|
1303
|
-
--thumbs-too-close: Clamp(
|
|
1304
|
-
-1,
|
|
1305
|
-
1000 * (Min(1, Max(var(--cb) - var(--ca) - 5, -1)) + 0.001),
|
|
1306
|
-
1
|
|
1307
|
-
);
|
|
1308
|
-
--thumb-close-to-min: Min(
|
|
1309
|
-
1,
|
|
1310
|
-
Max(var(--ca) - 2, 0)
|
|
1311
|
-
); // 2% threshold
|
|
1312
|
-
--thumb-close-to-max: Min(
|
|
1313
|
-
1,
|
|
1314
|
-
Max(98 - var(--cb), 0)
|
|
1315
|
-
); // 2% threshold
|
|
1316
|
-
|
|
1317
|
-
@mixin thumb {
|
|
1318
|
-
appearance: none;
|
|
1319
|
-
height: var(--thumb-size);
|
|
1320
|
-
width: var(--thumb-size);
|
|
1321
|
-
pointer-events: auto;
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
display: inline-block;
|
|
1325
|
-
height: Max(var(--track-height), var(--thumb-size));
|
|
1326
|
-
position: absolute;
|
|
1327
|
-
z-index: 1;
|
|
1328
|
-
top: 40px;
|
|
1329
|
-
left: -32px;
|
|
1330
|
-
z-index: 1;
|
|
1331
|
-
width: 95px;
|
|
1332
|
-
transform: rotate(270deg);
|
|
1333
|
-
|
|
1334
|
-
&__progress {
|
|
1335
|
-
--start-end: calc(var(--thumb-size) / 2);
|
|
1336
|
-
--clip-end: calc(100% - (var(--cb)) * 1%);
|
|
1337
|
-
--clip-start: calc(var(--ca) * 1%);
|
|
1338
|
-
--clip: inset(-20px var(--clip-end) -20px var(--clip-start));
|
|
1339
|
-
position: absolute;
|
|
1340
|
-
left: var(--start-end);
|
|
1341
|
-
right: var(--start-end);
|
|
1342
|
-
top: calc(var(--thumb-size) / 2 - var(--track-height) / 2);
|
|
1343
|
-
height: calc(var(--track-height));
|
|
1344
|
-
background: var(--progress-background, #eee);
|
|
1345
|
-
border: 2px solid;
|
|
1346
|
-
pointer-events: none;
|
|
1347
|
-
z-index: -1;
|
|
1348
|
-
border-radius: var(--progress-radius);
|
|
1349
|
-
|
|
1350
|
-
// fill area
|
|
1351
|
-
&::before {
|
|
1352
|
-
content: '';
|
|
1353
|
-
position: absolute;
|
|
1354
|
-
left: 0;
|
|
1355
|
-
right: 0;
|
|
1356
|
-
clip-path: var(--clip);
|
|
1357
|
-
top: 0;
|
|
1358
|
-
bottom: 0;
|
|
1359
|
-
z-index: 1;
|
|
1360
|
-
border-radius: inherit;
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
|
-
// shadow-effect
|
|
1364
|
-
&::after {
|
|
1365
|
-
content: '';
|
|
1366
|
-
position: absolute;
|
|
1367
|
-
top: 0;
|
|
1368
|
-
right: 0;
|
|
1369
|
-
bottom: 0;
|
|
1370
|
-
left: 0;
|
|
1371
|
-
pointer-events: none;
|
|
1372
|
-
border-radius: inherit;
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
|
-
& > input {
|
|
1377
|
-
-webkit-appearance: none;
|
|
1378
|
-
width: 100%;
|
|
1379
|
-
height: var(--thumb-size);
|
|
1380
|
-
margin: 0;
|
|
1381
|
-
position: absolute;
|
|
1382
|
-
left: 0;
|
|
1383
|
-
cursor: -webkit-grab;
|
|
1384
|
-
cursor: grab;
|
|
1385
|
-
outline: none;
|
|
1386
|
-
background: none;
|
|
1387
|
-
|
|
1388
|
-
&:not(:only-of-type) {
|
|
1389
|
-
pointer-events: none;
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
&::-webkit-slider-thumb {
|
|
1393
|
-
@include thumb;
|
|
1394
|
-
}
|
|
1395
|
-
&::-moz-range-thumb {
|
|
1396
|
-
@include thumb;
|
|
1397
|
-
}
|
|
1398
|
-
&::-ms-thumb {
|
|
1399
|
-
@include thumb;
|
|
1400
|
-
}
|
|
847
|
+
.progress-indicator {
|
|
848
|
+
width: 0;
|
|
849
|
+
height: 100%;
|
|
850
|
+
position: relative;
|
|
851
|
+
user-select: none;
|
|
852
|
+
//colors
|
|
853
|
+
background-color: var(--primary700);
|
|
854
|
+
&.progress-animation {
|
|
855
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
856
|
+
transition-duration: 0.01s;
|
|
857
|
+
transition-property: all;
|
|
858
|
+
transition: width 0.1s linear;
|
|
859
|
+
//colors
|
|
860
|
+
background-color: var(--primary700);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
//Custom thumb
|
|
864
|
+
.progress-thumb {
|
|
865
|
+
//Cliquable thumb
|
|
866
|
+
--progress-thumb-size: 30px;
|
|
867
|
+
width: var(--progress-thumb-size);
|
|
868
|
+
height: var(--progress-thumb-size);
|
|
869
|
+
position: absolute;
|
|
1401
870
|
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
871
|
+
right: calc(var(--progress-thumb-size) / -2);
|
|
872
|
+
top: calc(
|
|
873
|
+
-1 * (
|
|
874
|
+
var(--progress-thumb-size) / 2 - var(--progress-bar-height) / 2
|
|
875
|
+
) - var(--progress-bar-border-height) / 2
|
|
876
|
+
);
|
|
877
|
+
display: flex;
|
|
878
|
+
align-items: center;
|
|
879
|
+
justify-content: center;
|
|
880
|
+
&::after {
|
|
881
|
+
content: '';
|
|
882
|
+
//Visible thumb
|
|
883
|
+
height: 16px;
|
|
884
|
+
width: 16px;
|
|
885
|
+
//Colors and styling
|
|
886
|
+
border-radius: 50%;
|
|
887
|
+
background-color: var(--primary700);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
1406
890
|
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
& + output {
|
|
1414
|
-
&:not(:only-of-type) {
|
|
1415
|
-
--flip: calc(var(--thumbs-too-close) * -1);
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
891
|
+
&:hover {
|
|
892
|
+
.seek-tooltip {
|
|
893
|
+
//tooltip visible only when hovering progress-area
|
|
894
|
+
opacity: 1;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
1419
897
|
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
898
|
+
.seek-tooltip {
|
|
899
|
+
position: absolute;
|
|
900
|
+
top: -30px;
|
|
901
|
+
opacity: 0;
|
|
902
|
+
user-select: none;
|
|
903
|
+
//Colors
|
|
904
|
+
background-color: var(--primary100);
|
|
905
|
+
color: var(--primary700);
|
|
906
|
+
border-radius: 1px;
|
|
907
|
+
padding: 2px;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
1430
911
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
912
|
+
//Controls
|
|
913
|
+
.pb-controls {
|
|
914
|
+
padding: 12px 32px;
|
|
915
|
+
@media screen and (max-width: 800px) {
|
|
916
|
+
padding: 12px 12px;
|
|
917
|
+
}
|
|
918
|
+
width: 100%;
|
|
919
|
+
//height: 76px;
|
|
920
|
+
height: auto;
|
|
921
|
+
display: flex;
|
|
922
|
+
flex-flow: row wrap;
|
|
923
|
+
justify-content: space-between;
|
|
924
|
+
-webkit-justify-content: space-between;
|
|
925
|
+
align-items: center;
|
|
926
|
+
|
|
927
|
+
.pb-areas {
|
|
928
|
+
display: flex;
|
|
929
|
+
flex-flow: row nowrap;
|
|
930
|
+
justify-content: center;
|
|
931
|
+
align-items: center;
|
|
1437
932
|
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
--x-offset: calc(var(--completed-b) * -1%);
|
|
1441
|
-
--pos: calc(
|
|
1442
|
-
((var(--value) - var(--min)) / (var(--max) - var(--min))) *
|
|
1443
|
-
68%
|
|
1444
|
-
);
|
|
933
|
+
button {
|
|
934
|
+
position: relative;
|
|
1445
935
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
936
|
+
&::before {
|
|
937
|
+
content: attr(data-title);
|
|
938
|
+
position: absolute;
|
|
939
|
+
top: -50px;
|
|
940
|
+
right: 0;
|
|
941
|
+
margin-left: -35px;
|
|
942
|
+
word-break: keep-all;
|
|
943
|
+
white-space: pre;
|
|
944
|
+
display: none;
|
|
945
|
+
opacity: 0;
|
|
946
|
+
width: fit-content;
|
|
947
|
+
//user-select:none;
|
|
948
|
+
//Colors and styling
|
|
949
|
+
background-color: var(--primary100);
|
|
950
|
+
color: var(--primary700);
|
|
951
|
+
border-radius: 1px;
|
|
952
|
+
padding: 2px;
|
|
953
|
+
}
|
|
954
|
+
//Icons btn specific
|
|
955
|
+
&.playbar-btn {
|
|
956
|
+
&::before {
|
|
957
|
+
left: 0 !important;
|
|
958
|
+
margin-left: 0 !important;
|
|
959
|
+
}
|
|
960
|
+
margin-right: 16px;
|
|
961
|
+
//Style
|
|
962
|
+
border-radius: 50%;
|
|
963
|
+
background-color: var(--primary700);
|
|
964
|
+
//Style
|
|
965
|
+
&:hover {
|
|
966
|
+
background-color: var(--primary600);
|
|
967
|
+
}
|
|
968
|
+
@media screen and (max-width: 800px) {
|
|
969
|
+
height: 32px;
|
|
970
|
+
width: 32px;
|
|
971
|
+
}
|
|
972
|
+
svg {
|
|
973
|
+
//Style
|
|
974
|
+
fill: var(--primary100);
|
|
975
|
+
}
|
|
976
|
+
svg.play-icon {
|
|
977
|
+
margin-left: 11.875%; // 11.8% off center on the design
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
&.volume-btn {
|
|
981
|
+
svg.volume-low-icon {
|
|
982
|
+
height: 17.75px;
|
|
1468
983
|
}
|
|
1469
984
|
}
|
|
1470
985
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
padding: 4px;
|
|
986
|
+
//Manage displayLabel (dynamic class)
|
|
987
|
+
button.displayLabel {
|
|
988
|
+
&:hover,
|
|
989
|
+
&:focus {
|
|
990
|
+
&::before {
|
|
991
|
+
display: block;
|
|
992
|
+
opacity: 1;
|
|
993
|
+
}
|
|
1480
994
|
}
|
|
1481
|
-
|
|
1482
|
-
position: absolute;
|
|
1483
|
-
width: 294px;
|
|
1484
|
-
|
|
1485
|
-
.subtitleBtns {
|
|
1486
|
-
width: 100%;
|
|
1487
|
-
height: 40px;
|
|
1488
|
-
padding: 0 24px;
|
|
1489
|
-
line-height: 40px;
|
|
1490
|
-
border: none;
|
|
1491
|
-
text-align: left;
|
|
995
|
+
}
|
|
1492
996
|
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
997
|
+
.pb-timer {
|
|
998
|
+
width: max-content;
|
|
999
|
+
span {
|
|
1000
|
+
//colors
|
|
1001
|
+
color: var(--primary700);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
//Volume
|
|
1005
|
+
.volume-controls {
|
|
1006
|
+
--volumecontrols-height: 22px;
|
|
1007
|
+
--volume-thumb-size: 16px;
|
|
1008
|
+
display: flex;
|
|
1009
|
+
flex-flow: row wrap;
|
|
1010
|
+
justify-content: center;
|
|
1011
|
+
position: relative;
|
|
1012
|
+
height: var(--volumecontrols-height);
|
|
1013
|
+
&:hover {
|
|
1014
|
+
//button title //DisplayLabel is a dynamic class
|
|
1015
|
+
.volume-slider.displayLabel + span {
|
|
1016
|
+
display: block;
|
|
1017
|
+
opacity: 1;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
.volume-slider {
|
|
1021
|
+
-webkit-appearance: none;
|
|
1022
|
+
width: 100px;
|
|
1023
|
+
//Responsive
|
|
1024
|
+
@media screen and (max-width: 800px) {
|
|
1025
|
+
width: 80px;
|
|
1026
|
+
}
|
|
1027
|
+
border-radius: 24px;
|
|
1028
|
+
cursor: pointer;
|
|
1029
|
+
position: relative;
|
|
1030
|
+
z-index: 2;
|
|
1031
|
+
&::-webkit-slider-runnable-track {
|
|
1032
|
+
background: transparent;
|
|
1033
|
+
}
|
|
1034
|
+
//Input slider thumb
|
|
1035
|
+
@mixin volume-thumb {
|
|
1036
|
+
-webkit-appearance: none;
|
|
1037
|
+
width: var(--volume-thumb-size);
|
|
1038
|
+
height: var(--volume-thumb-size);
|
|
1039
|
+
border-radius: 50%;
|
|
1040
|
+
position: relative;
|
|
1041
|
+
cursor: pointer;
|
|
1042
|
+
}
|
|
1043
|
+
&::-webkit-slider-thumb {
|
|
1044
|
+
@include volume-thumb;
|
|
1045
|
+
}
|
|
1046
|
+
//button title
|
|
1047
|
+
& + span {
|
|
1048
|
+
position: absolute;
|
|
1049
|
+
top: -62px;
|
|
1050
|
+
right: 0;
|
|
1051
|
+
margin-left: -35px;
|
|
1052
|
+
word-break: keep-all;
|
|
1053
|
+
white-space: pre;
|
|
1054
|
+
display: none;
|
|
1055
|
+
opacity: 0;
|
|
1056
|
+
user-select: none;
|
|
1057
|
+
//Colors
|
|
1058
|
+
background-color: var(--primary100);
|
|
1059
|
+
color: var(--primary700);
|
|
1060
|
+
border-radius: 1px;
|
|
1061
|
+
padding: 2px;
|
|
1062
|
+
}
|
|
1063
|
+
//DisplayLabel is a dynamic class
|
|
1064
|
+
&.displayLabel:focus {
|
|
1065
|
+
& + span {
|
|
1066
|
+
display: block;
|
|
1067
|
+
opacity: 1;
|
|
1497
1068
|
}
|
|
1498
1069
|
}
|
|
1499
1070
|
}
|
|
1071
|
+
|
|
1072
|
+
.volume-progress {
|
|
1073
|
+
--volumeIndicator-height: 9px;
|
|
1074
|
+
height: var(--volumeIndicator-height);
|
|
1075
|
+
top: calc(
|
|
1076
|
+
var(--volumecontrols-height) / 2 - var(--volumeIndicator-height) / 2
|
|
1077
|
+
); //centrer en hauteur
|
|
1078
|
+
width: calc(
|
|
1079
|
+
100% - var(--volume-thumb-size) / 2
|
|
1080
|
+
); //Width smaller than the range width to be sure the progress width don't exceed the range width
|
|
1081
|
+
position: absolute;
|
|
1082
|
+
border-radius: 20px;
|
|
1083
|
+
background-repeat: no-repeat;
|
|
1084
|
+
background-size: var(--background-size-vs, 0%) 100%; //Js dynamic variable
|
|
1085
|
+
//colors
|
|
1086
|
+
border: 2px solid var(--primary700);
|
|
1087
|
+
background-image: linear-gradient(
|
|
1088
|
+
var(--primary700),
|
|
1089
|
+
var(--primary700)
|
|
1090
|
+
);
|
|
1091
|
+
background-image: -moz-linear-gradient(
|
|
1092
|
+
var(--primary700),
|
|
1093
|
+
var(--primary700)
|
|
1094
|
+
);
|
|
1095
|
+
background-image: -webkit-linear-gradient(
|
|
1096
|
+
var(--primary700),
|
|
1097
|
+
var(--primary700)
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1500
1100
|
}
|
|
1501
1101
|
}
|
|
1502
1102
|
}
|
|
1503
1103
|
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1104
|
+
svg {
|
|
1105
|
+
//width: 19px;
|
|
1106
|
+
//height: 19px;
|
|
1107
|
+
//colors
|
|
1108
|
+
//stroke: var(--primary700);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
button {
|
|
1112
|
+
height: 48px;
|
|
1113
|
+
width: 48px;
|
|
1114
|
+
background-color: transparent;
|
|
1115
|
+
fill: var(--primary700);
|
|
1116
|
+
padding: 0;
|
|
1117
|
+
display: flex;
|
|
1118
|
+
justify-content: center;
|
|
1119
|
+
align-items: center;
|
|
1120
|
+
svg {
|
|
1121
|
+
height: 24px;
|
|
1122
|
+
@media screen and (max-width: 800px) {
|
|
1123
|
+
height: 18px;
|
|
1124
|
+
}
|
|
1515
1125
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1126
|
+
&:hover,
|
|
1127
|
+
&:focus,
|
|
1128
|
+
&:target {
|
|
1129
|
+
fill: var(--primary100);
|
|
1130
|
+
}
|
|
1131
|
+
&:hover {
|
|
1132
|
+
background-color: var(--primary600);
|
|
1133
|
+
}
|
|
1134
|
+
&:focus {
|
|
1135
|
+
background-color: var(--primary600);
|
|
1136
|
+
outline: 1px solid var(--primary600);
|
|
1137
|
+
outline-offset: 2px;
|
|
1138
|
+
}
|
|
1139
|
+
&:target {
|
|
1140
|
+
background-color: var(--primary800);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
//Colors for volume-slider (thumb and background)
|
|
1146
|
+
|
|
1147
|
+
.volume-slider {
|
|
1148
|
+
--primary100: #deeff8;
|
|
1149
|
+
--primary700: #005c8d;
|
|
1150
|
+
--primary900: #003552;
|
|
1151
|
+
background: transparent;
|
|
1152
|
+
&::-webkit-slider-thumb {
|
|
1153
|
+
border: solid var(--primary700) 1px;
|
|
1154
|
+
background: var(--primary700);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
&::-moz-range-thumb {
|
|
1158
|
+
border: solid var(--primary700) 1px;
|
|
1159
|
+
background: var(--primary700);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
//CSS for audio only
|
|
1163
|
+
.audio.pb-wrapper {
|
|
1164
|
+
border-radius: 4px;
|
|
1165
|
+
position: initial;
|
|
1166
|
+
.pb-controls {
|
|
1167
|
+
padding: 8px 16px;
|
|
1168
|
+
.volume-controls {
|
|
1169
|
+
margin-left: 8px;
|
|
1170
|
+
width: 100%;
|
|
1171
|
+
--volume-thumb-size: 12px;
|
|
1172
|
+
.volume-slider {
|
|
1173
|
+
width: 50px;
|
|
1174
|
+
}
|
|
1175
|
+
.volume-progress {
|
|
1176
|
+
--volumeIndicator-height: 6px;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
.pb-timer {
|
|
1181
|
+
margin-right: 20px;
|
|
1182
|
+
}
|
|
1183
|
+
.pb-timeline {
|
|
1184
|
+
.progress-area {
|
|
1185
|
+
justify-content: center;
|
|
1186
|
+
}
|
|
1187
|
+
.pb-progress-bar {
|
|
1188
|
+
border-radius: 4px;
|
|
1189
|
+
//max-width: 90%;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
.volume-btn {
|
|
1193
|
+
margin-left: 16px;
|
|
1194
|
+
}
|
|
1195
|
+
.pb-areas {
|
|
1196
|
+
width: 100%;
|
|
1197
|
+
display: grid;
|
|
1198
|
+
grid-template-columns:
|
|
1199
|
+
min-content
|
|
1200
|
+
min-content
|
|
1201
|
+
1fr
|
|
1202
|
+
min-content
|
|
1203
|
+
min-content;
|
|
1204
|
+
align-items: center;
|
|
1205
|
+
justify-content: center;
|
|
1206
|
+
button {
|
|
1207
|
+
height: 24px;
|
|
1208
|
+
width: 24px;
|
|
1209
|
+
&.playbar-btn {
|
|
1210
|
+
margin-right: 8px;
|
|
1211
|
+
}
|
|
1212
|
+
svg {
|
|
1213
|
+
height: 12.25px;
|
|
1214
|
+
@media screen and (max-width: 800px) {
|
|
1215
|
+
height: 18px;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
&.volume-btn {
|
|
1219
|
+
svg {
|
|
1220
|
+
height: 16px;
|
|
1221
|
+
}
|
|
1222
|
+
svg.volume-low-icon {
|
|
1223
|
+
height: 14px;
|
|
1526
1224
|
}
|
|
1527
1225
|
}
|
|
1528
1226
|
}
|
|
1529
1227
|
}
|
|
1530
1228
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1229
|
+
//Playback button video (to finish)
|
|
1230
|
+
.playback-button {
|
|
1231
|
+
.playback-wrapper {
|
|
1232
|
+
opacity: 0;
|
|
1233
|
+
}
|
|
1234
|
+
&.initial {
|
|
1235
|
+
.playback-wrapper {
|
|
1236
|
+
animation-name: initial;
|
|
1237
|
+
opacity: 1;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
&.playback-animation {
|
|
1241
|
+
.playback-wrapper {
|
|
1242
|
+
opacity: 0;
|
|
1243
|
+
animation-name: handlePlayBack;
|
|
1244
|
+
animation-duration: 0.8s;
|
|
1245
|
+
animation-timing-function: ease-in-out;
|
|
1537
1246
|
}
|
|
1538
1247
|
}
|
|
1539
1248
|
}
|
|
1249
|
+
|
|
1250
|
+
@keyframes handlePlayBack {
|
|
1251
|
+
0% {
|
|
1252
|
+
opacity: 0;
|
|
1253
|
+
}
|
|
1254
|
+
50% {
|
|
1255
|
+
opacity: 1;
|
|
1256
|
+
transform: scale(0.95);
|
|
1257
|
+
}
|
|
1258
|
+
100% {
|
|
1259
|
+
opacity: 0;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
@keyframes disappear {
|
|
1264
|
+
0% {
|
|
1265
|
+
opacity: 1;
|
|
1266
|
+
}
|
|
1267
|
+
100% {
|
|
1268
|
+
opacity: 0;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1540
1271
|
</style>
|