fcad-core-dragon 2.1.0-beta.1 → 2.1.0-beta.3
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/CHANGELOG +40 -0
- package/package.json +30 -31
- package/src/components/AppBase.vue +167 -39
- package/src/components/AppBaseButton.test.js +0 -1
- package/src/components/AppBaseModule.vue +103 -116
- package/src/components/AppBasePage.vue +13 -13
- package/src/components/AppCompInputCheckBoxNx.vue +1 -1
- package/src/components/AppCompInputRadioNx.vue +1 -1
- package/src/components/AppCompMenu.vue +2 -1
- package/src/components/AppCompPlayBarNext.vue +157 -16
- package/src/components/AppCompPopUpNext.vue +3 -3
- package/src/components/AppCompQuizNext.vue +1 -1
- package/src/components/AppCompQuizRecall.vue +2 -3
- package/src/components/AppCompTableOfContent.vue +1 -1
- package/src/components/tests__/useTimer.spec.js +91 -0
- package/src/composables/useIdleDetector.js +56 -0
- package/src/composables/useQuiz.js +1 -1
- package/src/composables/useTimer.js +175 -0
- package/src/main.js +2 -0
- package/src/module/stores/appStore.js +10 -34
- package/src/module/xapi/ADL.js +1 -0
- package/src/plugins/analytics.js +34 -0
- package/src/plugins/i18n.js +9 -27
- package/src/router/index.js +6 -3
- package/src/components/AppCompPlayBarProgress.vue +0 -82
- package/src/mixins/$mediaMixins.js +0 -809
- package/src/mixins/timerMixin.js +0 -195
- package/src/module/xapi/wrapper copy.js +0 -1963
|
@@ -1,809 +0,0 @@
|
|
|
1
|
-
//import { mapState } from 'pinia'
|
|
2
|
-
/*
|
|
3
|
-
@ Description: Mixins to extends general fonctionnalities in a media component (audio, video)
|
|
4
|
-
@ Note: Must be used along component AppCompVideoPlayer, AppCompAudio and AppCompPlaybar or the components will not work
|
|
5
|
-
*/
|
|
6
|
-
import { mapState, mapActions } from 'pinia'
|
|
7
|
-
import { useAppStore } from '../module/stores/appStore'
|
|
8
|
-
const $extendsMedia = {
|
|
9
|
-
data: () => {
|
|
10
|
-
return {
|
|
11
|
-
//Container Playbar
|
|
12
|
-
pbContainer: null,
|
|
13
|
-
//ShowControls (show the playbar or not, default is true)
|
|
14
|
-
showControlsValue: true,
|
|
15
|
-
//Player
|
|
16
|
-
isPlaying: false,
|
|
17
|
-
canReplay: false,
|
|
18
|
-
savedIsPlaying: false, //To get the playing status on mousemove on the progressBar
|
|
19
|
-
//ProgressBar
|
|
20
|
-
currentTime: 0,
|
|
21
|
-
progressArea: null,
|
|
22
|
-
progressBar: null,
|
|
23
|
-
progressIndicator: null,
|
|
24
|
-
progressThumb: null,
|
|
25
|
-
progressThumbDown: false,
|
|
26
|
-
progressThumbHover: false,
|
|
27
|
-
//Volume
|
|
28
|
-
volumeBtn: null,
|
|
29
|
-
volumeSlider: null,
|
|
30
|
-
volumeIndicator: null,
|
|
31
|
-
currentVolume: null,
|
|
32
|
-
savedVolume: 0.5, //Saved volume when muted
|
|
33
|
-
//muted
|
|
34
|
-
muted: false,
|
|
35
|
-
|
|
36
|
-
//Labels
|
|
37
|
-
//Strings for screenreaders (duration et time)
|
|
38
|
-
mediaA11Y: {
|
|
39
|
-
label: 'progress',
|
|
40
|
-
valMax: null,
|
|
41
|
-
valNow: null,
|
|
42
|
-
valueText: null,
|
|
43
|
-
timeCode: 0,
|
|
44
|
-
duration: 0
|
|
45
|
-
},
|
|
46
|
-
//buttons label (all the buttons that need labels management in the playbar)
|
|
47
|
-
btnsLabelDisplay: {
|
|
48
|
-
'btn-subtitles': false,
|
|
49
|
-
'btn-transcript': false,
|
|
50
|
-
'btn-fullscreen': false,
|
|
51
|
-
'playbar-play': false,
|
|
52
|
-
'playbar-volume': false,
|
|
53
|
-
'volume-slider': false
|
|
54
|
-
},
|
|
55
|
-
//FocusState to manage arrows keydown on the 2 sliders (progress and volume)
|
|
56
|
-
focusState: {
|
|
57
|
-
progressBar: false,
|
|
58
|
-
volumeSlider: false
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
computed: {
|
|
63
|
-
...mapState(useAppStore, [
|
|
64
|
-
'getCurrentPage',
|
|
65
|
-
'getModuleChildren',
|
|
66
|
-
'hasMediaElOrTimeline',
|
|
67
|
-
'getCurrentMediaDuration',
|
|
68
|
-
'getCurrentBrowser',
|
|
69
|
-
|
|
70
|
-
'getAutoplayEnabled',
|
|
71
|
-
'getMediaVolume',
|
|
72
|
-
'getModuleInfo',
|
|
73
|
-
'getMediaSubtitles',
|
|
74
|
-
'getMediaPlaybarValues',
|
|
75
|
-
'getUserInteraction',
|
|
76
|
-
'getMediaMuted'
|
|
77
|
-
]),
|
|
78
|
-
//MediaElement
|
|
79
|
-
mediaElement() {
|
|
80
|
-
if (!this.mediaToPlay) return null
|
|
81
|
-
const { mElement } = this.mediaToPlay
|
|
82
|
-
return mElement ? mElement : null
|
|
83
|
-
},
|
|
84
|
-
//Media Progress
|
|
85
|
-
//Time display : duration
|
|
86
|
-
mediaDurationTime() {
|
|
87
|
-
if (this.mediaDuration > 0)
|
|
88
|
-
return this.$helper.formatTime(this.mediaDuration)
|
|
89
|
-
else return '00:00'
|
|
90
|
-
},
|
|
91
|
-
//Time display : timecode
|
|
92
|
-
timecode() {
|
|
93
|
-
if (this.currentTime && typeof (this.currentTime === Number)) {
|
|
94
|
-
return this.$helper.formatTime(this.currentTime)
|
|
95
|
-
} else return '00:00'
|
|
96
|
-
},
|
|
97
|
-
//ProgressPercentage for progressBarIndicator width
|
|
98
|
-
progressBarPercentage() {
|
|
99
|
-
if (this.currentTime && this.mediaDuration)
|
|
100
|
-
return (this.currentTime / this.mediaDuration) * 100
|
|
101
|
-
else return 0
|
|
102
|
-
},
|
|
103
|
-
progressBarEnded() {
|
|
104
|
-
return this.currentTime >= Math.floor(this.mediaDuration)
|
|
105
|
-
},
|
|
106
|
-
//Volume
|
|
107
|
-
volumeState() {
|
|
108
|
-
let state = null
|
|
109
|
-
switch (true) {
|
|
110
|
-
case this.muted || this.currentVolume <= 0:
|
|
111
|
-
state = 'muted'
|
|
112
|
-
break
|
|
113
|
-
|
|
114
|
-
case !this.muted && this.currentVolume <= 0.5:
|
|
115
|
-
state = 'low'
|
|
116
|
-
break
|
|
117
|
-
case !this.muted && this.currentVolume > 0.5:
|
|
118
|
-
state = 'high'
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return state
|
|
122
|
-
},
|
|
123
|
-
//Volume progress for slider background
|
|
124
|
-
volumeSliderBackground() {
|
|
125
|
-
return (this.currentVolume * 100).toFixed(0).toString() + '%'
|
|
126
|
-
},
|
|
127
|
-
//Volume from store
|
|
128
|
-
mediaVolume() {
|
|
129
|
-
// return this.getMediaVolume
|
|
130
|
-
return this.getMediaPlaybarValues('volume')
|
|
131
|
-
},
|
|
132
|
-
//media from store
|
|
133
|
-
mediaMuted() {
|
|
134
|
-
return this.getMediaMuted
|
|
135
|
-
},
|
|
136
|
-
//Labels
|
|
137
|
-
playLabel() {
|
|
138
|
-
let label = null
|
|
139
|
-
switch (true) {
|
|
140
|
-
case this.isPlaying:
|
|
141
|
-
label = this.$t('button.pause')
|
|
142
|
-
break
|
|
143
|
-
|
|
144
|
-
case this.canReplay:
|
|
145
|
-
label = this.$t('button.replay')
|
|
146
|
-
break
|
|
147
|
-
|
|
148
|
-
default:
|
|
149
|
-
label = this.$t('button.play')
|
|
150
|
-
}
|
|
151
|
-
return label
|
|
152
|
-
},
|
|
153
|
-
volumeLabel() {
|
|
154
|
-
let label = null
|
|
155
|
-
switch (true) {
|
|
156
|
-
case this.muted:
|
|
157
|
-
label = `${this.$t('button.unmute')}`
|
|
158
|
-
break
|
|
159
|
-
case !this.muted:
|
|
160
|
-
label = `${this.$t('button.mute')}`
|
|
161
|
-
break
|
|
162
|
-
}
|
|
163
|
-
return label
|
|
164
|
-
},
|
|
165
|
-
volumeLevelA11Y() {
|
|
166
|
-
const w = this.$i18n.locale === 'en' ? 'at' : 'à'
|
|
167
|
-
const level = Math.round(this.currentVolume * 100)
|
|
168
|
-
let txtA11Y = `Volume ${w} ${level}%`
|
|
169
|
-
|
|
170
|
-
return txtA11Y
|
|
171
|
-
}
|
|
172
|
-
},
|
|
173
|
-
watch: {
|
|
174
|
-
getUserInteraction: {
|
|
175
|
-
immediate: true,
|
|
176
|
-
deep: true,
|
|
177
|
-
handler() {
|
|
178
|
-
if (!this.getUserInteraction) return
|
|
179
|
-
this.getViewedSatus()
|
|
180
|
-
this.setMediaVolume()
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
},
|
|
184
|
-
|
|
185
|
-
methods: {
|
|
186
|
-
...mapActions(useAppStore, ['setMediaMuted', 'setMediaPlaybarValues']),
|
|
187
|
-
/**
|
|
188
|
-
* @description - Set all the DOM elements for medias
|
|
189
|
-
*/
|
|
190
|
-
initializeMediaElm() {
|
|
191
|
-
this.pbContainer = this.$refs['$pb-container']
|
|
192
|
-
//ProgressBar
|
|
193
|
-
this.progressArea = this.$refs['$progress-area']
|
|
194
|
-
this.progressBar = this.$refs['$progress-bar']
|
|
195
|
-
this.progressIndicator = this.$refs['$progress-indicator']
|
|
196
|
-
this.progressThumb = this.$refs['$progress-thumb']
|
|
197
|
-
//SeekTooltip
|
|
198
|
-
this.seekTooltip = this.$refs['$seek-tooltip']
|
|
199
|
-
//Volume//
|
|
200
|
-
this.volumeBtn = this.$refs['$btn-volume']
|
|
201
|
-
this.volumeSlider = this.$refs['$volume-slider']
|
|
202
|
-
this.volumeIndicator = this.$refs['$volume-progress']
|
|
203
|
-
},
|
|
204
|
-
/**
|
|
205
|
-
* @description - handle all the listeners for medias
|
|
206
|
-
*/
|
|
207
|
-
setMediaHandlers() {
|
|
208
|
-
if (this.mediaElement) {
|
|
209
|
-
//Prevent default on keys used for navigation in the player (prevent scrollbar to be trigger when changing volume)
|
|
210
|
-
this.pbContainer.addEventListener('keydown', this.keysPreventDefault)
|
|
211
|
-
//progressBar events
|
|
212
|
-
this.progressArea.addEventListener('click', this.seekingProgress)
|
|
213
|
-
//window handlers for playbar progress
|
|
214
|
-
window.addEventListener('mousemove', this.progressWindowMove)
|
|
215
|
-
window.addEventListener('mouseup', this.progressWindowUp)
|
|
216
|
-
//EndprogressBar
|
|
217
|
-
//Update data when media as a timeupdate/ended
|
|
218
|
-
this.mediaElement.addEventListener(
|
|
219
|
-
'timeupdate',
|
|
220
|
-
this.updateProgressBarTime
|
|
221
|
-
)
|
|
222
|
-
this.mediaElement.addEventListener('ended', this.mediaEnded)
|
|
223
|
-
//Volume
|
|
224
|
-
this.volumeSlider.addEventListener('input', this.updateVolumeLevel)
|
|
225
|
-
//Hotkeys
|
|
226
|
-
this.pbContainer.addEventListener('keydown', this.handleMediaControls)
|
|
227
|
-
|
|
228
|
-
//Bus
|
|
229
|
-
//this.$bus.$on('play-media', this.handleMediaControls)
|
|
230
|
-
}
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* @description - Unset all the listeners (medias)
|
|
235
|
-
*/
|
|
236
|
-
removeMediaHandlers() {
|
|
237
|
-
if (this.mediaElement) {
|
|
238
|
-
//progressBar events
|
|
239
|
-
this.progressArea.removeEventListener('click', this.seekingProgress)
|
|
240
|
-
//window handlers for playbar progress
|
|
241
|
-
window.removeEventListener('mousemove', this.progressWindowMove)
|
|
242
|
-
window.removeEventListener('mouseup', this.progressWindowUp)
|
|
243
|
-
|
|
244
|
-
this.mediaElement.removeEventListener(
|
|
245
|
-
'timeupdate',
|
|
246
|
-
this.updateProgressBarTime
|
|
247
|
-
)
|
|
248
|
-
this.mediaElement.removeEventListener('ended', this.mediaEnded)
|
|
249
|
-
|
|
250
|
-
//Volume
|
|
251
|
-
this.volumeSlider.removeEventListener('input', this.updateVolumeLevel)
|
|
252
|
-
//Keys
|
|
253
|
-
this.pbContainer.removeEventListener('keydown', this.keysPreventDefault)
|
|
254
|
-
this.pbContainer.removeEventListener(
|
|
255
|
-
'keydown',
|
|
256
|
-
this.handleMediaControls
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
/**
|
|
261
|
-
* @description - play or pause the media
|
|
262
|
-
* @fires manage-media-players - to the PAge the media in play
|
|
263
|
-
*/
|
|
264
|
-
togglePlay() {
|
|
265
|
-
//If the progressBar is at the end, restart the media
|
|
266
|
-
if (this.progressBarEnded) {
|
|
267
|
-
this.mediaElement.currentTime = 0
|
|
268
|
-
this.currentTime = 0
|
|
269
|
-
}
|
|
270
|
-
//MediaElement
|
|
271
|
-
this.isPlaying ? this.mediaElement.pause() : this.mediaElement.play()
|
|
272
|
-
//Data
|
|
273
|
-
if (!this.isPlaying) {
|
|
274
|
-
//Signal to set this mediaElement as the last playing
|
|
275
|
-
this.$bus.$emit('manage-media-players', this.mediaToPlay)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
this.isPlaying = !this.isPlaying
|
|
279
|
-
this.canReplay = false
|
|
280
|
-
},
|
|
281
|
-
/**
|
|
282
|
-
* @description - Set the media to a new time (if its a time between 0 and max)
|
|
283
|
-
*/
|
|
284
|
-
setMediaTime(time) {
|
|
285
|
-
if (time <= 0) this.mediaElement.currentTime = 0
|
|
286
|
-
else if (time > this.mediaDuration)
|
|
287
|
-
this.mediaElement.currentTime = this.mediaDuration
|
|
288
|
-
else this.mediaElement.currentTime = time
|
|
289
|
-
//Handle finish Media if its set to max duration
|
|
290
|
-
if (this.progressBarEnded) {
|
|
291
|
-
this.mediaEnded()
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
/**
|
|
295
|
-
* @description - Set the media Ended if it is set to the end of the progressBar by the user or if it plays until the end
|
|
296
|
-
*/
|
|
297
|
-
|
|
298
|
-
mediaEnded() {
|
|
299
|
-
//Don't make the media play when release progressBar thumb and the media is Ended
|
|
300
|
-
this.savedIsPlaying = false
|
|
301
|
-
//Pausing mediaElement is isPlaying
|
|
302
|
-
if (this.mediaElement && this.isPlaying) {
|
|
303
|
-
this.mediaElement.pause()
|
|
304
|
-
this.isPlaying = false
|
|
305
|
-
}
|
|
306
|
-
this.$bus.$emit('media-viewed', this.mediaToPlay.id)
|
|
307
|
-
this.canReplay = true
|
|
308
|
-
if (this.mediaToPlay.mType === 'video') this.showControls()
|
|
309
|
-
},
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* @description get the view Status of the current media from UserInteraction
|
|
313
|
-
*/
|
|
314
|
-
getViewedSatus() {
|
|
315
|
-
//Should get the viewed Status from UserInteraction
|
|
316
|
-
let { activityRef, id } = this.getCurrentPage
|
|
317
|
-
if (
|
|
318
|
-
!this.getUserInteraction[activityRef] ||
|
|
319
|
-
!this.getUserInteraction[activityRef][id]
|
|
320
|
-
)
|
|
321
|
-
return
|
|
322
|
-
const { userInteraction } = this.getUserInteraction[activityRef][id]
|
|
323
|
-
if (!userInteraction.mediasViewed || !userInteraction.mediasViewed.length)
|
|
324
|
-
return
|
|
325
|
-
const { mediasViewed } = userInteraction
|
|
326
|
-
//Should update the can replay state of media
|
|
327
|
-
this.canReplay = mediasViewed.includes(this.mediaElement.id)
|
|
328
|
-
},
|
|
329
|
-
/**
|
|
330
|
-
* @description controls the level Of the media volume
|
|
331
|
-
* @param d string, optional volUp or volDown to Add or Remove 0.05 from volume value
|
|
332
|
-
*/
|
|
333
|
-
updateVolumeLevel(d = null) {
|
|
334
|
-
if (!this.mediaElement) return
|
|
335
|
-
if (this.mediaElement.muted) {
|
|
336
|
-
this.mediaElement.muted = this.muted = false
|
|
337
|
-
//Send muted state to the store
|
|
338
|
-
this.setMutedState(this.muted)
|
|
339
|
-
}
|
|
340
|
-
switch (true) {
|
|
341
|
-
case d == 'volUP':
|
|
342
|
-
//Set volume Up
|
|
343
|
-
if (this.mediaElement.volume >= 1) return
|
|
344
|
-
if (this.mediaElement.volume >= 0.95) {
|
|
345
|
-
this.mediaElement.volume = 1
|
|
346
|
-
} else {
|
|
347
|
-
this.mediaElement.volume = (
|
|
348
|
-
this.mediaElement.volume + 0.05
|
|
349
|
-
).toFixed(2)
|
|
350
|
-
}
|
|
351
|
-
this.volumeSlider.value = this.currentVolume =
|
|
352
|
-
this.mediaElement.volume
|
|
353
|
-
break
|
|
354
|
-
|
|
355
|
-
case d == 'volDOWN':
|
|
356
|
-
//Set volume Down
|
|
357
|
-
if (this.mediaElement.volume <= 0) return
|
|
358
|
-
if (this.mediaElement.volume <= 0.05) {
|
|
359
|
-
this.mediaElement.volume = 0
|
|
360
|
-
} else {
|
|
361
|
-
this.mediaElement.volume = (
|
|
362
|
-
this.mediaElement.volume - 0.05
|
|
363
|
-
).toFixed(2)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
this.volumeSlider.value = this.currentVolume =
|
|
367
|
-
this.mediaElement.volume
|
|
368
|
-
break
|
|
369
|
-
|
|
370
|
-
default: {
|
|
371
|
-
//set volume
|
|
372
|
-
this.currentVolume = this.mediaElement.volume =
|
|
373
|
-
this.volumeSlider.value
|
|
374
|
-
this.currentVolume = parseFloat(this.currentVolume).toFixed(2)
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
if (!this.muted) this.savedVolume = this.currentVolume
|
|
378
|
-
this.setMediaPlaybarValues({
|
|
379
|
-
volume: this.savedVolume
|
|
380
|
-
}) // Save the volume in the Store
|
|
381
|
-
},
|
|
382
|
-
/**
|
|
383
|
-
* @description - Toggle the state fo the sound
|
|
384
|
-
*/
|
|
385
|
-
toggleMute() {
|
|
386
|
-
//Check first the volume of the media
|
|
387
|
-
if (this.mediaElement.volume == 0) this.muted = true
|
|
388
|
-
|
|
389
|
-
this.muted = !this.muted
|
|
390
|
-
this.mediaElement.muted = this.muted // set the muted state of the media
|
|
391
|
-
|
|
392
|
-
//Send mutedstate to the store
|
|
393
|
-
this.setMutedState(this.muted)
|
|
394
|
-
|
|
395
|
-
if (this.muted) {
|
|
396
|
-
this.mediaElement.volume = 0
|
|
397
|
-
this.savedVolume = this.currentVolume
|
|
398
|
-
this.volumeSlider.value = 0
|
|
399
|
-
this.currentVolume = 0
|
|
400
|
-
}
|
|
401
|
-
if (!this.muted) {
|
|
402
|
-
this.volumeSlider.value = this.savedVolume
|
|
403
|
-
this.currentVolume = this.mediaElement.volume = this.volumeSlider.value
|
|
404
|
-
}
|
|
405
|
-
},
|
|
406
|
-
|
|
407
|
-
/** @description Save the muted in the Store */
|
|
408
|
-
setMutedState() {
|
|
409
|
-
this.setMediaMuted(this.muted)
|
|
410
|
-
},
|
|
411
|
-
//Keyboard event methods
|
|
412
|
-
/**
|
|
413
|
-
* @description Method to prevent default on keys used for navigation in the player (prevent scrollbar to be trigger when changing volume)
|
|
414
|
-
* */
|
|
415
|
-
keysPreventDefault(evt) {
|
|
416
|
-
if (
|
|
417
|
-
['Space', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].indexOf(
|
|
418
|
-
evt.key
|
|
419
|
-
) > -1
|
|
420
|
-
) {
|
|
421
|
-
evt.preventDefault()
|
|
422
|
-
}
|
|
423
|
-
},
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* @description Method to handle the keyboard input to controle the media player
|
|
427
|
-
*@summary Keyboard actions:
|
|
428
|
-
* *** Left-Arrow/ Right-Arrow : move foward/Backward media by 5s
|
|
429
|
-
* *** Up-Arrow/ Down-Arrow: Increase/Decrease media volume by 5%
|
|
430
|
-
* *** c : show/ hide subtitle
|
|
431
|
-
* *** f : enter/ exit fullscreen
|
|
432
|
-
* *** k : play/ pause media
|
|
433
|
-
* *** m : Mute/ Unmute volume
|
|
434
|
-
* *** t : show transcript
|
|
435
|
-
*/
|
|
436
|
-
|
|
437
|
-
handleMediaControls(e) {
|
|
438
|
-
e = e.code
|
|
439
|
-
this.showControls()
|
|
440
|
-
switch (e) {
|
|
441
|
-
case 'ArrowLeft':
|
|
442
|
-
//If focus is on Volume, VolDown
|
|
443
|
-
if (this.focusState.volumeSlider) {
|
|
444
|
-
//VolDown
|
|
445
|
-
this.updateVolumeLevel('volDOWN')
|
|
446
|
-
break
|
|
447
|
-
} else {
|
|
448
|
-
//Go back 5s in media timeline
|
|
449
|
-
this.cursorLeft()
|
|
450
|
-
break
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
case 'ArrowRight':
|
|
454
|
-
//If focus is on Volume, VolUp
|
|
455
|
-
if (this.focusState.volumeSlider) {
|
|
456
|
-
//VolUp
|
|
457
|
-
this.updateVolumeLevel('volUP')
|
|
458
|
-
break
|
|
459
|
-
} else {
|
|
460
|
-
//Move forward 5s in media timeline
|
|
461
|
-
this.cursorRight()
|
|
462
|
-
break
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
case 'ArrowUp':
|
|
466
|
-
//If focus is on progressBar, cursorRight
|
|
467
|
-
if (this.focusState.progressBar) {
|
|
468
|
-
//Move forward 5s in media timeline
|
|
469
|
-
this.cursorRight()
|
|
470
|
-
break
|
|
471
|
-
} else {
|
|
472
|
-
//VolUp
|
|
473
|
-
this.updateVolumeLevel('volUP')
|
|
474
|
-
break
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
case 'ArrowDown':
|
|
478
|
-
//If focus is on progressBar, cursorRight
|
|
479
|
-
if (this.focusState.progressBar) {
|
|
480
|
-
//Go back 5s in media timeline
|
|
481
|
-
this.cursorLeft()
|
|
482
|
-
break
|
|
483
|
-
} else {
|
|
484
|
-
//Voldown
|
|
485
|
-
this.updateVolumeLevel('volDOWN')
|
|
486
|
-
break
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
case 'KeyM':
|
|
490
|
-
this.toggleMute()
|
|
491
|
-
break
|
|
492
|
-
|
|
493
|
-
case 'KeyF':
|
|
494
|
-
if (this.mediaToPlay.mType == 'audio') break
|
|
495
|
-
//Toggle fullScreen
|
|
496
|
-
this.toggleFullScreen()
|
|
497
|
-
break
|
|
498
|
-
|
|
499
|
-
case 'KeyT':
|
|
500
|
-
if (this.mediaToPlay.mType == 'audio') break
|
|
501
|
-
//Toggle transcript view
|
|
502
|
-
this.toggleViewTranscript()
|
|
503
|
-
break
|
|
504
|
-
|
|
505
|
-
case 'KeyC':
|
|
506
|
-
if (this.mediaToPlay.mType == 'audio') break
|
|
507
|
-
//Toggle subtitle view
|
|
508
|
-
this.toggleViewSubtitle()
|
|
509
|
-
break
|
|
510
|
-
|
|
511
|
-
case 'KeyK':
|
|
512
|
-
//Play Pause on k bar pressed
|
|
513
|
-
if (this.mediaToPlay.mType == 'audio') this.togglePlay()
|
|
514
|
-
//Play/pause video with the playBackAnim if it is triggerd with KeyK
|
|
515
|
-
else this.handlePlayVideo('playBackAnim')
|
|
516
|
-
break
|
|
517
|
-
}
|
|
518
|
-
},
|
|
519
|
-
/**
|
|
520
|
-
* @description - Activate the label of a button include in btnsLabelDisplay on Hover/Focus on the button. Deactivate the label in all the others btns
|
|
521
|
-
*/
|
|
522
|
-
activateLabel(elm) {
|
|
523
|
-
const id = elm.id
|
|
524
|
-
this.btnsLabelDisplay[id] = true
|
|
525
|
-
for (const property in this.btnsLabelDisplay) {
|
|
526
|
-
if (property !== id) {
|
|
527
|
-
this.btnsLabelDisplay[property] = false
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
},
|
|
531
|
-
/**
|
|
532
|
-
* @description - Get currenttime from media
|
|
533
|
-
*/
|
|
534
|
-
|
|
535
|
-
getCurrentTime() {
|
|
536
|
-
this.currentTime = this.mediaElement.currentTime
|
|
537
|
-
return this.mediaElement.currentTime
|
|
538
|
-
},
|
|
539
|
-
/**
|
|
540
|
-
* @description - controls to move the media timeline backward
|
|
541
|
-
*/
|
|
542
|
-
cursorLeft() {
|
|
543
|
-
this.setMediaTime(this.getCurrentTime() - 5)
|
|
544
|
-
},
|
|
545
|
-
/**
|
|
546
|
-
* @description - control to move the media timeline forwrad
|
|
547
|
-
*/
|
|
548
|
-
cursorRight() {
|
|
549
|
-
this.setMediaTime(this.getCurrentTime() + 5)
|
|
550
|
-
},
|
|
551
|
-
//ProgressBar Methods
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* @description - Update currentTime and timing strings when media is playing
|
|
555
|
-
*/
|
|
556
|
-
updateProgressBarTime(e) {
|
|
557
|
-
//Get currentTime from the event
|
|
558
|
-
this.currentTime = e.target.currentTime
|
|
559
|
-
//Update strings
|
|
560
|
-
this.setProgressBarA11Y()
|
|
561
|
-
//If replay is true and the progressIndicator is not at the end, set canReplay to false
|
|
562
|
-
if (this.canReplay) this.canReplay = false
|
|
563
|
-
//If replay is false and progressIndicator is at the end, set canReplay to true
|
|
564
|
-
if (
|
|
565
|
-
!this.canReplay &&
|
|
566
|
-
this.currentTime >= Math.floor(this.mediaDuration)
|
|
567
|
-
) {
|
|
568
|
-
this.canReplay = true
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* @description - Set mediatime depending on progressBar click
|
|
574
|
-
*/
|
|
575
|
-
seekingProgress(e) {
|
|
576
|
-
if (!this.progressThumbDown && !this.progressThumbHover) {
|
|
577
|
-
const updatedTime =
|
|
578
|
-
(e.offsetX / this.progressBar.offsetWidth) * this.mediaDuration
|
|
579
|
-
this.setMediaTime(updatedTime)
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* @description - Set mediatime depending on mousemove on the screen (when progress thumb is mousedown)
|
|
585
|
-
*/
|
|
586
|
-
progressWindowMove(ev) {
|
|
587
|
-
if (this.progressThumbDown) {
|
|
588
|
-
if (this.isPlaying) this.togglePlay()
|
|
589
|
-
this.getTimeFromClickPos(ev)
|
|
590
|
-
let timeToSet = Math.floor(this.getTimeFromClickPos(ev))
|
|
591
|
-
if (timeToSet < 0) timeToSet = 0
|
|
592
|
-
else if (timeToSet > this.duration) timeToSet = this.duration
|
|
593
|
-
this.currentTime = timeToSet
|
|
594
|
-
}
|
|
595
|
-
},
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* @description - Update thumb state (mouseup) when the mouse is up on the screen
|
|
599
|
-
*/
|
|
600
|
-
progressWindowUp(ev) {
|
|
601
|
-
if (this.progressThumbDown) {
|
|
602
|
-
this.setMediaTime(this.currentTime)
|
|
603
|
-
this.progressThumbDown = false
|
|
604
|
-
//savedIsPlaying is the playing status saved on mousedown event on the thumb (the video is paused when moving on the progressBar)
|
|
605
|
-
if (this.isPlaying !== this.savedIsPlaying) this.togglePlay()
|
|
606
|
-
}
|
|
607
|
-
},
|
|
608
|
-
/**
|
|
609
|
-
* @description - Get the time corresponding of the position of the click on the progressBar
|
|
610
|
-
*/
|
|
611
|
-
getTimeFromClickPos(ev) {
|
|
612
|
-
let timeToSet = 0
|
|
613
|
-
//La progress Bar
|
|
614
|
-
const progressBar = this.progressBar
|
|
615
|
-
//La position de la progressBar dans la page
|
|
616
|
-
const left = progressBar.getBoundingClientRect().left
|
|
617
|
-
//Position du click par rapport à la progressBar
|
|
618
|
-
let clickPos = ev.clientX - left
|
|
619
|
-
//Si la position est à gauche de la progressBar, retourner 0s
|
|
620
|
-
if (clickPos < 0) return 0
|
|
621
|
-
//Obtenir le width de la progressBar
|
|
622
|
-
const width = progressBar.offsetWidth
|
|
623
|
-
//Obtenir le ratio de la position du click vs width de la progressBar
|
|
624
|
-
let percentage = clickPos / width
|
|
625
|
-
//Si > que 1, veux dire que le clique est à droite de la progressBar (mettre le curseur à la fin)
|
|
626
|
-
percentage = percentage > 1 ? 1 : percentage
|
|
627
|
-
//Ratio * temps total du media donne la progressiob
|
|
628
|
-
timeToSet = percentage * this.mediaDuration
|
|
629
|
-
return timeToSet
|
|
630
|
-
},
|
|
631
|
-
|
|
632
|
-
//End progressBar methods
|
|
633
|
-
|
|
634
|
-
//Labels
|
|
635
|
-
|
|
636
|
-
/** @description - methode to set A11Y support for screen reader on progress bar element (video/audio/) */
|
|
637
|
-
setProgressBarA11Y() {
|
|
638
|
-
const w = this.$i18n.locale === 'en' ? 'at' : 'à'
|
|
639
|
-
const dm =
|
|
640
|
-
this.$i18n.locale === 'en'
|
|
641
|
-
? `${this.mediaToPlay.mType} duration`
|
|
642
|
-
: `durée ${this.mediaToPlay.mType}`
|
|
643
|
-
|
|
644
|
-
this.mediaA11Y.valMax = Math.round(this.mediaElement.duration)
|
|
645
|
-
this.mediaA11Y.valNow = Math.round(this.currentTime)
|
|
646
|
-
|
|
647
|
-
//format text output for screen reader
|
|
648
|
-
let currentTimeArray = this.timecode.split(':')
|
|
649
|
-
let fullTimeArray = this.mediaDurationTime.split(':')
|
|
650
|
-
let hrsTxt, mnTxt, ssTxt, HRSTxt, MNTxt, SSTxt, fTimeTxt, cTimeTxt
|
|
651
|
-
const mediaTitle = this.mediaToPlay.mTitle || this.mediaToPlay.mType
|
|
652
|
-
this.mediaA11Y.label = this.$t('a11y_sr.seek_slider')
|
|
653
|
-
|
|
654
|
-
//format string to remove leading 0 digit for time
|
|
655
|
-
const formatNum = (n) => {
|
|
656
|
-
return n[0] == '0' ? n.substring(1).trim() : n.trim()
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
const formatMsg = (x, y) => {
|
|
660
|
-
let formatStr = this.$t('a11y_sr.range_expression')
|
|
661
|
-
.replace('{x}', x)
|
|
662
|
-
.replace('{y}', y)
|
|
663
|
-
|
|
664
|
-
return formatStr
|
|
665
|
-
}
|
|
666
|
-
switch (fullTimeArray.length) {
|
|
667
|
-
case 3:
|
|
668
|
-
if (!currentTimeArray.length) return
|
|
669
|
-
|
|
670
|
-
//format current hours text text with plurialization apply
|
|
671
|
-
hrsTxt =
|
|
672
|
-
currentTimeArray.length == 3 && parseInt(currentTimeArray[0]) > 0
|
|
673
|
-
? `${formatNum(currentTimeArray[0])} ${this.$tc(
|
|
674
|
-
'a11y_sr.time.hours',
|
|
675
|
-
formatNum(currentTimeArray[0])
|
|
676
|
-
)}`
|
|
677
|
-
: ''
|
|
678
|
-
|
|
679
|
-
//format minutes text text with plurialization apply
|
|
680
|
-
mnTxt =
|
|
681
|
-
parseInt(currentTimeArray[1]) > 0
|
|
682
|
-
? `${formatNum(currentTimeArray[1])} ${this.$tc(
|
|
683
|
-
'a11y_sr.time.minute',
|
|
684
|
-
formatNum(currentTimeArray[1])
|
|
685
|
-
)}`
|
|
686
|
-
: ''
|
|
687
|
-
|
|
688
|
-
//format seconds text with plurialization apply
|
|
689
|
-
ssTxt =
|
|
690
|
-
parseInt(currentTimeArray[2]) > 0
|
|
691
|
-
? `${formatNum(currentTimeArray[2])} ${this.$tc(
|
|
692
|
-
'a11y_sr.time.second',
|
|
693
|
-
formatNum(currentTimeArray[2])
|
|
694
|
-
)}`
|
|
695
|
-
: `0 ${this.$tc('a11y_sr.time.second')}`
|
|
696
|
-
|
|
697
|
-
HRSTxt =
|
|
698
|
-
parseInt(fullTimeArray[0]) > 0
|
|
699
|
-
? `${formatNum(fullTimeArray[0])} ${this.$tc(
|
|
700
|
-
'a11y_sr.time.hours',
|
|
701
|
-
formatNum(fullTimeArray[0])
|
|
702
|
-
)}`
|
|
703
|
-
: ''
|
|
704
|
-
|
|
705
|
-
MNTxt =
|
|
706
|
-
parseInt(fullTimeArray[1]) > 0
|
|
707
|
-
? `${formatNum(fullTimeArray[1])} ${this.$tc(
|
|
708
|
-
'a11y_sr.time.minute',
|
|
709
|
-
formatNum(fullTimeArray[1])
|
|
710
|
-
)}`
|
|
711
|
-
: ''
|
|
712
|
-
|
|
713
|
-
SSTxt =
|
|
714
|
-
parseInt(fullTimeArray[2]) > 0
|
|
715
|
-
? `${formatNum(fullTimeArray[2])} ${this.$tc(
|
|
716
|
-
'a11y_sr.time.second',
|
|
717
|
-
formatNum(fullTimeArray[2])
|
|
718
|
-
)}`
|
|
719
|
-
: ''
|
|
720
|
-
|
|
721
|
-
cTimeTxt = `${hrsTxt} ${mnTxt} ${ssTxt}`
|
|
722
|
-
fTimeTxt = `${HRSTxt} ${MNTxt} ${SSTxt}`
|
|
723
|
-
|
|
724
|
-
//Format to show 0 when no value is present
|
|
725
|
-
cTimeTxt = cTimeTxt.trim().length ? cTimeTxt.trim() : 0
|
|
726
|
-
|
|
727
|
-
// Set sr text for timeCode && duration
|
|
728
|
-
this.mediaA11Y.timeCode = `${this.mediaToPlay.mType} ${w} ${cTimeTxt}`
|
|
729
|
-
this.mediaA11Y.duration = `${dm} ${fTimeTxt}`
|
|
730
|
-
this.mediaA11Y.valueText = `${mediaTitle} ${formatMsg(cTimeTxt, fTimeTxt)}`
|
|
731
|
-
|
|
732
|
-
break
|
|
733
|
-
case 2:
|
|
734
|
-
if (!currentTimeArray.length) return
|
|
735
|
-
|
|
736
|
-
//format current time text
|
|
737
|
-
mnTxt =
|
|
738
|
-
parseInt(currentTimeArray[0]) > 0
|
|
739
|
-
? `${formatNum(currentTimeArray[0])} ${this.$tc(
|
|
740
|
-
'a11y_sr.time.minute',
|
|
741
|
-
formatNum(currentTimeArray[0])
|
|
742
|
-
)}`
|
|
743
|
-
: ''
|
|
744
|
-
ssTxt =
|
|
745
|
-
parseInt(currentTimeArray[1]) > 0
|
|
746
|
-
? `${formatNum(currentTimeArray[1])} ${this.$tc(
|
|
747
|
-
'a11y_sr.time.second',
|
|
748
|
-
formatNum(currentTimeArray[1])
|
|
749
|
-
)}`
|
|
750
|
-
: `0 ${this.$tc('a11y_sr.time.second')}`
|
|
751
|
-
|
|
752
|
-
// format full time text
|
|
753
|
-
MNTxt =
|
|
754
|
-
parseInt(fullTimeArray[0]) > 0
|
|
755
|
-
? `${formatNum(fullTimeArray[0])} ${this.$tc(
|
|
756
|
-
'a11y_sr.time.minute',
|
|
757
|
-
formatNum(fullTimeArray[0])
|
|
758
|
-
)}`
|
|
759
|
-
: ''
|
|
760
|
-
SSTxt =
|
|
761
|
-
parseInt(fullTimeArray[1]) > 0
|
|
762
|
-
? `${formatNum(fullTimeArray[1])} ${this.$tc(
|
|
763
|
-
'a11y_sr.time.second',
|
|
764
|
-
formatNum(fullTimeArray[1])
|
|
765
|
-
)}`
|
|
766
|
-
: ''
|
|
767
|
-
|
|
768
|
-
cTimeTxt = `${mnTxt} ${ssTxt}`
|
|
769
|
-
fTimeTxt = `${MNTxt} ${SSTxt}`
|
|
770
|
-
|
|
771
|
-
//Format to show 0 when no value is present
|
|
772
|
-
cTimeTxt = cTimeTxt.trim().length ? cTimeTxt.trim() : 0
|
|
773
|
-
|
|
774
|
-
// Set sr text for timeCode && duration
|
|
775
|
-
this.mediaA11Y.timeCode = `${this.mediaToPlay.mType} ${w} ${cTimeTxt}`
|
|
776
|
-
this.mediaA11Y.duration = `${dm} ${fTimeTxt}`
|
|
777
|
-
|
|
778
|
-
this.mediaA11Y.valueText = `${mediaTitle} ${formatMsg(cTimeTxt, fTimeTxt)}`
|
|
779
|
-
|
|
780
|
-
break
|
|
781
|
-
}
|
|
782
|
-
},
|
|
783
|
-
/**
|
|
784
|
-
* @description - Deactivate the label of a button include in btnsLabelDisplay on mouseout/blur of this button
|
|
785
|
-
*/
|
|
786
|
-
deactivateLabel(elm) {
|
|
787
|
-
const id = elm.id
|
|
788
|
-
this.btnsLabelDisplay[id] = false
|
|
789
|
-
},
|
|
790
|
-
/**
|
|
791
|
-
* @description - Update the state of the elm describe by the string (focus or not) for keydown arrow management in handleMediaControls method (volume | progress bar can use arrow up-down and left-right only on focus)
|
|
792
|
-
*/
|
|
793
|
-
changeFocusState(string, bool) {
|
|
794
|
-
this.focusState[string] = bool
|
|
795
|
-
},
|
|
796
|
-
/**
|
|
797
|
-
* @description - handle initial volume level
|
|
798
|
-
*/
|
|
799
|
-
setMediaVolume() {
|
|
800
|
-
//Set media muted or with the savedVolume
|
|
801
|
-
this.muted = this.mediaMuted
|
|
802
|
-
if (!this.muted)
|
|
803
|
-
return (this.currentVolume = this.savedVolume = this.mediaVolume)
|
|
804
|
-
this.savedVolume = this.mediaVolume
|
|
805
|
-
this.currentVolume = 0
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
export default $extendsMedia
|