vidply 1.0.28 → 1.0.29
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/dist/dev/{vidply.TranscriptManager-QSF2PWUN.js → vidply.TranscriptManager-T677KF4N.js} +4 -5
- package/dist/dev/{vidply.TranscriptManager-QSF2PWUN.js.map → vidply.TranscriptManager-T677KF4N.js.map} +2 -2
- package/dist/dev/{vidply.chunk-SRM7VNHG.js → vidply.chunk-GS2JX5RQ.js} +136 -95
- package/dist/dev/vidply.chunk-GS2JX5RQ.js.map +7 -0
- package/dist/dev/vidply.esm.js +1674 -310
- package/dist/dev/vidply.esm.js.map +4 -4
- package/dist/legacy/vidply.js +1776 -348
- package/dist/legacy/vidply.js.map +4 -4
- package/dist/legacy/vidply.min.js +1 -1
- package/dist/legacy/vidply.min.meta.json +92 -24
- package/dist/prod/vidply.TranscriptManager-WFZSW6NR.min.js +6 -0
- package/dist/prod/vidply.chunk-LGTJRPUL.min.js +6 -0
- package/dist/prod/vidply.esm.min.js +8 -8
- package/dist/vidply.esm.min.meta.json +92 -24
- package/package.json +1 -1
- package/src/controls/ControlBar.js +3 -7
- package/src/controls/TranscriptManager.js +7 -7
- package/src/core/AudioDescriptionManager.js +701 -0
- package/src/core/Player.js +4776 -4921
- package/src/core/SignLanguageManager.js +1134 -0
- package/src/utils/DOMUtils.js +153 -114
- package/src/utils/MenuFactory.js +374 -0
- package/dist/dev/vidply.TranscriptManager-GZKY44ON.js +0 -1744
- package/dist/dev/vidply.TranscriptManager-GZKY44ON.js.map +0 -7
- package/dist/dev/vidply.TranscriptManager-UTJBQC5B.js +0 -1744
- package/dist/dev/vidply.TranscriptManager-UTJBQC5B.js.map +0 -7
- package/dist/dev/vidply.chunk-5663PYKK.js +0 -1631
- package/dist/dev/vidply.chunk-5663PYKK.js.map +0 -7
- package/dist/dev/vidply.chunk-SRM7VNHG.js.map +0 -7
- package/dist/dev/vidply.chunk-UH5MTGKF.js +0 -1630
- package/dist/dev/vidply.chunk-UH5MTGKF.js.map +0 -7
- package/dist/dev/vidply.de-RXAJM5QE.js +0 -181
- package/dist/dev/vidply.de-RXAJM5QE.js.map +0 -7
- package/dist/dev/vidply.de-THBIMP4S.js +0 -180
- package/dist/dev/vidply.de-THBIMP4S.js.map +0 -7
- package/dist/dev/vidply.es-6VWDNNNL.js +0 -180
- package/dist/dev/vidply.es-6VWDNNNL.js.map +0 -7
- package/dist/dev/vidply.es-SADVLJTQ.js +0 -181
- package/dist/dev/vidply.es-SADVLJTQ.js.map +0 -7
- package/dist/dev/vidply.fr-V3VAYBBT.js +0 -181
- package/dist/dev/vidply.fr-V3VAYBBT.js.map +0 -7
- package/dist/dev/vidply.fr-WHTWCHWT.js +0 -180
- package/dist/dev/vidply.fr-WHTWCHWT.js.map +0 -7
- package/dist/dev/vidply.ja-BFQNPOFI.js +0 -180
- package/dist/dev/vidply.ja-BFQNPOFI.js.map +0 -7
- package/dist/dev/vidply.ja-KL2TLZGJ.js +0 -181
- package/dist/dev/vidply.ja-KL2TLZGJ.js.map +0 -7
- package/dist/prod/vidply.TranscriptManager-DZ2WZU3K.min.js +0 -6
- package/dist/prod/vidply.TranscriptManager-E5QHGFIR.min.js +0 -6
- package/dist/prod/vidply.TranscriptManager-UZ6DUFB6.min.js +0 -6
- package/dist/prod/vidply.chunk-5DWTMWEO.min.js +0 -6
- package/dist/prod/vidply.chunk-IBNYTGGM.min.js +0 -6
- package/dist/prod/vidply.chunk-MBUR3U5L.min.js +0 -6
- package/dist/prod/vidply.de-HGJBCLLE.min.js +0 -6
- package/dist/prod/vidply.de-SWFW4HYT.min.js +0 -6
- package/dist/prod/vidply.es-7BJ2DJAY.min.js +0 -6
- package/dist/prod/vidply.es-CZEBXCZN.min.js +0 -6
- package/dist/prod/vidply.fr-DPVR5DFY.min.js +0 -6
- package/dist/prod/vidply.fr-HFOL7MWA.min.js +0 -6
- package/dist/prod/vidply.ja-PEBVWKVH.min.js +0 -6
- package/dist/prod/vidply.ja-QTVU5C25.min.js +0 -6
package/dist/dev/vidply.esm.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
focusFirstMenuItem,
|
|
22
22
|
i18n,
|
|
23
23
|
preventDragOnElement
|
|
24
|
-
} from "./vidply.chunk-
|
|
24
|
+
} from "./vidply.chunk-GS2JX5RQ.js";
|
|
25
25
|
|
|
26
26
|
// src/utils/EventEmitter.js
|
|
27
27
|
var EventEmitter = class {
|
|
@@ -64,6 +64,33 @@ var EventEmitter = class {
|
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
+
// src/utils/PerformanceUtils.js
|
|
68
|
+
function debounce(func, wait = 100) {
|
|
69
|
+
let timeout;
|
|
70
|
+
return function executedFunction(...args) {
|
|
71
|
+
const later = () => {
|
|
72
|
+
clearTimeout(timeout);
|
|
73
|
+
func(...args);
|
|
74
|
+
};
|
|
75
|
+
clearTimeout(timeout);
|
|
76
|
+
timeout = setTimeout(later, wait);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function isMobile(breakpoint = 768) {
|
|
80
|
+
return window.innerWidth < breakpoint;
|
|
81
|
+
}
|
|
82
|
+
function rafWithTimeout(callback, timeout = 100) {
|
|
83
|
+
let called = false;
|
|
84
|
+
const execute = () => {
|
|
85
|
+
if (!called) {
|
|
86
|
+
called = true;
|
|
87
|
+
callback();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
requestAnimationFrame(execute);
|
|
91
|
+
setTimeout(execute, timeout);
|
|
92
|
+
}
|
|
93
|
+
|
|
67
94
|
// src/controls/ControlBar.js
|
|
68
95
|
var ControlBar = class {
|
|
69
96
|
constructor(player) {
|
|
@@ -84,17 +111,13 @@ var ControlBar = class {
|
|
|
84
111
|
this.setupAutoHide();
|
|
85
112
|
this.setupOverflowDetection();
|
|
86
113
|
}
|
|
87
|
-
// Helper method to check if we're on a mobile device
|
|
88
|
-
isMobile() {
|
|
89
|
-
return window.innerWidth < 768;
|
|
90
|
-
}
|
|
91
114
|
// Helper method to detect touch devices
|
|
92
115
|
isTouchDevice() {
|
|
93
116
|
return "ontouchstart" in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
|
|
94
117
|
}
|
|
95
118
|
// Smart menu positioning to avoid overflow
|
|
96
119
|
positionMenu(menu, button, immediate = false) {
|
|
97
|
-
const
|
|
120
|
+
const mobile = isMobile();
|
|
98
121
|
const isOverflowMenu = menu.classList.contains(`${this.player.options.classPrefix}-overflow-menu-list`);
|
|
99
122
|
const isFullscreen = this.player.state.fullscreen;
|
|
100
123
|
if (isFullscreen && menu.parentElement === this.player.container) {
|
|
@@ -135,7 +158,7 @@ var ControlBar = class {
|
|
|
135
158
|
}
|
|
136
159
|
return;
|
|
137
160
|
}
|
|
138
|
-
if (
|
|
161
|
+
if (mobile) {
|
|
139
162
|
const isVolumeMenu = menu.classList.contains(`${this.player.options.classPrefix}-volume-menu`);
|
|
140
163
|
const doMobilePositioning = () => {
|
|
141
164
|
const parentContainer = button.parentElement;
|
|
@@ -2503,33 +2526,6 @@ var ControlBar = class {
|
|
|
2503
2526
|
}
|
|
2504
2527
|
};
|
|
2505
2528
|
|
|
2506
|
-
// src/utils/PerformanceUtils.js
|
|
2507
|
-
function debounce(func, wait = 100) {
|
|
2508
|
-
let timeout;
|
|
2509
|
-
return function executedFunction(...args) {
|
|
2510
|
-
const later = () => {
|
|
2511
|
-
clearTimeout(timeout);
|
|
2512
|
-
func(...args);
|
|
2513
|
-
};
|
|
2514
|
-
clearTimeout(timeout);
|
|
2515
|
-
timeout = setTimeout(later, wait);
|
|
2516
|
-
};
|
|
2517
|
-
}
|
|
2518
|
-
function isMobile(breakpoint = 768) {
|
|
2519
|
-
return window.innerWidth < breakpoint;
|
|
2520
|
-
}
|
|
2521
|
-
function rafWithTimeout(callback, timeout = 100) {
|
|
2522
|
-
let called = false;
|
|
2523
|
-
const execute = () => {
|
|
2524
|
-
if (!called) {
|
|
2525
|
-
called = true;
|
|
2526
|
-
callback();
|
|
2527
|
-
}
|
|
2528
|
-
};
|
|
2529
|
-
requestAnimationFrame(execute);
|
|
2530
|
-
setTimeout(execute, timeout);
|
|
2531
|
-
}
|
|
2532
|
-
|
|
2533
2529
|
// src/controls/CaptionManager.js
|
|
2534
2530
|
var CaptionManager = class {
|
|
2535
2531
|
constructor(player) {
|
|
@@ -3059,97 +3055,1552 @@ var KeyboardManager = class {
|
|
|
3059
3055
|
}
|
|
3060
3056
|
};
|
|
3061
3057
|
|
|
3062
|
-
// src/core/
|
|
3063
|
-
var
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
this.
|
|
3068
|
-
|
|
3069
|
-
|
|
3058
|
+
// src/core/AudioDescriptionManager.js
|
|
3059
|
+
var AudioDescriptionManager = class {
|
|
3060
|
+
constructor(player) {
|
|
3061
|
+
this.player = player;
|
|
3062
|
+
this.enabled = false;
|
|
3063
|
+
this.desiredState = false;
|
|
3064
|
+
this.src = player.options.audioDescriptionSrc;
|
|
3065
|
+
this.sourceElement = null;
|
|
3066
|
+
this.originalSource = null;
|
|
3067
|
+
this.captionTracks = [];
|
|
3068
|
+
}
|
|
3069
|
+
/**
|
|
3070
|
+
* Initialize audio description from source elements
|
|
3071
|
+
* Called during player initialization
|
|
3072
|
+
*/
|
|
3073
|
+
initFromSourceElements(sourceElements, trackElements) {
|
|
3074
|
+
for (const sourceEl of sourceElements) {
|
|
3075
|
+
const descSrc = sourceEl.getAttribute("data-desc-src");
|
|
3076
|
+
const origSrc = sourceEl.getAttribute("data-orig-src");
|
|
3077
|
+
if (descSrc || origSrc) {
|
|
3078
|
+
if (!this.sourceElement) {
|
|
3079
|
+
this.sourceElement = sourceEl;
|
|
3080
|
+
}
|
|
3081
|
+
if (origSrc) {
|
|
3082
|
+
if (!this.originalSource) {
|
|
3083
|
+
this.originalSource = origSrc;
|
|
3084
|
+
}
|
|
3085
|
+
if (!this.player.originalSrc) {
|
|
3086
|
+
this.player.originalSrc = origSrc;
|
|
3087
|
+
}
|
|
3088
|
+
} else {
|
|
3089
|
+
const currentSrcAttr = sourceEl.getAttribute("src");
|
|
3090
|
+
if (!this.originalSource && currentSrcAttr) {
|
|
3091
|
+
this.originalSource = currentSrcAttr;
|
|
3092
|
+
}
|
|
3093
|
+
if (!this.player.originalSrc && currentSrcAttr) {
|
|
3094
|
+
this.player.originalSrc = currentSrcAttr;
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
if (descSrc && !this.src) {
|
|
3098
|
+
this.src = descSrc;
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3070
3101
|
}
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3102
|
+
trackElements.forEach((trackEl) => {
|
|
3103
|
+
const trackKind = trackEl.getAttribute("kind");
|
|
3104
|
+
const trackDescSrc = trackEl.getAttribute("data-desc-src");
|
|
3105
|
+
if ((trackKind === "captions" || trackKind === "subtitles" || trackKind === "chapters" || trackKind === "descriptions") && trackDescSrc) {
|
|
3106
|
+
this.captionTracks.push({
|
|
3107
|
+
trackElement: trackEl,
|
|
3108
|
+
originalSrc: trackEl.getAttribute("src"),
|
|
3109
|
+
describedSrc: trackDescSrc,
|
|
3110
|
+
originalTrackSrc: trackEl.getAttribute("data-orig-src") || trackEl.getAttribute("src"),
|
|
3111
|
+
explicit: true
|
|
3112
|
+
});
|
|
3113
|
+
this.player.log(`Found explicit described ${trackKind} track: ${trackEl.getAttribute("src")} -> ${trackDescSrc}`);
|
|
3114
|
+
}
|
|
3115
|
+
});
|
|
3116
|
+
}
|
|
3117
|
+
/**
|
|
3118
|
+
* Check if audio description is available
|
|
3119
|
+
*/
|
|
3120
|
+
isAvailable() {
|
|
3121
|
+
const hasSourceElementsWithDesc = this.player.sourceElements.some(
|
|
3122
|
+
(el) => el.getAttribute("data-desc-src")
|
|
3123
|
+
);
|
|
3124
|
+
return !!(this.src || hasSourceElementsWithDesc || this.captionTracks.length > 0);
|
|
3125
|
+
}
|
|
3126
|
+
/**
|
|
3127
|
+
* Enable audio description
|
|
3128
|
+
*/
|
|
3129
|
+
async enable() {
|
|
3130
|
+
const hasSourceElementsWithDesc = this.player.sourceElements.some(
|
|
3131
|
+
(el) => el.getAttribute("data-desc-src")
|
|
3132
|
+
);
|
|
3133
|
+
const hasTracksWithDesc = this.captionTracks.length > 0;
|
|
3134
|
+
if (!this.src && !hasSourceElementsWithDesc && !hasTracksWithDesc) {
|
|
3135
|
+
console.warn("VidPly: No audio description source, source elements, or tracks provided");
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
this.desiredState = true;
|
|
3139
|
+
const currentTime = this.player.state.currentTime;
|
|
3140
|
+
const wasPlaying = this.player.state.playing;
|
|
3141
|
+
const posterValue = this.player.element.poster || this.player.element.getAttribute("poster") || this.player.options.poster;
|
|
3142
|
+
const shouldKeepPoster = currentTime < 0.1 && !wasPlaying;
|
|
3143
|
+
const currentCaptionText = this._getCurrentCaptionText();
|
|
3144
|
+
if (this.sourceElement) {
|
|
3145
|
+
await this._enableWithSourceElement(currentTime, wasPlaying, posterValue, shouldKeepPoster, currentCaptionText);
|
|
3146
|
+
} else {
|
|
3147
|
+
await this._enableWithDirectSrc(currentTime, wasPlaying, posterValue, shouldKeepPoster);
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Disable audio description
|
|
3152
|
+
*/
|
|
3153
|
+
async disable() {
|
|
3154
|
+
if (!this.player.originalSrc) {
|
|
3155
|
+
return;
|
|
3156
|
+
}
|
|
3157
|
+
this.desiredState = false;
|
|
3158
|
+
const currentTime = this.player.state.currentTime;
|
|
3159
|
+
const wasPlaying = this.player.state.playing;
|
|
3160
|
+
const posterValue = this.player.element.poster || this.player.element.getAttribute("poster") || this.player.options.poster;
|
|
3161
|
+
const shouldKeepPoster = currentTime < 0.1 && !wasPlaying;
|
|
3162
|
+
const currentCaptionText = this._getCurrentCaptionText();
|
|
3163
|
+
if (this.sourceElement) {
|
|
3164
|
+
await this._disableWithSourceElement(currentTime, wasPlaying, posterValue, shouldKeepPoster, currentCaptionText);
|
|
3165
|
+
} else {
|
|
3166
|
+
await this._disableWithDirectSrc(currentTime, wasPlaying, posterValue);
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
/**
|
|
3170
|
+
* Toggle audio description
|
|
3171
|
+
*/
|
|
3172
|
+
async toggle() {
|
|
3173
|
+
const descriptionTrack = this.player.findTextTrack("descriptions");
|
|
3174
|
+
const hasAudioDescriptionSrc = this.isAvailable();
|
|
3175
|
+
if (descriptionTrack && !hasAudioDescriptionSrc) {
|
|
3176
|
+
if (descriptionTrack.mode === "showing") {
|
|
3177
|
+
descriptionTrack.mode = "hidden";
|
|
3178
|
+
this.enabled = false;
|
|
3179
|
+
this.player.emit("audiodescriptiondisabled");
|
|
3180
|
+
} else {
|
|
3181
|
+
descriptionTrack.mode = "showing";
|
|
3182
|
+
this.enabled = true;
|
|
3183
|
+
this.player.emit("audiodescriptionenabled");
|
|
3184
|
+
}
|
|
3185
|
+
} else if (descriptionTrack && hasAudioDescriptionSrc) {
|
|
3186
|
+
if (this.enabled) {
|
|
3187
|
+
this.desiredState = false;
|
|
3188
|
+
await this.disable();
|
|
3189
|
+
} else {
|
|
3190
|
+
descriptionTrack.mode = "showing";
|
|
3191
|
+
this.desiredState = true;
|
|
3192
|
+
await this.enable();
|
|
3193
|
+
}
|
|
3194
|
+
} else if (hasAudioDescriptionSrc) {
|
|
3195
|
+
if (this.enabled) {
|
|
3196
|
+
this.desiredState = false;
|
|
3197
|
+
await this.disable();
|
|
3198
|
+
} else {
|
|
3199
|
+
this.desiredState = true;
|
|
3200
|
+
await this.enable();
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
/**
|
|
3205
|
+
* Get current caption text for synchronization
|
|
3206
|
+
*/
|
|
3207
|
+
_getCurrentCaptionText() {
|
|
3208
|
+
if (this.player.captionManager && this.player.captionManager.currentTrack && this.player.captionManager.currentCue) {
|
|
3209
|
+
return this.player.captionManager.currentCue.text;
|
|
3210
|
+
}
|
|
3211
|
+
return null;
|
|
3212
|
+
}
|
|
3213
|
+
/**
|
|
3214
|
+
* Validate that a track URL exists
|
|
3215
|
+
*/
|
|
3216
|
+
async _validateTrackExists(url) {
|
|
3217
|
+
try {
|
|
3218
|
+
const response = await fetch(url, { method: "HEAD" });
|
|
3219
|
+
return response.ok;
|
|
3220
|
+
} catch {
|
|
3221
|
+
return false;
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
/**
|
|
3225
|
+
* Swap caption tracks to described versions
|
|
3226
|
+
*/
|
|
3227
|
+
async _swapCaptionTracks(toDescribed = true) {
|
|
3228
|
+
if (this.captionTracks.length === 0) return [];
|
|
3229
|
+
const swappedTracks = [];
|
|
3230
|
+
const validationPromises = this.captionTracks.map(async (trackInfo) => {
|
|
3231
|
+
if (trackInfo.trackElement && trackInfo.describedSrc) {
|
|
3232
|
+
if (trackInfo.explicit === true) {
|
|
3233
|
+
try {
|
|
3234
|
+
const exists = await this._validateTrackExists(
|
|
3235
|
+
toDescribed ? trackInfo.describedSrc : trackInfo.originalSrc
|
|
3236
|
+
);
|
|
3237
|
+
return { trackInfo, exists };
|
|
3238
|
+
} catch {
|
|
3239
|
+
return { trackInfo, exists: false };
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
return { trackInfo, exists: false };
|
|
3244
|
+
});
|
|
3245
|
+
const validationResults = await Promise.all(validationPromises);
|
|
3246
|
+
const tracksToSwap = validationResults.filter((result) => result.exists);
|
|
3247
|
+
if (tracksToSwap.length > 0) {
|
|
3248
|
+
const trackModes = /* @__PURE__ */ new Map();
|
|
3249
|
+
tracksToSwap.forEach(({ trackInfo }) => {
|
|
3250
|
+
const textTrack = trackInfo.trackElement.track;
|
|
3251
|
+
if (textTrack) {
|
|
3252
|
+
trackModes.set(trackInfo, {
|
|
3253
|
+
wasShowing: textTrack.mode === "showing",
|
|
3254
|
+
wasHidden: textTrack.mode === "hidden"
|
|
3255
|
+
});
|
|
3256
|
+
} else {
|
|
3257
|
+
trackModes.set(trackInfo, { wasShowing: false, wasHidden: false });
|
|
3079
3258
|
}
|
|
3080
3259
|
});
|
|
3081
|
-
const
|
|
3082
|
-
|
|
3083
|
-
|
|
3260
|
+
const tracksToReadd = tracksToSwap.map(({ trackInfo }) => {
|
|
3261
|
+
const attributes = {};
|
|
3262
|
+
Array.from(trackInfo.trackElement.attributes).forEach((attr) => {
|
|
3263
|
+
attributes[attr.name] = attr.value;
|
|
3264
|
+
});
|
|
3265
|
+
const result = {
|
|
3266
|
+
trackInfo,
|
|
3267
|
+
oldSrc: trackInfo.trackElement.getAttribute("src"),
|
|
3268
|
+
parent: trackInfo.trackElement.parentNode,
|
|
3269
|
+
nextSibling: trackInfo.trackElement.nextSibling,
|
|
3270
|
+
attributes
|
|
3271
|
+
};
|
|
3272
|
+
trackInfo.trackElement.remove();
|
|
3273
|
+
return result;
|
|
3274
|
+
});
|
|
3275
|
+
this.player.element.load();
|
|
3276
|
+
await new Promise((resolve) => {
|
|
3277
|
+
setTimeout(() => {
|
|
3278
|
+
tracksToReadd.forEach(({ trackInfo, parent, nextSibling, attributes }) => {
|
|
3279
|
+
swappedTracks.push(trackInfo);
|
|
3280
|
+
const newTrackElement = document.createElement("track");
|
|
3281
|
+
const newSrc = toDescribed ? trackInfo.describedSrc : trackInfo.originalSrc;
|
|
3282
|
+
newTrackElement.setAttribute("src", newSrc);
|
|
3283
|
+
Object.keys(attributes).forEach((attrName) => {
|
|
3284
|
+
if (attrName !== "src" && attrName !== "data-desc-src") {
|
|
3285
|
+
newTrackElement.setAttribute(attrName, attributes[attrName]);
|
|
3286
|
+
}
|
|
3287
|
+
});
|
|
3288
|
+
const targetParent = parent || this.player.element;
|
|
3289
|
+
if (nextSibling && nextSibling.parentNode) {
|
|
3290
|
+
targetParent.insertBefore(newTrackElement, nextSibling);
|
|
3291
|
+
} else {
|
|
3292
|
+
targetParent.appendChild(newTrackElement);
|
|
3293
|
+
}
|
|
3294
|
+
trackInfo.trackElement = newTrackElement;
|
|
3295
|
+
});
|
|
3296
|
+
this.player.invalidateTrackCache();
|
|
3297
|
+
const setupNewTracks = () => {
|
|
3298
|
+
this.player.setManagedTimeout(() => {
|
|
3299
|
+
swappedTracks.forEach((trackInfo) => {
|
|
3300
|
+
const newTextTrack = trackInfo.trackElement.track;
|
|
3301
|
+
if (newTextTrack) {
|
|
3302
|
+
const modeInfo = trackModes.get(trackInfo) || { wasShowing: false, wasHidden: false };
|
|
3303
|
+
newTextTrack.mode = "hidden";
|
|
3304
|
+
const restoreMode = () => {
|
|
3305
|
+
if (modeInfo.wasShowing || modeInfo.wasHidden) {
|
|
3306
|
+
newTextTrack.mode = "hidden";
|
|
3307
|
+
} else {
|
|
3308
|
+
newTextTrack.mode = "disabled";
|
|
3309
|
+
}
|
|
3310
|
+
};
|
|
3311
|
+
if (newTextTrack.readyState >= 2) {
|
|
3312
|
+
restoreMode();
|
|
3313
|
+
} else {
|
|
3314
|
+
newTextTrack.addEventListener("load", restoreMode, { once: true });
|
|
3315
|
+
newTextTrack.addEventListener("error", restoreMode, { once: true });
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
});
|
|
3319
|
+
}, 300);
|
|
3320
|
+
};
|
|
3321
|
+
if (this.player.element.readyState >= 1) {
|
|
3322
|
+
setTimeout(setupNewTracks, 200);
|
|
3323
|
+
} else {
|
|
3324
|
+
this.player.element.addEventListener("loadedmetadata", setupNewTracks, { once: true });
|
|
3325
|
+
setTimeout(setupNewTracks, 2e3);
|
|
3326
|
+
}
|
|
3327
|
+
resolve();
|
|
3328
|
+
}, 100);
|
|
3084
3329
|
});
|
|
3085
|
-
this.element.innerHTML = "";
|
|
3086
|
-
this.element.appendChild(mediaElement);
|
|
3087
|
-
this.element = mediaElement;
|
|
3088
3330
|
}
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3331
|
+
return swappedTracks;
|
|
3332
|
+
}
|
|
3333
|
+
/**
|
|
3334
|
+
* Update source elements to described versions
|
|
3335
|
+
*/
|
|
3336
|
+
_updateSourceElements(toDescribed = true) {
|
|
3337
|
+
const sourceElements = this.player.sourceElements;
|
|
3338
|
+
const sourcesToUpdate = [];
|
|
3339
|
+
sourceElements.forEach((sourceEl) => {
|
|
3340
|
+
const descSrcAttr = sourceEl.getAttribute("data-desc-src");
|
|
3341
|
+
const currentSrc = sourceEl.getAttribute("src");
|
|
3342
|
+
if (descSrcAttr) {
|
|
3343
|
+
const type = sourceEl.getAttribute("type");
|
|
3344
|
+
let origSrc = sourceEl.getAttribute("data-orig-src") || currentSrc;
|
|
3345
|
+
sourcesToUpdate.push({
|
|
3346
|
+
src: toDescribed ? descSrcAttr : origSrc,
|
|
3347
|
+
type,
|
|
3348
|
+
origSrc,
|
|
3349
|
+
descSrc: descSrcAttr
|
|
3350
|
+
});
|
|
3351
|
+
} else {
|
|
3352
|
+
sourcesToUpdate.push({
|
|
3353
|
+
src: sourceEl.getAttribute("src"),
|
|
3354
|
+
type: sourceEl.getAttribute("type"),
|
|
3355
|
+
origSrc: null,
|
|
3356
|
+
descSrc: null
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
3359
|
+
});
|
|
3360
|
+
if (this.player.element.hasAttribute("src")) {
|
|
3361
|
+
this.player.element.removeAttribute("src");
|
|
3362
|
+
}
|
|
3363
|
+
sourceElements.forEach((sourceEl) => sourceEl.remove());
|
|
3364
|
+
sourcesToUpdate.forEach((sourceInfo) => {
|
|
3365
|
+
const newSource = document.createElement("source");
|
|
3366
|
+
newSource.setAttribute("src", sourceInfo.src);
|
|
3367
|
+
if (sourceInfo.type) {
|
|
3368
|
+
newSource.setAttribute("type", sourceInfo.type);
|
|
3369
|
+
}
|
|
3370
|
+
if (sourceInfo.origSrc) {
|
|
3371
|
+
newSource.setAttribute("data-orig-src", sourceInfo.origSrc);
|
|
3372
|
+
}
|
|
3373
|
+
if (sourceInfo.descSrc) {
|
|
3374
|
+
newSource.setAttribute("data-desc-src", sourceInfo.descSrc);
|
|
3375
|
+
}
|
|
3376
|
+
const firstTrack = this.player.element.querySelector("track");
|
|
3377
|
+
if (firstTrack) {
|
|
3378
|
+
this.player.element.insertBefore(newSource, firstTrack);
|
|
3379
|
+
} else {
|
|
3380
|
+
this.player.element.appendChild(newSource);
|
|
3381
|
+
}
|
|
3382
|
+
});
|
|
3383
|
+
this.player._sourceElementsDirty = true;
|
|
3384
|
+
this.player._sourceElementsCache = null;
|
|
3385
|
+
}
|
|
3386
|
+
/**
|
|
3387
|
+
* Wait for media to be ready
|
|
3388
|
+
*/
|
|
3389
|
+
async _waitForMediaReady(needSeek = false) {
|
|
3390
|
+
await new Promise((resolve) => {
|
|
3391
|
+
if (this.player.element.readyState >= 1) {
|
|
3392
|
+
resolve();
|
|
3393
|
+
} else {
|
|
3394
|
+
const onLoad = () => {
|
|
3395
|
+
this.player.element.removeEventListener("loadedmetadata", onLoad);
|
|
3396
|
+
resolve();
|
|
3397
|
+
};
|
|
3398
|
+
this.player.element.addEventListener("loadedmetadata", onLoad);
|
|
3399
|
+
}
|
|
3400
|
+
});
|
|
3401
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
3402
|
+
if (needSeek) {
|
|
3403
|
+
await new Promise((resolve) => {
|
|
3404
|
+
if (this.player.element.readyState >= 3) {
|
|
3405
|
+
resolve();
|
|
3406
|
+
} else {
|
|
3407
|
+
const onCanPlay = () => {
|
|
3408
|
+
this.player.element.removeEventListener("canplay", onCanPlay);
|
|
3409
|
+
this.player.element.removeEventListener("canplaythrough", onCanPlay);
|
|
3410
|
+
resolve();
|
|
3411
|
+
};
|
|
3412
|
+
this.player.element.addEventListener("canplay", onCanPlay, { once: true });
|
|
3413
|
+
this.player.element.addEventListener("canplaythrough", onCanPlay, { once: true });
|
|
3414
|
+
setTimeout(() => {
|
|
3415
|
+
this.player.element.removeEventListener("canplay", onCanPlay);
|
|
3416
|
+
this.player.element.removeEventListener("canplaythrough", onCanPlay);
|
|
3417
|
+
resolve();
|
|
3418
|
+
}, 3e3);
|
|
3419
|
+
}
|
|
3420
|
+
});
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
/**
|
|
3424
|
+
* Restore playback state after source change
|
|
3425
|
+
*/
|
|
3426
|
+
async _restorePlaybackState(currentTime, wasPlaying, shouldKeepPoster, currentCaptionText) {
|
|
3427
|
+
let syncTime = currentTime;
|
|
3428
|
+
if (currentCaptionText && this.player.captionManager && this.player.captionManager.tracks.length > 0) {
|
|
3429
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3430
|
+
const matchingTime = this.player.findMatchingCaptionTime(
|
|
3431
|
+
currentCaptionText,
|
|
3432
|
+
this.player.captionManager.tracks
|
|
3433
|
+
);
|
|
3434
|
+
if (matchingTime !== null) {
|
|
3435
|
+
syncTime = matchingTime;
|
|
3436
|
+
if (this.player.options.debug) {
|
|
3437
|
+
this.player.log(`[VidPly] Syncing via caption: ${currentTime}s -> ${syncTime}s`);
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
if (syncTime > 0) {
|
|
3442
|
+
this.player.seek(syncTime);
|
|
3443
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
3444
|
+
}
|
|
3445
|
+
if (wasPlaying) {
|
|
3446
|
+
await this.player.play();
|
|
3447
|
+
this.player.setManagedTimeout(() => {
|
|
3448
|
+
this.player.hidePosterOverlay();
|
|
3449
|
+
}, 100);
|
|
3450
|
+
} else {
|
|
3451
|
+
this.player.pause();
|
|
3452
|
+
if (!shouldKeepPoster) {
|
|
3453
|
+
this.player.hidePosterOverlay();
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
/**
|
|
3458
|
+
* Enable with source element method
|
|
3459
|
+
*/
|
|
3460
|
+
async _enableWithSourceElement(currentTime, wasPlaying, posterValue, shouldKeepPoster, currentCaptionText) {
|
|
3461
|
+
await this._swapCaptionTracks(true);
|
|
3462
|
+
this._updateSourceElements(true);
|
|
3463
|
+
if (posterValue && this.player.element.tagName === "VIDEO") {
|
|
3464
|
+
this.player.element.poster = posterValue;
|
|
3465
|
+
}
|
|
3466
|
+
this.player.element.load();
|
|
3467
|
+
await this._waitForMediaReady(currentTime > 0 || wasPlaying);
|
|
3468
|
+
await this._restorePlaybackState(currentTime, wasPlaying, shouldKeepPoster, currentCaptionText);
|
|
3469
|
+
if (!this.desiredState) return;
|
|
3470
|
+
this.enabled = true;
|
|
3471
|
+
this.player.state.audioDescriptionEnabled = true;
|
|
3472
|
+
this.player.emit("audiodescriptionenabled");
|
|
3473
|
+
this._reloadTranscript();
|
|
3474
|
+
}
|
|
3475
|
+
/**
|
|
3476
|
+
* Enable with direct src method
|
|
3477
|
+
*/
|
|
3478
|
+
async _enableWithDirectSrc(currentTime, wasPlaying, posterValue, shouldKeepPoster) {
|
|
3479
|
+
await this._swapCaptionTracks(true);
|
|
3480
|
+
if (posterValue && this.player.element.tagName === "VIDEO") {
|
|
3481
|
+
this.player.element.poster = posterValue;
|
|
3482
|
+
}
|
|
3483
|
+
this.player.element.src = this.src;
|
|
3484
|
+
await this._waitForMediaReady(currentTime > 0 || wasPlaying);
|
|
3485
|
+
if (currentTime > 0) {
|
|
3486
|
+
this.player.seek(currentTime);
|
|
3487
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
3488
|
+
}
|
|
3489
|
+
if (wasPlaying) {
|
|
3490
|
+
await this.player.play();
|
|
3491
|
+
} else {
|
|
3492
|
+
this.player.pause();
|
|
3493
|
+
if (!shouldKeepPoster) {
|
|
3494
|
+
this.player.hidePosterOverlay();
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3497
|
+
if (!this.desiredState) return;
|
|
3498
|
+
this.enabled = true;
|
|
3499
|
+
this.player.state.audioDescriptionEnabled = true;
|
|
3500
|
+
this.player.emit("audiodescriptionenabled");
|
|
3501
|
+
this._reloadTranscript();
|
|
3502
|
+
}
|
|
3503
|
+
/**
|
|
3504
|
+
* Disable with source element method
|
|
3505
|
+
*/
|
|
3506
|
+
async _disableWithSourceElement(currentTime, wasPlaying, posterValue, shouldKeepPoster, currentCaptionText) {
|
|
3507
|
+
await this._swapCaptionTracks(false);
|
|
3508
|
+
this._updateSourceElements(false);
|
|
3509
|
+
if (posterValue && this.player.element.tagName === "VIDEO") {
|
|
3510
|
+
this.player.element.poster = posterValue;
|
|
3511
|
+
}
|
|
3512
|
+
this.player.element.load();
|
|
3513
|
+
this.player.invalidateTrackCache();
|
|
3514
|
+
await this._waitForMediaReady(currentTime > 0 || wasPlaying);
|
|
3515
|
+
await this._restorePlaybackState(currentTime, wasPlaying, shouldKeepPoster, currentCaptionText);
|
|
3516
|
+
if (this.player.captionManager) {
|
|
3517
|
+
this.player.captionManager.destroy();
|
|
3518
|
+
this.player.captionManager = new CaptionManager(this.player);
|
|
3519
|
+
}
|
|
3520
|
+
if (this.desiredState) return;
|
|
3521
|
+
this.enabled = false;
|
|
3522
|
+
this.player.state.audioDescriptionEnabled = false;
|
|
3523
|
+
this.player.emit("audiodescriptiondisabled");
|
|
3524
|
+
this._reloadTranscript();
|
|
3525
|
+
}
|
|
3526
|
+
/**
|
|
3527
|
+
* Disable with direct src method
|
|
3528
|
+
*/
|
|
3529
|
+
async _disableWithDirectSrc(currentTime, wasPlaying, posterValue) {
|
|
3530
|
+
await this._swapCaptionTracks(false);
|
|
3531
|
+
if (posterValue && this.player.element.tagName === "VIDEO") {
|
|
3532
|
+
this.player.element.poster = posterValue;
|
|
3533
|
+
}
|
|
3534
|
+
const originalSrcToUse = this.originalSource || this.player.originalSrc;
|
|
3535
|
+
this.player.element.src = originalSrcToUse;
|
|
3536
|
+
this.player.element.load();
|
|
3537
|
+
await this._waitForMediaReady(currentTime > 0 || wasPlaying);
|
|
3538
|
+
if (currentTime > 0) {
|
|
3539
|
+
this.player.seek(currentTime);
|
|
3540
|
+
}
|
|
3541
|
+
if (wasPlaying) {
|
|
3542
|
+
await this.player.play();
|
|
3543
|
+
}
|
|
3544
|
+
if (this.desiredState) return;
|
|
3545
|
+
this.enabled = false;
|
|
3546
|
+
this.player.state.audioDescriptionEnabled = false;
|
|
3547
|
+
this.player.emit("audiodescriptiondisabled");
|
|
3548
|
+
this._reloadTranscript();
|
|
3549
|
+
}
|
|
3550
|
+
/**
|
|
3551
|
+
* Reload transcript after audio description state change
|
|
3552
|
+
*/
|
|
3553
|
+
_reloadTranscript() {
|
|
3554
|
+
if (this.player.transcriptManager && this.player.transcriptManager.isVisible) {
|
|
3555
|
+
this.player.setManagedTimeout(() => {
|
|
3556
|
+
if (this.player.transcriptManager && this.player.transcriptManager.loadTranscriptData) {
|
|
3557
|
+
this.player.transcriptManager.loadTranscriptData();
|
|
3558
|
+
}
|
|
3559
|
+
}, 800);
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
/**
|
|
3563
|
+
* Update sources (called when playlist changes)
|
|
3564
|
+
*/
|
|
3565
|
+
updateSources(audioDescriptionSrc) {
|
|
3566
|
+
this.src = audioDescriptionSrc || null;
|
|
3567
|
+
this.enabled = false;
|
|
3568
|
+
this.desiredState = false;
|
|
3569
|
+
this.sourceElement = null;
|
|
3570
|
+
this.originalSource = null;
|
|
3571
|
+
this.captionTracks = [];
|
|
3572
|
+
}
|
|
3573
|
+
/**
|
|
3574
|
+
* Reinitialize from current player elements (called after playlist loads new tracks)
|
|
3575
|
+
*/
|
|
3576
|
+
reinitialize() {
|
|
3577
|
+
this.player.invalidateTrackCache();
|
|
3578
|
+
this.initFromSourceElements(this.player.sourceElements, this.player.trackElements);
|
|
3579
|
+
}
|
|
3580
|
+
/**
|
|
3581
|
+
* Cleanup
|
|
3582
|
+
*/
|
|
3583
|
+
destroy() {
|
|
3584
|
+
this.enabled = false;
|
|
3585
|
+
this.desiredState = false;
|
|
3586
|
+
this.captionTracks = [];
|
|
3587
|
+
this.sourceElement = null;
|
|
3588
|
+
this.originalSource = null;
|
|
3589
|
+
}
|
|
3590
|
+
};
|
|
3591
|
+
|
|
3592
|
+
// src/core/SignLanguageManager.js
|
|
3593
|
+
var SignLanguageManager = class {
|
|
3594
|
+
constructor(player) {
|
|
3595
|
+
this.player = player;
|
|
3596
|
+
this.src = player.options.signLanguageSrc;
|
|
3597
|
+
this.sources = player.options.signLanguageSources || {};
|
|
3598
|
+
this.currentLanguage = null;
|
|
3599
|
+
this.desiredPosition = player.options.signLanguagePosition || "bottom-right";
|
|
3600
|
+
this.wrapper = null;
|
|
3601
|
+
this.header = null;
|
|
3602
|
+
this.video = null;
|
|
3603
|
+
this.selector = null;
|
|
3604
|
+
this.settingsButton = null;
|
|
3605
|
+
this.settingsMenu = null;
|
|
3606
|
+
this.resizeHandles = [];
|
|
3607
|
+
this.enabled = false;
|
|
3608
|
+
this.settingsMenuVisible = false;
|
|
3609
|
+
this.settingsMenuJustOpened = false;
|
|
3610
|
+
this.documentClickHandlerAdded = false;
|
|
3611
|
+
this.handlers = null;
|
|
3612
|
+
this.settingsHandlers = null;
|
|
3613
|
+
this.interactionHandlers = null;
|
|
3614
|
+
this.draggable = null;
|
|
3615
|
+
this.documentClickHandler = null;
|
|
3616
|
+
this.settingsMenuKeyHandler = null;
|
|
3617
|
+
this.customKeyHandler = null;
|
|
3618
|
+
this.dragOptionButton = null;
|
|
3619
|
+
this.dragOptionText = null;
|
|
3620
|
+
this.resizeOptionButton = null;
|
|
3621
|
+
this.resizeOptionText = null;
|
|
3622
|
+
}
|
|
3623
|
+
/**
|
|
3624
|
+
* Check if sign language is available
|
|
3625
|
+
*/
|
|
3626
|
+
isAvailable() {
|
|
3627
|
+
return Object.keys(this.sources).length > 0 || !!this.src;
|
|
3628
|
+
}
|
|
3629
|
+
/**
|
|
3630
|
+
* Enable sign language video
|
|
3631
|
+
*/
|
|
3632
|
+
enable() {
|
|
3633
|
+
const hasMultipleSources = Object.keys(this.sources).length > 0;
|
|
3634
|
+
const hasSingleSource = !!this.src;
|
|
3635
|
+
if (!hasMultipleSources && !hasSingleSource) {
|
|
3636
|
+
console.warn("No sign language video source provided");
|
|
3637
|
+
return;
|
|
3638
|
+
}
|
|
3639
|
+
if (this.wrapper) {
|
|
3640
|
+
this.wrapper.style.display = "block";
|
|
3641
|
+
this.enabled = true;
|
|
3642
|
+
this.player.state.signLanguageEnabled = true;
|
|
3643
|
+
this.player.emit("signlanguageenabled");
|
|
3644
|
+
this.player.setManagedTimeout(() => {
|
|
3645
|
+
if (this.settingsButton && document.contains(this.settingsButton)) {
|
|
3646
|
+
this.settingsButton.focus({ preventScroll: true });
|
|
3647
|
+
}
|
|
3648
|
+
}, 150);
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
let initialLang = null;
|
|
3652
|
+
let initialSrc = null;
|
|
3653
|
+
if (hasMultipleSources) {
|
|
3654
|
+
initialLang = this._determineInitialLanguage();
|
|
3655
|
+
initialSrc = this.sources[initialLang];
|
|
3656
|
+
this.currentLanguage = initialLang;
|
|
3657
|
+
} else {
|
|
3658
|
+
initialSrc = this.src;
|
|
3659
|
+
}
|
|
3660
|
+
this._createWrapper();
|
|
3661
|
+
this._createHeader(hasMultipleSources, initialLang);
|
|
3662
|
+
this._createVideo(initialSrc);
|
|
3663
|
+
this._createResizeHandles();
|
|
3664
|
+
this.wrapper.appendChild(this.header);
|
|
3665
|
+
this.wrapper.appendChild(this.video);
|
|
3666
|
+
this.resizeHandles.forEach((handle) => this.wrapper.appendChild(handle));
|
|
3667
|
+
this._applyInitialSize();
|
|
3668
|
+
this.player.container.appendChild(this.wrapper);
|
|
3669
|
+
requestAnimationFrame(() => {
|
|
3670
|
+
this.constrainPosition();
|
|
3671
|
+
});
|
|
3672
|
+
this.video.currentTime = this.player.state.currentTime;
|
|
3673
|
+
if (!this.player.state.paused) {
|
|
3674
|
+
this.video.play();
|
|
3675
|
+
}
|
|
3676
|
+
this._setupInteraction();
|
|
3677
|
+
this._setupEventHandlers(hasMultipleSources);
|
|
3678
|
+
this.enabled = true;
|
|
3679
|
+
this.player.state.signLanguageEnabled = true;
|
|
3680
|
+
this.player.emit("signlanguageenabled");
|
|
3681
|
+
this.player.setManagedTimeout(() => {
|
|
3682
|
+
if (this.settingsButton && document.contains(this.settingsButton)) {
|
|
3683
|
+
this.settingsButton.focus({ preventScroll: true });
|
|
3684
|
+
}
|
|
3685
|
+
}, 150);
|
|
3686
|
+
}
|
|
3687
|
+
/**
|
|
3688
|
+
* Disable sign language video
|
|
3689
|
+
*/
|
|
3690
|
+
disable() {
|
|
3691
|
+
if (this.settingsMenuVisible) {
|
|
3692
|
+
this.hideSettingsMenu({ focusButton: false });
|
|
3693
|
+
}
|
|
3694
|
+
if (this.wrapper) {
|
|
3695
|
+
this.wrapper.style.display = "none";
|
|
3696
|
+
}
|
|
3697
|
+
this.enabled = false;
|
|
3698
|
+
this.player.state.signLanguageEnabled = false;
|
|
3699
|
+
this.player.emit("signlanguagedisabled");
|
|
3700
|
+
}
|
|
3701
|
+
/**
|
|
3702
|
+
* Toggle sign language video
|
|
3703
|
+
*/
|
|
3704
|
+
toggle() {
|
|
3705
|
+
if (this.enabled) {
|
|
3706
|
+
this.disable();
|
|
3707
|
+
} else {
|
|
3708
|
+
this.enable();
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
/**
|
|
3712
|
+
* Switch to a different sign language
|
|
3713
|
+
*/
|
|
3714
|
+
switchLanguage(langCode) {
|
|
3715
|
+
if (!this.sources[langCode] || !this.video) {
|
|
3716
|
+
return;
|
|
3717
|
+
}
|
|
3718
|
+
const currentTime = this.video.currentTime;
|
|
3719
|
+
const wasPlaying = !this.video.paused;
|
|
3720
|
+
this.video.src = this.sources[langCode];
|
|
3721
|
+
this.currentLanguage = langCode;
|
|
3722
|
+
this.video.currentTime = currentTime;
|
|
3723
|
+
if (wasPlaying) {
|
|
3724
|
+
this.video.play().catch(() => {
|
|
3725
|
+
});
|
|
3726
|
+
}
|
|
3727
|
+
this.player.emit("signlanguagelanguagechanged", langCode);
|
|
3728
|
+
}
|
|
3729
|
+
/**
|
|
3730
|
+
* Get language label
|
|
3731
|
+
*/
|
|
3732
|
+
getLanguageLabel(langCode) {
|
|
3733
|
+
const langNames = {
|
|
3734
|
+
"en": "English",
|
|
3735
|
+
"de": "Deutsch",
|
|
3736
|
+
"es": "Español",
|
|
3737
|
+
"fr": "Français",
|
|
3738
|
+
"it": "Italiano",
|
|
3739
|
+
"ja": "日本語",
|
|
3740
|
+
"pt": "Português",
|
|
3741
|
+
"ar": "العربية",
|
|
3742
|
+
"hi": "हिन्दी"
|
|
3743
|
+
};
|
|
3744
|
+
return langNames[langCode] || langCode.toUpperCase();
|
|
3745
|
+
}
|
|
3746
|
+
/**
|
|
3747
|
+
* Determine initial sign language
|
|
3748
|
+
*/
|
|
3749
|
+
_determineInitialLanguage() {
|
|
3750
|
+
if (this.player.captionManager && this.player.captionManager.currentTrack) {
|
|
3751
|
+
const captionLang = this.player.captionManager.currentTrack.language?.toLowerCase().split("-")[0];
|
|
3752
|
+
if (captionLang && this.sources[captionLang]) {
|
|
3753
|
+
return captionLang;
|
|
3754
|
+
}
|
|
3755
|
+
}
|
|
3756
|
+
if (this.player.options.language) {
|
|
3757
|
+
const playerLang = this.player.options.language.toLowerCase().split("-")[0];
|
|
3758
|
+
if (this.sources[playerLang]) {
|
|
3759
|
+
return playerLang;
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3762
|
+
return Object.keys(this.sources)[0];
|
|
3763
|
+
}
|
|
3764
|
+
/**
|
|
3765
|
+
* Create wrapper element
|
|
3766
|
+
*/
|
|
3767
|
+
_createWrapper() {
|
|
3768
|
+
this.wrapper = document.createElement("div");
|
|
3769
|
+
this.wrapper.className = "vidply-sign-language-wrapper";
|
|
3770
|
+
this.wrapper.setAttribute("tabindex", "0");
|
|
3771
|
+
this.wrapper.setAttribute("aria-label", i18n.t("player.signLanguageDragResize"));
|
|
3772
|
+
}
|
|
3773
|
+
/**
|
|
3774
|
+
* Create header element
|
|
3775
|
+
*/
|
|
3776
|
+
_createHeader(hasMultipleSources, initialLang) {
|
|
3777
|
+
const classPrefix = this.player.options.classPrefix;
|
|
3778
|
+
this.header = DOMUtils.createElement("div", {
|
|
3779
|
+
className: `${classPrefix}-sign-language-header`,
|
|
3780
|
+
attributes: { "tabindex": "0" }
|
|
3781
|
+
});
|
|
3782
|
+
const headerLeft = DOMUtils.createElement("div", {
|
|
3783
|
+
className: `${classPrefix}-sign-language-header-left`
|
|
3784
|
+
});
|
|
3785
|
+
const title = DOMUtils.createElement("h3", {
|
|
3786
|
+
textContent: i18n.t("player.signLanguageVideo")
|
|
3787
|
+
});
|
|
3788
|
+
this._createSettingsButton(headerLeft);
|
|
3789
|
+
if (hasMultipleSources) {
|
|
3790
|
+
this._createLanguageSelector(headerLeft, initialLang);
|
|
3791
|
+
}
|
|
3792
|
+
headerLeft.appendChild(title);
|
|
3793
|
+
const closeButton = this._createCloseButton();
|
|
3794
|
+
this.header.appendChild(headerLeft);
|
|
3795
|
+
this.header.appendChild(closeButton);
|
|
3796
|
+
this.settingsMenuVisible = false;
|
|
3797
|
+
this.settingsMenu = null;
|
|
3798
|
+
this.settingsMenuJustOpened = false;
|
|
3799
|
+
}
|
|
3800
|
+
/**
|
|
3801
|
+
* Create settings button
|
|
3802
|
+
*/
|
|
3803
|
+
_createSettingsButton(container) {
|
|
3804
|
+
const classPrefix = this.player.options.classPrefix;
|
|
3805
|
+
const ariaLabel = i18n.t("player.signLanguageSettings");
|
|
3806
|
+
this.settingsButton = DOMUtils.createElement("button", {
|
|
3807
|
+
className: `${classPrefix}-sign-language-settings`,
|
|
3808
|
+
attributes: {
|
|
3809
|
+
"type": "button",
|
|
3810
|
+
"aria-label": ariaLabel,
|
|
3811
|
+
"aria-expanded": "false"
|
|
3812
|
+
}
|
|
3813
|
+
});
|
|
3814
|
+
this.settingsButton.appendChild(createIconElement("settings"));
|
|
3815
|
+
DOMUtils.attachTooltip(this.settingsButton, ariaLabel, classPrefix);
|
|
3816
|
+
this.settingsHandlers = {
|
|
3817
|
+
click: (e) => {
|
|
3818
|
+
e.preventDefault();
|
|
3819
|
+
e.stopPropagation();
|
|
3820
|
+
if (this.documentClickHandler) {
|
|
3821
|
+
this.settingsMenuJustOpened = true;
|
|
3822
|
+
setTimeout(() => {
|
|
3823
|
+
this.settingsMenuJustOpened = false;
|
|
3824
|
+
}, 100);
|
|
3825
|
+
}
|
|
3826
|
+
if (this.settingsMenuVisible) {
|
|
3827
|
+
this.hideSettingsMenu();
|
|
3828
|
+
} else {
|
|
3829
|
+
this.showSettingsMenu();
|
|
3830
|
+
}
|
|
3831
|
+
},
|
|
3832
|
+
keydown: (e) => {
|
|
3833
|
+
if (e.key === "d" || e.key === "D") {
|
|
3834
|
+
e.preventDefault();
|
|
3835
|
+
e.stopPropagation();
|
|
3836
|
+
this.toggleKeyboardDragMode();
|
|
3837
|
+
} else if (e.key === "r" || e.key === "R") {
|
|
3838
|
+
e.preventDefault();
|
|
3839
|
+
e.stopPropagation();
|
|
3840
|
+
this.toggleResizeMode();
|
|
3841
|
+
} else if (e.key === "Escape" && this.settingsMenuVisible) {
|
|
3842
|
+
e.preventDefault();
|
|
3843
|
+
e.stopPropagation();
|
|
3844
|
+
this.hideSettingsMenu();
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
};
|
|
3848
|
+
this.settingsButton.addEventListener("click", this.settingsHandlers.click);
|
|
3849
|
+
this.settingsButton.addEventListener("keydown", this.settingsHandlers.keydown);
|
|
3850
|
+
container.appendChild(this.settingsButton);
|
|
3851
|
+
}
|
|
3852
|
+
/**
|
|
3853
|
+
* Create language selector
|
|
3854
|
+
*/
|
|
3855
|
+
_createLanguageSelector(container, initialLang) {
|
|
3856
|
+
const classPrefix = this.player.options.classPrefix;
|
|
3857
|
+
const selectId = `${classPrefix}-sign-language-select-${Date.now()}`;
|
|
3858
|
+
const options = Object.keys(this.sources).map((langCode) => ({
|
|
3859
|
+
value: langCode,
|
|
3860
|
+
text: this.getLanguageLabel(langCode),
|
|
3861
|
+
selected: langCode === initialLang
|
|
3862
|
+
}));
|
|
3863
|
+
const { label, select } = createLabeledSelect({
|
|
3864
|
+
classPrefix,
|
|
3865
|
+
labelClass: `${classPrefix}-sign-language-label`,
|
|
3866
|
+
selectClass: `${classPrefix}-sign-language-select`,
|
|
3867
|
+
labelText: "settings.language",
|
|
3868
|
+
selectId,
|
|
3869
|
+
options,
|
|
3870
|
+
onChange: (e) => {
|
|
3871
|
+
e.stopPropagation();
|
|
3872
|
+
this.switchLanguage(e.target.value);
|
|
3873
|
+
}
|
|
3874
|
+
});
|
|
3875
|
+
this.selector = select;
|
|
3876
|
+
const selectorWrapper = DOMUtils.createElement("div", {
|
|
3877
|
+
className: `${classPrefix}-sign-language-selector-wrapper`
|
|
3878
|
+
});
|
|
3879
|
+
selectorWrapper.appendChild(label);
|
|
3880
|
+
selectorWrapper.appendChild(this.selector);
|
|
3881
|
+
preventDragOnElement(selectorWrapper);
|
|
3882
|
+
container.appendChild(selectorWrapper);
|
|
3883
|
+
}
|
|
3884
|
+
/**
|
|
3885
|
+
* Create close button
|
|
3886
|
+
*/
|
|
3887
|
+
_createCloseButton() {
|
|
3888
|
+
const classPrefix = this.player.options.classPrefix;
|
|
3889
|
+
const ariaLabel = i18n.t("player.closeSignLanguage");
|
|
3890
|
+
const closeButton = DOMUtils.createElement("button", {
|
|
3891
|
+
className: `${classPrefix}-sign-language-close`,
|
|
3892
|
+
attributes: {
|
|
3893
|
+
"type": "button",
|
|
3894
|
+
"aria-label": ariaLabel
|
|
3895
|
+
}
|
|
3896
|
+
});
|
|
3897
|
+
closeButton.appendChild(createIconElement("close"));
|
|
3898
|
+
DOMUtils.attachTooltip(closeButton, ariaLabel, classPrefix);
|
|
3899
|
+
closeButton.addEventListener("click", () => {
|
|
3900
|
+
this.disable();
|
|
3901
|
+
if (this.player.controlBar?.controls?.signLanguage) {
|
|
3902
|
+
setTimeout(() => {
|
|
3903
|
+
this.player.controlBar.controls.signLanguage.focus({ preventScroll: true });
|
|
3904
|
+
}, 0);
|
|
3905
|
+
}
|
|
3906
|
+
});
|
|
3907
|
+
return closeButton;
|
|
3908
|
+
}
|
|
3909
|
+
/**
|
|
3910
|
+
* Create video element
|
|
3911
|
+
*/
|
|
3912
|
+
_createVideo(src) {
|
|
3913
|
+
this.video = document.createElement("video");
|
|
3914
|
+
this.video.className = "vidply-sign-language-video";
|
|
3915
|
+
this.video.src = src;
|
|
3916
|
+
this.video.setAttribute("aria-label", i18n.t("player.signLanguage"));
|
|
3917
|
+
this.video.muted = true;
|
|
3918
|
+
this.video.setAttribute("playsinline", "");
|
|
3919
|
+
}
|
|
3920
|
+
/**
|
|
3921
|
+
* Create resize handles
|
|
3922
|
+
*/
|
|
3923
|
+
_createResizeHandles() {
|
|
3924
|
+
const classPrefix = this.player.options.classPrefix;
|
|
3925
|
+
this.resizeHandles = ["n", "s", "e", "w", "ne", "nw", "se", "sw"].map((dir) => {
|
|
3926
|
+
const handle = DOMUtils.createElement("div", {
|
|
3927
|
+
className: `${classPrefix}-sign-resize-handle ${classPrefix}-sign-resize-${dir}`,
|
|
3928
|
+
attributes: {
|
|
3929
|
+
"data-direction": dir,
|
|
3930
|
+
"data-vidply-managed-resize": "true",
|
|
3931
|
+
"aria-hidden": "true"
|
|
3932
|
+
}
|
|
3933
|
+
});
|
|
3934
|
+
handle.style.display = "none";
|
|
3935
|
+
return handle;
|
|
3936
|
+
});
|
|
3937
|
+
}
|
|
3938
|
+
/**
|
|
3939
|
+
* Apply initial size
|
|
3940
|
+
*/
|
|
3941
|
+
_applyInitialSize() {
|
|
3942
|
+
const saved = this.player.storage.getSignLanguagePreferences();
|
|
3943
|
+
if (saved?.size?.width) {
|
|
3944
|
+
this.wrapper.style.width = saved.size.width;
|
|
3945
|
+
} else {
|
|
3946
|
+
this.wrapper.style.width = "280px";
|
|
3947
|
+
}
|
|
3948
|
+
this.wrapper.style.height = "auto";
|
|
3949
|
+
}
|
|
3950
|
+
/**
|
|
3951
|
+
* Setup interaction (drag and resize)
|
|
3952
|
+
*/
|
|
3953
|
+
_setupInteraction() {
|
|
3954
|
+
const isMobile2 = window.innerWidth < 768;
|
|
3955
|
+
const isFullscreen = this.player.state.fullscreen;
|
|
3956
|
+
if (isMobile2 && !isFullscreen) {
|
|
3957
|
+
if (this.draggable) {
|
|
3958
|
+
this.draggable.destroy();
|
|
3959
|
+
this.draggable = null;
|
|
3960
|
+
}
|
|
3961
|
+
return;
|
|
3962
|
+
}
|
|
3963
|
+
if (this.draggable) return;
|
|
3964
|
+
const classPrefix = this.player.options.classPrefix;
|
|
3965
|
+
this.draggable = new DraggableResizable(this.wrapper, {
|
|
3966
|
+
dragHandle: this.header,
|
|
3967
|
+
resizeHandles: this.resizeHandles,
|
|
3968
|
+
constrainToViewport: true,
|
|
3969
|
+
maintainAspectRatio: true,
|
|
3970
|
+
minWidth: 150,
|
|
3971
|
+
minHeight: 100,
|
|
3972
|
+
classPrefix: `${classPrefix}-sign`,
|
|
3973
|
+
keyboardDragKey: "d",
|
|
3974
|
+
keyboardResizeKey: "r",
|
|
3975
|
+
keyboardStep: 10,
|
|
3976
|
+
keyboardStepLarge: 50,
|
|
3977
|
+
pointerResizeIndicatorText: i18n.t("player.signLanguageResizeActive"),
|
|
3978
|
+
onPointerResizeToggle: (enabled) => {
|
|
3979
|
+
this.resizeHandles.forEach((handle) => {
|
|
3980
|
+
handle.style.display = enabled ? "block" : "none";
|
|
3981
|
+
});
|
|
3982
|
+
},
|
|
3983
|
+
onDragStart: (e) => {
|
|
3984
|
+
if (e.target.closest(`.${classPrefix}-sign-language-close`) || e.target.closest(`.${classPrefix}-sign-language-settings`) || e.target.closest(`.${classPrefix}-sign-language-select`) || e.target.closest(`.${classPrefix}-sign-language-label`) || e.target.closest(`.${classPrefix}-sign-language-settings-menu`)) {
|
|
3985
|
+
return false;
|
|
3986
|
+
}
|
|
3987
|
+
return true;
|
|
3988
|
+
}
|
|
3989
|
+
});
|
|
3990
|
+
this._setupCustomKeyHandler();
|
|
3991
|
+
this.interactionHandlers = {
|
|
3992
|
+
draggable: this.draggable,
|
|
3993
|
+
customKeyHandler: this.customKeyHandler
|
|
3994
|
+
};
|
|
3995
|
+
}
|
|
3996
|
+
/**
|
|
3997
|
+
* Setup custom keyboard handler
|
|
3998
|
+
*/
|
|
3999
|
+
_setupCustomKeyHandler() {
|
|
4000
|
+
this.customKeyHandler = (e) => {
|
|
4001
|
+
const key = e.key.toLowerCase();
|
|
4002
|
+
if (this.settingsMenuVisible) return;
|
|
4003
|
+
if (key === "home") {
|
|
4004
|
+
e.preventDefault();
|
|
4005
|
+
e.stopPropagation();
|
|
4006
|
+
if (this.draggable) {
|
|
4007
|
+
if (this.draggable.pointerResizeMode) {
|
|
4008
|
+
this.draggable.disablePointerResizeMode();
|
|
4009
|
+
}
|
|
4010
|
+
this.draggable.manuallyPositioned = false;
|
|
4011
|
+
this.constrainPosition();
|
|
4012
|
+
}
|
|
4013
|
+
return;
|
|
4014
|
+
}
|
|
4015
|
+
if (key === "r") {
|
|
4016
|
+
e.preventDefault();
|
|
4017
|
+
e.stopPropagation();
|
|
4018
|
+
if (this.toggleResizeMode()) {
|
|
4019
|
+
this.wrapper.focus({ preventScroll: true });
|
|
4020
|
+
}
|
|
4021
|
+
return;
|
|
4022
|
+
}
|
|
4023
|
+
if (key === "escape") {
|
|
4024
|
+
e.preventDefault();
|
|
4025
|
+
e.stopPropagation();
|
|
4026
|
+
if (this.draggable?.pointerResizeMode) {
|
|
4027
|
+
this.draggable.disablePointerResizeMode();
|
|
4028
|
+
return;
|
|
4029
|
+
}
|
|
4030
|
+
if (this.draggable?.keyboardDragMode) {
|
|
4031
|
+
this.draggable.disableKeyboardDragMode();
|
|
4032
|
+
return;
|
|
4033
|
+
}
|
|
4034
|
+
this.disable();
|
|
4035
|
+
if (this.player.controlBar?.controls?.signLanguage) {
|
|
4036
|
+
setTimeout(() => {
|
|
4037
|
+
this.player.controlBar.controls.signLanguage.focus({ preventScroll: true });
|
|
4038
|
+
}, 0);
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
4041
|
+
};
|
|
4042
|
+
this.wrapper.addEventListener("keydown", this.customKeyHandler);
|
|
4043
|
+
}
|
|
4044
|
+
/**
|
|
4045
|
+
* Setup event handlers
|
|
4046
|
+
*/
|
|
4047
|
+
_setupEventHandlers(hasMultipleSources) {
|
|
4048
|
+
this.handlers = {
|
|
4049
|
+
play: () => {
|
|
4050
|
+
if (this.video) this.video.play();
|
|
4051
|
+
},
|
|
4052
|
+
pause: () => {
|
|
4053
|
+
if (this.video) this.video.pause();
|
|
4054
|
+
},
|
|
4055
|
+
timeupdate: () => {
|
|
4056
|
+
if (this.video && Math.abs(this.video.currentTime - this.player.state.currentTime) > 0.5) {
|
|
4057
|
+
this.video.currentTime = this.player.state.currentTime;
|
|
4058
|
+
}
|
|
4059
|
+
},
|
|
4060
|
+
ratechange: () => {
|
|
4061
|
+
if (this.video) this.video.playbackRate = this.player.state.playbackSpeed;
|
|
4062
|
+
}
|
|
4063
|
+
};
|
|
4064
|
+
this.player.on("play", this.handlers.play);
|
|
4065
|
+
this.player.on("pause", this.handlers.pause);
|
|
4066
|
+
this.player.on("timeupdate", this.handlers.timeupdate);
|
|
4067
|
+
this.player.on("ratechange", this.handlers.ratechange);
|
|
4068
|
+
if (hasMultipleSources) {
|
|
4069
|
+
this.handlers.captionChange = () => {
|
|
4070
|
+
if (this.player.captionManager?.currentTrack && this.selector) {
|
|
4071
|
+
const captionLang = this.player.captionManager.currentTrack.language?.toLowerCase().split("-")[0];
|
|
4072
|
+
if (captionLang && this.sources[captionLang] && this.currentLanguage !== captionLang) {
|
|
4073
|
+
this.switchLanguage(captionLang);
|
|
4074
|
+
this.selector.value = captionLang;
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
};
|
|
4078
|
+
this.player.on("captionsenabled", this.handlers.captionChange);
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
/**
|
|
4082
|
+
* Constrain position within video wrapper
|
|
4083
|
+
*/
|
|
4084
|
+
constrainPosition() {
|
|
4085
|
+
if (!this.wrapper || !this.player.videoWrapper) return;
|
|
4086
|
+
if (this.draggable?.manuallyPositioned) return;
|
|
4087
|
+
if (!this.wrapper.style.width) {
|
|
4088
|
+
this.wrapper.style.width = "280px";
|
|
4089
|
+
}
|
|
4090
|
+
const videoWrapperRect = this.player.videoWrapper.getBoundingClientRect();
|
|
4091
|
+
const containerRect = this.player.container.getBoundingClientRect();
|
|
4092
|
+
const wrapperRect = this.wrapper.getBoundingClientRect();
|
|
4093
|
+
const videoWrapperLeft = videoWrapperRect.left - containerRect.left;
|
|
4094
|
+
const videoWrapperTop = videoWrapperRect.top - containerRect.top;
|
|
4095
|
+
const videoWrapperWidth = videoWrapperRect.width;
|
|
4096
|
+
const videoWrapperHeight = videoWrapperRect.height;
|
|
4097
|
+
let wrapperWidth = wrapperRect.width || 280;
|
|
4098
|
+
let wrapperHeight = wrapperRect.height || 280 * 9 / 16;
|
|
4099
|
+
let left, top;
|
|
4100
|
+
const margin = 16;
|
|
4101
|
+
const controlsHeight = 95;
|
|
4102
|
+
const position = this.desiredPosition || "bottom-right";
|
|
4103
|
+
switch (position) {
|
|
4104
|
+
case "bottom-right":
|
|
4105
|
+
left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;
|
|
4106
|
+
top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;
|
|
4107
|
+
break;
|
|
4108
|
+
case "bottom-left":
|
|
4109
|
+
left = videoWrapperLeft + margin;
|
|
4110
|
+
top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;
|
|
4111
|
+
break;
|
|
4112
|
+
case "top-right":
|
|
4113
|
+
left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;
|
|
4114
|
+
top = videoWrapperTop + margin;
|
|
4115
|
+
break;
|
|
4116
|
+
case "top-left":
|
|
4117
|
+
left = videoWrapperLeft + margin;
|
|
4118
|
+
top = videoWrapperTop + margin;
|
|
4119
|
+
break;
|
|
4120
|
+
default:
|
|
4121
|
+
left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;
|
|
4122
|
+
top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;
|
|
4123
|
+
}
|
|
4124
|
+
left = Math.max(videoWrapperLeft, Math.min(left, videoWrapperLeft + videoWrapperWidth - wrapperWidth));
|
|
4125
|
+
top = Math.max(videoWrapperTop, Math.min(top, videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight));
|
|
4126
|
+
this.wrapper.style.left = `${left}px`;
|
|
4127
|
+
this.wrapper.style.top = `${top}px`;
|
|
4128
|
+
this.wrapper.style.right = "auto";
|
|
4129
|
+
this.wrapper.style.bottom = "auto";
|
|
4130
|
+
}
|
|
4131
|
+
/**
|
|
4132
|
+
* Show settings menu
|
|
4133
|
+
*/
|
|
4134
|
+
showSettingsMenu() {
|
|
4135
|
+
this.settingsMenuJustOpened = true;
|
|
4136
|
+
setTimeout(() => {
|
|
4137
|
+
this.settingsMenuJustOpened = false;
|
|
4138
|
+
}, 350);
|
|
4139
|
+
this._addDocumentClickHandler();
|
|
4140
|
+
if (this.settingsMenu) {
|
|
4141
|
+
this.settingsMenu.style.display = "block";
|
|
4142
|
+
this.settingsMenuVisible = true;
|
|
4143
|
+
this.settingsButton?.setAttribute("aria-expanded", "true");
|
|
4144
|
+
this._attachMenuKeyboardNavigation();
|
|
4145
|
+
this._positionSettingsMenu();
|
|
4146
|
+
this._updateDragOptionState();
|
|
4147
|
+
this._updateResizeOptionState();
|
|
4148
|
+
focusFirstMenuItem(this.settingsMenu, `.${this.player.options.classPrefix}-sign-language-settings-item`);
|
|
4149
|
+
return;
|
|
4150
|
+
}
|
|
4151
|
+
this._createSettingsMenu();
|
|
4152
|
+
}
|
|
4153
|
+
/**
|
|
4154
|
+
* Hide settings menu
|
|
4155
|
+
*/
|
|
4156
|
+
hideSettingsMenu({ focusButton = true } = {}) {
|
|
4157
|
+
if (this.settingsMenu) {
|
|
4158
|
+
this.settingsMenu.style.display = "none";
|
|
4159
|
+
this.settingsMenuVisible = false;
|
|
4160
|
+
this.settingsMenuJustOpened = false;
|
|
4161
|
+
if (this.settingsMenuKeyHandler) {
|
|
4162
|
+
this.settingsMenu.removeEventListener("keydown", this.settingsMenuKeyHandler);
|
|
4163
|
+
this.settingsMenuKeyHandler = null;
|
|
4164
|
+
}
|
|
4165
|
+
const classPrefix = this.player.options.classPrefix;
|
|
4166
|
+
const menuItems = Array.from(this.settingsMenu.querySelectorAll(`.${classPrefix}-sign-language-settings-item`));
|
|
4167
|
+
menuItems.forEach((item) => item.setAttribute("tabindex", "-1"));
|
|
4168
|
+
if (this.settingsButton) {
|
|
4169
|
+
this.settingsButton.setAttribute("aria-expanded", "false");
|
|
4170
|
+
if (focusButton) {
|
|
4171
|
+
this.settingsButton.focus({ preventScroll: true });
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
/**
|
|
4177
|
+
* Add document click handler
|
|
4178
|
+
*/
|
|
4179
|
+
_addDocumentClickHandler() {
|
|
4180
|
+
if (this.documentClickHandlerAdded) return;
|
|
4181
|
+
this.documentClickHandler = (e) => {
|
|
4182
|
+
if (this.settingsMenuJustOpened) return;
|
|
4183
|
+
if (this.settingsButton && (this.settingsButton === e.target || this.settingsButton.contains(e.target))) {
|
|
4184
|
+
return;
|
|
4185
|
+
}
|
|
4186
|
+
if (this.settingsMenu && this.settingsMenu.contains(e.target)) {
|
|
4187
|
+
return;
|
|
4188
|
+
}
|
|
4189
|
+
if (this.settingsMenuVisible) {
|
|
4190
|
+
this.hideSettingsMenu();
|
|
4191
|
+
}
|
|
4192
|
+
};
|
|
4193
|
+
setTimeout(() => {
|
|
4194
|
+
document.addEventListener("mousedown", this.documentClickHandler, true);
|
|
4195
|
+
this.documentClickHandlerAdded = true;
|
|
4196
|
+
}, 300);
|
|
4197
|
+
}
|
|
4198
|
+
/**
|
|
4199
|
+
* Create settings menu
|
|
4200
|
+
*/
|
|
4201
|
+
_createSettingsMenu() {
|
|
4202
|
+
const classPrefix = this.player.options.classPrefix;
|
|
4203
|
+
this.settingsMenu = DOMUtils.createElement("div", {
|
|
4204
|
+
className: `${classPrefix}-sign-language-settings-menu`,
|
|
4205
|
+
attributes: { "role": "menu" }
|
|
4206
|
+
});
|
|
4207
|
+
const dragOption = createMenuItem({
|
|
4208
|
+
classPrefix,
|
|
4209
|
+
itemClass: `${classPrefix}-sign-language-settings-item`,
|
|
4210
|
+
icon: "move",
|
|
4211
|
+
label: "player.enableSignDragMode",
|
|
4212
|
+
hasTextClass: true,
|
|
4213
|
+
onClick: () => {
|
|
4214
|
+
this.toggleKeyboardDragMode();
|
|
4215
|
+
this.hideSettingsMenu();
|
|
4216
|
+
}
|
|
4217
|
+
});
|
|
4218
|
+
dragOption.setAttribute("role", "switch");
|
|
4219
|
+
dragOption.setAttribute("aria-checked", "false");
|
|
4220
|
+
this._removeTooltipFromMenuItem(dragOption);
|
|
4221
|
+
this.dragOptionButton = dragOption;
|
|
4222
|
+
this.dragOptionText = dragOption.querySelector(`.${classPrefix}-settings-text`);
|
|
4223
|
+
this._updateDragOptionState();
|
|
4224
|
+
const resizeOption = createMenuItem({
|
|
4225
|
+
classPrefix,
|
|
4226
|
+
itemClass: `${classPrefix}-sign-language-settings-item`,
|
|
4227
|
+
icon: "resize",
|
|
4228
|
+
label: "player.enableSignResizeMode",
|
|
4229
|
+
hasTextClass: true,
|
|
4230
|
+
onClick: (event) => {
|
|
4231
|
+
event.preventDefault();
|
|
4232
|
+
event.stopPropagation();
|
|
4233
|
+
const enabled = this.toggleResizeMode({ focus: false });
|
|
4234
|
+
if (enabled) {
|
|
4235
|
+
this.hideSettingsMenu({ focusButton: false });
|
|
4236
|
+
setTimeout(() => {
|
|
4237
|
+
if (this.wrapper) this.wrapper.focus({ preventScroll: true });
|
|
4238
|
+
}, 20);
|
|
4239
|
+
} else {
|
|
4240
|
+
this.hideSettingsMenu({ focusButton: true });
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
});
|
|
4244
|
+
resizeOption.setAttribute("role", "switch");
|
|
4245
|
+
resizeOption.setAttribute("aria-checked", "false");
|
|
4246
|
+
this._removeTooltipFromMenuItem(resizeOption);
|
|
4247
|
+
this.resizeOptionButton = resizeOption;
|
|
4248
|
+
this.resizeOptionText = resizeOption.querySelector(`.${classPrefix}-settings-text`);
|
|
4249
|
+
this._updateResizeOptionState();
|
|
4250
|
+
const closeOption = createMenuItem({
|
|
4251
|
+
classPrefix,
|
|
4252
|
+
itemClass: `${classPrefix}-sign-language-settings-item`,
|
|
4253
|
+
icon: "close",
|
|
4254
|
+
label: "transcript.closeMenu",
|
|
4255
|
+
onClick: () => this.hideSettingsMenu()
|
|
4256
|
+
});
|
|
4257
|
+
this._removeTooltipFromMenuItem(closeOption);
|
|
4258
|
+
this.settingsMenu.appendChild(dragOption);
|
|
4259
|
+
this.settingsMenu.appendChild(resizeOption);
|
|
4260
|
+
this.settingsMenu.appendChild(closeOption);
|
|
4261
|
+
this.settingsMenu.style.visibility = "hidden";
|
|
4262
|
+
this.settingsMenu.style.display = "block";
|
|
4263
|
+
if (this.settingsButton?.parentNode) {
|
|
4264
|
+
this.settingsButton.insertAdjacentElement("afterend", this.settingsMenu);
|
|
4265
|
+
} else if (this.wrapper) {
|
|
4266
|
+
this.wrapper.appendChild(this.settingsMenu);
|
|
4267
|
+
}
|
|
4268
|
+
this._positionSettingsMenuImmediate();
|
|
4269
|
+
requestAnimationFrame(() => {
|
|
4270
|
+
if (this.settingsMenu) {
|
|
4271
|
+
this.settingsMenu.style.visibility = "visible";
|
|
4272
|
+
}
|
|
4273
|
+
});
|
|
4274
|
+
this._attachMenuKeyboardNavigation();
|
|
4275
|
+
this.settingsMenuVisible = true;
|
|
4276
|
+
this.settingsButton?.setAttribute("aria-expanded", "true");
|
|
4277
|
+
this._updateDragOptionState();
|
|
4278
|
+
this._updateResizeOptionState();
|
|
4279
|
+
focusFirstMenuItem(this.settingsMenu, `.${classPrefix}-sign-language-settings-item`);
|
|
4280
|
+
}
|
|
4281
|
+
/**
|
|
4282
|
+
* Remove tooltip from menu item
|
|
4283
|
+
*/
|
|
4284
|
+
_removeTooltipFromMenuItem(item) {
|
|
4285
|
+
const classPrefix = this.player.options.classPrefix;
|
|
4286
|
+
const tooltip = item.querySelector(`.${classPrefix}-tooltip`);
|
|
4287
|
+
if (tooltip) tooltip.remove();
|
|
4288
|
+
const buttonText = item.querySelector(`.${classPrefix}-button-text`);
|
|
4289
|
+
if (buttonText) buttonText.remove();
|
|
4290
|
+
}
|
|
4291
|
+
/**
|
|
4292
|
+
* Attach menu keyboard navigation
|
|
4293
|
+
*/
|
|
4294
|
+
_attachMenuKeyboardNavigation() {
|
|
4295
|
+
if (this.settingsMenuKeyHandler) {
|
|
4296
|
+
this.settingsMenu.removeEventListener("keydown", this.settingsMenuKeyHandler);
|
|
4297
|
+
}
|
|
4298
|
+
this.settingsMenuKeyHandler = attachMenuKeyboardNavigation(
|
|
4299
|
+
this.settingsMenu,
|
|
4300
|
+
this.settingsButton,
|
|
4301
|
+
`.${this.player.options.classPrefix}-sign-language-settings-item`,
|
|
4302
|
+
() => this.hideSettingsMenu({ focusButton: true })
|
|
4303
|
+
);
|
|
4304
|
+
}
|
|
4305
|
+
/**
|
|
4306
|
+
* Position settings menu immediately
|
|
4307
|
+
*/
|
|
4308
|
+
_positionSettingsMenuImmediate() {
|
|
4309
|
+
if (!this.settingsMenu || !this.settingsButton) return;
|
|
4310
|
+
const buttonRect = this.settingsButton.getBoundingClientRect();
|
|
4311
|
+
const menuRect = this.settingsMenu.getBoundingClientRect();
|
|
4312
|
+
const viewportWidth = window.innerWidth;
|
|
4313
|
+
const viewportHeight = window.innerHeight;
|
|
4314
|
+
const parentContainer = this.settingsButton.parentElement;
|
|
4315
|
+
if (!parentContainer) return;
|
|
4316
|
+
const parentRect = parentContainer.getBoundingClientRect();
|
|
4317
|
+
const buttonCenterX = buttonRect.left + buttonRect.width / 2 - parentRect.left;
|
|
4318
|
+
const buttonBottom = buttonRect.bottom - parentRect.top;
|
|
4319
|
+
const buttonTop = buttonRect.top - parentRect.top;
|
|
4320
|
+
const spaceAbove = buttonRect.top;
|
|
4321
|
+
const spaceBelow = viewportHeight - buttonRect.bottom;
|
|
4322
|
+
let menuTop = buttonBottom + 8;
|
|
4323
|
+
let menuBottom = null;
|
|
4324
|
+
if (spaceBelow < menuRect.height + 20 && spaceAbove > spaceBelow) {
|
|
4325
|
+
menuTop = null;
|
|
4326
|
+
const parentHeight = parentRect.bottom - parentRect.top;
|
|
4327
|
+
menuBottom = parentHeight - buttonTop + 8;
|
|
4328
|
+
this.settingsMenu.classList.add("vidply-menu-above");
|
|
4329
|
+
} else {
|
|
4330
|
+
this.settingsMenu.classList.remove("vidply-menu-above");
|
|
4331
|
+
}
|
|
4332
|
+
let menuLeft = buttonCenterX - menuRect.width / 2;
|
|
4333
|
+
let menuRight = "auto";
|
|
4334
|
+
let transformX = "translateX(0)";
|
|
4335
|
+
const menuLeftAbsolute = buttonRect.left + buttonRect.width / 2 - menuRect.width / 2;
|
|
4336
|
+
if (menuLeftAbsolute < 10) {
|
|
4337
|
+
menuLeft = 0;
|
|
4338
|
+
} else if (menuLeftAbsolute + menuRect.width > viewportWidth - 10) {
|
|
4339
|
+
menuLeft = "auto";
|
|
4340
|
+
menuRight = 0;
|
|
4341
|
+
} else {
|
|
4342
|
+
menuLeft = buttonCenterX;
|
|
4343
|
+
transformX = "translateX(-50%)";
|
|
4344
|
+
}
|
|
4345
|
+
if (menuTop !== null) {
|
|
4346
|
+
this.settingsMenu.style.top = `${menuTop}px`;
|
|
4347
|
+
this.settingsMenu.style.bottom = "auto";
|
|
4348
|
+
} else if (menuBottom !== null) {
|
|
4349
|
+
this.settingsMenu.style.top = "auto";
|
|
4350
|
+
this.settingsMenu.style.bottom = `${menuBottom}px`;
|
|
4351
|
+
}
|
|
4352
|
+
if (menuLeft !== "auto") {
|
|
4353
|
+
this.settingsMenu.style.left = `${menuLeft}px`;
|
|
4354
|
+
this.settingsMenu.style.right = "auto";
|
|
4355
|
+
} else {
|
|
4356
|
+
this.settingsMenu.style.left = "auto";
|
|
4357
|
+
this.settingsMenu.style.right = `${menuRight}px`;
|
|
4358
|
+
}
|
|
4359
|
+
this.settingsMenu.style.transform = transformX;
|
|
4360
|
+
}
|
|
4361
|
+
/**
|
|
4362
|
+
* Position settings menu with RAF
|
|
4363
|
+
*/
|
|
4364
|
+
_positionSettingsMenu() {
|
|
4365
|
+
requestAnimationFrame(() => {
|
|
4366
|
+
setTimeout(() => {
|
|
4367
|
+
this._positionSettingsMenuImmediate();
|
|
4368
|
+
}, 10);
|
|
4369
|
+
});
|
|
4370
|
+
}
|
|
4371
|
+
/**
|
|
4372
|
+
* Toggle keyboard drag mode
|
|
4373
|
+
*/
|
|
4374
|
+
toggleKeyboardDragMode() {
|
|
4375
|
+
if (this.draggable) {
|
|
4376
|
+
const wasEnabled = this.draggable.keyboardDragMode;
|
|
4377
|
+
this.draggable.toggleKeyboardDragMode();
|
|
4378
|
+
const isEnabled = this.draggable.keyboardDragMode;
|
|
4379
|
+
if (!wasEnabled && isEnabled) {
|
|
4380
|
+
this._enableMoveMode();
|
|
4381
|
+
}
|
|
4382
|
+
this._updateDragOptionState();
|
|
4383
|
+
}
|
|
4384
|
+
}
|
|
4385
|
+
/**
|
|
4386
|
+
* Enable move mode visual feedback
|
|
4387
|
+
*/
|
|
4388
|
+
_enableMoveMode() {
|
|
4389
|
+
this.wrapper.classList.add(`${this.player.options.classPrefix}-sign-move-mode`);
|
|
4390
|
+
this._updateResizeOptionState();
|
|
4391
|
+
setTimeout(() => {
|
|
4392
|
+
this.wrapper.classList.remove(`${this.player.options.classPrefix}-sign-move-mode`);
|
|
4393
|
+
}, 2e3);
|
|
4394
|
+
}
|
|
4395
|
+
/**
|
|
4396
|
+
* Toggle resize mode
|
|
4397
|
+
*/
|
|
4398
|
+
toggleResizeMode({ focus = true } = {}) {
|
|
4399
|
+
if (!this.draggable) return false;
|
|
4400
|
+
if (this.draggable.pointerResizeMode) {
|
|
4401
|
+
this.draggable.disablePointerResizeMode({ focus });
|
|
4402
|
+
this._updateResizeOptionState();
|
|
4403
|
+
return false;
|
|
4404
|
+
}
|
|
4405
|
+
this.draggable.enablePointerResizeMode({ focus });
|
|
4406
|
+
this._updateResizeOptionState();
|
|
4407
|
+
return true;
|
|
4408
|
+
}
|
|
4409
|
+
/**
|
|
4410
|
+
* Update drag option state
|
|
4411
|
+
*/
|
|
4412
|
+
_updateDragOptionState() {
|
|
4413
|
+
if (!this.dragOptionButton) return;
|
|
4414
|
+
const isEnabled = !!this.draggable?.keyboardDragMode;
|
|
4415
|
+
const text = isEnabled ? i18n.t("player.disableSignDragMode") : i18n.t("player.enableSignDragMode");
|
|
4416
|
+
const ariaLabel = isEnabled ? i18n.t("player.disableSignDragModeAria") : i18n.t("player.enableSignDragModeAria");
|
|
4417
|
+
this.dragOptionButton.setAttribute("aria-checked", isEnabled ? "true" : "false");
|
|
4418
|
+
this.dragOptionButton.setAttribute("aria-label", ariaLabel);
|
|
4419
|
+
if (this.dragOptionText) {
|
|
4420
|
+
this.dragOptionText.textContent = text;
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
/**
|
|
4424
|
+
* Update resize option state
|
|
4425
|
+
*/
|
|
4426
|
+
_updateResizeOptionState() {
|
|
4427
|
+
if (!this.resizeOptionButton) return;
|
|
4428
|
+
const isEnabled = !!this.draggable?.pointerResizeMode;
|
|
4429
|
+
const text = isEnabled ? i18n.t("player.disableSignResizeMode") : i18n.t("player.enableSignResizeMode");
|
|
4430
|
+
const ariaLabel = isEnabled ? i18n.t("player.disableSignResizeModeAria") : i18n.t("player.enableSignResizeModeAria");
|
|
4431
|
+
this.resizeOptionButton.setAttribute("aria-checked", isEnabled ? "true" : "false");
|
|
4432
|
+
this.resizeOptionButton.setAttribute("aria-label", ariaLabel);
|
|
4433
|
+
if (this.resizeOptionText) {
|
|
4434
|
+
this.resizeOptionText.textContent = text;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
/**
|
|
4438
|
+
* Save preferences
|
|
4439
|
+
*/
|
|
4440
|
+
savePreferences() {
|
|
4441
|
+
if (!this.wrapper) return;
|
|
4442
|
+
this.player.storage.saveSignLanguagePreferences({
|
|
4443
|
+
size: { width: this.wrapper.style.width }
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
/**
|
|
4447
|
+
* Update sources (called when playlist changes)
|
|
4448
|
+
*/
|
|
4449
|
+
updateSources(signLanguageSrc, signLanguageSources) {
|
|
4450
|
+
this.src = signLanguageSrc || null;
|
|
4451
|
+
this.sources = signLanguageSources || {};
|
|
4452
|
+
this.currentLanguage = null;
|
|
4453
|
+
}
|
|
4454
|
+
/**
|
|
4455
|
+
* Cleanup
|
|
4456
|
+
*/
|
|
4457
|
+
cleanup() {
|
|
4458
|
+
if (this.settingsMenuVisible) {
|
|
4459
|
+
this.hideSettingsMenu({ focusButton: false });
|
|
4460
|
+
}
|
|
4461
|
+
if (this.documentClickHandler && this.documentClickHandlerAdded) {
|
|
4462
|
+
document.removeEventListener("mousedown", this.documentClickHandler, true);
|
|
4463
|
+
this.documentClickHandlerAdded = false;
|
|
4464
|
+
this.documentClickHandler = null;
|
|
4465
|
+
}
|
|
4466
|
+
if (this.settingsHandlers && this.settingsButton) {
|
|
4467
|
+
this.settingsButton.removeEventListener("click", this.settingsHandlers.click);
|
|
4468
|
+
this.settingsButton.removeEventListener("keydown", this.settingsHandlers.keydown);
|
|
4469
|
+
}
|
|
4470
|
+
this.settingsHandlers = null;
|
|
4471
|
+
if (this.handlers) {
|
|
4472
|
+
this.player.off("play", this.handlers.play);
|
|
4473
|
+
this.player.off("pause", this.handlers.pause);
|
|
4474
|
+
this.player.off("timeupdate", this.handlers.timeupdate);
|
|
4475
|
+
this.player.off("ratechange", this.handlers.ratechange);
|
|
4476
|
+
if (this.handlers.captionChange) {
|
|
4477
|
+
this.player.off("captionsenabled", this.handlers.captionChange);
|
|
4478
|
+
}
|
|
4479
|
+
this.handlers = null;
|
|
4480
|
+
}
|
|
4481
|
+
if (this.wrapper && this.customKeyHandler) {
|
|
4482
|
+
this.wrapper.removeEventListener("keydown", this.customKeyHandler);
|
|
4483
|
+
}
|
|
4484
|
+
if (this.draggable) {
|
|
4485
|
+
if (this.draggable.pointerResizeMode) {
|
|
4486
|
+
this.draggable.disablePointerResizeMode();
|
|
4487
|
+
}
|
|
4488
|
+
this.draggable.destroy();
|
|
4489
|
+
this.draggable = null;
|
|
4490
|
+
}
|
|
4491
|
+
this.interactionHandlers = null;
|
|
4492
|
+
if (this.wrapper?.parentNode) {
|
|
4493
|
+
if (this.video) {
|
|
4494
|
+
this.video.pause();
|
|
4495
|
+
this.video.src = "";
|
|
4496
|
+
}
|
|
4497
|
+
this.wrapper.parentNode.removeChild(this.wrapper);
|
|
4498
|
+
}
|
|
4499
|
+
this.wrapper = null;
|
|
4500
|
+
this.video = null;
|
|
4501
|
+
this.settingsButton = null;
|
|
4502
|
+
this.settingsMenu = null;
|
|
4503
|
+
}
|
|
4504
|
+
/**
|
|
4505
|
+
* Destroy
|
|
4506
|
+
*/
|
|
4507
|
+
destroy() {
|
|
4508
|
+
this.cleanup();
|
|
4509
|
+
this.enabled = false;
|
|
4510
|
+
}
|
|
4511
|
+
};
|
|
4512
|
+
|
|
4513
|
+
// src/core/Player.js
|
|
4514
|
+
var playerInstanceCounter = 0;
|
|
4515
|
+
var Player = class _Player extends EventEmitter {
|
|
4516
|
+
constructor(element, options = {}) {
|
|
4517
|
+
super();
|
|
4518
|
+
this.element = typeof element === "string" ? document.querySelector(element) : element;
|
|
4519
|
+
if (!this.element) {
|
|
4520
|
+
throw new Error("VidPly: Element not found");
|
|
4521
|
+
}
|
|
4522
|
+
playerInstanceCounter++;
|
|
4523
|
+
this.instanceId = playerInstanceCounter;
|
|
4524
|
+
if (this.element.tagName !== "VIDEO" && this.element.tagName !== "AUDIO") {
|
|
4525
|
+
const mediaType = options.mediaType || "video";
|
|
4526
|
+
const mediaElement = document.createElement(mediaType);
|
|
4527
|
+
Array.from(this.element.attributes).forEach((attr) => {
|
|
4528
|
+
if (attr.name !== "id" && attr.name !== "class" && !attr.name.startsWith("data-")) {
|
|
4529
|
+
mediaElement.setAttribute(attr.name, attr.value);
|
|
4530
|
+
}
|
|
4531
|
+
});
|
|
4532
|
+
const tracks = this.element.querySelectorAll("track");
|
|
4533
|
+
tracks.forEach((track) => {
|
|
4534
|
+
mediaElement.appendChild(track.cloneNode(true));
|
|
4535
|
+
});
|
|
4536
|
+
this.element.innerHTML = "";
|
|
4537
|
+
this.element.appendChild(mediaElement);
|
|
4538
|
+
this.element = mediaElement;
|
|
4539
|
+
}
|
|
4540
|
+
this._originalElement = this.element;
|
|
4541
|
+
this.options = {
|
|
4542
|
+
// Display
|
|
4543
|
+
width: null,
|
|
4544
|
+
height: null,
|
|
4545
|
+
poster: null,
|
|
4546
|
+
responsive: true,
|
|
4547
|
+
fillContainer: false,
|
|
4548
|
+
// Playback
|
|
4549
|
+
autoplay: false,
|
|
4550
|
+
loop: false,
|
|
4551
|
+
muted: false,
|
|
4552
|
+
volume: 0.8,
|
|
4553
|
+
playbackSpeed: 1,
|
|
4554
|
+
preload: "metadata",
|
|
4555
|
+
startTime: 0,
|
|
4556
|
+
playsInline: true,
|
|
4557
|
+
// Enable inline playback on iOS (prevents native fullscreen)
|
|
4558
|
+
// Controls
|
|
4559
|
+
controls: true,
|
|
4560
|
+
hideControlsDelay: 3e3,
|
|
4561
|
+
playPauseButton: true,
|
|
4562
|
+
progressBar: true,
|
|
4563
|
+
currentTime: true,
|
|
4564
|
+
duration: true,
|
|
4565
|
+
volumeControl: true,
|
|
4566
|
+
muteButton: true,
|
|
4567
|
+
chaptersButton: true,
|
|
4568
|
+
qualityButton: true,
|
|
4569
|
+
captionStyleButton: true,
|
|
4570
|
+
speedButton: true,
|
|
4571
|
+
captionsButton: true,
|
|
4572
|
+
transcriptButton: true,
|
|
4573
|
+
fullscreenButton: true,
|
|
4574
|
+
pipButton: false,
|
|
4575
|
+
// Seeking
|
|
4576
|
+
seekInterval: 10,
|
|
4577
|
+
seekIntervalLarge: 30,
|
|
4578
|
+
// Captions
|
|
4579
|
+
captions: true,
|
|
4580
|
+
captionsDefault: false,
|
|
4581
|
+
captionsFontSize: "100%",
|
|
4582
|
+
captionsFontFamily: "sans-serif",
|
|
4583
|
+
captionsColor: "#FFFFFF",
|
|
4584
|
+
captionsBackgroundColor: "#000000",
|
|
4585
|
+
captionsOpacity: 0.8,
|
|
4586
|
+
// Audio Description
|
|
4587
|
+
audioDescription: true,
|
|
4588
|
+
audioDescriptionSrc: null,
|
|
4589
|
+
// URL to audio-described version
|
|
4590
|
+
audioDescriptionButton: true,
|
|
4591
|
+
// Sign Language
|
|
4592
|
+
signLanguage: true,
|
|
4593
|
+
signLanguageSrc: null,
|
|
4594
|
+
// URL to sign language video
|
|
4595
|
+
signLanguageButton: true,
|
|
4596
|
+
signLanguagePosition: "bottom-right",
|
|
4597
|
+
// Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'
|
|
4598
|
+
// Transcripts
|
|
4599
|
+
transcript: false,
|
|
4600
|
+
transcriptPosition: "external",
|
|
4601
|
+
transcriptContainer: null,
|
|
4602
|
+
// Keyboard
|
|
4603
|
+
keyboard: true,
|
|
3153
4604
|
keyboardShortcuts: {
|
|
3154
4605
|
"play-pause": [" ", "p", "k"],
|
|
3155
4606
|
"volume-up": ["ArrowUp"],
|
|
@@ -3246,6 +4697,58 @@ var Player = class _Player extends EventEmitter {
|
|
|
3246
4697
|
this.settingsDialog = null;
|
|
3247
4698
|
this.metadataCueChangeHandler = null;
|
|
3248
4699
|
this.metadataAlertHandlers = /* @__PURE__ */ new Map();
|
|
4700
|
+
this.audioDescriptionManager = new AudioDescriptionManager(this);
|
|
4701
|
+
this.signLanguageManager = new SignLanguageManager(this);
|
|
4702
|
+
Object.defineProperties(this, {
|
|
4703
|
+
signLanguageWrapper: {
|
|
4704
|
+
get: () => this.signLanguageManager.wrapper,
|
|
4705
|
+
set: (v) => {
|
|
4706
|
+
this.signLanguageManager.wrapper = v;
|
|
4707
|
+
}
|
|
4708
|
+
},
|
|
4709
|
+
signLanguageVideo: {
|
|
4710
|
+
get: () => this.signLanguageManager.video,
|
|
4711
|
+
set: (v) => {
|
|
4712
|
+
this.signLanguageManager.video = v;
|
|
4713
|
+
}
|
|
4714
|
+
},
|
|
4715
|
+
signLanguageHeader: {
|
|
4716
|
+
get: () => this.signLanguageManager.header,
|
|
4717
|
+
set: (v) => {
|
|
4718
|
+
this.signLanguageManager.header = v;
|
|
4719
|
+
}
|
|
4720
|
+
},
|
|
4721
|
+
signLanguageSettingsButton: {
|
|
4722
|
+
get: () => this.signLanguageManager.settingsButton,
|
|
4723
|
+
set: (v) => {
|
|
4724
|
+
this.signLanguageManager.settingsButton = v;
|
|
4725
|
+
}
|
|
4726
|
+
},
|
|
4727
|
+
signLanguageSettingsMenu: {
|
|
4728
|
+
get: () => this.signLanguageManager.settingsMenu,
|
|
4729
|
+
set: (v) => {
|
|
4730
|
+
this.signLanguageManager.settingsMenu = v;
|
|
4731
|
+
}
|
|
4732
|
+
},
|
|
4733
|
+
signLanguageSettingsMenuVisible: {
|
|
4734
|
+
get: () => this.signLanguageManager.settingsMenuVisible,
|
|
4735
|
+
set: (v) => {
|
|
4736
|
+
this.signLanguageManager.settingsMenuVisible = v;
|
|
4737
|
+
}
|
|
4738
|
+
},
|
|
4739
|
+
signLanguageDraggable: {
|
|
4740
|
+
get: () => this.signLanguageManager.draggable,
|
|
4741
|
+
set: (v) => {
|
|
4742
|
+
this.signLanguageManager.draggable = v;
|
|
4743
|
+
}
|
|
4744
|
+
},
|
|
4745
|
+
currentSignLanguage: {
|
|
4746
|
+
get: () => this.signLanguageManager.currentLanguage,
|
|
4747
|
+
set: (v) => {
|
|
4748
|
+
this.signLanguageManager.currentLanguage = v;
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
});
|
|
3249
4752
|
this.init();
|
|
3250
4753
|
}
|
|
3251
4754
|
async init() {
|
|
@@ -3339,7 +4842,7 @@ var Player = class _Player extends EventEmitter {
|
|
|
3339
4842
|
if (!this.options.transcript && !this.options.transcriptButton) {
|
|
3340
4843
|
return null;
|
|
3341
4844
|
}
|
|
3342
|
-
const module = await import("./vidply.TranscriptManager-
|
|
4845
|
+
const module = await import("./vidply.TranscriptManager-T677KF4N.js");
|
|
3343
4846
|
const Manager = module.TranscriptManager || module.default;
|
|
3344
4847
|
if (!Manager) {
|
|
3345
4848
|
return null;
|
|
@@ -3506,53 +5009,7 @@ var Player = class _Player extends EventEmitter {
|
|
|
3506
5009
|
}
|
|
3507
5010
|
this.currentSource = src;
|
|
3508
5011
|
this._pendingSource = null;
|
|
3509
|
-
|
|
3510
|
-
for (const sourceEl of sourceElements) {
|
|
3511
|
-
const descSrc = sourceEl.getAttribute("data-desc-src");
|
|
3512
|
-
const origSrc = sourceEl.getAttribute("data-orig-src");
|
|
3513
|
-
if (descSrc || origSrc) {
|
|
3514
|
-
if (!this.audioDescriptionSourceElement) {
|
|
3515
|
-
this.audioDescriptionSourceElement = sourceEl;
|
|
3516
|
-
}
|
|
3517
|
-
if (origSrc) {
|
|
3518
|
-
if (!this.originalAudioDescriptionSource) {
|
|
3519
|
-
this.originalAudioDescriptionSource = origSrc;
|
|
3520
|
-
}
|
|
3521
|
-
if (!this.originalSrc) {
|
|
3522
|
-
this.originalSrc = origSrc;
|
|
3523
|
-
}
|
|
3524
|
-
} else {
|
|
3525
|
-
const currentSrcAttr = sourceEl.getAttribute("src");
|
|
3526
|
-
if (!this.originalAudioDescriptionSource && currentSrcAttr) {
|
|
3527
|
-
this.originalAudioDescriptionSource = currentSrcAttr;
|
|
3528
|
-
}
|
|
3529
|
-
if (!this.originalSrc && currentSrcAttr) {
|
|
3530
|
-
this.originalSrc = currentSrcAttr;
|
|
3531
|
-
}
|
|
3532
|
-
}
|
|
3533
|
-
if (descSrc && !this.audioDescriptionSrc) {
|
|
3534
|
-
this.audioDescriptionSrc = descSrc;
|
|
3535
|
-
}
|
|
3536
|
-
}
|
|
3537
|
-
}
|
|
3538
|
-
const trackElements = this.trackElements;
|
|
3539
|
-
trackElements.forEach((trackEl) => {
|
|
3540
|
-
const trackKind = trackEl.getAttribute("kind");
|
|
3541
|
-
const trackDescSrc = trackEl.getAttribute("data-desc-src");
|
|
3542
|
-
if (trackKind === "captions" || trackKind === "subtitles" || trackKind === "chapters") {
|
|
3543
|
-
if (trackDescSrc) {
|
|
3544
|
-
this.audioDescriptionCaptionTracks.push({
|
|
3545
|
-
trackElement: trackEl,
|
|
3546
|
-
originalSrc: trackEl.getAttribute("src"),
|
|
3547
|
-
describedSrc: trackDescSrc,
|
|
3548
|
-
originalTrackSrc: trackEl.getAttribute("data-orig-src") || trackEl.getAttribute("src"),
|
|
3549
|
-
explicit: true
|
|
3550
|
-
// Explicitly defined, so we should validate it
|
|
3551
|
-
});
|
|
3552
|
-
this.log(`Found explicit described ${trackKind} track: ${trackEl.getAttribute("src")} -> ${trackDescSrc}`);
|
|
3553
|
-
}
|
|
3554
|
-
}
|
|
3555
|
-
});
|
|
5012
|
+
this.audioDescriptionManager.initFromSourceElements(this.sourceElements, this.trackElements);
|
|
3556
5013
|
if (!this.originalSrc) {
|
|
3557
5014
|
this.originalSrc = src;
|
|
3558
5015
|
}
|
|
@@ -3796,6 +5253,9 @@ var Player = class _Player extends EventEmitter {
|
|
|
3796
5253
|
if (trackConfig.default) {
|
|
3797
5254
|
track.default = true;
|
|
3798
5255
|
}
|
|
5256
|
+
if (trackConfig.describedSrc) {
|
|
5257
|
+
track.setAttribute("data-desc-src", trackConfig.describedSrc);
|
|
5258
|
+
}
|
|
3799
5259
|
const firstChild = this.element.firstChild;
|
|
3800
5260
|
if (firstChild && firstChild.nodeType === Node.ELEMENT_NODE && firstChild.tagName !== "TRACK") {
|
|
3801
5261
|
this.element.insertBefore(track, firstChild);
|
|
@@ -3810,6 +5270,13 @@ var Player = class _Player extends EventEmitter {
|
|
|
3810
5270
|
this.audioDescriptionSrc = config.audioDescriptionSrc || null;
|
|
3811
5271
|
this.signLanguageSrc = config.signLanguageSrc || null;
|
|
3812
5272
|
this.originalSrc = config.src;
|
|
5273
|
+
if (this.audioDescriptionManager) {
|
|
5274
|
+
this.audioDescriptionManager.updateSources(config.audioDescriptionSrc);
|
|
5275
|
+
this.audioDescriptionManager.reinitialize();
|
|
5276
|
+
}
|
|
5277
|
+
if (this.signLanguageManager) {
|
|
5278
|
+
this.signLanguageManager.updateSources(config.signLanguageSrc, config.signLanguageSources);
|
|
5279
|
+
}
|
|
3813
5280
|
if (wasAudioDescriptionEnabled) {
|
|
3814
5281
|
this.disableAudioDescription();
|
|
3815
5282
|
}
|
|
@@ -4217,8 +5684,12 @@ var Player = class _Player extends EventEmitter {
|
|
|
4217
5684
|
}
|
|
4218
5685
|
return null;
|
|
4219
5686
|
}
|
|
4220
|
-
// Audio Description
|
|
5687
|
+
// Audio Description (delegated to AudioDescriptionManager)
|
|
4221
5688
|
async enableAudioDescription() {
|
|
5689
|
+
return this.audioDescriptionManager.enable();
|
|
5690
|
+
}
|
|
5691
|
+
// Legacy method body preserved for reference - can be removed after testing
|
|
5692
|
+
async _legacyEnableAudioDescription() {
|
|
4222
5693
|
const hasSourceElementsWithDesc = this.sourceElements.some((el) => el.getAttribute("data-desc-src"));
|
|
4223
5694
|
const hasTracksWithDesc = this.audioDescriptionCaptionTracks.length > 0;
|
|
4224
5695
|
if (!this.audioDescriptionSrc && !hasSourceElementsWithDesc && !hasTracksWithDesc) {
|
|
@@ -4951,6 +6422,10 @@ var Player = class _Player extends EventEmitter {
|
|
|
4951
6422
|
this.emit("audiodescriptionenabled");
|
|
4952
6423
|
}
|
|
4953
6424
|
async disableAudioDescription() {
|
|
6425
|
+
return this.audioDescriptionManager.disable();
|
|
6426
|
+
}
|
|
6427
|
+
// Legacy method body preserved for reference - can be removed after testing
|
|
6428
|
+
async _legacyDisableAudioDescription() {
|
|
4954
6429
|
if (!this.originalSrc) {
|
|
4955
6430
|
return;
|
|
4956
6431
|
}
|
|
@@ -5225,64 +6700,14 @@ var Player = class _Player extends EventEmitter {
|
|
|
5225
6700
|
this.emit("audiodescriptiondisabled");
|
|
5226
6701
|
}
|
|
5227
6702
|
async toggleAudioDescription() {
|
|
5228
|
-
|
|
5229
|
-
const hasAudioDescriptionSrc = this.audioDescriptionSrc || this.sourceElements.some((el) => el.getAttribute("data-desc-src"));
|
|
5230
|
-
if (descriptionTrack && hasAudioDescriptionSrc) {
|
|
5231
|
-
if (this.state.audioDescriptionEnabled) {
|
|
5232
|
-
this._audioDescriptionDesiredState = false;
|
|
5233
|
-
descriptionTrack.mode = "hidden";
|
|
5234
|
-
await this.disableAudioDescription();
|
|
5235
|
-
} else {
|
|
5236
|
-
this._audioDescriptionDesiredState = true;
|
|
5237
|
-
await this.enableAudioDescription();
|
|
5238
|
-
const enableDescriptionTrack = () => {
|
|
5239
|
-
this.invalidateTrackCache();
|
|
5240
|
-
const descTrack = this.findTextTrack("descriptions");
|
|
5241
|
-
if (descTrack) {
|
|
5242
|
-
if (descTrack.mode === "disabled") {
|
|
5243
|
-
descTrack.mode = "hidden";
|
|
5244
|
-
this.setManagedTimeout(() => {
|
|
5245
|
-
descTrack.mode = "showing";
|
|
5246
|
-
}, 50);
|
|
5247
|
-
} else {
|
|
5248
|
-
descTrack.mode = "showing";
|
|
5249
|
-
}
|
|
5250
|
-
} else if (this.element.readyState < 2) {
|
|
5251
|
-
this.setManagedTimeout(enableDescriptionTrack, 100);
|
|
5252
|
-
}
|
|
5253
|
-
};
|
|
5254
|
-
if (this.element.readyState >= 1) {
|
|
5255
|
-
this.setManagedTimeout(enableDescriptionTrack, 200);
|
|
5256
|
-
} else {
|
|
5257
|
-
this.element.addEventListener("loadedmetadata", () => {
|
|
5258
|
-
this.setManagedTimeout(enableDescriptionTrack, 200);
|
|
5259
|
-
}, { once: true });
|
|
5260
|
-
}
|
|
5261
|
-
}
|
|
5262
|
-
} else if (descriptionTrack) {
|
|
5263
|
-
if (descriptionTrack.mode === "showing") {
|
|
5264
|
-
this._audioDescriptionDesiredState = false;
|
|
5265
|
-
descriptionTrack.mode = "hidden";
|
|
5266
|
-
this.state.audioDescriptionEnabled = false;
|
|
5267
|
-
this.emit("audiodescriptiondisabled");
|
|
5268
|
-
} else {
|
|
5269
|
-
this._audioDescriptionDesiredState = true;
|
|
5270
|
-
descriptionTrack.mode = "showing";
|
|
5271
|
-
this.state.audioDescriptionEnabled = true;
|
|
5272
|
-
this.emit("audiodescriptionenabled");
|
|
5273
|
-
}
|
|
5274
|
-
} else if (hasAudioDescriptionSrc) {
|
|
5275
|
-
if (this.state.audioDescriptionEnabled) {
|
|
5276
|
-
this._audioDescriptionDesiredState = false;
|
|
5277
|
-
await this.disableAudioDescription();
|
|
5278
|
-
} else {
|
|
5279
|
-
this._audioDescriptionDesiredState = true;
|
|
5280
|
-
await this.enableAudioDescription();
|
|
5281
|
-
}
|
|
5282
|
-
}
|
|
6703
|
+
return this.audioDescriptionManager.toggle();
|
|
5283
6704
|
}
|
|
5284
|
-
// Sign Language
|
|
6705
|
+
// Sign Language (delegated to SignLanguageManager)
|
|
5285
6706
|
enableSignLanguage() {
|
|
6707
|
+
return this.signLanguageManager.enable();
|
|
6708
|
+
}
|
|
6709
|
+
// Legacy method body preserved for reference - can be removed after testing
|
|
6710
|
+
_legacyEnableSignLanguage() {
|
|
5286
6711
|
const hasMultipleSources = Object.keys(this.signLanguageSources).length > 0;
|
|
5287
6712
|
const hasSingleSource = !!this.signLanguageSrc;
|
|
5288
6713
|
if (!hasMultipleSources && !hasSingleSource) {
|
|
@@ -5533,23 +6958,16 @@ var Player = class _Player extends EventEmitter {
|
|
|
5533
6958
|
}, 150);
|
|
5534
6959
|
}
|
|
5535
6960
|
disableSignLanguage() {
|
|
5536
|
-
|
|
5537
|
-
this.hideSignLanguageSettingsMenu({ focusButton: false });
|
|
5538
|
-
}
|
|
5539
|
-
if (this.signLanguageWrapper) {
|
|
5540
|
-
this.signLanguageWrapper.style.display = "none";
|
|
5541
|
-
}
|
|
5542
|
-
this.state.signLanguageEnabled = false;
|
|
5543
|
-
this.emit("signlanguagedisabled");
|
|
6961
|
+
return this.signLanguageManager.disable();
|
|
5544
6962
|
}
|
|
5545
6963
|
toggleSignLanguage() {
|
|
5546
|
-
|
|
5547
|
-
this.disableSignLanguage();
|
|
5548
|
-
} else {
|
|
5549
|
-
this.enableSignLanguage();
|
|
5550
|
-
}
|
|
6964
|
+
return this.signLanguageManager.toggle();
|
|
5551
6965
|
}
|
|
5552
6966
|
setupSignLanguageInteraction() {
|
|
6967
|
+
return this.signLanguageManager._setupInteraction();
|
|
6968
|
+
}
|
|
6969
|
+
// Legacy method preserved for reference
|
|
6970
|
+
_legacySetupSignLanguageInteraction() {
|
|
5553
6971
|
if (!this.signLanguageWrapper) return;
|
|
5554
6972
|
const isMobile2 = window.innerWidth < 768;
|
|
5555
6973
|
const isFullscreen = this.state.fullscreen;
|
|
@@ -5687,6 +7105,10 @@ var Player = class _Player extends EventEmitter {
|
|
|
5687
7105
|
return langNames[langCode] || langCode.toUpperCase();
|
|
5688
7106
|
}
|
|
5689
7107
|
switchSignLanguage(langCode) {
|
|
7108
|
+
return this.signLanguageManager.switchLanguage(langCode);
|
|
7109
|
+
}
|
|
7110
|
+
// Legacy method preserved for reference
|
|
7111
|
+
_legacySwitchSignLanguage(langCode) {
|
|
5690
7112
|
if (!this.signLanguageSources[langCode] || !this.signLanguageVideo) {
|
|
5691
7113
|
return;
|
|
5692
7114
|
}
|
|
@@ -5702,6 +7124,10 @@ var Player = class _Player extends EventEmitter {
|
|
|
5702
7124
|
this.emit("signlanguagelanguagechanged", langCode);
|
|
5703
7125
|
}
|
|
5704
7126
|
showSignLanguageSettingsMenu() {
|
|
7127
|
+
return this.signLanguageManager.showSettingsMenu();
|
|
7128
|
+
}
|
|
7129
|
+
// Legacy method preserved for reference
|
|
7130
|
+
_legacyShowSignLanguageSettingsMenu() {
|
|
5705
7131
|
this.signLanguageSettingsMenuJustOpened = true;
|
|
5706
7132
|
setTimeout(() => {
|
|
5707
7133
|
this.signLanguageSettingsMenuJustOpened = false;
|
|
@@ -5845,25 +7271,7 @@ var Player = class _Player extends EventEmitter {
|
|
|
5845
7271
|
focusFirstMenuItem(this.signLanguageSettingsMenu, `.${this.options.classPrefix}-sign-language-settings-item`);
|
|
5846
7272
|
}
|
|
5847
7273
|
hideSignLanguageSettingsMenu({ focusButton = true } = {}) {
|
|
5848
|
-
|
|
5849
|
-
this.signLanguageSettingsMenu.style.display = "none";
|
|
5850
|
-
this.signLanguageSettingsMenuVisible = false;
|
|
5851
|
-
this.signLanguageSettingsMenuJustOpened = false;
|
|
5852
|
-
if (this.signLanguageSettingsMenuKeyHandler) {
|
|
5853
|
-
this.signLanguageSettingsMenu.removeEventListener("keydown", this.signLanguageSettingsMenuKeyHandler);
|
|
5854
|
-
this.signLanguageSettingsMenuKeyHandler = null;
|
|
5855
|
-
}
|
|
5856
|
-
const menuItems = Array.from(this.signLanguageSettingsMenu.querySelectorAll(`.${this.options.classPrefix}-sign-language-settings-item`));
|
|
5857
|
-
menuItems.forEach((item) => {
|
|
5858
|
-
item.setAttribute("tabindex", "-1");
|
|
5859
|
-
});
|
|
5860
|
-
if (this.signLanguageSettingsButton) {
|
|
5861
|
-
this.signLanguageSettingsButton.setAttribute("aria-expanded", "false");
|
|
5862
|
-
if (focusButton) {
|
|
5863
|
-
this.signLanguageSettingsButton.focus({ preventScroll: true });
|
|
5864
|
-
}
|
|
5865
|
-
}
|
|
5866
|
-
}
|
|
7274
|
+
return this.signLanguageManager.hideSettingsMenu({ focusButton });
|
|
5867
7275
|
}
|
|
5868
7276
|
positionSignLanguageSettingsMenuImmediate() {
|
|
5869
7277
|
if (!this.signLanguageSettingsMenu || !this.signLanguageSettingsButton) return;
|
|
@@ -5967,6 +7375,13 @@ var Player = class _Player extends EventEmitter {
|
|
|
5967
7375
|
}
|
|
5968
7376
|
}
|
|
5969
7377
|
constrainSignLanguagePosition() {
|
|
7378
|
+
return this.signLanguageManager.constrainPosition();
|
|
7379
|
+
}
|
|
7380
|
+
saveSignLanguagePreferences() {
|
|
7381
|
+
return this.signLanguageManager.savePreferences();
|
|
7382
|
+
}
|
|
7383
|
+
// Legacy methods preserved for reference - can be removed after testing
|
|
7384
|
+
_legacyConstrainSignLanguagePosition() {
|
|
5970
7385
|
if (!this.signLanguageWrapper || !this.videoWrapper) return;
|
|
5971
7386
|
if (this.signLanguageDraggable && this.signLanguageDraggable.manuallyPositioned) {
|
|
5972
7387
|
return;
|
|
@@ -6016,7 +7431,7 @@ var Player = class _Player extends EventEmitter {
|
|
|
6016
7431
|
this.signLanguageWrapper.style.bottom = "auto";
|
|
6017
7432
|
this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter((c) => c.startsWith("vidply-sign-position-")));
|
|
6018
7433
|
}
|
|
6019
|
-
|
|
7434
|
+
_legacySaveSignLanguagePreferences() {
|
|
6020
7435
|
if (!this.signLanguageWrapper) return;
|
|
6021
7436
|
this.storage.saveSignLanguagePreferences({
|
|
6022
7437
|
size: {
|
|
@@ -6026,58 +7441,7 @@ var Player = class _Player extends EventEmitter {
|
|
|
6026
7441
|
});
|
|
6027
7442
|
}
|
|
6028
7443
|
cleanupSignLanguage() {
|
|
6029
|
-
|
|
6030
|
-
this.hideSignLanguageSettingsMenu({ focusButton: false });
|
|
6031
|
-
}
|
|
6032
|
-
if (this.signLanguageDocumentClickHandler && this.signLanguageDocumentClickHandlerAdded) {
|
|
6033
|
-
document.removeEventListener("mousedown", this.signLanguageDocumentClickHandler, true);
|
|
6034
|
-
this.signLanguageDocumentClickHandlerAdded = false;
|
|
6035
|
-
this.signLanguageDocumentClickHandler = null;
|
|
6036
|
-
}
|
|
6037
|
-
if (this.signLanguageSettingsHandlers) {
|
|
6038
|
-
if (this.signLanguageSettingsButton) {
|
|
6039
|
-
this.signLanguageSettingsButton.removeEventListener("click", this.signLanguageSettingsHandlers.settingsClick);
|
|
6040
|
-
this.signLanguageSettingsButton.removeEventListener("keydown", this.signLanguageSettingsHandlers.settingsKeydown);
|
|
6041
|
-
}
|
|
6042
|
-
this.signLanguageSettingsHandlers = null;
|
|
6043
|
-
}
|
|
6044
|
-
if (this.signLanguageHandlers) {
|
|
6045
|
-
this.off("play", this.signLanguageHandlers.play);
|
|
6046
|
-
this.off("pause", this.signLanguageHandlers.pause);
|
|
6047
|
-
this.off("timeupdate", this.signLanguageHandlers.timeupdate);
|
|
6048
|
-
this.off("ratechange", this.signLanguageHandlers.ratechange);
|
|
6049
|
-
if (this.signLanguageHandlers.captionChange) {
|
|
6050
|
-
this.off("captionsenabled", this.signLanguageHandlers.captionChange);
|
|
6051
|
-
}
|
|
6052
|
-
this.signLanguageHandlers = null;
|
|
6053
|
-
}
|
|
6054
|
-
if (this.signLanguageInteractionHandlers) {
|
|
6055
|
-
if (this.signLanguageHeader && this.signLanguageInteractionHandlers.headerKeyHandler) {
|
|
6056
|
-
this.signLanguageHeader.removeEventListener("keydown", this.signLanguageInteractionHandlers.headerKeyHandler);
|
|
6057
|
-
}
|
|
6058
|
-
if (this.signLanguageWrapper && this.signLanguageInteractionHandlers.customKeyHandler) {
|
|
6059
|
-
this.signLanguageWrapper.removeEventListener("keydown", this.signLanguageInteractionHandlers.customKeyHandler);
|
|
6060
|
-
}
|
|
6061
|
-
}
|
|
6062
|
-
if (this.signLanguageDraggable) {
|
|
6063
|
-
if (this.signLanguageDraggable.pointerResizeMode) {
|
|
6064
|
-
this.signLanguageDraggable.disablePointerResizeMode();
|
|
6065
|
-
}
|
|
6066
|
-
this.signLanguageDraggable.destroy();
|
|
6067
|
-
this.signLanguageDraggable = null;
|
|
6068
|
-
}
|
|
6069
|
-
this.signLanguageInteractionHandlers = null;
|
|
6070
|
-
if (this.signLanguageWrapper && this.signLanguageWrapper.parentNode) {
|
|
6071
|
-
if (this.signLanguageVideo) {
|
|
6072
|
-
this.signLanguageVideo.pause();
|
|
6073
|
-
this.signLanguageVideo.src = "";
|
|
6074
|
-
}
|
|
6075
|
-
this.signLanguageWrapper.parentNode.removeChild(this.signLanguageWrapper);
|
|
6076
|
-
}
|
|
6077
|
-
this.signLanguageWrapper = null;
|
|
6078
|
-
this.signLanguageVideo = null;
|
|
6079
|
-
this.signLanguageSettingsButton = null;
|
|
6080
|
-
this.signLanguageSettingsMenu = null;
|
|
7444
|
+
return this.signLanguageManager.cleanup();
|
|
6081
7445
|
}
|
|
6082
7446
|
// Settings
|
|
6083
7447
|
// Settings dialog removed - using individual control buttons instead
|