myetv-player 1.1.3 → 1.1.5
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/README.md +14 -0
- package/css/myetv-player.css +65 -0
- package/css/myetv-player.min.css +1 -1
- package/dist/myetv-player.js +229 -99
- package/dist/myetv-player.min.js +167 -72
- package/package.json +3 -1
- package/plugins/vimeo/myetv-player-vimeo.js +223 -0
- package/plugins/youtube/myetv-player-youtube-plugin.js +484 -244
- package/scss/_controls.scss +21 -0
- package/scss/_menus.scss +49 -0
- package/src/controls.js +212 -83
- package/src/core.js +17 -16
package/dist/myetv-player.min.js
CHANGED
|
@@ -372,22 +372,23 @@ constructor(videoElement, options = {}) {
|
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
this.options = {
|
|
375
|
-
showQualitySelector: true,
|
|
376
|
-
showSpeedControl: true,
|
|
377
|
-
showFullscreen: true,
|
|
378
|
-
showPictureInPicture: true,
|
|
379
|
-
showSubtitles: true,
|
|
380
|
-
subtitlesEnabled: false,
|
|
381
|
-
autoHide: true,
|
|
382
|
-
autoHideDelay: 3000,
|
|
375
|
+
showQualitySelector: true, // Enable quality selector button
|
|
376
|
+
showSpeedControl: true, // Enable speed control button
|
|
377
|
+
showFullscreen: true, // Enable fullscreen button
|
|
378
|
+
showPictureInPicture: true, // Enable PiP button
|
|
379
|
+
showSubtitles: true, // Enable subtitles button
|
|
380
|
+
subtitlesEnabled: false, // Enable subtitles by default if available
|
|
381
|
+
autoHide: true, // auto-hide controls when idle
|
|
382
|
+
autoHideDelay: 3000, // hide controls after ... seconds of inactivity (specificed in milliseconds)
|
|
383
|
+
hideCursor: true, // hide mouse cursor when idle
|
|
383
384
|
poster: null, // URL of poster image
|
|
384
385
|
showPosterOnEnd: false, // Show poster again when video ends
|
|
385
|
-
keyboardControls: true,
|
|
386
|
-
showSeekTooltip: true,
|
|
387
|
-
showTitleOverlay: false,
|
|
388
|
-
videoTitle: '',
|
|
389
|
-
videoSubtitle: '',
|
|
390
|
-
persistentTitle: false,
|
|
386
|
+
keyboardControls: true, // Enable keyboard controls
|
|
387
|
+
showSeekTooltip: true, // Show tooltip on seek bar at mouse hover
|
|
388
|
+
showTitleOverlay: false, // Show video title overlay
|
|
389
|
+
videoTitle: '', // Title text to show in overlay
|
|
390
|
+
videoSubtitle: '', // Subtitle text to show in overlay
|
|
391
|
+
persistentTitle: false, // If true, title overlay stays visible
|
|
391
392
|
debug: false, // Enable/disable debug logging
|
|
392
393
|
autoplay: false, // if video should autoplay at start
|
|
393
394
|
defaultQuality: 'auto', // 'auto', '1080p', '720p', '480p', etc.
|
|
@@ -417,8 +418,8 @@ constructor(videoElement, options = {}) {
|
|
|
417
418
|
|
|
418
419
|
seekHandleShape: 'circle', // Available shape: none, circle, square, diamond, arrow, triangle, heart, star
|
|
419
420
|
|
|
420
|
-
audiofile: false,
|
|
421
|
-
audiowave: false,
|
|
421
|
+
audiofile: false, // if true, adapt player to audio file (hide video element)
|
|
422
|
+
audiowave: false, // if true, show audio wave visualization (Web Audio API)
|
|
422
423
|
|
|
423
424
|
resolution: "normal", // "normal", "4:3", "16:9", "stretched", "fit-to-screen", "scale-to-fit"
|
|
424
425
|
...options
|
|
@@ -2598,6 +2599,7 @@ initAutoHide() {
|
|
|
2598
2599
|
|
|
2599
2600
|
onMouseMoveInPlayer(e) {
|
|
2600
2601
|
this.showControlsNow();
|
|
2602
|
+
this.showCursor();
|
|
2601
2603
|
this.resetAutoHideTimer();
|
|
2602
2604
|
}
|
|
2603
2605
|
|
|
@@ -2655,39 +2657,37 @@ resetAutoHideTimer() {
|
|
|
2655
2657
|
showControlsNow() {
|
|
2656
2658
|
if (this.controls) {
|
|
2657
2659
|
this.controls.classList.add('show');
|
|
2658
|
-
}
|
|
2659
2660
|
|
|
2660
2661
|
if (this.container) {
|
|
2661
2662
|
this.container.classList.add('has-controls');
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2662
2665
|
this.updateControlbarHeight();
|
|
2663
2666
|
|
|
2664
2667
|
if (this.updateWatermarkPosition) {
|
|
2665
2668
|
this.updateWatermarkPosition();
|
|
2666
2669
|
}
|
|
2667
|
-
}
|
|
2668
2670
|
|
|
2669
2671
|
if (this.options.showTitleOverlay && !this.options.persistentTitle && this.options.videoTitle) {
|
|
2670
2672
|
this.showTitleOverlay();
|
|
2671
2673
|
}
|
|
2672
2674
|
|
|
2675
|
+
this.showCursor();
|
|
2676
|
+
|
|
2673
2677
|
if (this.autoHideDebug && this.options.debug) console.log('✅ Controls shown');
|
|
2678
|
+
}
|
|
2674
2679
|
}
|
|
2675
2680
|
|
|
2676
2681
|
hideControlsNow() {
|
|
2677
2682
|
|
|
2678
2683
|
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
|
2679
|
-
|
|
2680
2684
|
if (this.mouseOverControls && !isTouchDevice) {
|
|
2681
|
-
if (this.autoHideDebug && this.options.debug)
|
|
2682
|
-
console.log('🚫 Not hiding - mouse still over controls');
|
|
2683
|
-
}
|
|
2685
|
+
if (this.autoHideDebug && this.options.debug) console.log('❌ Not hiding - mouse still over controls');
|
|
2684
2686
|
return;
|
|
2685
2687
|
}
|
|
2686
2688
|
|
|
2687
2689
|
if (this.video && this.video.paused) {
|
|
2688
|
-
if (this.autoHideDebug && this.options.debug)
|
|
2689
|
-
console.log('🚫 Not hiding - video is paused');
|
|
2690
|
-
}
|
|
2690
|
+
if (this.autoHideDebug && this.options.debug) console.log('❌ Not hiding - video is paused');
|
|
2691
2691
|
return;
|
|
2692
2692
|
}
|
|
2693
2693
|
|
|
@@ -2696,20 +2696,21 @@ hideControlsNow() {
|
|
|
2696
2696
|
|
|
2697
2697
|
if (this.container) {
|
|
2698
2698
|
this.container.classList.remove('has-controls');
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2699
2701
|
this.updateControlbarHeight();
|
|
2700
2702
|
|
|
2701
2703
|
if (this.updateWatermarkPosition) {
|
|
2702
2704
|
this.updateWatermarkPosition();
|
|
2703
2705
|
}
|
|
2704
|
-
}
|
|
2705
|
-
}
|
|
2706
2706
|
|
|
2707
2707
|
if (this.options.showTitleOverlay && !this.options.persistentTitle) {
|
|
2708
2708
|
this.hideTitleOverlay();
|
|
2709
2709
|
}
|
|
2710
2710
|
|
|
2711
|
-
|
|
2712
|
-
|
|
2711
|
+
this.hideCursor();
|
|
2712
|
+
|
|
2713
|
+
if (this.autoHideDebug && this.options.debug) console.log('✅ Controls hidden');
|
|
2713
2714
|
}
|
|
2714
2715
|
}
|
|
2715
2716
|
|
|
@@ -3107,46 +3108,87 @@ populateSettingsMenu() {
|
|
|
3107
3108
|
if (this.options.showSpeedControl) {
|
|
3108
3109
|
const speedLabel = this.t('playback_speed') || 'Playback Speed';
|
|
3109
3110
|
const currentSpeed = this.video ? this.video.playbackRate : 1;
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
<
|
|
3113
|
-
<div class="settings-
|
|
3114
|
-
<
|
|
3115
|
-
<
|
|
3116
|
-
<div class="settings-suboption ${currentSpeed === 1 ? 'active' : ''}" data-speed="1">1x</div>
|
|
3117
|
-
<div class="settings-suboption ${currentSpeed === 1.25 ? 'active' : ''}" data-speed="1.25">1.25x</div>
|
|
3118
|
-
<div class="settings-suboption ${currentSpeed === 1.5 ? 'active' : ''}" data-speed="1.5">1.5x</div>
|
|
3119
|
-
<div class="settings-suboption ${currentSpeed === 2 ? 'active' : ''}" data-speed="2">2x</div>
|
|
3111
|
+
|
|
3112
|
+
menuHTML += `
|
|
3113
|
+
<div class="settings-expandable-wrapper">
|
|
3114
|
+
<div class="settings-option expandable-trigger" data-action="speed-expand">
|
|
3115
|
+
<span class="settings-option-label">${speedLabel}: ${currentSpeed}x</span>
|
|
3116
|
+
<span class="expand-arrow">▼</span>
|
|
3120
3117
|
</div>
|
|
3121
|
-
|
|
3118
|
+
<div class="settings-expandable-content" style="display: none;">`;
|
|
3119
|
+
|
|
3120
|
+
const speeds = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
3121
|
+
speeds.forEach(speed => {
|
|
3122
|
+
const isActive = Math.abs(speed - currentSpeed) < 0.01;
|
|
3123
|
+
menuHTML += `<div class="settings-suboption ${isActive ? 'active' : ''}" data-speed="${speed}">${speed}x</div>`;
|
|
3124
|
+
});
|
|
3125
|
+
|
|
3126
|
+
menuHTML += `</div></div>`;
|
|
3122
3127
|
}
|
|
3123
3128
|
|
|
3124
3129
|
if (this.options.showSubtitles && this.textTracks && this.textTracks.length > 0) {
|
|
3125
3130
|
const subtitlesLabel = this.t('subtitles') || 'Subtitles';
|
|
3126
3131
|
const currentTrack = this.currentSubtitleTrack;
|
|
3127
|
-
const currentLabel = this.subtitlesEnabled && currentTrack
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
<span class="settings-option-label">${subtitlesLabel}</span>
|
|
3133
|
-
<span class="
|
|
3134
|
-
|
|
3135
|
-
<div class="settings-
|
|
3136
|
-
|
|
3137
|
-
</div>`;
|
|
3132
|
+
const currentLabel = this.subtitlesEnabled && currentTrack ? currentTrack.label : (this.t('subtitlesoff') || 'Off');
|
|
3133
|
+
|
|
3134
|
+
menuHTML += `
|
|
3135
|
+
<div class="settings-expandable-wrapper">
|
|
3136
|
+
<div class="settings-option expandable-trigger" data-action="subtitles-expand">
|
|
3137
|
+
<span class="settings-option-label">${subtitlesLabel}: ${currentLabel}</span>
|
|
3138
|
+
<span class="expand-arrow">▼</span>
|
|
3139
|
+
</div>
|
|
3140
|
+
<div class="settings-expandable-content" style="display: none;">`;
|
|
3141
|
+
|
|
3142
|
+
menuHTML += `<div class="settings-suboption ${!this.subtitlesEnabled ? 'active' : ''}" data-track="off">${this.t('subtitlesoff') || 'Off'}</div>`;
|
|
3138
3143
|
|
|
3139
3144
|
this.textTracks.forEach((trackData, index) => {
|
|
3140
3145
|
const isActive = this.currentSubtitleTrack === trackData.track;
|
|
3141
|
-
menuHTML += `<div class="settings-suboption ${isActive ? 'active' : ''}" data-track="${index}"
|
|
3142
|
-
${trackData.label}
|
|
3143
|
-
</div>`;
|
|
3146
|
+
menuHTML += `<div class="settings-suboption ${isActive ? 'active' : ''}" data-track="${index}">${trackData.label}</div>`;
|
|
3144
3147
|
});
|
|
3145
3148
|
|
|
3146
|
-
menuHTML +=
|
|
3149
|
+
menuHTML += `</div></div>`;
|
|
3147
3150
|
}
|
|
3148
3151
|
|
|
3149
3152
|
settingsMenu.innerHTML = menuHTML;
|
|
3153
|
+
|
|
3154
|
+
this.addSettingsMenuScrollbar();
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
addSettingsMenuScrollbar() {
|
|
3158
|
+
const settingsMenu = this.controls?.querySelector('.settings-menu');
|
|
3159
|
+
if (!settingsMenu) return;
|
|
3160
|
+
|
|
3161
|
+
const playerHeight = this.container.offsetHeight;
|
|
3162
|
+
const maxMenuHeight = playerHeight - 100;
|
|
3163
|
+
|
|
3164
|
+
settingsMenu.style.maxHeight = `${maxMenuHeight}px`;
|
|
3165
|
+
settingsMenu.style.overflowY = 'auto';
|
|
3166
|
+
settingsMenu.style.overflowX = 'hidden';
|
|
3167
|
+
|
|
3168
|
+
if (!document.getElementById('player-settings-scrollbar-style')) {
|
|
3169
|
+
const scrollbarStyle = document.createElement('style');
|
|
3170
|
+
scrollbarStyle.id = 'player-settings-scrollbar-style';
|
|
3171
|
+
scrollbarStyle.textContent = `
|
|
3172
|
+
.settings-menu::-webkit-scrollbar {
|
|
3173
|
+
width: 6px;
|
|
3174
|
+
}
|
|
3175
|
+
.settings-menu::-webkit-scrollbar-track {
|
|
3176
|
+
background: rgba(255,255,255,0.05);
|
|
3177
|
+
border-radius: 3px;
|
|
3178
|
+
}
|
|
3179
|
+
.settings-menu::-webkit-scrollbar-thumb {
|
|
3180
|
+
background: rgba(255,255,255,0.3);
|
|
3181
|
+
border-radius: 3px;
|
|
3182
|
+
}
|
|
3183
|
+
.settings-menu::-webkit-scrollbar-thumb:hover {
|
|
3184
|
+
background: rgba(255,255,255,0.5);
|
|
3185
|
+
}
|
|
3186
|
+
`;
|
|
3187
|
+
document.head.appendChild(scrollbarStyle);
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
settingsMenu.style.scrollbarWidth = 'thin';
|
|
3191
|
+
settingsMenu.style.scrollbarColor = 'rgba(255,255,255,0.3) transparent';
|
|
3150
3192
|
}
|
|
3151
3193
|
|
|
3152
3194
|
bindSettingsMenuEvents() {
|
|
@@ -3156,6 +3198,24 @@ bindSettingsMenuEvents() {
|
|
|
3156
3198
|
settingsMenu.addEventListener('click', (e) => {
|
|
3157
3199
|
e.stopPropagation();
|
|
3158
3200
|
|
|
3201
|
+
if (e.target.classList.contains('expandable-trigger') || e.target.closest('.expandable-trigger')) {
|
|
3202
|
+
const trigger = e.target.classList.contains('expandable-trigger') ? e.target : e.target.closest('.expandable-trigger');
|
|
3203
|
+
const wrapper = trigger.closest('.settings-expandable-wrapper');
|
|
3204
|
+
const content = wrapper.querySelector('.settings-expandable-content');
|
|
3205
|
+
const arrow = trigger.querySelector('.expand-arrow');
|
|
3206
|
+
|
|
3207
|
+
const isExpanded = content.style.display !== 'none';
|
|
3208
|
+
|
|
3209
|
+
if (isExpanded) {
|
|
3210
|
+
content.style.display = 'none';
|
|
3211
|
+
arrow.style.transform = 'rotate(0deg)';
|
|
3212
|
+
} else {
|
|
3213
|
+
content.style.display = 'block';
|
|
3214
|
+
arrow.style.transform = 'rotate(180deg)';
|
|
3215
|
+
}
|
|
3216
|
+
return;
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3159
3219
|
if (e.target.classList.contains('settings-option') || e.target.closest('.settings-option')) {
|
|
3160
3220
|
const option = e.target.classList.contains('settings-option') ? e.target : e.target.closest('.settings-option');
|
|
3161
3221
|
const action = option.getAttribute('data-action');
|
|
@@ -3167,29 +3227,28 @@ bindSettingsMenuEvents() {
|
|
|
3167
3227
|
}
|
|
3168
3228
|
|
|
3169
3229
|
if (e.target.classList.contains('settings-suboption')) {
|
|
3170
|
-
const
|
|
3171
|
-
const
|
|
3230
|
+
const wrapper = e.target.closest('.settings-expandable-wrapper');
|
|
3231
|
+
const trigger = wrapper.querySelector('.expandable-trigger');
|
|
3232
|
+
const action = trigger.getAttribute('data-action');
|
|
3172
3233
|
|
|
3173
|
-
if (action === 'speed') {
|
|
3234
|
+
if (action === 'speed-expand') {
|
|
3174
3235
|
const speed = parseFloat(e.target.getAttribute('data-speed'));
|
|
3175
3236
|
if (speed && speed > 0 && this.video && !this.isChangingQuality) {
|
|
3176
3237
|
this.video.playbackRate = speed;
|
|
3177
3238
|
|
|
3178
|
-
|
|
3179
|
-
opt.classList.remove('active');
|
|
3180
|
-
});
|
|
3239
|
+
wrapper.querySelectorAll('.settings-suboption').forEach(opt => opt.classList.remove('active'));
|
|
3181
3240
|
e.target.classList.add('active');
|
|
3182
3241
|
|
|
3183
|
-
const
|
|
3184
|
-
if (
|
|
3242
|
+
const label = trigger.querySelector('.settings-option-label');
|
|
3243
|
+
if (label) {
|
|
3244
|
+
const speedLabel = this.t('playback_speed') || 'Playback Speed';
|
|
3245
|
+
label.textContent = `${speedLabel}: ${speed}x`;
|
|
3246
|
+
}
|
|
3185
3247
|
|
|
3186
3248
|
this.triggerEvent('speedchange', { speed, previousSpeed: this.video.playbackRate });
|
|
3187
3249
|
}
|
|
3188
|
-
}
|
|
3189
|
-
|
|
3190
|
-
else if (action === 'subtitles') {
|
|
3250
|
+
} else if (action === 'subtitles-expand') {
|
|
3191
3251
|
const trackData = e.target.getAttribute('data-track');
|
|
3192
|
-
|
|
3193
3252
|
if (trackData === 'off') {
|
|
3194
3253
|
this.disableSubtitles();
|
|
3195
3254
|
} else {
|
|
@@ -3197,13 +3256,14 @@ bindSettingsMenuEvents() {
|
|
|
3197
3256
|
this.enableSubtitleTrack(trackIndex);
|
|
3198
3257
|
}
|
|
3199
3258
|
|
|
3200
|
-
|
|
3201
|
-
opt.classList.remove('active');
|
|
3202
|
-
});
|
|
3259
|
+
wrapper.querySelectorAll('.settings-suboption').forEach(opt => opt.classList.remove('active'));
|
|
3203
3260
|
e.target.classList.add('active');
|
|
3204
3261
|
|
|
3205
|
-
const
|
|
3206
|
-
if (
|
|
3262
|
+
const label = trigger.querySelector('.settings-option-label');
|
|
3263
|
+
if (label) {
|
|
3264
|
+
const subtitlesLabel = this.t('subtitles') || 'Subtitles';
|
|
3265
|
+
label.textContent = `${subtitlesLabel}: ${e.target.textContent}`;
|
|
3266
|
+
}
|
|
3207
3267
|
}
|
|
3208
3268
|
}
|
|
3209
3269
|
});
|
|
@@ -3464,6 +3524,41 @@ isAutoHideInitialized() {
|
|
|
3464
3524
|
return this.autoHideInitialized;
|
|
3465
3525
|
}
|
|
3466
3526
|
|
|
3527
|
+
hideCursor() {
|
|
3528
|
+
if (!this.options.hideCursor) {
|
|
3529
|
+
return; // Do not hide cursor if option is disabled
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
if (this.container) {
|
|
3533
|
+
this.container.classList.add('hide-cursor');
|
|
3534
|
+
if (this.options.debug) console.log('🖱️ Cursor hidden');
|
|
3535
|
+
}
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3538
|
+
showCursor() {
|
|
3539
|
+
if (this.container) {
|
|
3540
|
+
this.container.classList.remove('hide-cursor');
|
|
3541
|
+
if (this.options.debug) console.log('🖱️ Cursor shown');
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
|
|
3545
|
+
enableCursorHiding() {
|
|
3546
|
+
this.options.hideCursor = true;
|
|
3547
|
+
if (this.options.debug) console.log('Cursor hiding enabled');
|
|
3548
|
+
return this;
|
|
3549
|
+
}
|
|
3550
|
+
|
|
3551
|
+
disableCursorHiding() {
|
|
3552
|
+
this.options.hideCursor = false;
|
|
3553
|
+
this.showCursor(); // Ensure cursor is shown immediately
|
|
3554
|
+
if (this.options.debug) console.log('Cursor hiding disabled');
|
|
3555
|
+
return this;
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
isCursorHidingEnabled() {
|
|
3559
|
+
return this.options.hideCursor;
|
|
3560
|
+
}
|
|
3561
|
+
|
|
3467
3562
|
showPlaylistControls() {
|
|
3468
3563
|
if (!this.playlistPrevBtn || !this.playlistNextBtn) return;
|
|
3469
3564
|
|
package/package.json
CHANGED
|
@@ -264,6 +264,9 @@
|
|
|
264
264
|
// Setup event listeners
|
|
265
265
|
this.setupEventListeners();
|
|
266
266
|
|
|
267
|
+
//create overlay for mouse detection
|
|
268
|
+
this.createMouseMoveOverlay();
|
|
269
|
+
|
|
267
270
|
// Load available qualities
|
|
268
271
|
this.loadQualities();
|
|
269
272
|
|
|
@@ -429,6 +432,224 @@
|
|
|
429
432
|
});
|
|
430
433
|
}
|
|
431
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Create transparent overlay for click detection
|
|
437
|
+
*/
|
|
438
|
+
createMouseMoveOverlay() {
|
|
439
|
+
if (this.mouseMoveOverlay) return;
|
|
440
|
+
|
|
441
|
+
this.mouseMoveOverlay = document.createElement('div');
|
|
442
|
+
this.mouseMoveOverlay.className = 'vimeo-mousemove-overlay';
|
|
443
|
+
this.mouseMoveOverlay.style.cssText = `
|
|
444
|
+
position: absolute;
|
|
445
|
+
top: 0;
|
|
446
|
+
left: 0;
|
|
447
|
+
width: 100%;
|
|
448
|
+
height: 100%;
|
|
449
|
+
z-index: 2;
|
|
450
|
+
background: transparent;
|
|
451
|
+
pointer-events: auto;
|
|
452
|
+
cursor: default;
|
|
453
|
+
`;
|
|
454
|
+
|
|
455
|
+
// Insert before controls
|
|
456
|
+
this.player.container.insertBefore(this.mouseMoveOverlay, this.player.controls);
|
|
457
|
+
|
|
458
|
+
// Setup mouse detection
|
|
459
|
+
this.setupMouseMoveDetection();
|
|
460
|
+
|
|
461
|
+
// Click handler for play/pause
|
|
462
|
+
this.mouseMoveOverlay.addEventListener('click', (e) => {
|
|
463
|
+
e.preventDefault();
|
|
464
|
+
e.stopPropagation();
|
|
465
|
+
|
|
466
|
+
const doubleTap = this.player.options.doubleTapPause;
|
|
467
|
+
const pauseClick = this.player.options.pauseClick;
|
|
468
|
+
|
|
469
|
+
if (doubleTap) {
|
|
470
|
+
// Check if controls are hidden
|
|
471
|
+
let controlsHidden = false;
|
|
472
|
+
if (this.player.controls) {
|
|
473
|
+
controlsHidden = this.player.controls.classList.contains('hide');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (!controlsHidden) {
|
|
477
|
+
const controls = this.player.container.querySelector('.controls');
|
|
478
|
+
if (controls) {
|
|
479
|
+
controlsHidden = controls.classList.contains('hide');
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (!controlsHidden && this.player.controls) {
|
|
484
|
+
const style = window.getComputedStyle(this.player.controls);
|
|
485
|
+
controlsHidden = (style.opacity === '0' || style.visibility === 'hidden');
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (controlsHidden) {
|
|
489
|
+
// Show controls
|
|
490
|
+
if (this.player.showControlsNow) {
|
|
491
|
+
this.player.showControlsNow();
|
|
492
|
+
}
|
|
493
|
+
if (this.player.resetAutoHideTimer) {
|
|
494
|
+
this.player.resetAutoHideTimer();
|
|
495
|
+
}
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
this.togglePlayPause();
|
|
500
|
+
} else if (pauseClick) {
|
|
501
|
+
this.togglePlayPause();
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Mouse move handler
|
|
506
|
+
this.mouseMoveOverlay.addEventListener('mousemove', (e) => {
|
|
507
|
+
if (this.player.onMouseMove) {
|
|
508
|
+
this.player.onMouseMove(e);
|
|
509
|
+
}
|
|
510
|
+
if (this.player.resetAutoHideTimer) {
|
|
511
|
+
this.player.resetAutoHideTimer();
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
if (this.options.debug) {
|
|
516
|
+
console.log('[Vimeo] Mouse overlay created');
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Setup mouse move detection
|
|
522
|
+
*/
|
|
523
|
+
setupMouseMoveDetection() {
|
|
524
|
+
// Track last mouse position
|
|
525
|
+
this.lastMouseX = null;
|
|
526
|
+
this.lastMouseY = null;
|
|
527
|
+
this.mouseCheckInterval = null;
|
|
528
|
+
|
|
529
|
+
// Mouse enter
|
|
530
|
+
this.player.container.addEventListener('mouseenter', () => {
|
|
531
|
+
if (this.options.debug) {
|
|
532
|
+
console.log('[Vimeo] Mouse entered - show controls');
|
|
533
|
+
}
|
|
534
|
+
if (this.player.showControlsNow) {
|
|
535
|
+
this.player.showControlsNow();
|
|
536
|
+
}
|
|
537
|
+
if (this.player.resetAutoHideTimer) {
|
|
538
|
+
this.player.resetAutoHideTimer();
|
|
539
|
+
}
|
|
540
|
+
this.startMousePositionTracking();
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
// Mouse leave
|
|
544
|
+
this.player.container.addEventListener('mouseleave', () => {
|
|
545
|
+
if (this.options.debug) {
|
|
546
|
+
console.log('[Vimeo] Mouse left');
|
|
547
|
+
}
|
|
548
|
+
this.stopMousePositionTracking();
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// Mouse move
|
|
552
|
+
this.player.container.addEventListener('mousemove', (e) => {
|
|
553
|
+
this.lastMouseX = e.clientX;
|
|
554
|
+
this.lastMouseY = e.clientY;
|
|
555
|
+
if (this.player.onMouseMove) {
|
|
556
|
+
this.player.onMouseMove(e);
|
|
557
|
+
}
|
|
558
|
+
if (this.player.resetAutoHideTimer) {
|
|
559
|
+
this.player.resetAutoHideTimer();
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Start mouse position tracking
|
|
566
|
+
*/
|
|
567
|
+
startMousePositionTracking() {
|
|
568
|
+
if (this.mouseCheckInterval) return;
|
|
569
|
+
|
|
570
|
+
this.mouseCheckInterval = setInterval(() => {
|
|
571
|
+
// Track mouse position over iframe
|
|
572
|
+
const handleGlobalMove = (e) => {
|
|
573
|
+
const newX = e.clientX;
|
|
574
|
+
const newY = e.clientY;
|
|
575
|
+
|
|
576
|
+
if (this.lastMouseX !== newX || this.lastMouseY !== newY) {
|
|
577
|
+
this.lastMouseX = newX;
|
|
578
|
+
this.lastMouseY = newY;
|
|
579
|
+
|
|
580
|
+
const rect = this.player.container.getBoundingClientRect();
|
|
581
|
+
const isInside = (
|
|
582
|
+
newX >= rect.left &&
|
|
583
|
+
newX <= rect.right &&
|
|
584
|
+
newY >= rect.top &&
|
|
585
|
+
newY <= rect.bottom
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
if (isInside) {
|
|
589
|
+
if (this.player.showControlsNow) {
|
|
590
|
+
this.player.showControlsNow();
|
|
591
|
+
}
|
|
592
|
+
if (this.player.resetAutoHideTimer) {
|
|
593
|
+
this.player.resetAutoHideTimer();
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
document.addEventListener('mousemove', handleGlobalMove, { once: true, passive: true });
|
|
600
|
+
}, 100);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Stop mouse position tracking
|
|
605
|
+
*/
|
|
606
|
+
stopMousePositionTracking() {
|
|
607
|
+
if (this.mouseCheckInterval) {
|
|
608
|
+
clearInterval(this.mouseCheckInterval);
|
|
609
|
+
this.mouseCheckInterval = null;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Toggle play/pause
|
|
615
|
+
*/
|
|
616
|
+
togglePlayPause() {
|
|
617
|
+
if (!this.vimeoPlayer) return;
|
|
618
|
+
|
|
619
|
+
this.vimeoPlayer.getPaused().then(paused => {
|
|
620
|
+
if (paused) {
|
|
621
|
+
// Use player's play method to trigger UI update
|
|
622
|
+
if (this.player.play) {
|
|
623
|
+
this.player.play();
|
|
624
|
+
} else if (this.player.video && this.player.video.play) {
|
|
625
|
+
this.player.video.play();
|
|
626
|
+
}
|
|
627
|
+
} else {
|
|
628
|
+
// Use player's pause method to trigger UI update
|
|
629
|
+
if (this.player.pause) {
|
|
630
|
+
this.player.pause();
|
|
631
|
+
} else if (this.player.video && this.player.video.pause) {
|
|
632
|
+
this.player.video.pause();
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}).catch(err => {
|
|
636
|
+
if (this.options.debug) {
|
|
637
|
+
console.error('[Vimeo] GetPaused error:', err);
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Remove mouse overlay
|
|
644
|
+
*/
|
|
645
|
+
removeMouseMoveOverlay() {
|
|
646
|
+
if (this.mouseMoveOverlay) {
|
|
647
|
+
this.mouseMoveOverlay.remove();
|
|
648
|
+
this.mouseMoveOverlay = null;
|
|
649
|
+
}
|
|
650
|
+
this.stopMousePositionTracking();
|
|
651
|
+
}
|
|
652
|
+
|
|
432
653
|
/**
|
|
433
654
|
* Load available qualities and sync with MYETV player
|
|
434
655
|
*/
|
|
@@ -912,6 +1133,8 @@
|
|
|
912
1133
|
* Dispose plugin
|
|
913
1134
|
*/
|
|
914
1135
|
dispose() {
|
|
1136
|
+
this.removeMouseMoveOverlay();
|
|
1137
|
+
|
|
915
1138
|
// Cleanup PIP observers and listeners
|
|
916
1139
|
if (this.pipObserver) {
|
|
917
1140
|
this.pipObserver.disconnect();
|