myetv-player 1.6.6 → 1.6.7

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.
@@ -830,6 +830,9 @@ constructor(videoElement, options = {}) {
830
830
  hls: false
831
831
  };
832
832
 
833
+ this.settingsMenuOriginalParent = null;
834
+ this.settingsMenuInModal = false;
835
+
833
836
  this.lastTimeUpdate = 0; // For throttling timeupdate events
834
837
  // Inject default styles
835
838
  this.injectDefaultControlbarStyles();
@@ -4135,6 +4138,45 @@ createMoreInfoModal() {
4135
4138
  openMoreInfoModal() {
4136
4139
  if (!this.moreinfoModal) return;
4137
4140
 
4141
+ // If settings menu is in modal, restore it first
4142
+ if (this.settingsMenuInModal) {
4143
+ const settingsMenu = this.moreinfoModal.querySelector('.settings-menu');
4144
+
4145
+ if (settingsMenu && this.settingsMenuOriginalParent) {
4146
+ // Restore menu to original position
4147
+ this.settingsMenuOriginalParent.appendChild(settingsMenu);
4148
+
4149
+ // Reset menu styles
4150
+ settingsMenu.style.position = '';
4151
+ settingsMenu.style.top = '';
4152
+ settingsMenu.style.right = '';
4153
+ settingsMenu.style.opacity = '';
4154
+ settingsMenu.style.visibility = '';
4155
+ settingsMenu.style.transform = '';
4156
+ settingsMenu.style.display = '';
4157
+ settingsMenu.style.maxHeight = '';
4158
+ settingsMenu.classList.remove('active');
4159
+
4160
+ this.settingsMenuInModal = false;
4161
+
4162
+ if (this.options.debug) {
4163
+ console.log('[More Info] Menu restored before showing more info');
4164
+ }
4165
+ }
4166
+ }
4167
+
4168
+ // Get modal elements
4169
+ const modalTitle = this.moreinfoModal.querySelector('.moreinfo-modal-title');
4170
+ const modalBody = this.moreinfoModal.querySelector('.moreinfo-modal-body');
4171
+
4172
+ if (!modalTitle || !modalBody) return;
4173
+
4174
+ // Set content for more info
4175
+ modalTitle.textContent = this.decodeHTMLEntities(this.options.moreinfoTitle || '');
4176
+ modalBody.innerHTML = this.decodeHTMLEntities(this.options.moreinfoDescription || '');
4177
+ modalBody.className = 'moreinfo-modal-body'; // Reset class (remove settings-modal-body)
4178
+
4179
+ // Show modal
4138
4180
  this.moreinfoModal.style.display = 'flex';
4139
4181
 
4140
4182
  if (this.options.debug) {
@@ -4149,10 +4191,140 @@ openMoreInfoModal() {
4149
4191
  closeMoreInfoModal() {
4150
4192
  if (!this.moreinfoModal) return;
4151
4193
 
4194
+ // Check if settings menu needs to be restored (only if it's in modal)
4195
+ if (this.settingsMenuInModal) {
4196
+ const settingsMenu = this.moreinfoModal.querySelector('.settings-menu');
4197
+
4198
+ if (settingsMenu && this.settingsMenuOriginalParent) {
4199
+ // Restore menu to original position
4200
+ this.settingsMenuOriginalParent.appendChild(settingsMenu);
4201
+
4202
+ // Reset menu styles
4203
+ settingsMenu.style.position = '';
4204
+ settingsMenu.style.top = '';
4205
+ settingsMenu.style.right = '';
4206
+ settingsMenu.style.opacity = '';
4207
+ settingsMenu.style.visibility = '';
4208
+ settingsMenu.style.transform = '';
4209
+ settingsMenu.style.display = '';
4210
+ settingsMenu.style.maxHeight = '';
4211
+ settingsMenu.classList.remove('active');
4212
+
4213
+ this.settingsMenuInModal = false;
4214
+
4215
+ if (this.options.debug) {
4216
+ console.log('[Settings Modal] Menu restored to original position');
4217
+ }
4218
+ }
4219
+ }
4220
+
4152
4221
  this.moreinfoModal.style.display = 'none';
4153
4222
 
4154
4223
  if (this.options.debug) {
4155
- console.log('[More Info] Modal closed');
4224
+ console.log('[Modal] Modal closed');
4225
+ }
4226
+ }
4227
+
4228
+ /**
4229
+ * Open settings menu in modal
4230
+ * @returns {void}
4231
+ */
4232
+ openSettingsInModal() {
4233
+ if (!this.moreinfoModal) return;
4234
+
4235
+ // Get the settings menu element
4236
+ const settingsMenu = this.container?.querySelector('.settings-menu');
4237
+ if (!settingsMenu) {
4238
+ console.error('[Settings Modal] Settings menu not found!');
4239
+ return;
4240
+ }
4241
+
4242
+ // IMPORTANT: Only populate if menu is empty (first time)
4243
+ if (settingsMenu.children.length === 0) {
4244
+ this.populateSettingsMenu();
4245
+
4246
+ if (this.options.debug) {
4247
+ console.log('[Settings Modal] Menu populated for first time');
4248
+ }
4249
+ }
4250
+
4251
+ // Get modal elements
4252
+ const modalTitle = this.moreinfoModal.querySelector('.moreinfo-modal-title');
4253
+ const modalBody = this.moreinfoModal.querySelector('.moreinfo-modal-body');
4254
+
4255
+ if (!modalTitle || !modalBody) return;
4256
+
4257
+ // Set modal title
4258
+ modalTitle.textContent = this.t('settings_menu');
4259
+
4260
+ // CRITICAL: Move (not clone) the actual settings menu into the modal
4261
+ modalBody.innerHTML = ''; // Clear modal body
4262
+
4263
+ // Save reference to original parent for restoration later
4264
+ if (!this.settingsMenuOriginalParent) {
4265
+ this.settingsMenuOriginalParent = settingsMenu.parentNode;
4266
+ }
4267
+
4268
+ // Move the menu into modal body
4269
+ modalBody.appendChild(settingsMenu);
4270
+ modalBody.className = 'moreinfo-modal-body settings-modal-body';
4271
+
4272
+ // Make menu visible (remove dropdown positioning)
4273
+ settingsMenu.style.position = 'relative';
4274
+ settingsMenu.style.top = 'auto';
4275
+ settingsMenu.style.right = 'auto';
4276
+ settingsMenu.style.opacity = '1';
4277
+ settingsMenu.style.visibility = 'visible';
4278
+ settingsMenu.style.transform = 'none';
4279
+ settingsMenu.style.display = 'block';
4280
+ settingsMenu.style.maxHeight = 'none';
4281
+ settingsMenu.classList.add('active');
4282
+
4283
+ // Mark that settings menu is in modal
4284
+ this.settingsMenuInModal = true;
4285
+
4286
+ // Show modal
4287
+ this.moreinfoModal.style.display = 'flex';
4288
+
4289
+ // Add event delegation for "More Info" button
4290
+ this.addModalEventDelegation(modalBody);
4291
+
4292
+ if (this.options.debug) {
4293
+ console.log('[Settings Modal] Modal opened - menu moved into modal');
4294
+ }
4295
+ }
4296
+
4297
+ /**
4298
+ * Add event delegation for modal-specific actions
4299
+ * @param {HTMLElement} modalBody
4300
+ */
4301
+ addModalEventDelegation(modalBody) {
4302
+ if (!modalBody) return;
4303
+
4304
+ // Remove previous listener if exists
4305
+ if (this.modalClickHandler) {
4306
+ modalBody.removeEventListener('click', this.modalClickHandler);
4307
+ }
4308
+
4309
+ // Create new handler
4310
+ this.modalClickHandler = (e) => {
4311
+ // Handle "More Information" button
4312
+ const moreInfoBtn = e.target.closest('[data-action="moreinfo"]');
4313
+ if (moreInfoBtn) {
4314
+ e.stopPropagation();
4315
+ if (this.options.debug) {
4316
+ console.log('[Settings Modal] More Info clicked');
4317
+ }
4318
+ this.openMoreInfoModal();
4319
+ return;
4320
+ }
4321
+ };
4322
+
4323
+ // Add event listener
4324
+ modalBody.addEventListener('click', this.modalClickHandler);
4325
+
4326
+ if (this.options.debug) {
4327
+ console.log('[Settings Modal] Event delegation added for More Info');
4156
4328
  }
4157
4329
  }
4158
4330
 
@@ -4296,44 +4468,20 @@ bindSettingsMenuEvents() {
4296
4468
 
4297
4469
  if (!settingsMenu || !settingsBtn) return;
4298
4470
 
4299
- // Toggle menu on button click
4471
+ // Open settings in modal
4300
4472
  settingsBtn.addEventListener('click', (e) => {
4301
4473
  e.stopPropagation();
4302
- settingsMenu.classList.toggle('active');
4303
-
4304
- // When menu is opened, set max height and overflow
4305
- if (settingsMenu.classList.contains('active')) {
4306
- const containerRect = this.container.getBoundingClientRect();
4307
- const btnRect = settingsBtn.getBoundingClientRect();
4308
-
4309
- // Calculate available space below the button
4310
- const spaceBelow = containerRect.bottom - btnRect.bottom - 30; // 30px margin
4311
-
4312
- // Minimum 300px, maximum 600px or available space
4313
- const maxMenuHeight = Math.max(300, Math.min(600, spaceBelow));
4314
-
4315
- settingsMenu.style.maxHeight = `${maxMenuHeight}px`;
4316
- settingsMenu.style.overflowY = 'auto';
4317
- settingsMenu.style.overflowX = 'hidden';
4318
-
4319
- if (this.options.debug) {
4320
- console.log(`Settings menu opened: height=${maxMenuHeight}px (available=${spaceBelow}px)`);
4321
- }
4322
- } else {
4323
- // Reset when closing
4324
- settingsMenu.style.maxHeight = '600px'; // Default max height
4325
- settingsMenu.style.overflowY = 'auto';
4326
- }
4474
+ this.openSettingsInModal();
4327
4475
  });
4328
4476
 
4329
- // Close menu when clicking outside
4477
+ // Close menu when clicking outside (for when menu is back in original position)
4330
4478
  document.addEventListener('click', (e) => {
4331
4479
  if (!settingsBtn?.contains(e.target) && !settingsMenu?.contains(e.target)) {
4332
4480
  settingsMenu?.classList.remove('active');
4333
4481
  }
4334
4482
  });
4335
4483
 
4336
- // Manage clicks inside the menu
4484
+ // Manage clicks inside the menu (this handles speed, subtitles, pip, etc.)
4337
4485
  settingsMenu.addEventListener('click', (e) => {
4338
4486
  e.stopPropagation();
4339
4487
 
@@ -4356,7 +4504,7 @@ bindSettingsMenuEvents() {
4356
4504
  return;
4357
4505
  }
4358
4506
 
4359
- // Handle direct actions (like PiP)
4507
+ // Handle direct actions (PiP, More Info, etc.)
4360
4508
  if (e.target.classList.contains('settings-option') || e.target.closest('.settings-option')) {
4361
4509
  const option = e.target.classList.contains('settings-option') ? e.target : e.target.closest('.settings-option');
4362
4510
  const action = option.getAttribute('data-action');
@@ -4368,16 +4516,15 @@ bindSettingsMenuEvents() {
4368
4516
 
4369
4517
  // Handle More Info action
4370
4518
  if (action === 'moreinfo') {
4519
+ if (this.options.debug) {
4520
+ console.log('[Settings] More Info clicked');
4521
+ }
4371
4522
  this.openMoreInfoModal();
4372
- // Close settings menu
4373
- settingsMenu.classList.remove('active');
4374
- const settingsBtn = this.container?.querySelector('.settings-btn');
4375
- if (settingsBtn) settingsBtn.classList.remove('active');
4376
4523
  return;
4377
4524
  }
4378
4525
  }
4379
4526
 
4380
- // Handle submenu actions
4527
+ // Handle submenu actions (speed, subtitles)
4381
4528
  if (e.target.classList.contains('settings-suboption')) {
4382
4529
  const wrapper = e.target.closest('.settings-expandable-wrapper');
4383
4530
  const trigger = wrapper.querySelector('.expandable-trigger');
@@ -4401,6 +4548,10 @@ bindSettingsMenuEvents() {
4401
4548
 
4402
4549
  // Trigger event
4403
4550
  this.triggerEvent('speedchange', { speed, previousSpeed: this.video.playbackRate });
4551
+
4552
+ if (this.options.debug) {
4553
+ console.log('[Settings] Speed changed to', speed);
4554
+ }
4404
4555
  }
4405
4556
  } else if (action === 'subtitles_expand') {
4406
4557
  const trackData = e.target.getAttribute('data-track');
@@ -4421,9 +4572,17 @@ bindSettingsMenuEvents() {
4421
4572
  const subtitlesLabel = this.t('subtitles') || 'Subtitles';
4422
4573
  label.innerHTML = `${subtitlesLabel} <strong>${e.target.textContent}</strong>`;
4423
4574
  }
4575
+
4576
+ if (this.options.debug) {
4577
+ console.log('[Settings] Subtitle changed to', trackData);
4578
+ }
4424
4579
  }
4425
4580
  }
4426
4581
  });
4582
+
4583
+ if (this.options.debug) {
4584
+ console.log('[Settings] Menu events bound');
4585
+ }
4427
4586
  }
4428
4587
 
4429
4588
  /* TITLE OVERLAY MANAGEMENT */
@@ -769,6 +769,9 @@ constructor(videoElement, options = {}) {
769
769
  hls: false
770
770
  };
771
771
 
772
+ this.settingsMenuOriginalParent = null;
773
+ this.settingsMenuInModal = false;
774
+
772
775
  this.lastTimeUpdate = 0; // For throttling timeupdate events
773
776
 
774
777
  this.injectDefaultControlbarStyles();
@@ -3739,6 +3742,40 @@ createMoreInfoModal() {
3739
3742
  openMoreInfoModal() {
3740
3743
  if (!this.moreinfoModal) return;
3741
3744
 
3745
+ if (this.settingsMenuInModal) {
3746
+ const settingsMenu = this.moreinfoModal.querySelector('.settings-menu');
3747
+
3748
+ if (settingsMenu && this.settingsMenuOriginalParent) {
3749
+
3750
+ this.settingsMenuOriginalParent.appendChild(settingsMenu);
3751
+
3752
+ settingsMenu.style.position = '';
3753
+ settingsMenu.style.top = '';
3754
+ settingsMenu.style.right = '';
3755
+ settingsMenu.style.opacity = '';
3756
+ settingsMenu.style.visibility = '';
3757
+ settingsMenu.style.transform = '';
3758
+ settingsMenu.style.display = '';
3759
+ settingsMenu.style.maxHeight = '';
3760
+ settingsMenu.classList.remove('active');
3761
+
3762
+ this.settingsMenuInModal = false;
3763
+
3764
+ if (this.options.debug) {
3765
+ console.log('[More Info] Menu restored before showing more info');
3766
+ }
3767
+ }
3768
+ }
3769
+
3770
+ const modalTitle = this.moreinfoModal.querySelector('.moreinfo-modal-title');
3771
+ const modalBody = this.moreinfoModal.querySelector('.moreinfo-modal-body');
3772
+
3773
+ if (!modalTitle || !modalBody) return;
3774
+
3775
+ modalTitle.textContent = this.decodeHTMLEntities(this.options.moreinfoTitle || '');
3776
+ modalBody.innerHTML = this.decodeHTMLEntities(this.options.moreinfoDescription || '');
3777
+ modalBody.className = 'moreinfo-modal-body'; // Reset class (remove settings-modal-body)
3778
+
3742
3779
  this.moreinfoModal.style.display = 'flex';
3743
3780
 
3744
3781
  if (this.options.debug) {
@@ -3749,10 +3786,116 @@ openMoreInfoModal() {
3749
3786
  closeMoreInfoModal() {
3750
3787
  if (!this.moreinfoModal) return;
3751
3788
 
3789
+ if (this.settingsMenuInModal) {
3790
+ const settingsMenu = this.moreinfoModal.querySelector('.settings-menu');
3791
+
3792
+ if (settingsMenu && this.settingsMenuOriginalParent) {
3793
+
3794
+ this.settingsMenuOriginalParent.appendChild(settingsMenu);
3795
+
3796
+ settingsMenu.style.position = '';
3797
+ settingsMenu.style.top = '';
3798
+ settingsMenu.style.right = '';
3799
+ settingsMenu.style.opacity = '';
3800
+ settingsMenu.style.visibility = '';
3801
+ settingsMenu.style.transform = '';
3802
+ settingsMenu.style.display = '';
3803
+ settingsMenu.style.maxHeight = '';
3804
+ settingsMenu.classList.remove('active');
3805
+
3806
+ this.settingsMenuInModal = false;
3807
+
3808
+ if (this.options.debug) {
3809
+ console.log('[Settings Modal] Menu restored to original position');
3810
+ }
3811
+ }
3812
+ }
3813
+
3752
3814
  this.moreinfoModal.style.display = 'none';
3753
3815
 
3754
3816
  if (this.options.debug) {
3755
- console.log('[More Info] Modal closed');
3817
+ console.log('[Modal] Modal closed');
3818
+ }
3819
+ }
3820
+
3821
+ openSettingsInModal() {
3822
+ if (!this.moreinfoModal) return;
3823
+
3824
+ const settingsMenu = this.container?.querySelector('.settings-menu');
3825
+ if (!settingsMenu) {
3826
+ console.error('[Settings Modal] Settings menu not found!');
3827
+ return;
3828
+ }
3829
+
3830
+ if (settingsMenu.children.length === 0) {
3831
+ this.populateSettingsMenu();
3832
+
3833
+ if (this.options.debug) {
3834
+ console.log('[Settings Modal] Menu populated for first time');
3835
+ }
3836
+ }
3837
+
3838
+ const modalTitle = this.moreinfoModal.querySelector('.moreinfo-modal-title');
3839
+ const modalBody = this.moreinfoModal.querySelector('.moreinfo-modal-body');
3840
+
3841
+ if (!modalTitle || !modalBody) return;
3842
+
3843
+ modalTitle.textContent = this.t('settings_menu');
3844
+
3845
+ modalBody.innerHTML = ''; // Clear modal body
3846
+
3847
+ if (!this.settingsMenuOriginalParent) {
3848
+ this.settingsMenuOriginalParent = settingsMenu.parentNode;
3849
+ }
3850
+
3851
+ modalBody.appendChild(settingsMenu);
3852
+ modalBody.className = 'moreinfo-modal-body settings-modal-body';
3853
+
3854
+ settingsMenu.style.position = 'relative';
3855
+ settingsMenu.style.top = 'auto';
3856
+ settingsMenu.style.right = 'auto';
3857
+ settingsMenu.style.opacity = '1';
3858
+ settingsMenu.style.visibility = 'visible';
3859
+ settingsMenu.style.transform = 'none';
3860
+ settingsMenu.style.display = 'block';
3861
+ settingsMenu.style.maxHeight = 'none';
3862
+ settingsMenu.classList.add('active');
3863
+
3864
+ this.settingsMenuInModal = true;
3865
+
3866
+ this.moreinfoModal.style.display = 'flex';
3867
+
3868
+ this.addModalEventDelegation(modalBody);
3869
+
3870
+ if (this.options.debug) {
3871
+ console.log('[Settings Modal] Modal opened - menu moved into modal');
3872
+ }
3873
+ }
3874
+
3875
+ addModalEventDelegation(modalBody) {
3876
+ if (!modalBody) return;
3877
+
3878
+ if (this.modalClickHandler) {
3879
+ modalBody.removeEventListener('click', this.modalClickHandler);
3880
+ }
3881
+
3882
+ this.modalClickHandler = (e) => {
3883
+
3884
+ const moreInfoBtn = e.target.closest('[data-action="moreinfo"]');
3885
+ if (moreInfoBtn) {
3886
+ e.stopPropagation();
3887
+ if (this.options.debug) {
3888
+ console.log('[Settings Modal] More Info clicked');
3889
+ }
3890
+ this.openMoreInfoModal();
3891
+ return;
3892
+ }
3893
+ };
3894
+
3895
+ modalBody.addEventListener('click', this.modalClickHandler);
3896
+
3897
+ if (this.options.debug) {
3898
+ console.log('[Settings Modal] Event delegation added for More Info');
3756
3899
  }
3757
3900
  }
3758
3901
 
@@ -3882,28 +4025,7 @@ bindSettingsMenuEvents() {
3882
4025
 
3883
4026
  settingsBtn.addEventListener('click', (e) => {
3884
4027
  e.stopPropagation();
3885
- settingsMenu.classList.toggle('active');
3886
-
3887
- if (settingsMenu.classList.contains('active')) {
3888
- const containerRect = this.container.getBoundingClientRect();
3889
- const btnRect = settingsBtn.getBoundingClientRect();
3890
-
3891
- const spaceBelow = containerRect.bottom - btnRect.bottom - 30; // 30px margin
3892
-
3893
- const maxMenuHeight = Math.max(300, Math.min(600, spaceBelow));
3894
-
3895
- settingsMenu.style.maxHeight = `${maxMenuHeight}px`;
3896
- settingsMenu.style.overflowY = 'auto';
3897
- settingsMenu.style.overflowX = 'hidden';
3898
-
3899
- if (this.options.debug) {
3900
- console.log(`Settings menu opened: height=${maxMenuHeight}px (available=${spaceBelow}px)`);
3901
- }
3902
- } else {
3903
-
3904
- settingsMenu.style.maxHeight = '600px'; // Default max height
3905
- settingsMenu.style.overflowY = 'auto';
3906
- }
4028
+ this.openSettingsInModal();
3907
4029
  });
3908
4030
 
3909
4031
  document.addEventListener('click', (e) => {
@@ -3943,11 +4065,10 @@ bindSettingsMenuEvents() {
3943
4065
  }
3944
4066
 
3945
4067
  if (action === 'moreinfo') {
4068
+ if (this.options.debug) {
4069
+ console.log('[Settings] More Info clicked');
4070
+ }
3946
4071
  this.openMoreInfoModal();
3947
-
3948
- settingsMenu.classList.remove('active');
3949
- const settingsBtn = this.container?.querySelector('.settings-btn');
3950
- if (settingsBtn) settingsBtn.classList.remove('active');
3951
4072
  return;
3952
4073
  }
3953
4074
  }
@@ -3972,6 +4093,10 @@ bindSettingsMenuEvents() {
3972
4093
  }
3973
4094
 
3974
4095
  this.triggerEvent('speedchange', { speed, previousSpeed: this.video.playbackRate });
4096
+
4097
+ if (this.options.debug) {
4098
+ console.log('[Settings] Speed changed to', speed);
4099
+ }
3975
4100
  }
3976
4101
  } else if (action === 'subtitles_expand') {
3977
4102
  const trackData = e.target.getAttribute('data-track');
@@ -3990,9 +4115,17 @@ bindSettingsMenuEvents() {
3990
4115
  const subtitlesLabel = this.t('subtitles') || 'Subtitles';
3991
4116
  label.innerHTML = `${subtitlesLabel} <strong>${e.target.textContent}</strong>`;
3992
4117
  }
4118
+
4119
+ if (this.options.debug) {
4120
+ console.log('[Settings] Subtitle changed to', trackData);
4121
+ }
3993
4122
  }
3994
4123
  }
3995
4124
  });
4125
+
4126
+ if (this.options.debug) {
4127
+ console.log('[Settings] Menu events bound');
4128
+ }
3996
4129
  }
3997
4130
 
3998
4131
  showTitleOverlay() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myetv-player",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "description": "MYETV Video Player - Modular HTML5 video player with plugin support for YouTube, Vimeo, Twitch, Facebook, Cloudflare Stream and streaming protocols (HLS/DASH)",
5
5
  "main": "dist/myetv-player.js",
6
6
  "files": [
@@ -67,3 +67,4 @@
67
67
 
68
68
 
69
69
 
70
+