j1-template 2024.3.20 → 2024.3.22

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.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/_layouts/page.html +1 -0
  3. data/assets/data/amplitude_app.html +87 -73
  4. data/assets/theme/j1/adapter/js/advertising.js +40 -38
  5. data/assets/theme/j1/adapter/js/algolia.js +13 -11
  6. data/assets/theme/j1/adapter/js/amplitude.js +882 -490
  7. data/assets/theme/j1/adapter/js/analytics.js +19 -17
  8. data/assets/theme/j1/adapter/js/asciidoctor.js +10 -8
  9. data/assets/theme/j1/adapter/js/attic.js +24 -22
  10. data/assets/theme/j1/adapter/js/bmd.js +10 -8
  11. data/assets/theme/j1/adapter/js/carousel.js +12 -9
  12. data/assets/theme/j1/adapter/js/chatbot.js +106 -104
  13. data/assets/theme/j1/adapter/js/clipboard.js +16 -14
  14. data/assets/theme/j1/adapter/js/comments.js +24 -22
  15. data/assets/theme/j1/adapter/js/cookieConsent.js +5 -1
  16. data/assets/theme/j1/adapter/js/customFunctions.js +12 -10
  17. data/assets/theme/j1/adapter/js/customModule.js +10 -8
  18. data/assets/theme/j1/adapter/js/docsearch.js +33 -31
  19. data/assets/theme/j1/adapter/js/dropdowns.js +16 -14
  20. data/assets/theme/j1/adapter/js/fab.js +34 -32
  21. data/assets/theme/j1/adapter/js/gallery.js +21 -19
  22. data/assets/theme/j1/adapter/js/gemini.js +66 -64
  23. data/assets/theme/j1/adapter/js/iconPicker.js +31 -29
  24. data/assets/theme/j1/adapter/js/iconPickerPage.js +11 -9
  25. data/assets/theme/j1/adapter/js/iframer.js +17 -15
  26. data/assets/theme/j1/adapter/js/j1.js +146 -143
  27. data/assets/theme/j1/adapter/js/lazyLoader.js +33 -31
  28. data/assets/theme/j1/adapter/js/lightbox.js +9 -7
  29. data/assets/theme/j1/adapter/js/logger.js +11 -9
  30. data/assets/theme/j1/adapter/js/lunr.js +37 -35
  31. data/assets/theme/j1/adapter/js/masonry.js +23 -21
  32. data/assets/theme/j1/adapter/js/masterslider.js +31 -29
  33. data/assets/theme/j1/adapter/js/mmenu.js +25 -23
  34. data/assets/theme/j1/adapter/js/navigator.js +43 -41
  35. data/assets/theme/j1/adapter/js/particles.js +12 -10
  36. data/assets/theme/j1/adapter/js/rangeSlider.js +21 -19
  37. data/assets/theme/j1/adapter/js/rouge.js +10 -8
  38. data/assets/theme/j1/adapter/js/rtable.js +14 -12
  39. data/assets/theme/j1/adapter/js/rtextResizer.js +10 -8
  40. data/assets/theme/j1/adapter/js/scroller.js +15 -13
  41. data/assets/theme/j1/adapter/js/slick.js +18 -16
  42. data/assets/theme/j1/adapter/js/slimSelect.js +30 -28
  43. data/assets/theme/j1/adapter/js/speak2me.js +25 -23
  44. data/assets/theme/j1/adapter/js/swiper.js +13 -11
  45. data/assets/theme/j1/adapter/js/themeToggler.js +11 -9
  46. data/assets/theme/j1/adapter/js/themes.js +25 -23
  47. data/assets/theme/j1/adapter/js/toccer.js +13 -11
  48. data/assets/theme/j1/adapter/js/translator.js +19 -16
  49. data/assets/theme/j1/adapter/js/videojs.js +9 -7
  50. data/assets/theme/j1/adapter/js/waves.js +18 -16
  51. data/assets/theme/j1/core/js/template.js +11180 -10968
  52. data/assets/theme/j1/core/js/template.min.js +13 -18
  53. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/amplitude.css +50 -4
  54. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/amplitude.min.css +1 -1
  55. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/compact.css +197 -403
  56. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/compact.min.css +1 -1
  57. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/large.css +70 -46
  58. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/large.min.css +1 -1
  59. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/mini.css +72 -9
  60. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/mini.min.css +2 -1
  61. data/assets/theme/j1/modules/amplitudejs/js/tech/ytp.js +481 -417
  62. data/assets/theme/j1/modules/backstretch/js/backstretch.js +2 -2
  63. data/assets/theme/j1/modules/backstretch/js/backstretch.min.js +1 -1
  64. data/assets/theme/j1/modules/cookieConsent/js/cookieConsent.js +11 -11
  65. data/assets/theme/j1/modules/cookieConsent/js/cookieConsent.min.js +2 -1
  66. data/assets/theme/j1/modules/dropdowns/js/dropdowns.js +2 -2
  67. data/assets/theme/j1/modules/dropdowns/js/dropdowns.min.js +1 -1
  68. data/assets/theme/j1/modules/fab/js/fab.js +2 -2
  69. data/assets/theme/j1/modules/fab/js/fab.min.js +1 -1
  70. data/assets/theme/j1/modules/lunr/js/j1.js +1 -1
  71. data/assets/theme/j1/modules/lunr/js/j1.min.js +2 -1
  72. data/assets/theme/j1/modules/rtable/js/rtable.js +2 -2
  73. data/assets/theme/j1/modules/rtable/js/rtable.min.js +2 -1
  74. data/assets/theme/j1/modules/scroller/js/scroller.js +31 -29
  75. data/assets/theme/j1/modules/scroller/js/scroller.min.js +2 -1
  76. data/assets/theme/j1/modules/themeSwitcher/js/switcher.js +26 -26
  77. data/assets/theme/j1/modules/themeSwitcher/js/switcher.min.js +2 -1
  78. data/assets/theme/j1/modules/translator/js/translator.js +17 -17
  79. data/assets/theme/j1/modules/translator/js/translator.min.js +1 -1
  80. data/assets/theme/j1/modules/videojs/js/plugins/players/dm/dailymotion.js +10 -8
  81. data/assets/theme/j1/modules/videojs/js/plugins/players/dm/dailymotion.min.js +1 -1
  82. data/assets/theme/j1/modules/videojs/js/plugins/players/vm/vimeo.js +9 -7
  83. data/assets/theme/j1/modules/videojs/js/plugins/players/vm/vimeo.min.js +1 -1
  84. data/assets/theme/j1/modules/videojs/js/plugins/players/wt/wistia.js +13 -11
  85. data/assets/theme/j1/modules/videojs/js/plugins/players/wt/wistia.min.js +1 -1
  86. data/assets/theme/j1/modules/videojs/js/plugins/players/yt/youtube.js +10 -8
  87. data/assets/theme/j1/modules/videojs/js/plugins/players/yt/youtube.min.js +1 -1
  88. data/lib/j1/version.rb +1 -1
  89. data/lib/starter_web/README.md +5 -5
  90. data/lib/starter_web/_config.yml +1 -1
  91. data/lib/starter_web/_data/modules/amplitude_app.yml +4 -4
  92. data/lib/starter_web/_data/modules/amplitude_playlists.yml +168 -123
  93. data/lib/starter_web/_data/modules/defaults/amplitude.yml +8 -3
  94. data/lib/starter_web/_data/modules/swiper_app.yml +67 -0
  95. data/lib/starter_web/_data/modules/swiper_playlists.yml +26 -0
  96. data/lib/starter_web/_data/templates/feed.xml +1 -1
  97. data/lib/starter_web/_includes/attributes.asciidoc +5 -4
  98. data/lib/starter_web/_plugins/asciidoctor/videojs-block.rb +8 -0
  99. data/lib/starter_web/_plugins/asciidoctor/youtube-block.rb +7 -0
  100. data/lib/starter_web/_plugins/index/lunr.rb +1 -1
  101. data/lib/starter_web/assets/audio/album/emancipator/Alligator.mp3 +0 -0
  102. data/lib/starter_web/assets/audio/album/emancipator/DabCity.mp3 +0 -0
  103. data/lib/starter_web/assets/audio/album/emancipator/SeaToSky.mp3 +0 -0
  104. data/lib/starter_web/assets/audio/album/emancipator/TimeForSpace.mp3 +0 -0
  105. data/lib/starter_web/assets/audio/cover/emancipator/alligator.jpg +0 -0
  106. data/lib/starter_web/assets/audio/cover/emancipator/anthem.jpg +0 -0
  107. data/lib/starter_web/assets/audio/cover/emancipator/dab-city.jpg +0 -0
  108. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn.jpg +0 -0
  109. data/lib/starter_web/assets/audio/cover/emancipator/safe-in-the-steep-cliffs.jpg +0 -0
  110. data/lib/starter_web/assets/audio/cover/emancipator/sea-to-sky.jpg +0 -0
  111. data/lib/starter_web/assets/audio/cover/emancipator/soon-it-will-be-cold-enough.jpg +0 -0
  112. data/lib/starter_web/assets/audio/cover/emancipator/tine-for-space.jpg +0 -0
  113. data/lib/starter_web/assets/image/icon/bokeh/bokeh-32x32.ico +0 -0
  114. data/lib/starter_web/assets/image/icon/bokeh/bokeh.ico +0 -0
  115. data/lib/starter_web/assets/image/icon/bokeh/logo-160x160.png +0 -0
  116. data/lib/starter_web/assets/image/icon/hyvor-talk/hyvore-talk.ico +0 -0
  117. data/lib/starter_web/assets/image/icon/hyvor-talk/jpg/hyvor-logo.512x512.jpg +0 -0
  118. data/lib/starter_web/assets/image/icon/hyvor-talk/png/hyvor-logo.24x24.jpg +0 -0
  119. data/lib/starter_web/assets/image/icon/hyvor-talk/png/hyvor-logo.24x24.png +0 -0
  120. data/lib/starter_web/assets/image/icon/hyvor-talk/png/hyvor-logo.512x512.png +0 -0
  121. data/lib/starter_web/assets/image/icon/hyvor-talk/scalable/hyvor-logo.svg +81 -0
  122. data/lib/starter_web/assets/image/icon/jupyter/jupyter-32x32.ico +0 -0
  123. data/lib/starter_web/assets/image/icon/jupyter/jupyter.ico +0 -0
  124. data/lib/starter_web/assets/image/icon/jupyter/logo.png +0 -0
  125. data/lib/starter_web/assets/image/icon/mdi/mdi.svg +1 -0
  126. data/lib/starter_web/assets/image/icon/mdi/mdil.svg +1 -0
  127. data/lib/starter_web/assets/image/icon/scalable/facebook.svg +34 -0
  128. data/lib/starter_web/assets/image/icon/scalable/google.svg +35 -0
  129. data/lib/starter_web/assets/image/icon/scalable/ibm.svg +24 -0
  130. data/lib/starter_web/assets/image/icon/scalable/microsoft.svg +42 -0
  131. data/lib/starter_web/assets/image/module/swiper/simple/test/image/diana_krall.jpg +0 -0
  132. data/lib/starter_web/index.html +3 -3
  133. data/lib/starter_web/package.json +1 -1
  134. data/lib/starter_web/pages/public/learn/where_to_go.adoc +1 -1
  135. data/lib/starter_web/pages/public/tools/previewer/preview_amplitudejs.adoc +3 -18
  136. data/lib/starter_web/pages/public/tools/tester/app_tester_amplitudejs_yt.adoc +6 -6
  137. data/lib/starter_web/pages/public/tools/tester/app_tester_swiper.adoc +87 -0
  138. data/lib/starter_web/pages/public/tour/_includes/attributes.asciidoc +3 -3
  139. data/lib/starter_web/pages/public/tour/{play_audio.adoc → audio_data.adoc} +35 -55
  140. data/lib/starter_web/pages/public/tour/{present_images.adoc → image_data.adoc} +4 -5
  141. data/lib/starter_web/pages/public/tour/{play_video.adoc → video_data.adoc} +17 -16
  142. metadata +42 -14
  143. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/anthem.jpg +0 -0
  144. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/from-dusk-to-dawn.jpg +0 -0
  145. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/safe-in-the-steep-cliffs.jpg +0 -0
  146. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/soon-it-will-be-cold-enough.jpg +0 -0
  147. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn → !info}/!sound.links.txt +0 -0
  148. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn/Anthem.mp3 → Anthem.mp3} +0 -0
  149. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn/DuskToDawn.mp3 → DuskToDawn.mp3} +0 -0
  150. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn/FirstSnow.mp3 → FirstSnow.mp3} +0 -0
  151. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn/SafeInTheSteepCliffs.mp3 → SafeInTheSteepCliffs.mp3} +0 -0
@@ -6,7 +6,7 @@ regenerate: true
6
6
 
7
7
  {% comment %}
8
8
  # -----------------------------------------------------------------------------
9
- # ~/assets/theme/j1/modules/amplitudejs/js/plugins/tech/ytp.31.js
9
+ # ~/assets/theme/j1/modules/amplitudejs/js/plugins/tech/ytp.33.js
10
10
  # AmplitudeJS V5 Tech for J1 Template
11
11
  #
12
12
  # Product/Info:
@@ -60,7 +60,7 @@ regenerate: true
60
60
 
61
61
  /*
62
62
  # -----------------------------------------------------------------------------
63
- # ~/assets/theme/j1/modules/amplitudejs/js/plugins/tech/ytp.31.js
63
+ # ~/assets/theme/j1/modules/amplitudejs/js/plugins/tech/ytp.33.js
64
64
  # AmplitudeJS V5 Plugin|Tech for J1 Template
65
65
  #
66
66
  # Product/Info:
@@ -84,6 +84,21 @@ regenerate: true
84
84
 
85
85
  // YT API settings
86
86
  // ---------------------------------------------------------------------------
87
+
88
+ var YT_PLAYER_ERROR = {
89
+ INVALID_PARAMETER: 2,
90
+ INVALID_PLAYER: 5,
91
+ VIDEO_NOT_ALLOWED: 101,
92
+ VIDEO_NOT_ALLOWED: 150
93
+ };
94
+
95
+ var YT_PLAYER_ERROR_NAMES = {
96
+ 2: "invalid parameter",
97
+ 5: "invalid player",
98
+ 101: "video not allowed",
99
+ 150: "video not allowed"
100
+ };
101
+
87
102
  var YT_PLAYER_STATE = {
88
103
  UNSTARTED: -1,
89
104
  ENDED: 0,
@@ -211,7 +226,7 @@ regenerate: true
211
226
  // fade-in audio (if enabled)
212
227
  if (playerFadeAudio) {
213
228
  currentVolume = player.getVolume();
214
- logger.debug('\n' + `FADE-IN audio on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
229
+ logger.debug(`FADE-IN audio on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
215
230
  ytpFadeInAudio({
216
231
  playerID: playerID,
217
232
  targetVolume: currentVolume,
@@ -249,7 +264,7 @@ regenerate: true
249
264
 
250
265
  // fade-out audio (if enabled)
251
266
  if (isVideoChanged && playerFadeAudio) {
252
- logger.debug('\n' + `FADE-OUT audio on processOnVideoEnd at trackID|VideoID: ${trackID}|${activeVideoID}`);
267
+ logger.debug(`FADE-OUT audio on processOnVideoEnd at trackID|VideoID: ${trackID}|${activeVideoID}`);
253
268
  ytpFadeOutAudio({
254
269
  playerID: playerID,
255
270
  speed: 'default'
@@ -259,11 +274,11 @@ regenerate: true
259
274
  // if (!activeVideoElement.audio_single) {
260
275
  if (isVideoChanged) {
261
276
  // load next video
262
- logger.debug('\n' + `LOAD next VIDEO on processOnVideoEnd at trackID|playlist: ${trackID}|${playlist}`);
277
+ logger.debug(`LOAD next VIDEO on processOnVideoEnd at trackID|playlist: ${trackID}|${playlist}`);
263
278
  loadNextVideo(playlist, songIndex);
264
279
  } else {
265
280
  // skip loading next video if a single video is used for playlist
266
- logger.debug('\n' + `LOAD next TRACK in video on processOnVideoEnd at trackID|playlist: ${trackID}|${playlist}`);
281
+ logger.debug(`LOAD next TRACK in video on processOnVideoEnd at trackID|playlist: ${trackID}|${playlist}`);
267
282
  }
268
283
 
269
284
  } // END processOnVideoEnd
@@ -271,21 +286,23 @@ regenerate: true
271
286
  // ---------------------------------------------------------------------------
272
287
  // doNothingOnStateChange(state)
273
288
  //
289
+ // wrraper for states that are not processed
274
290
  // ---------------------------------------------------------------------------
275
291
  function doNothingOnStateChange(state) {
276
292
  if (state > 0) {
277
- logger.warn('\n' + `DO NOTHING on StateChange for state: ${YT_PLAYER_STATE_NAMES[state]}`);
293
+ logger.warn(`DO NOTHING on StateChange for state: ${YT_PLAYER_STATE_NAMES[state]}`);
278
294
  } else {
279
- logger.warn('\n' + `DO NOTHING on StateChange for state: ${YT_PLAYER_STATE_NAMES[6]}`);
295
+ logger.warn(`DO NOTHING on StateChange for state: ${YT_PLAYER_STATE_NAMES[6]}`);
280
296
  }
281
- } // ENS doNothingOnStateChange
297
+ } // END doNothingOnStateChange
282
298
 
283
299
  // ---------------------------------------------------------------------------
284
300
  // processOnStateChangePlaying()
285
301
  //
302
+ // wrapper for processing players on state PLAYING
286
303
  // ---------------------------------------------------------------------------
287
304
  function processOnStateChangePlaying(event, playlist, songIndex) {
288
- var activeSong, playlist, playerID, videoID,
305
+ var activeSong, activePlaylist, playerID, videoID,
289
306
  ytPlayer, songs, songIndex,
290
307
  currentPlayer, previousPlayer, trackID;
291
308
 
@@ -295,15 +312,19 @@ regenerate: true
295
312
  checkActiveVideoElementYTP();
296
313
 
297
314
  // get active song settings (manually)
298
- activeSong = getActiveSong();
315
+ activeSong = getActiveSong();
299
316
 
300
- playlist = activeSong.playlist;
317
+ activePlaylist = playlist;
301
318
  playerID = activeSong.playerID;
302
319
  videoID = activeSong.videoID;
303
320
  songs = activeSong.songs;
304
- songIndex = activeSong.index;
321
+ // songIndex = activeSong.index;
305
322
  currentPlayer = activeSong.player;
306
323
  previousPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player
324
+ trackID = songIndex + 1;
325
+
326
+ logger.debug(`PLAY audio on YTP at playlist|trackID: ${activePlaylist}|${trackID}`);
327
+ // logger.debug(`PLAY video on StateChange (playing) at playlist|trackID: ${playList}|${trackID}`);
307
328
 
308
329
  // save YT player GLOBAL data for later use (e.g. events)
309
330
  j1.adapter.amplitude.data.activePlayer = 'ytp';
@@ -325,18 +346,18 @@ regenerate: true
325
346
  updateProgressBarsYTP();
326
347
  }, 500);
327
348
 
328
- trackID = songIndex + 1;
329
- logger.debug('\n' + `PLAY video on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
349
+ // update meta data
350
+ ytpUpdatMetaContainers(activeSong);
330
351
 
331
352
  // check|process video for configured START position (if set)
332
353
  // -------------------------------------------------------------------------
333
354
  var songStartSec = activeSong.startSec;
334
355
  if (songStartSec) {
335
- var tsStartSec = seconds2timestamp(songStartSec);
356
+ var tsStartSec = j1.adapter.amplitude.seconds2timestamp(songStartSec);
336
357
  var songCurrentTime = ytPlayer.getCurrentTime();
337
358
 
338
359
  if (songCurrentTime < songStartSec) {
339
- logger.debug('\n' + `START video on StateChange at trackID|timestamp: ${trackID}|${tsStartSec}`);
360
+ logger.debug(`START video on StateChange at trackID|timestamp: ${trackID}|${tsStartSec}`);
340
361
  processOnVideoStart(ytPlayer, songStartSec);
341
362
  }
342
363
  } // END if songStartEnabled
@@ -345,13 +366,13 @@ regenerate: true
345
366
  // -------------------------------------------------------------------------
346
367
  var songEndSec = activeSong.endSec;
347
368
  if (songEndSec) {
348
- var tsEndSec = seconds2timestamp(songEndSec);
369
+ var tsEndSec = j1.adapter.amplitude.seconds2timestamp(songEndSec);
349
370
 
350
371
  var checkOnVideoEnd = setInterval(function() {
351
372
  var songCurrentTime = ytPlayer.getCurrentTime();
352
373
 
353
374
  if (songCurrentTime >= songEndSec) {
354
- logger.debug('\n' + `STOP video on StateChange at trackID|timestamp: ${trackID}|${tsEndSec}`);
375
+ logger.debug(`STOP video on StateChange at trackID|timestamp: ${trackID}|${tsEndSec}`);
355
376
  processOnVideoEnd(ytPlayer);
356
377
 
357
378
  clearInterval(checkOnVideoEnd);
@@ -359,67 +380,56 @@ regenerate: true
359
380
  }, 500); // END checkOnVideoEnd
360
381
  } // END if songEndEnabled
361
382
 
362
- // stop active AT players running in parallel
363
- // -------------------------------------------------------------------------
364
- var atpPlayerState = Amplitude.getPlayerState();
365
- if (atpPlayerState === 'playing') {
366
- Amplitude.stop();
383
+ // stop active AT|YT players running in parallel except the current
384
+ ytpStopParallelActivePlayers(playerID);
367
385
 
368
- // clear button MINI PlayerPlayPause (AT player)
369
- var buttonPlayerPlayPause = document.getElementsByClassName("mini-player-play-pause");
370
- for (var i=0; i<buttonPlayerPlayPause.length; i++) {
371
- var htmlElement = buttonPlayerPlayPause[i];
372
-
373
- if (htmlElement.dataset.amplitudeSource === 'audio') {
386
+ // clear button MINI PlayerPlayPause (AT player)
387
+ var buttonPlayerPlayPauseMini = document.getElementsByClassName("mini-player-play-pause");
388
+ for (var i=0; i<buttonPlayerPlayPauseMini.length; i++) {
389
+ var htmlElement = buttonPlayerPlayPauseMini[i];
390
+
391
+ // toggle classes on state playing
392
+ if (htmlElement.dataset.amplitudeSource === 'audio') {
393
+ if (htmlElement.classList.contains('amplitude-playing')) {
374
394
  htmlElement.classList.remove('amplitude-playing');
375
395
  htmlElement.classList.add('amplitude-paused');
376
396
  }
377
-
378
- } // END for MINI buttonPlayerPlayPause
379
-
380
- // clear button COMPACT PlayerPlayPause (AT player)
381
- var buttonPlayerPlayPause = document.getElementsByClassName("compact-player-play-pause");
382
- for (var i=0; i<buttonPlayerPlayPause.length; i++) {
383
- var htmlElement = buttonPlayerPlayPause[i];
384
-
385
- if (htmlElement.dataset.amplitudeSource === 'audio') {
397
+ }
398
+
399
+ } // END for MINI buttonPlayerPlayPause
400
+
401
+ // clear button COMPACT PlayerPlayPause (AT player)
402
+ var buttonPlayerPlayPauseCompact = document.getElementsByClassName("compact-player-play-pause");
403
+ for (var i=0; i<buttonPlayerPlayPauseCompact.length; i++) {
404
+ var htmlElement = buttonPlayerPlayPauseCompact[i];
405
+
406
+ // toggle classes on state playing
407
+ if (htmlElement.dataset.amplitudeSource === 'audio') {
408
+ if (htmlElement.classList.contains('amplitude-playing')) {
386
409
  htmlElement.classList.remove('amplitude-playing');
387
410
  htmlElement.classList.add('amplitude-paused');
388
411
  }
389
-
390
- } // END for COMACT buttonPlayerPlayPause
412
+ }
413
+
414
+ } // END for COMACT buttonPlayerPlayPause
391
415
 
392
- // clear button LARGE PlayerPlayPause (AT player)
393
- var buttonPlayerPlayPause = document.getElementsByClassName("large-player-play-pause");
394
- for (var i=0; i<buttonPlayerPlayPause.length; i++) {
395
- var htmlElement = buttonPlayerPlayPause[i];
396
-
397
- if (htmlElement.dataset.amplitudeSource === 'audio') {
416
+ // clear button LARGE PlayerPlayPause (AT player)
417
+ var buttonPlayerPlayPauseLarge = document.getElementsByClassName("large-player-play-pause");
418
+ for (var i=0; i<buttonPlayerPlayPauseLarge.length; i++) {
419
+ var htmlElement = buttonPlayerPlayPauseLarge[i];
420
+
421
+ // toggle classes on state playing
422
+ if (htmlElement.dataset.amplitudeSource === 'audio') {
423
+ if (htmlElement.classList.contains('amplitude-playing')) {
398
424
  htmlElement.classList.remove('amplitude-playing');
399
425
  htmlElement.classList.add('amplitude-paused');
400
426
  }
427
+ }
401
428
 
402
- } // END for LARGE buttonPlayerPlayPause
403
-
404
- } // END if atpPlayerState 'playing'
405
-
406
- // TODO: check if YT player stop is needed
407
- // stop active YT players running in parallel except the current
408
- // if (previousPlayer.options.videoId !== videoID) {
409
- // logger.debug('\n' + `STOP all video on StateChange running in parallel at trackID|playerID: ${trackID}|${playerID}`);
410
- // var playerState = (previousPlayer.getPlayerState() > 0) ? previousPlayer.getPlayerState() : 6;
411
- // var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
412
-
413
- // if (ytPlayerState === 'playing' || ytPlayerState === 'paused') {
414
- // previousPlayer.stopVideo();
415
- // }
416
- // }
417
-
418
- // stopAllActivePlayers(playerID);
429
+ } // END for LARGE buttonPlayerPlayPause
419
430
 
420
431
  } // END processOnStateChangePlaying
421
432
 
422
-
423
433
  // ---------------------------------------------------------------------------
424
434
  // processOnStateChangeEnded()
425
435
  //
@@ -431,7 +441,7 @@ regenerate: true
431
441
  // save player current time data for later use
432
442
  ytPlayerCurrentTime = ytPlayer.getCurrentTime();
433
443
 
434
- logger.debug('\n' + `NEXT video on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
444
+ logger.debug(`NEXT video on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
435
445
 
436
446
  // load NEXT song (video) in playlist
437
447
  loadNextVideo(playlist, songIndex);
@@ -518,50 +528,6 @@ regenerate: true
518
528
  current[lastKey] = value;
519
529
  }
520
530
 
521
- // ---------------------------------------------------------------------------
522
- // timestamp2seconds
523
- // ---------------------------------------------------------------------------
524
- function timestamp2seconds(timestamp) {
525
- // split timestamp
526
- const parts = timestamp.split(':');
527
-
528
- // check timestamp format
529
- if (parts.length !== 3) {
530
- // return "invalid timestamp";
531
- return false;
532
- }
533
-
534
- // convert parts to integers
535
- const hours = parseInt(parts[0], 10);
536
- const minutes = parseInt(parts[1], 10);
537
- const seconds = parseInt(parts[2], 10);
538
-
539
- // check valid timestamp values
540
- if (isNaN(hours) || isNaN(minutes) || isNaN(seconds) ||
541
- hours < 0 || hours > 23 ||
542
- minutes < 0 || minutes > 59 ||
543
- seconds < 0 || seconds > 59) {
544
- return "invalid timestamp";
545
- }
546
-
547
- const totalSeconds = (hours * 3600) + (minutes * 60) + seconds;
548
- return totalSeconds;
549
- } // END timestamp2seconds
550
-
551
- // ---------------------------------------------------------------------------
552
- // seconds2timestamp
553
- // ---------------------------------------------------------------------------
554
- function seconds2timestamp(seconds) {
555
- const hours = Math.floor(seconds / 3600);
556
- const minutes = Math.floor((seconds % 3600) / 60);
557
- const remainSeconds = seconds % 60;
558
- const tsHours = hours.toString().padStart(2, '0');
559
- const tsMinutes = minutes.toString().padStart(2, '0');
560
- const tsSeconds = remainSeconds.toString().padStart(2, '0');
561
-
562
- return `${tsHours}:${tsMinutes}:${tsSeconds}`;
563
- } // END seconds2timestamp
564
-
565
531
  // ---------------------------------------------------------------------------
566
532
  // ytpFadeInAudio
567
533
  // ---------------------------------------------------------------------------
@@ -592,18 +558,10 @@ regenerate: true
592
558
  currentStep = 1;
593
559
 
594
560
  if (volumeSlider === undefined || volumeSlider === null) {
595
- logger.warn('\n' + 'no volume slider found at playerID: ' + settings.playerID);
561
+ logger.warn('no volume slider found at playerID: ' + settings.playerID);
596
562
  return;
597
563
  }
598
564
 
599
- // (ytPlayer.isMuted()) && ytPlayer.unMute();
600
-
601
- // skip fade-in when volume is already at target value
602
- // if (ytPlayer.getVolume() >= targetVolume) {
603
- // logger.warn('\n' + 'skipped fade-in for current video on volume: ', targetVolume);
604
- // return;
605
- // }
606
-
607
565
  // Start the players volume muted
608
566
  ytPlayer.setVolume(0);
609
567
 
@@ -648,7 +606,7 @@ regenerate: true
648
606
  currentStep = 0;
649
607
 
650
608
  if (volumeSlider === undefined || volumeSlider === null) {
651
- logger.warn('\n' + 'no volume slider found at playerID: ' + settings.playerID);
609
+ logger.warn('no volume slider found at playerID: ' + settings.playerID);
652
610
  return;
653
611
  }
654
612
 
@@ -672,7 +630,7 @@ regenerate: true
672
630
  function initYtAPI() {
673
631
  startTimeModule = Date.now();
674
632
 
675
- logger.info('\n' + 'Initialize plugin|tech (ytp) : started');
633
+ logger.info('Initialize plugin|tech (ytp) : started');
676
634
 
677
635
  // Load YT IFrame Player API asynchronously
678
636
  // -------------------------------------------------------------------------
@@ -709,7 +667,6 @@ regenerate: true
709
667
 
710
668
  ytpSongIndex = songIndex;
711
669
 
712
-
713
670
  // play sonng (video) in playlist
714
671
  if (songIndex <= songs.length - 1) {
715
672
  songMetaData = songs[songIndex];
@@ -720,8 +677,7 @@ regenerate: true
720
677
  j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
721
678
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytVideoID;
722
679
 
723
-
724
- logger.debug('\n' + `SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
680
+ logger.debug(`SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
725
681
  ytPlayer.loadVideoById(ytVideoID);
726
682
 
727
683
  // delay after switch video
@@ -739,7 +695,7 @@ regenerate: true
739
695
  loadCoverImage(songMetaData);
740
696
 
741
697
  // update meta data
742
- updatMetaContainers(songMetaData);
698
+ // ytpUpdatMetaContainers(songMetaData);
743
699
 
744
700
  // set song (video) active at index in playlist
745
701
  setSongActive(playlist, songIndex);
@@ -769,7 +725,7 @@ regenerate: true
769
725
  j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
770
726
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
771
727
 
772
- logger.debug('\n' + `SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
728
+ logger.debug(`SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
773
729
  ytPlayer.loadVideoById(ytVideoID);
774
730
 
775
731
  // delay after switch video
@@ -784,11 +740,10 @@ regenerate: true
784
740
  loadCoverImage(songMetaData);
785
741
 
786
742
  // update meta data
787
- updatMetaContainers(songMetaData);
743
+ // ytpUpdatMetaContainers(songMetaData);
788
744
 
789
- // set AJS play_pause button paused
790
- var playPauseButtonClass = `large-player-play-pause-${playerID}`
791
- setPlayPauseButtonPaused(playPauseButtonClass);
745
+ var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
746
+ togglePlayPauseButton(playPauseButtonClass);
792
747
 
793
748
  // set song (video) active at index in playlist
794
749
  setSongActive(playlist, songIndex);
@@ -837,7 +792,7 @@ regenerate: true
837
792
  {% endif %}{% endfor %}
838
793
 
839
794
  clearInterval(dependencies_ytp_ready);
840
- logger.info('\n' + 'Initialize APIPlayers : ready');
795
+ logger.info('Initialize APIPlayers : ready');
841
796
  } // END if ready
842
797
 
843
798
  }, 10); // END dependencies_ytp_ready
@@ -884,8 +839,8 @@ regenerate: true
884
839
  var ytpHeight = ('{{player.yt_player.height}}'.length > 0) ? '{{player.yt_player.height}}' : '{{amplitude_defaults.player.yt_player.height}}';
885
840
  var ytpWidth = ('{{player.yt_player.width}}'.length > 0) ? '{{player.yt_player.width}}' : '{{amplitude_defaults.player.yt_player.width}}';
886
841
 
887
- logger.info('\n' + 'AJS YouTube iFrame API: ready');
888
- logger.info('\n' + 'configure player on ID: #{{player.id}}');
842
+ logger.info('AJS YouTube iFrame API: ready');
843
+ logger.info('configure player on ID: #{{player.id}}');
889
844
 
890
845
  // create a hidden YT Player iFrame container
891
846
  //
@@ -897,13 +852,15 @@ regenerate: true
897
852
  height: ytpHeight,
898
853
  width: ytpWidth,
899
854
  videoId: ytpVideoID,
855
+ // videoId: 'bloedsinn',
900
856
  playerVars: {
901
857
  autoplay: ytpAutoPlay,
902
858
  loop: ytpLoop
903
859
  },
904
860
  events: {
905
- 'onReady': {{player.id}}OnPlayerReady,
906
- 'onStateChange': {{player.id}}OnPlayerStateChange
861
+ 'onReady': {{player.id}}OnPlayerReady,
862
+ 'onStateChange': {{player.id}}OnPlayerStateChange,
863
+ 'onError': {{player.id}}OnPlayerErrors
907
864
  }
908
865
  });
909
866
 
@@ -934,19 +891,23 @@ regenerate: true
934
891
 
935
892
  } // END if playerExistsInPage()
936
893
 
937
- function checkPlayingStatus(player) {
938
- if (player.getPlayerState() === YT_PLAYER_STATE.PLAYING) {
939
- // code run after video is playing
940
- // console.debug("checkPlayingStatus: AJS YouTube Player state: PLAYING");
941
- // do nothing
942
- return;
943
- } else {
944
- // re-check player state required
945
- // console.debug("checkPlayingStatus: AJS YouTube Player state:", player.getPlayerState());
946
- }
947
- } // END checkPlayingStatus
894
+ // AJS YouTube Player errors fired by the YT API
895
+ // ---------------------------------------------------------------------
896
+ function {{player.id}}OnPlayerErrors(event) {
897
+ var eventData, ytPlayer, videoID;
898
+
899
+ eventData = event.data;
900
+ ytPlayer = event.target;
901
+ videoID = ytPlayer.options.videoId;
948
902
 
949
- // run AJS YouTube Player initialization
903
+ logger.error(`YT API Error '${YT_PLAYER_ERROR_NAMES[eventData]}' for VideoID: '${videoID}'`);
904
+
905
+ // save YT player GLOBAL data for later use (e.g. events)
906
+ j1.adapter.amplitude.data.ytpGlobals['ytApiError'] = eventData;
907
+
908
+ }
909
+
910
+ // AJS YouTube Player initialization fired by the YT API
950
911
  // ---------------------------------------------------------------------
951
912
  function {{player.id}}OnPlayerReady(event) {
952
913
  var hours, minutes, seconds,
@@ -957,7 +918,7 @@ regenerate: true
957
918
  ytPlayerReady = true;
958
919
  playerVolumePreset = parseInt({{player.volume_slider.preset_value}});
959
920
 
960
- logger.debug('\n' + `FOUND video ready at ID: {{player.id}}`);
921
+ logger.debug(`FOUND video ready at ID: {{player.id}}`);
961
922
 
962
923
  // set video playback quality to a minimum
963
924
  ytPlayer.setPlaybackQuality('small');
@@ -982,13 +943,11 @@ regenerate: true
982
943
  }
983
944
  }
984
945
 
985
- logger.info('\n' + 'AJS YouTube Player on ID {{player.id}}: ready');
946
+ logger.info('AJS YouTube Player on ID {{player.id}}: ready');
986
947
 
987
948
  // save YT player GLOBAL data for later use (e.g. events)
988
949
  j1.adapter.amplitude.data.ytpGlobals['ytPlayerReady'] = ytPlayerReady;
989
-
990
- // save YT player data for later use (e.g. events)
991
- // j1.adapter.amplitude.data.ytPlayers.{{player.id}}.playerReady = ytPlayerReady;
950
+ j1.adapter.amplitude.data.ytpGlobals['ytApiError'] = 0;
992
951
 
993
952
  // get duration hours (if configured)
994
953
  if ({{player.display_hours}} ) {
@@ -1020,12 +979,12 @@ regenerate: true
1020
979
  // -------------------------------------------------------------------
1021
980
  endTimeModule = Date.now();
1022
981
 
1023
- logger.info('\n' + 'Initialize plugin|tech (ytp) : finished');
982
+ logger.info('Initialize plugin|tech (ytp) : finished');
1024
983
 
1025
984
  if (playerCounter > 0) {
1026
- logger.info('\n' + 'Found players of type video (YTP) in page: ' + playerCounter);
985
+ logger.info('Found players of type video (YTP) in page: ' + playerCounter);
1027
986
  } else {
1028
- logger.warn('\n' + 'Found NO players of type video (YTP) in page');
987
+ logger.warn('Found NO players of type video (YTP) in page');
1029
988
  }
1030
989
 
1031
990
  // update activeVideoElement data structure for the ACTIVE video
@@ -1035,14 +994,14 @@ regenerate: true
1035
994
  }, checkActiveVideoInterval);
1036
995
  // END checkActiveVideoElementYTP
1037
996
 
1038
- logger.info('\n' + 'plugin|tech initializing time: ' + (endTimeModule-startTimeModule) + 'ms');
997
+ logger.info('plugin|tech initializing time: ' + (endTimeModule-startTimeModule) + 'ms');
1039
998
 
1040
999
  } // END onPlayerReady()
1041
1000
 
1042
1001
  // ---------------------------------------------------------------------
1043
1002
  // OnPlayerStateChange
1044
1003
  //
1045
- // process Player|Video specific functions on state change
1004
+ // process all YT Player specific state changes
1046
1005
  // ---------------------------------------------------------------------
1047
1006
  // NOTE:
1048
1007
  // The YT API fires a lot of INTERMEDIATE states. MOST of them gets
@@ -1050,6 +1009,8 @@ regenerate: true
1050
1009
  // are being set; e.g. start|stop positions for a video (when)
1051
1010
  // configured.
1052
1011
  // ---------------------------------------------------------------------
1012
+ // AJS YouTube Player state changes fired by the YT API
1013
+ // ---------------------------------------------------------------------
1053
1014
  function {{player.id}}OnPlayerStateChange(event) {
1054
1015
  var currentTime, playlist, ytPlayer, ytVideoID,
1055
1016
  songs, songIndex, trackID, playerID, songMetaData;
@@ -1101,8 +1062,8 @@ regenerate: true
1101
1062
  processOnStateChangeEnded(event, playlist, songIndex);
1102
1063
  break;
1103
1064
  default:
1104
- logger.error('\n' + `UNKNOWN event on StateChange fired`);
1105
- } // END case
1065
+ logger.error(`UNKNOWN event on StateChange fired: ${event.data}`);
1066
+ } // END switch event.data
1106
1067
 
1107
1068
  } // END {{player.id}}OnPlayerStateChange
1108
1069
 
@@ -1111,7 +1072,6 @@ regenerate: true
1111
1072
 
1112
1073
  } // END onYouTubeIframeAPIReady
1113
1074
 
1114
-
1115
1075
  // ---------------------------------------------------------------------------
1116
1076
  // main
1117
1077
  // ===========================================================================
@@ -1130,28 +1090,27 @@ regenerate: true
1130
1090
  // ---------------------------------------------------------------------------
1131
1091
  initUiEventsForAJS();
1132
1092
 
1133
-
1134
1093
  // ---------------------------------------------------------------------------
1135
1094
  // Base AJS Player functions
1136
1095
  // ===========================================================================
1137
1096
 
1138
1097
  // ---------------------------------------------------------------------------
1139
- // updatMetaContainers(metaData)
1098
+ // ytpUpdatMetaContainers(metaData)
1140
1099
  //
1141
1100
  // update song name in meta-containers
1142
1101
  // ---------------------------------------------------------------------------
1143
- function updatMetaContainers(metaData) {
1144
- var playerID, playlist, songName, artistName, albumName,
1145
- largePlayerSongAudioRating;
1102
+ function ytpUpdatMetaContainers(metaData) {
1103
+ var playerID, playlist, trackID, rating;
1146
1104
 
1147
- playlist = metaData.playlist;
1148
- playerID = playlist + '_large';
1105
+ playlist = metaData.playlist;
1106
+ playerID = playlist + '_large';
1107
+ rating = metaData.rating;
1108
+ trackID = metaData.index + 1;
1149
1109
 
1150
- var trackID = metaData.index + 1;
1151
- logger.debug('\n' + `UPDATE metadata on updatMetaContainers for trackID|playlist at: ${trackID}|${playlist}`);
1110
+ logger.debug(`UPDATE metadata on ytpUpdatMetaContainers for trackID|playlist at: ${trackID}|${playlist}`);
1152
1111
 
1153
1112
  // update song name in meta-containers
1154
- songName = document.getElementsByClassName("song-name");
1113
+ var songName = document.getElementsByClassName("song-name");
1155
1114
  if (songName.length) {
1156
1115
  for (var i=0; i<songName.length; i++) {
1157
1116
  var currentPlaylist = songName[i].dataset.amplitudePlaylist;
@@ -1162,10 +1121,10 @@ regenerate: true
1162
1121
  }
1163
1122
 
1164
1123
  // update artist name in meta-containers
1165
- artistName = document.getElementsByClassName("artist");
1124
+ var artistName = document.getElementsByClassName("artist");
1166
1125
  if (artistName.length) {
1167
1126
  for (var i=0; i<artistName.length; i++) {
1168
- var currentPlaylist = songName[i].dataset.amplitudePlaylist;
1127
+ var currentPlaylist = artistName[i].dataset.amplitudePlaylist;
1169
1128
  if (currentPlaylist === playlist) {
1170
1129
  artistName[i].innerHTML = metaData.artist;
1171
1130
  }
@@ -1173,7 +1132,7 @@ regenerate: true
1173
1132
  }
1174
1133
 
1175
1134
  // update album name in meta-containers
1176
- albumName = document.getElementsByClassName("album");
1135
+ var albumName = document.getElementsByClassName("album");
1177
1136
  if (albumName.length) {
1178
1137
  for (var i=0; i<albumName.length; i++) {
1179
1138
  var currentPlaylist = songName[i].dataset.amplitudePlaylist;
@@ -1184,27 +1143,32 @@ regenerate: true
1184
1143
  }
1185
1144
 
1186
1145
  // update song rating in screen controls
1187
- largePlayerSongAudioRating = document.getElementsByClassName("audio-rating-screen-controls");
1188
- if (largePlayerSongAudioRating.length) {
1189
- for (var i=0; i<largePlayerSongAudioRating.length; i++) {
1190
- var currentPlaylist = largePlayerSongAudioRating[i].dataset.amplitudePlaylist;
1146
+ var songAudioRating = document.getElementsByClassName("audio-rating-screen-controls");
1147
+ if (songAudioRating.length) {
1148
+ for (var i=0; i<songAudioRating.length; i++) {
1149
+ var currentPlaylist = songAudioRating[i].dataset.amplitudePlaylist;
1191
1150
  if (currentPlaylist === playlist) {
1192
1151
  if (metaData.rating) {
1193
- var trackID = metaData.index + 1;
1194
-
1195
- // save YT player data for later use (e.g. events)
1196
- j1.adapter.amplitude.data.ytPlayers[playerID].videoID = metaData.videoID;
1152
+ songAudioRating[i].innerHTML = `<img src="/assets/image/pattern/rating/scalable/${metaData.rating}-star.svg" alt="song rating">`;
1153
+ }
1154
+ }
1155
+ }
1156
+ } // END if songAudioRating
1197
1157
 
1198
- logger.debug('\n' + `UPDATE song rating on updatMetaContainers for trackID|playlist at: ${trackID}|${playlist} with a value of: ${metaData.rating}`);
1199
- largePlayerSongAudioRating[i].innerHTML = '<img src="/assets/image/pattern/rating/scalable/' + metaData.rating + '-star.svg"' + 'alt="song rating">';
1200
- } else {
1201
- largePlayerSongAudioRating[i].innerHTML = '';
1158
+ // update song info in screen controls
1159
+ var songAudioInfo = document.getElementsByClassName("audio-info-link-screen-controls");
1160
+ if (songAudioInfo.length) {
1161
+ for (var i=0; i<songAudioInfo.length; i++) {
1162
+ var currentPlaylist = songAudioInfo[i].dataset.amplitudePlaylist;
1163
+ if (currentPlaylist === playlist) {
1164
+ if (metaData.audio_info) {
1165
+ songAudioInfo[i].setAttribute("href", metaData.audio_info);
1202
1166
  }
1203
1167
  }
1204
1168
  }
1205
- } // END if largePlayerSongAudioRating
1169
+ } // END if songAudioInfo
1206
1170
 
1207
- } // END updatMetaContainers
1171
+ } // END ytpUpdatMetaContainers
1208
1172
 
1209
1173
  // ---------------------------------------------------------------------------
1210
1174
  // loadCoverImage(metaData)
@@ -1218,46 +1182,67 @@ regenerate: true
1218
1182
  selector = ".cover-image-" + metaData.playlist;
1219
1183
  coverImage = document.querySelector(selector);
1220
1184
  coverImage.src = metaData.cover_art_url;
1185
+
1221
1186
  } // END loadCoverImage
1222
1187
 
1223
1188
  // ---------------------------------------------------------------------------
1224
- // stopAllActivePlayers(exceptPlayer)
1189
+ // ytpStopParallelActivePlayers(exceptPlayer)
1225
1190
  //
1226
1191
  // if multiple players used on a page, stop ALL active AT|YT players
1227
- // running in parallel execpet the exceptPlayer
1192
+ // running in parallel skipping the exceptPlayer
1228
1193
  // ---------------------------------------------------------------------------
1229
- function stopAllActivePlayers(exceptPlayer) {
1194
+ function ytpStopParallelActivePlayers(exceptPlayer) {
1230
1195
 
1231
- // stop active AT players
1196
+ // stop active AT players running in parallel
1232
1197
  // -------------------------------------------------------------------------
1233
- var atpPlayerState = Amplitude.getPlayerState();
1234
- if (atpPlayerState === 'playing') {
1198
+ var atPlayerState = Amplitude.getPlayerState();
1199
+ if (atPlayerState === 'playing' || atPlayerState === 'paused') {
1235
1200
  Amplitude.stop();
1236
1201
  } // END stop active AT players
1237
1202
 
1238
- // stop active YT players
1203
+ // stop active YT players running in parallel
1239
1204
  // -------------------------------------------------------------------------
1240
1205
  const ytPlayers = Object.keys(j1.adapter.amplitude.data.ytPlayers);
1241
1206
  for (let i=0; i<ytPlayers.length; i++) {
1242
- const ytPlayerID = ytPlayers[i];
1243
- const playerProperties = j1.adapter.amplitude.data.ytPlayers[ytPlayerID];
1207
+ const ytPlayerID = ytPlayers[i];
1208
+ const playerProperties = j1.adapter.amplitude.data.ytPlayers[ytPlayerID];
1244
1209
 
1245
1210
  if (ytPlayerID !== exceptPlayer) {
1246
1211
  var player = j1.adapter.amplitude['data']['ytPlayers'][ytPlayerID]['player'];
1247
1212
  var playerState = (player.getPlayerState() > 0) ? player.getPlayerState() : 6;
1248
1213
  var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
1249
1214
 
1250
- // if (ytPlayerState === 'playing' || ytPlayerState === 'paused' || ytPlayerState === 'buffering' || ytPlayerState === 'cued' || ytPlayerState === 'unstarted') {
1251
- if (ytPlayerState === 'playing' || ytPlayerState === 'paused' || ytPlayerState === 'buffering' || ytPlayerState === 'cued' || ytPlayerState === 'unstarted') {
1252
- logger.debug('\n' + `STOP player at stopAllActivePlayers for id: ${ytPlayerID}`);
1253
- // player.mute();
1215
+ // toggle PlayPause buttons playing => puased
1216
+ // ---------------------------------------------------------------------
1217
+ if (ytPlayerState === 'playing' || ytPlayerState === 'paused') {
1218
+ logger.debug(`STOP player at ytpStopParallelActivePlayers for id: ${ytPlayerID}`);
1254
1219
  player.stopVideo();
1255
- j1.adapter.amplitude.data.ytpGlobals.activeIndex = 0;
1256
- }
1257
- }
1258
- } // END stop active YT players
1220
+ var ytpButtonPlayerPlayPause = document.getElementsByClassName("large-player-play-pause-" + ytPlayerID);
1221
+ for (var j=0; j<ytpButtonPlayerPlayPause.length; j++) {
1222
+
1223
+ var htmlElement = ytpButtonPlayerPlayPause[j];
1224
+ if (htmlElement.dataset.amplitudeSource === 'youtube') {
1225
+ if (htmlElement.classList.contains('amplitude-playing')) {
1226
+ htmlElement.classList.remove('amplitude-playing');
1227
+ htmlElement.classList.add('amplitude-paused');
1228
+ }
1229
+ // if (htmlElement.classList.contains('amplitude-paused')) {
1230
+ // htmlElement.classList.remove('amplitude-paused');
1231
+ // htmlElement.classList.add('amplitude-playing');
1232
+ // }
1233
+ }
1234
+
1235
+ } // END for ytpButtonPlayerPlayPause
1259
1236
 
1260
- } // END stopAllActivePlayers
1237
+ } // END if ytPlayerState
1238
+ } // END if ytPlayerID
1239
+
1240
+ // save AT player data for later use (e.g. events)
1241
+ // ---------------------------------------------------------------------
1242
+ j1.adapter.amplitude.data.ytpGlobals.activeIndex = 0;
1243
+
1244
+ } // END stop active YT players
1245
+ } // END ytpStopParallelActivePlayers
1261
1246
 
1262
1247
  // ---------------------------------------------------------------------------
1263
1248
  // getSongPlayed
@@ -1310,7 +1295,7 @@ regenerate: true
1310
1295
  }
1311
1296
  }
1312
1297
 
1313
- } // END setSongPlayed
1298
+ } // END setSongActive
1314
1299
 
1315
1300
  // ---------------------------------------------------------------------------
1316
1301
  // getProgressBarSelectedPositionPercentage
@@ -1365,20 +1350,18 @@ regenerate: true
1365
1350
  activeVideoElement.album = activeSong.album;
1366
1351
  activeVideoElement.artist = activeSong.artist;
1367
1352
  activeVideoElement.audio_info = activeSong.audio_info;
1368
- activeVideoElement.audio_single = activeSong.audio_single;
1369
1353
  activeVideoElement.currentTime = parseFloat(activeVideoElement.player.getCurrentTime());
1370
1354
  activeVideoElement.cover_art_url = activeSong.cover_art_url;
1371
1355
  activeVideoElement.duration = activeSong.duration;
1372
- activeVideoElement.endSec = timestamp2seconds(activeSong.end);
1356
+ activeVideoElement.endSec = j1.adapter.amplitude.timestamp2seconds(activeSong.end);
1373
1357
  activeVideoElement.endTS = activeSong.end;
1374
1358
  activeVideoElement.name = activeSong.name;
1375
- activeVideoElement.rating = activeSong.album;
1376
- activeVideoElement.startSec = timestamp2seconds(activeSong.start);
1359
+ activeVideoElement.rating = activeSong.rating;
1360
+ activeVideoElement.startSec = j1.adapter.amplitude.timestamp2seconds(activeSong.start);
1377
1361
  activeVideoElement.startTS = activeSong.start;
1378
1362
  activeVideoElement.url = activeSong.url;
1379
1363
 
1380
1364
  var videoArray = activeSong.url.split('=');
1381
-
1382
1365
  activeVideoElement.videoID = videoArray[1];
1383
1366
 
1384
1367
  }
@@ -1437,7 +1420,7 @@ regenerate: true
1437
1420
  activeClass = 'large-player-progress-' + playlist;
1438
1421
 
1439
1422
  if (activePlayer === undefined) {
1440
- logger.error('\n' + 'YT player not defined');
1423
+ logger.error('YT player not defined');
1441
1424
  return;
1442
1425
  }
1443
1426
 
@@ -1478,14 +1461,6 @@ regenerate: true
1478
1461
  ytPlayer = activeSongSettings.player;
1479
1462
  activePlaylist = activeSongSettings.playlist;
1480
1463
 
1481
- // if (activeSongSettings) {
1482
- // ytPlayer = activeSongSettings.player;
1483
- // activePlaylist = activeSongSettings.playlist;
1484
- // } else {
1485
- // ytPlayer = player;
1486
- // activePlaylist = playlist;
1487
- // }
1488
-
1489
1464
  // get current hours|minutes|seconds
1490
1465
  // -------------------------------------------------------------------------
1491
1466
  hours = ytpGetDurationHours(ytPlayer);
@@ -1690,7 +1665,6 @@ regenerate: true
1690
1665
 
1691
1666
  } // END ytpSeekTo
1692
1667
 
1693
-
1694
1668
  // ---------------------------------------------------------------------------
1695
1669
  // ytpGetBuffered
1696
1670
  //
@@ -1716,7 +1690,6 @@ regenerate: true
1716
1690
  return activeIndex;
1717
1691
  } // END ytpGetActiveIndex
1718
1692
 
1719
-
1720
1693
  // ---------------------------------------------------------------------------
1721
1694
  // ytpSetActiveIndex
1722
1695
  //
@@ -1854,7 +1827,6 @@ regenerate: true
1854
1827
  }
1855
1828
  } // END ytpGetDurationMinutes
1856
1829
 
1857
-
1858
1830
  // ---------------------------------------------------------------------------
1859
1831
  // ytpGetDurationSeconds
1860
1832
  //
@@ -1976,28 +1948,20 @@ regenerate: true
1976
1948
  // ---------------------------------------------------------------------------
1977
1949
  // setPlayPauseButtonPaused
1978
1950
  // ---------------------------------------------------------------------------
1979
- function setPlayPauseButtonPaused(elementClass) {
1980
- var button, htmlElement;
1981
-
1982
- button = document.getElementsByClassName(elementClass);
1983
- htmlElement = button[0];
1951
+ function setPlayPauseButtonPaused(element) {
1984
1952
 
1985
- htmlElement.classList.remove('amplitude-playing');
1986
- htmlElement.classList.add('amplitude-paused');
1953
+ element.classList.remove('amplitude-playing');
1954
+ element.classList.add('amplitude-paused');
1987
1955
 
1988
1956
  } // END setPlayPauseButtonPaused
1989
1957
 
1990
1958
  // ---------------------------------------------------------------------------
1991
1959
  // setPlayPauseButtonPlaying
1992
1960
  // ---------------------------------------------------------------------------
1993
- function setPlayPauseButtonPlaying(elementClass) {
1994
- var button, htmlElement;
1995
-
1996
- button = document.getElementsByClassName(elementClass);
1997
- htmlElement = button[0];
1961
+ function setPlayPauseButtonPlaying(element) {
1998
1962
 
1999
- htmlElement.classList.remove('amplitude-paused');
2000
- htmlElement.classList.add('amplitude-playing');
1963
+ element.classList.remove('amplitude-paused');
1964
+ element.classList.add('amplitude-playing');
2001
1965
 
2002
1966
  } // END setPlayPauseButtonPlaying
2003
1967
 
@@ -2077,8 +2041,9 @@ regenerate: true
2077
2041
 
2078
2042
  if (classString.includes(ytPlayerID)) {
2079
2043
  largePlayerPlayPauseButton[i].addEventListener('click', function(event) {
2080
- var activeSongSettings, songs, songMetaData, ytPlayer,
2081
- playlist, playerID, songIndex;
2044
+ var activeSongSettings, songs, songMetaData, playerData,
2045
+ ytPlayer, playerState, ytPlayerState, playlist,
2046
+ playerID, songIndex;
2082
2047
 
2083
2048
  playlist = this.getAttribute("data-amplitude-playlist");
2084
2049
  playerID = playlist + '_large';
@@ -2088,76 +2053,69 @@ regenerate: true
2088
2053
 
2089
2054
  // get active song settings (manually)
2090
2055
  activeSongSettings = getActiveSong();
2091
-
2092
- // TODO: Extend getSongIndex() for singleAudio
2093
- // var songIndex = (singleAudio) ? ytpSongIndex : getSongIndex(songs, ytVideoID);
2094
2056
  if (!activeSongSettings) {
2095
2057
  songIndex = 0;
2096
2058
  ytpSongIndex = 0;
2097
2059
  } else {
2098
-
2099
- // ytPlayerCurrentTime = activeSongSettings.currentTime;
2100
-
2101
2060
  if (activeSongSettings.playlist !== playlist) {
2102
2061
  songIndex = 0;
2103
2062
  ytpSongIndex = 0;
2104
2063
 
2105
2064
  // reset previous player settings
2106
- if (activeSongSettings.player !== undefined) {
2107
- activeSongSettings.player.stopVideo();
2108
- var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2109
- togglePlayPauseButton(playPauseButtonClass);
2110
- }
2065
+ // if (activeSongSettings.player !== undefined) {
2066
+ // activeSongSettings.player.stopVideo();
2067
+ // var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2068
+ // togglePlayPauseButton(playPauseButtonClass);
2069
+ // }
2111
2070
  } else {
2112
2071
  songIndex = ytpSongIndex;
2113
2072
  }
2114
- }
2073
+ } // END if activeSongSettings
2115
2074
 
2116
- // set song (video) active at index in playlist
2117
- setSongActive(playlist, songIndex);
2118
-
2119
- // reset progress bar settings
2120
- resetProgressBarYTP();
2075
+ if (j1.adapter.amplitude.data.ytpGlobals.ytApiError > 0) {
2076
+ // do nothing on API errors
2077
+ var trackID = songIndex + 1;
2078
+ logger.error(`DISABLED player for playlist|trackID: ${playlist}|${trackID} on API error '${YT_PLAYER_ERROR_NAMES[j1.adapter.amplitude.data.ytpGlobals.ytApiError]}'`);
2121
2079
 
2122
- // scroll song active at index in player
2123
- if (playerAutoScrollSongElement) {
2124
- scrollToActiveElement(playlist);
2080
+ return;
2125
2081
  }
2126
2082
 
2127
2083
  // update activeAudio data (manually)
2128
2084
  checkActiveVideoElementYTP();
2129
2085
 
2130
2086
  // get active song settings (manually)
2131
- activeSongSettings = getActiveSong();
2087
+ // activeSongSettings = getActiveSong();
2132
2088
 
2133
- songs = activeSongSettings.songs;
2134
- songMetaData = songs[songIndex];
2135
- ytPlayer = activeSongSettings.player;
2089
+ playerData = j1.adapter.amplitude.data.ytPlayers[playerID];
2090
+ ytPlayer = playerData.player;
2091
+ songIndex = playerData.activeIndex;
2092
+ songs = playerData.songs;
2136
2093
 
2137
2094
  // update meta data
2138
- updatMetaContainers(songMetaData);
2095
+ // songMetaData = songs[songIndex];
2096
+ // ytpUpdatMetaContainers(songMetaData);
2139
2097
 
2140
2098
  // save player GLOBAL data for later use (e.g. events)
2141
2099
  j1.adapter.amplitude.data.activePlayer = 'ytp';
2142
2100
  j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2143
2101
  j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2144
2102
 
2145
- // YT play|pause video
2103
+ // toggle YT play|pause video
2146
2104
  // ---------------------------------------------------------------
2147
- var playerState = ytPlayer.getPlayerState();
2148
- if (playerState < 0) {
2149
- var ytPlayerState = YT_PLAYER_STATE_NAMES[6];
2150
- } else {
2151
- var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
2152
- }
2105
+ playerState = ytPlayer.getPlayerState();
2106
+ ytPlayerState = (playerState < 0) ? YT_PLAYER_STATE_NAMES[6] : YT_PLAYER_STATE_NAMES[playerState];
2107
+
2108
+ // if (playerState < 0) {
2109
+ // var ytPlayerState = YT_PLAYER_STATE_NAMES[6];
2110
+ // } else {
2111
+ // var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
2112
+ // }
2153
2113
 
2114
+ // TOGGLE state 'playing' => 'paused'
2154
2115
  if (ytPlayerState === 'playing') {
2155
2116
  ytPlayer.pauseVideo();
2156
2117
 
2157
2118
  ytPlayerCurrentTime = ytPlayer.getCurrentTime();
2158
-
2159
- var trackID = songIndex + 1;
2160
- logger.debug('\n' + `PAUSE video for PlayPauseButton on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2161
2119
 
2162
2120
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2163
2121
  togglePlayPauseButton(playPauseButtonClass);
@@ -2167,12 +2125,13 @@ regenerate: true
2167
2125
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2168
2126
  }
2169
2127
 
2128
+ // TOGGLE state 'paused' => 'playing'
2170
2129
  if (ytPlayerState === 'paused') {
2171
2130
  ytPlayer.playVideo();
2172
2131
  ytpSeekTo(ytPlayer, ytPlayerCurrentTime, true);
2173
2132
 
2174
2133
  var trackID = songIndex + 1;
2175
- logger.debug('\n' + `PLAY video for PlayPauseButton on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2134
+ logger.debug(`PLAY video for PlayPauseButton on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2176
2135
 
2177
2136
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2178
2137
  togglePlayPauseButton(playPauseButtonClass);
@@ -2180,43 +2139,62 @@ regenerate: true
2180
2139
  // reset|update time settings
2181
2140
  resetCurrentTimeContainerYTP(ytPlayer, playlist);
2182
2141
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2183
- }
2142
+ } // if ytPlayerState === 'paused'
2184
2143
 
2144
+ // load (cued) video
2185
2145
  if (ytPlayerState === 'cued') {
2186
2146
  ytPlayer.playVideo();
2187
- var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2188
- togglePlayPauseButton(playPauseButtonClass);
2189
2147
 
2190
- // set song at songIndex active in playlist
2191
- setSongActive(playlist, songIndex);
2148
+ // wait for API error state
2149
+ setTimeout(() => {
2150
+ if (j1.adapter.amplitude.data.ytpGlobals.ytApiError > 0) {
2151
+ var trackID = songIndex + 1;
2152
+ logger.error(`DISABLED player for playlist|trackID: ${playlist}|${trackID} on API error '${YT_PLAYER_ERROR_NAMES[j1.adapter.amplitude.data.ytpGlobals.ytApiError]}'`);
2192
2153
 
2193
- // scroll song active at index in player
2194
- if (playerAutoScrollSongElement) {
2195
- scrollToActiveElement(playlist);
2196
- }
2154
+ // do nothing on API errors
2155
+ return;
2156
+ }
2197
2157
 
2198
- // reset|update time settings
2199
- resetCurrentTimeContainerYTP(ytPlayer, playlist);
2200
- updateDurationTimeContainerYTP(ytPlayer, playlist);
2201
- }
2158
+ // reset progress bar settings
2159
+ resetProgressBarYTP();
2160
+
2161
+ var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2162
+ togglePlayPauseButton(playPauseButtonClass);
2163
+
2164
+ // set song at songIndex active in playlist
2165
+ setSongActive(playlist, songIndex);
2166
+
2167
+ // scroll song active at index in player
2168
+ if (playerAutoScrollSongElement) {
2169
+ scrollToActiveElement(playlist);
2170
+ }
2171
+
2172
+ // reset|update time settings
2173
+ resetCurrentTimeContainerYTP(ytPlayer, playlist);
2174
+ updateDurationTimeContainerYTP(ytPlayer, playlist);
2175
+
2176
+ }, 100);
2177
+ } // END if ytPlayerState === 'cued'
2202
2178
 
2203
2179
  // TODO: unclear why state 'unstarted' is generated
2204
2180
  // on LAST item
2205
2181
  // workaround sofar
2206
- if (ytPlayerState === 'unstarted') {
2207
- ytPlayer.playVideo();
2208
- // ytPlayer.mute();
2209
-
2210
- var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2211
- togglePlayPauseButton(playPauseButtonClass);
2212
- resetCurrentTimeContainerYTP(ytPlayer, playlist);
2213
- updateDurationTimeContainerYTP(ytPlayer, playlist);
2214
- }
2182
+ // -------------------------------------------------------------
2183
+ // if (ytPlayerState === 'unstarted') {
2184
+ // ytPlayer.playVideo();
2185
+ // // ytPlayer.mute();
2186
+ //
2187
+ // var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2188
+ // togglePlayPauseButton(playPauseButtonClass);
2189
+ // resetCurrentTimeContainerYTP(ytPlayer, playlist);
2190
+ // updateDurationTimeContainerYTP(ytPlayer, playlist);
2191
+ // } // END if ytPlayerState === 'unstarted'
2215
2192
 
2216
2193
  // deactivate AJS events (if any)
2217
2194
  event.stopImmediatePropagation();
2218
- }); // END EventListener largePlayerPlayPauseButton 'click'
2219
- }
2195
+
2196
+ }); // END EventListener largePlayerPlayPauseButton 'click
2197
+ } // END if classString
2220
2198
  } // END for largePlayerPlayPauseButton
2221
2199
 
2222
2200
  // Overload AJS largePlayerSkipBackward button for YT
@@ -2240,7 +2218,7 @@ regenerate: true
2240
2218
  currentVideoTime = ytPlayer.getCurrentTime();
2241
2219
 
2242
2220
  if (playerState === YT_PLAYER_STATE.PLAYING || playerState === YT_PLAYER_STATE.PAUSED) {
2243
- logger.debug('\n' + `SKIP forward on Button skipForward for ${skipOffset} seconds`);
2221
+ logger.debug(`SKIP forward on Button skipForward for ${skipOffset} seconds`);
2244
2222
  ytpSeekTo(ytPlayer, currentVideoTime + skipOffset, true);
2245
2223
 
2246
2224
  }
@@ -2272,7 +2250,7 @@ regenerate: true
2272
2250
  currentVideoTime = ytPlayer.getCurrentTime();
2273
2251
 
2274
2252
  if (playerState === YT_PLAYER_STATE.PLAYING || playerState === YT_PLAYER_STATE.PAUSED) {
2275
- logger.debug('\n' + `SKIP backward on Button skipBackward for ${skipOffset} seconds`);
2253
+ logger.debug(`SKIP backward on Button skipBackward for ${skipOffset} seconds`);
2276
2254
  ytpSeekTo(ytPlayer, currentVideoTime - skipOffset, true);
2277
2255
  }
2278
2256
 
@@ -2303,12 +2281,17 @@ regenerate: true
2303
2281
  songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2304
2282
  ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2305
2283
 
2306
- if (ytPlayer === undefined) {
2307
- logger.error('\n' + 'YT player not defined');
2284
+ if (j1.adapter.amplitude.data.ytpGlobals.ytApiError > 0) {
2285
+ // do nothing on API errors
2286
+ var trackID = songIndex + 1;
2287
+ logger.error(`DISABLED player for playlist|trackID: ${playlist}|${trackID} on API error '${YT_PLAYER_ERROR_NAMES[j1.adapter.amplitude.data.ytpGlobals.ytApiError]}'`);
2288
+
2289
+ return;
2308
2290
  }
2309
2291
 
2310
- // stop active AT|YT players except the current
2311
- // stopAllActivePlayers(playerID);
2292
+ if (ytPlayer === undefined) {
2293
+ logger.error('YT player not defined');
2294
+ }
2312
2295
 
2313
2296
  // select video
2314
2297
  if (songIndex < songs.length-1) {
@@ -2339,7 +2322,7 @@ regenerate: true
2339
2322
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2340
2323
 
2341
2324
  trackID = songIndex + 1;
2342
- logger.debug('\n' + `SWITCH video for PlayerNextButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2325
+ logger.debug(`SWITCH video for PlayerNextButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2343
2326
  ytPlayer.loadVideoById(ytpVideoID);
2344
2327
 
2345
2328
  // delay after switch video
@@ -2363,7 +2346,6 @@ regenerate: true
2363
2346
 
2364
2347
  // set AJS play_pause button paused
2365
2348
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2366
- // setPlayPauseButtonPlaying(playPauseButtonClass);
2367
2349
  togglePlayPauseButton(playPauseButtonClass);
2368
2350
  } else {
2369
2351
  // toggle AJS play_pause button
@@ -2380,7 +2362,7 @@ regenerate: true
2380
2362
  loadCoverImage(songMetaData);
2381
2363
 
2382
2364
  // update meta data
2383
- updatMetaContainers(songMetaData);
2365
+ // ytpUpdatMetaContainers(songMetaData);
2384
2366
 
2385
2367
  // set song at songIndex active in playlist
2386
2368
  setSongActive(playlist, songIndex);
@@ -2419,12 +2401,17 @@ regenerate: true
2419
2401
  songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2420
2402
  ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2421
2403
 
2422
- if (ytPlayer === undefined) {
2423
- logger.error('\n' + 'YT player not defined');
2404
+ if (j1.adapter.amplitude.data.ytpGlobals.ytApiError > 0) {
2405
+ // do nothing on API errors
2406
+ var trackID = songIndex + 1;
2407
+ logger.error(`DISABLED player for playlist|trackID: ${playlist}|${trackID} on API error '${YT_PLAYER_ERROR_NAMES[j1.adapter.amplitude.data.ytpGlobals.ytApiError]}'`);
2408
+
2409
+ return;
2424
2410
  }
2425
2411
 
2426
- // stop active AT|YT players except the current
2427
- // stopAllActivePlayers(playerID);
2412
+ if (ytPlayer === undefined) {
2413
+ logger.error('YT player not defined');
2414
+ }
2428
2415
 
2429
2416
  // select video
2430
2417
  if (songIndex > 0 && songIndex <= songs.length - 1) {
@@ -2447,7 +2434,7 @@ regenerate: true
2447
2434
  j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2448
2435
  j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2449
2436
 
2450
- // load next video
2437
+ // load previous video
2451
2438
  // -----------------------------------------------------------------
2452
2439
 
2453
2440
  // save YT player data for later use (e.g. events)
@@ -2456,7 +2443,7 @@ regenerate: true
2456
2443
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2457
2444
 
2458
2445
  trackID = songIndex + 1;
2459
- logger.debug('\n' + `SWITCH video for PlayePreviousButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2446
+ logger.debug(`SWITCH video for PlayePreviousButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2460
2447
  ytPlayer.loadVideoById(ytpVideoID);
2461
2448
 
2462
2449
  // delay after switch video
@@ -2480,7 +2467,6 @@ regenerate: true
2480
2467
 
2481
2468
  // set AJS play_pause button paused
2482
2469
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2483
- // setPlayPauseButtonPlaying(playPauseButtonClass);
2484
2470
  togglePlayPauseButton(playPauseButtonClass);
2485
2471
  } else {
2486
2472
  // toggle AJS play_pause button
@@ -2497,7 +2483,7 @@ regenerate: true
2497
2483
  loadCoverImage(songMetaData);
2498
2484
 
2499
2485
  // update meta data
2500
- updatMetaContainers(songMetaData);
2486
+ // ytpUpdatMetaContainers(songMetaData);
2501
2487
 
2502
2488
  // set song at songIndex active in playlist
2503
2489
  setSongActive(playlist, songIndex);
@@ -2527,60 +2513,62 @@ regenerate: true
2527
2513
  largePlayerSongContainer[i].addEventListener('click', function(event) {
2528
2514
  var activeSongSettings, playlist, playerID, playerState,
2529
2515
  songs, songIndex, songName, singleAudio, trackID,
2530
- ytPlayer, ytpVideoID;
2516
+ ytPlayer, ytpVideoID, activeSongIndex, isSongIndexChanged;
2531
2517
 
2532
2518
  // set (current) playlist|song data
2533
- playlist = this.getAttribute("data-amplitude-playlist");
2534
- playerID = playlist + '_large';
2535
- songIndex = parseInt(this.getAttribute("data-amplitude-song-index"));
2536
- trackID = songIndex + 1;
2519
+ playlist = this.getAttribute("data-amplitude-playlist");
2520
+ playerID = playlist + '_large';
2521
+ songIndex = parseInt(this.getAttribute("data-amplitude-song-index"));
2522
+ trackID = songIndex + 1;
2523
+ activeSongIndex = j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex;
2524
+ isSongIndexChanged = (activeSongIndex !== songIndex) ? true : false;
2537
2525
 
2538
2526
  // update active song settings (manually)
2539
2527
  checkActiveVideoElementYTP();
2540
2528
 
2541
- // get active song settings (manually)
2542
- activeSongSettings = getActiveSong();
2543
-
2544
- if (activeSongSettings) {
2545
- // ytpCurrentTime = activeSongSettings.currentTime;
2546
- if (activeSongSettings.playlist !== playlist) {
2547
- // set current player settings
2548
- songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2549
- ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2550
-
2551
- // reset previous player settings
2552
- if (activeSongSettings.player !== undefined) {
2553
- activeSongSettings.player.stopVideo();
2554
- var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2555
- togglePlayPauseButton(playPauseButtonClass);
2556
- }
2557
- } else {
2558
- // set current player settings
2559
- songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2560
- ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2561
- }
2562
- } else {
2563
- // set current player settings
2564
- songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2565
- ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2566
- }
2567
-
2568
2529
  // set (current) song meta data
2530
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2569
2531
  songMetaData = songs[songIndex];
2570
2532
  songURL = songMetaData.url;
2571
2533
  ytpVideoID = songURL.split('=')[1];
2572
- playerState = ytPlayer.getPlayerState();
2534
+ // ytpVideoID = 'bloedsinn';
2535
+ ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2536
+ playerState = ytPlayer.getPlayerState();
2537
+
2538
+ // TOGGLE state 'playing' => 'paused' if video (audio) NOT changed
2539
+ if (playerState === YT_PLAYER_STATE.PLAYING && !isSongIndexChanged) {
2540
+ ytPlayer.pauseVideo();
2541
+ // get active song settings (manually)
2542
+ activeSongSettings = getActiveSong();
2573
2543
 
2574
- // TOGGLE state 'playing'|'paused' if video (audio) NOT changed
2575
- var isItemChanged = (j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex !== songIndex) ? true : false;
2576
- if (!isItemChanged && (playerState === YT_PLAYER_STATE.PLAYING || playerState === YT_PLAYER_STATE.PAUSED)) {
2544
+ if (activeSongSettings) {
2545
+ // ytpCurrentTime = activeSongSettings.currentTime;
2546
+ if (activeSongSettings.playlist !== playlist) {
2547
+ // set current player settings
2548
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2549
+ ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2550
+
2551
+ // reset previous player settings
2552
+ // if (activeSongSettings.player !== undefined) {
2553
+ // activeSongSettings.player.stopVideo();
2554
+ // var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2555
+ // togglePlayPauseButton(playPauseButtonClass);
2556
+ // }
2557
+ } else {
2558
+ // set current player settings
2559
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2560
+ ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2561
+ }
2562
+ } else {
2563
+ // set current player settings
2564
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2565
+ ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2566
+ }
2577
2567
 
2578
- if (playerState === YT_PLAYER_STATE.PLAYING) {
2579
- ytPlayer.pauseVideo();
2580
2568
  ytPlayerCurrentTime = ytPlayer.getCurrentTime();
2581
2569
 
2582
2570
  var trackID = songIndex + 1;
2583
- logger.debug('\n' + `PAUSE video for PlayerSongContainer on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2571
+ logger.debug(`PAUSE video for PlayerSongContainer on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2584
2572
 
2585
2573
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2586
2574
  togglePlayPauseButton(playPauseButtonClass);
@@ -2588,89 +2576,167 @@ regenerate: true
2588
2576
  // reset|update time settings
2589
2577
  resetCurrentTimeContainerYTP(ytPlayer, playlist);
2590
2578
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2591
- return;
2592
- }
2593
2579
 
2594
- if (playerState === YT_PLAYER_STATE.PAUSED) {
2580
+ // update global song index (start at 0)
2581
+ ytpSongIndex = songIndex;
2582
+
2583
+ // save YT player GLOBAL data for later use (e.g. events)
2584
+ j1.adapter.amplitude.data.activePlayer = 'ytp';
2585
+ j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2586
+ j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2587
+
2588
+ // save YT player data for later use (e.g. events)
2589
+ j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2590
+ j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2591
+
2592
+ // reset|update current time settings
2593
+ resetCurrentTimeContainerYTP(ytPlayer, playlist);
2594
+ updateDurationTimeContainerYTP(ytPlayer, playlist);
2595
+ resetProgressBarYTP();
2596
+
2597
+ // load the song cover image
2598
+ loadCoverImage(songMetaData);
2599
+
2600
+ // update meta data
2601
+ // ytpUpdatMetaContainers(songMetaData);
2602
+
2603
+ // set song at songIndex active in playlist
2604
+ setSongActive(playlist, songIndex);
2605
+
2606
+ // scroll song active at index in player
2607
+ if (playerAutoScrollSongElement) {
2608
+ scrollToActiveElement(playlist);
2609
+ }
2610
+
2611
+ // save YT player data for later use (e.g. events)
2612
+ j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2613
+ j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2614
+
2615
+ return;
2616
+ } // END if playerState === PLAYING
2617
+
2618
+ // TOGGLE state 'paused' => 'playing' if video (audio) NOT changed
2619
+ if (playerState === YT_PLAYER_STATE.PAUSED && !isSongIndexChanged) {
2595
2620
  ytPlayer.playVideo();
2596
2621
  ytpSeekTo(ytPlayer, ytPlayerCurrentTime, true);
2597
2622
 
2623
+ // get active song settings (manually)
2624
+ activeSongSettings = getActiveSong();
2625
+
2626
+ if (activeSongSettings) {
2627
+ // ytpCurrentTime = activeSongSettings.currentTime;
2628
+ if (activeSongSettings.playlist !== playlist) {
2629
+ // set current player settings
2630
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2631
+ ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2632
+
2633
+ // reset previous player settings
2634
+ // if (activeSongSettings.player !== undefined) {
2635
+ // activeSongSettings.player.stopVideo();
2636
+ // var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2637
+ // togglePlayPauseButton(playPauseButtonClass);
2638
+ // }
2639
+ } else {
2640
+ // set current player settings
2641
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2642
+ ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2643
+ }
2644
+ } else {
2645
+ // set current player settings
2646
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2647
+ ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2648
+ }
2649
+
2598
2650
  var trackID = songIndex + 1;
2599
- logger.debug('\n' + `PLAY video for PlayerSongContainer on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2651
+ logger.debug(`PLAY video for PlayerSongContainer on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2600
2652
 
2601
2653
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2602
2654
  togglePlayPauseButton(playPauseButtonClass);
2603
2655
 
2656
+ // update meta data
2657
+ // ytpUpdatMetaContainers(songMetaData);
2658
+
2604
2659
  // reset|update time settings
2605
2660
  resetCurrentTimeContainerYTP(ytPlayer, playlist);
2606
2661
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2607
- return;
2608
- }
2609
2662
 
2610
- } // END !changedAudio
2663
+ // set song at songIndex active in playlist
2664
+ setSongActive(playlist, songIndex);
2611
2665
 
2612
- // update global song index (start at 0)
2613
- ytpSongIndex = songIndex;
2666
+ return;
2667
+ } // END if playerState === PAUSED
2668
+
2669
+ if (isSongIndexChanged) {
2670
+ // load (next) video
2671
+ // -------------------------------------------------------------------
2672
+ trackID = songIndex + 1;
2673
+ logger.debug(`SWITCH video for PlayerSongContainer at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2674
+ ytPlayer.loadVideoById(ytpVideoID);
2614
2675
 
2615
- // stop active AT|YT players
2616
- // stopAllActivePlayers(playerID);
2676
+ // wait for API error state
2677
+ setTimeout(() => {
2678
+ if (j1.adapter.amplitude.data.ytpGlobals.ytApiError > 0) {
2679
+ var trackID = songIndex + 1;
2680
+ logger.error(`DISABLED player for playlist|trackID: ${playlist}|${trackID} on API error '${YT_PLAYER_ERROR_NAMES[j1.adapter.amplitude.data.ytpGlobals.ytApiError]}'`);
2617
2681
 
2618
- // save YT player GLOBAL data for later use (e.g. events)
2619
- j1.adapter.amplitude.data.activePlayer = 'ytp';
2620
- j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2621
- j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2682
+ // do nothing on API errors
2683
+ return;
2684
+ }
2622
2685
 
2623
- // save YT player data for later use (e.g. events)
2624
- j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2625
- j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2686
+ // update global song index (start at 0)
2687
+ ytpSongIndex = songIndex;
2626
2688
 
2627
- // reset|update current time settings
2628
- resetCurrentTimeContainerYTP(ytPlayer, playlist);
2629
- updateDurationTimeContainerYTP(ytPlayer, playlist);
2630
- resetProgressBarYTP();
2689
+ // save YT player GLOBAL data for later use (e.g. events)
2690
+ j1.adapter.amplitude.data.activePlayer = 'ytp';
2691
+ j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2692
+ j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2631
2693
 
2632
- // load the song cover image
2633
- loadCoverImage(songMetaData);
2694
+ // save YT player data for later use (e.g. events)
2695
+ j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2696
+ j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2634
2697
 
2635
- // update meta data
2636
- updatMetaContainers(songMetaData);
2698
+ // reset|update current time settings
2699
+ resetCurrentTimeContainerYTP(ytPlayer, playlist);
2700
+ updateDurationTimeContainerYTP(ytPlayer, playlist);
2701
+ resetProgressBarYTP();
2637
2702
 
2638
- // set AJS play_pause button playing
2639
- var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2640
- setPlayPauseButtonPlaying(playPauseButtonClass)
2703
+ // load the song cover image
2704
+ loadCoverImage(songMetaData);
2641
2705
 
2642
- // set song at songIndex active in playlist
2643
- setSongActive(playlist, songIndex);
2706
+ // update meta data
2707
+ // ytpUpdatMetaContainers(songMetaData);
2644
2708
 
2645
- // scroll song active at index in player
2646
- if (playerAutoScrollSongElement) {
2647
- scrollToActiveElement(playlist);
2648
- }
2709
+ var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2710
+ togglePlayPauseButton(playPauseButtonClass);
2649
2711
 
2650
- // save YT player data for later use (e.g. events)
2651
- j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2652
- j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2712
+ // set song at songIndex active in playlist
2713
+ setSongActive(playlist, songIndex);
2653
2714
 
2654
- // load next video
2655
- // -------------------------------------------------------------------
2656
- trackID = songIndex + 1;
2657
- logger.debug('\n' + `SWITCH video for PlayerSongContainer at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2658
- ytPlayer.loadVideoById(ytpVideoID);
2715
+ // scroll song active at index in player
2716
+ if (playerAutoScrollSongElement) {
2717
+ scrollToActiveElement(playlist);
2718
+ }
2659
2719
 
2660
- // mute sound after next video load
2661
- // -------------------------------------------------------------------
2662
- if (muteAfterVideoSwitchInterval) {
2663
- ytPlayer.mute();
2664
- setTimeout(() => {
2665
- ytPlayer.unMute();
2666
- }, muteAfterVideoSwitchInterval);
2667
- }
2720
+ // save YT player data for later use (e.g. events)
2721
+ j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2722
+ j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2723
+
2724
+ // mute sound after next video load
2725
+ // -------------------------------------------------------------------
2726
+ if (muteAfterVideoSwitchInterval) {
2727
+ ytPlayer.mute();
2728
+ setTimeout(() => {
2729
+ ytPlayer.unMute();
2730
+ }, muteAfterVideoSwitchInterval);
2731
+ }
2732
+ }, 100);
2733
+ } // END if isSongIndexChanged
2668
2734
 
2669
- // deactivate AJS events (if any)
2670
- event.stopImmediatePropagation();
2671
- }); // END EventListener 'click' SongContainer
2672
- } // END ifSWITCH video
2673
- } // END for
2735
+ // deactivate AJS events (if any)
2736
+ event.stopImmediatePropagation();
2737
+ }); // END EventListener
2738
+ } // END if classString
2739
+ } // END for largePlayerSongContainer
2674
2740
 
2675
2741
  // add listeners to all progress bars found
2676
2742
  // TODO: Fix for multiple players in page
@@ -2756,7 +2822,9 @@ regenerate: true
2756
2822
  var playerID = sliderID.split('volume_slider_')[1];
2757
2823
 
2758
2824
  // save YT player data for later use (e.g. events)
2759
- // j1.adapter.amplitude.data.ytPlayers[playerID].volumeSlider = volumeSlider;
2825
+ if (volumeSlider.dataset.amplitudeSource === 'youtube') {
2826
+ j1.adapter.amplitude.data.ytPlayers[playerID].volumeSlider = volumeSlider;
2827
+ }
2760
2828
 
2761
2829
  volumeSliders[i].addEventListener('click', function(event) {
2762
2830
 
@@ -2808,9 +2876,6 @@ regenerate: true
2808
2876
  var sliderID = volumeMutes[i].id;
2809
2877
  var playerID = sliderID.split('amplitude-mute_')[1];
2810
2878
 
2811
- // save YT player data for later use (e.g. events)
2812
- // j1.adapter.amplitude.data.ytPlayers[playerID].volumMute = volumMute;
2813
-
2814
2879
  volumeMutes[i].addEventListener('click', function(event) {
2815
2880
 
2816
2881
  // update active song settings (manually)
@@ -2848,8 +2913,7 @@ regenerate: true
2848
2913
 
2849
2914
  } // END if playerSettings.type 'large'
2850
2915
 
2851
- }
2852
-
2916
+ } // END if j1.adapter.amplitude['data']['ytPlayers'][ytPlayerID] !== undefined
2853
2917
  } // END mimikYTPlayerUiEventsForAJS
2854
2918
 
2855
2919
  {%- endcapture -%}