j1-template 2024.3.21 → 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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/assets/data/amplitude_app.html +60 -51
  3. data/assets/theme/j1/adapter/js/advertising.js +40 -38
  4. data/assets/theme/j1/adapter/js/algolia.js +13 -11
  5. data/assets/theme/j1/adapter/js/amplitude.js +504 -348
  6. data/assets/theme/j1/adapter/js/analytics.js +19 -17
  7. data/assets/theme/j1/adapter/js/asciidoctor.js +10 -8
  8. data/assets/theme/j1/adapter/js/attic.js +24 -22
  9. data/assets/theme/j1/adapter/js/bmd.js +10 -8
  10. data/assets/theme/j1/adapter/js/carousel.js +12 -9
  11. data/assets/theme/j1/adapter/js/chatbot.js +106 -104
  12. data/assets/theme/j1/adapter/js/clipboard.js +16 -14
  13. data/assets/theme/j1/adapter/js/comments.js +24 -22
  14. data/assets/theme/j1/adapter/js/cookieConsent.js +5 -1
  15. data/assets/theme/j1/adapter/js/customFunctions.js +12 -10
  16. data/assets/theme/j1/adapter/js/customModule.js +10 -8
  17. data/assets/theme/j1/adapter/js/docsearch.js +33 -31
  18. data/assets/theme/j1/adapter/js/dropdowns.js +16 -14
  19. data/assets/theme/j1/adapter/js/fab.js +34 -32
  20. data/assets/theme/j1/adapter/js/gallery.js +21 -19
  21. data/assets/theme/j1/adapter/js/gemini.js +66 -64
  22. data/assets/theme/j1/adapter/js/iconPicker.js +31 -29
  23. data/assets/theme/j1/adapter/js/iconPickerPage.js +11 -9
  24. data/assets/theme/j1/adapter/js/iframer.js +17 -15
  25. data/assets/theme/j1/adapter/js/j1.js +146 -143
  26. data/assets/theme/j1/adapter/js/lazyLoader.js +33 -31
  27. data/assets/theme/j1/adapter/js/lightbox.js +9 -7
  28. data/assets/theme/j1/adapter/js/logger.js +11 -9
  29. data/assets/theme/j1/adapter/js/lunr.js +37 -35
  30. data/assets/theme/j1/adapter/js/masonry.js +23 -21
  31. data/assets/theme/j1/adapter/js/masterslider.js +31 -29
  32. data/assets/theme/j1/adapter/js/mmenu.js +25 -23
  33. data/assets/theme/j1/adapter/js/navigator.js +43 -41
  34. data/assets/theme/j1/adapter/js/particles.js +12 -10
  35. data/assets/theme/j1/adapter/js/rangeSlider.js +21 -19
  36. data/assets/theme/j1/adapter/js/rouge.js +10 -8
  37. data/assets/theme/j1/adapter/js/rtable.js +14 -12
  38. data/assets/theme/j1/adapter/js/rtextResizer.js +10 -8
  39. data/assets/theme/j1/adapter/js/scroller.js +15 -13
  40. data/assets/theme/j1/adapter/js/slick.js +18 -16
  41. data/assets/theme/j1/adapter/js/slimSelect.js +30 -28
  42. data/assets/theme/j1/adapter/js/speak2me.js +25 -23
  43. data/assets/theme/j1/adapter/js/swiper.js +13 -11
  44. data/assets/theme/j1/adapter/js/themeToggler.js +11 -9
  45. data/assets/theme/j1/adapter/js/themes.js +25 -23
  46. data/assets/theme/j1/adapter/js/toccer.js +13 -11
  47. data/assets/theme/j1/adapter/js/translator.js +19 -16
  48. data/assets/theme/j1/adapter/js/videojs.js +9 -7
  49. data/assets/theme/j1/adapter/js/waves.js +18 -16
  50. data/assets/theme/j1/core/js/template.js +11180 -10968
  51. data/assets/theme/j1/core/js/template.min.js +13 -18
  52. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/amplitude.css +10 -4
  53. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/amplitude.min.css +1 -1
  54. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/compact.css +15 -8
  55. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/compact.min.css +2 -1
  56. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/large.css +35 -14
  57. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/large.min.css +1 -1
  58. data/assets/theme/j1/modules/amplitudejs/js/tech/ytp.js +475 -423
  59. data/assets/theme/j1/modules/backstretch/js/backstretch.js +2 -2
  60. data/assets/theme/j1/modules/backstretch/js/backstretch.min.js +1 -1
  61. data/assets/theme/j1/modules/cookieConsent/js/cookieConsent.js +11 -11
  62. data/assets/theme/j1/modules/cookieConsent/js/cookieConsent.min.js +2 -1
  63. data/assets/theme/j1/modules/dropdowns/js/dropdowns.js +2 -2
  64. data/assets/theme/j1/modules/dropdowns/js/dropdowns.min.js +1 -1
  65. data/assets/theme/j1/modules/fab/js/fab.js +2 -2
  66. data/assets/theme/j1/modules/fab/js/fab.min.js +1 -1
  67. data/assets/theme/j1/modules/lunr/js/j1.js +1 -1
  68. data/assets/theme/j1/modules/lunr/js/j1.min.js +2 -1
  69. data/assets/theme/j1/modules/rtable/js/rtable.js +2 -2
  70. data/assets/theme/j1/modules/rtable/js/rtable.min.js +2 -1
  71. data/assets/theme/j1/modules/scroller/js/scroller.js +31 -29
  72. data/assets/theme/j1/modules/scroller/js/scroller.min.js +2 -1
  73. data/assets/theme/j1/modules/themeSwitcher/js/switcher.js +26 -26
  74. data/assets/theme/j1/modules/themeSwitcher/js/switcher.min.js +2 -1
  75. data/assets/theme/j1/modules/translator/js/translator.js +17 -17
  76. data/assets/theme/j1/modules/translator/js/translator.min.js +1 -1
  77. data/assets/theme/j1/modules/videojs/js/plugins/players/dm/dailymotion.js +10 -8
  78. data/assets/theme/j1/modules/videojs/js/plugins/players/dm/dailymotion.min.js +1 -1
  79. data/assets/theme/j1/modules/videojs/js/plugins/players/vm/vimeo.js +9 -7
  80. data/assets/theme/j1/modules/videojs/js/plugins/players/vm/vimeo.min.js +1 -1
  81. data/assets/theme/j1/modules/videojs/js/plugins/players/wt/wistia.js +13 -11
  82. data/assets/theme/j1/modules/videojs/js/plugins/players/wt/wistia.min.js +1 -1
  83. data/assets/theme/j1/modules/videojs/js/plugins/players/yt/youtube.js +10 -8
  84. data/assets/theme/j1/modules/videojs/js/plugins/players/yt/youtube.min.js +1 -1
  85. data/lib/j1/version.rb +1 -1
  86. data/lib/starter_web/README.md +5 -5
  87. data/lib/starter_web/_config.yml +1 -1
  88. data/lib/starter_web/_data/modules/amplitude_playlists.yml +124 -79
  89. data/lib/starter_web/_data/modules/defaults/amplitude.yml +5 -3
  90. data/lib/starter_web/_data/templates/feed.xml +1 -1
  91. data/lib/starter_web/_plugins/asciidoctor/videojs-block.rb +8 -0
  92. data/lib/starter_web/_plugins/asciidoctor/youtube-block.rb +7 -0
  93. data/lib/starter_web/_plugins/index/lunr.rb +1 -1
  94. data/lib/starter_web/assets/audio/album/emancipator/Alligator.mp3 +0 -0
  95. data/lib/starter_web/assets/audio/album/emancipator/DabCity.mp3 +0 -0
  96. data/lib/starter_web/assets/audio/album/emancipator/SeaToSky.mp3 +0 -0
  97. data/lib/starter_web/assets/audio/album/emancipator/TimeForSpace.mp3 +0 -0
  98. data/lib/starter_web/assets/audio/cover/emancipator/alligator.jpg +0 -0
  99. data/lib/starter_web/assets/audio/cover/emancipator/anthem.jpg +0 -0
  100. data/lib/starter_web/assets/audio/cover/emancipator/dab-city.jpg +0 -0
  101. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn.jpg +0 -0
  102. data/lib/starter_web/assets/audio/cover/emancipator/safe-in-the-steep-cliffs.jpg +0 -0
  103. data/lib/starter_web/assets/audio/cover/emancipator/sea-to-sky.jpg +0 -0
  104. data/lib/starter_web/assets/audio/cover/emancipator/soon-it-will-be-cold-enough.jpg +0 -0
  105. data/lib/starter_web/assets/audio/cover/emancipator/tine-for-space.jpg +0 -0
  106. data/lib/starter_web/package.json +1 -1
  107. data/lib/starter_web/pages/public/tour/audio_data.adoc +11 -6
  108. metadata +19 -11
  109. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/anthem.jpg +0 -0
  110. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/from-dusk-to-dawn.jpg +0 -0
  111. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/safe-in-the-steep-cliffs.jpg +0 -0
  112. data/lib/starter_web/assets/audio/cover/emancipator/from-dusk-to-dawn/soon-it-will-be-cold-enough.jpg +0 -0
  113. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn → !info}/!sound.links.txt +0 -0
  114. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn/Anthem.mp3 → Anthem.mp3} +0 -0
  115. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn/DuskToDawn.mp3 → DuskToDawn.mp3} +0 -0
  116. /data/lib/starter_web/assets/audio/album/emancipator/{from-dusk-to-dawn/FirstSnow.mp3 → FirstSnow.mp3} +0 -0
  117. /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
@@ -275,19 +290,19 @@ regenerate: true
275
290
  // ---------------------------------------------------------------------------
276
291
  function doNothingOnStateChange(state) {
277
292
  if (state > 0) {
278
- 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]}`);
279
294
  } else {
280
- 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]}`);
281
296
  }
282
297
  } // END doNothingOnStateChange
283
298
 
284
299
  // ---------------------------------------------------------------------------
285
300
  // processOnStateChangePlaying()
286
301
  //
287
- // wrraper for processing on stae PLAYING
302
+ // wrapper for processing players on state PLAYING
288
303
  // ---------------------------------------------------------------------------
289
304
  function processOnStateChangePlaying(event, playlist, songIndex) {
290
- var activeSong, playlist, playerID, videoID,
305
+ var activeSong, activePlaylist, playerID, videoID,
291
306
  ytPlayer, songs, songIndex,
292
307
  currentPlayer, previousPlayer, trackID;
293
308
 
@@ -297,15 +312,19 @@ regenerate: true
297
312
  checkActiveVideoElementYTP();
298
313
 
299
314
  // get active song settings (manually)
300
- activeSong = getActiveSong();
315
+ activeSong = getActiveSong();
301
316
 
302
- playlist = activeSong.playlist;
317
+ activePlaylist = playlist;
303
318
  playerID = activeSong.playerID;
304
319
  videoID = activeSong.videoID;
305
320
  songs = activeSong.songs;
306
- songIndex = activeSong.index;
321
+ // songIndex = activeSong.index;
307
322
  currentPlayer = activeSong.player;
308
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}`);
309
328
 
310
329
  // save YT player GLOBAL data for later use (e.g. events)
311
330
  j1.adapter.amplitude.data.activePlayer = 'ytp';
@@ -327,18 +346,18 @@ regenerate: true
327
346
  updateProgressBarsYTP();
328
347
  }, 500);
329
348
 
330
- trackID = songIndex + 1;
331
- logger.debug('\n' + `PLAY video on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
349
+ // update meta data
350
+ ytpUpdatMetaContainers(activeSong);
332
351
 
333
352
  // check|process video for configured START position (if set)
334
353
  // -------------------------------------------------------------------------
335
354
  var songStartSec = activeSong.startSec;
336
355
  if (songStartSec) {
337
- var tsStartSec = seconds2timestamp(songStartSec);
356
+ var tsStartSec = j1.adapter.amplitude.seconds2timestamp(songStartSec);
338
357
  var songCurrentTime = ytPlayer.getCurrentTime();
339
358
 
340
359
  if (songCurrentTime < songStartSec) {
341
- logger.debug('\n' + `START video on StateChange at trackID|timestamp: ${trackID}|${tsStartSec}`);
360
+ logger.debug(`START video on StateChange at trackID|timestamp: ${trackID}|${tsStartSec}`);
342
361
  processOnVideoStart(ytPlayer, songStartSec);
343
362
  }
344
363
  } // END if songStartEnabled
@@ -347,13 +366,13 @@ regenerate: true
347
366
  // -------------------------------------------------------------------------
348
367
  var songEndSec = activeSong.endSec;
349
368
  if (songEndSec) {
350
- var tsEndSec = seconds2timestamp(songEndSec);
369
+ var tsEndSec = j1.adapter.amplitude.seconds2timestamp(songEndSec);
351
370
 
352
371
  var checkOnVideoEnd = setInterval(function() {
353
372
  var songCurrentTime = ytPlayer.getCurrentTime();
354
373
 
355
374
  if (songCurrentTime >= songEndSec) {
356
- logger.debug('\n' + `STOP video on StateChange at trackID|timestamp: ${trackID}|${tsEndSec}`);
375
+ logger.debug(`STOP video on StateChange at trackID|timestamp: ${trackID}|${tsEndSec}`);
357
376
  processOnVideoEnd(ytPlayer);
358
377
 
359
378
  clearInterval(checkOnVideoEnd);
@@ -361,68 +380,56 @@ regenerate: true
361
380
  }, 500); // END checkOnVideoEnd
362
381
  } // END if songEndEnabled
363
382
 
364
- // stop active AT players running in parallel
365
- // -------------------------------------------------------------------------
366
- var atpPlayerState = Amplitude.getPlayerState();
367
- if (atpPlayerState === 'playing') {
368
- Amplitude.stop();
383
+ // stop active AT|YT players running in parallel except the current
384
+ ytpStopParallelActivePlayers(playerID);
369
385
 
370
- // clear button MINI PlayerPlayPause (AT player)
371
- var buttonPlayerPlayPauseMini = document.getElementsByClassName("mini-player-play-pause");
372
- for (var i=0; i<buttonPlayerPlayPauseMini.length; i++) {
373
- var htmlElement = buttonPlayerPlayPauseMini[i];
374
-
375
- 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')) {
376
394
  htmlElement.classList.remove('amplitude-playing');
377
395
  htmlElement.classList.add('amplitude-paused');
378
396
  }
379
-
380
- } // END for MINI buttonPlayerPlayPause
381
-
382
- // clear button COMPACT PlayerPlayPause (AT player)
383
- var buttonPlayerPlayPauseCompact = document.getElementsByClassName("compact-player-play-pause");
384
- for (var i=0; i<buttonPlayerPlayPauseCompact.length; i++) {
385
- var htmlElement = buttonPlayerPlayPauseCompact[i];
386
-
387
- 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')) {
388
409
  htmlElement.classList.remove('amplitude-playing');
389
410
  htmlElement.classList.add('amplitude-paused');
390
411
  }
391
-
392
- } // END for COMACT buttonPlayerPlayPause
412
+ }
413
+
414
+ } // END for COMACT buttonPlayerPlayPause
393
415
 
394
- // clear button LARGE PlayerPlayPause (AT player)
395
- var buttonPlayerPlayPauseLarge = document.getElementsByClassName("large-player-play-pause");
396
- for (var i=0; i<buttonPlayerPlayPauseLarge.length; i++) {
397
- var htmlElement = buttonPlayerPlayPauseLarge[i];
398
-
399
- 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')) {
400
424
  htmlElement.classList.remove('amplitude-playing');
401
425
  htmlElement.classList.add('amplitude-paused');
402
426
  }
427
+ }
403
428
 
404
- } // END for LARGE buttonPlayerPlayPause
405
-
406
- } // END if atpPlayerState 'playing'
407
-
408
- // TODO: check if YT player stop is needed
409
- // -------------------------------------------------------------------------
410
- // stop active YT players running in parallel except the current
411
- // if (previousPlayer.options.videoId !== videoID) {
412
- // logger.debug('\n' + `STOP all video on StateChange running in parallel at trackID|playerID: ${trackID}|${playerID}`);
413
- // var playerState = (previousPlayer.getPlayerState() > 0) ? previousPlayer.getPlayerState() : 6;
414
- // var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
415
- //
416
- // if (ytPlayerState === 'playing' || ytPlayerState === 'paused') {
417
- // previousPlayer.stopVideo();
418
- // }
419
- // }
420
- //
421
- // stopAllActivePlayers(playerID);
429
+ } // END for LARGE buttonPlayerPlayPause
422
430
 
423
431
  } // END processOnStateChangePlaying
424
432
 
425
-
426
433
  // ---------------------------------------------------------------------------
427
434
  // processOnStateChangeEnded()
428
435
  //
@@ -434,7 +441,7 @@ regenerate: true
434
441
  // save player current time data for later use
435
442
  ytPlayerCurrentTime = ytPlayer.getCurrentTime();
436
443
 
437
- logger.debug('\n' + `NEXT video on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
444
+ logger.debug(`NEXT video on StateChange at trackID|VideoID: ${trackID}|${videoID}`);
438
445
 
439
446
  // load NEXT song (video) in playlist
440
447
  loadNextVideo(playlist, songIndex);
@@ -521,50 +528,6 @@ regenerate: true
521
528
  current[lastKey] = value;
522
529
  }
523
530
 
524
- // ---------------------------------------------------------------------------
525
- // timestamp2seconds
526
- // ---------------------------------------------------------------------------
527
- function timestamp2seconds(timestamp) {
528
- // split timestamp
529
- const parts = timestamp.split(':');
530
-
531
- // check timestamp format
532
- if (parts.length !== 3) {
533
- // return "invalid timestamp";
534
- return false;
535
- }
536
-
537
- // convert parts to integers
538
- const hours = parseInt(parts[0], 10);
539
- const minutes = parseInt(parts[1], 10);
540
- const seconds = parseInt(parts[2], 10);
541
-
542
- // check valid timestamp values
543
- if (isNaN(hours) || isNaN(minutes) || isNaN(seconds) ||
544
- hours < 0 || hours > 23 ||
545
- minutes < 0 || minutes > 59 ||
546
- seconds < 0 || seconds > 59) {
547
- return "invalid timestamp";
548
- }
549
-
550
- const totalSeconds = (hours * 3600) + (minutes * 60) + seconds;
551
- return totalSeconds;
552
- } // END timestamp2seconds
553
-
554
- // ---------------------------------------------------------------------------
555
- // seconds2timestamp
556
- // ---------------------------------------------------------------------------
557
- function seconds2timestamp(seconds) {
558
- const hours = Math.floor(seconds / 3600);
559
- const minutes = Math.floor((seconds % 3600) / 60);
560
- const remainSeconds = seconds % 60;
561
- const tsHours = hours.toString().padStart(2, '0');
562
- const tsMinutes = minutes.toString().padStart(2, '0');
563
- const tsSeconds = remainSeconds.toString().padStart(2, '0');
564
-
565
- return `${tsHours}:${tsMinutes}:${tsSeconds}`;
566
- } // END seconds2timestamp
567
-
568
531
  // ---------------------------------------------------------------------------
569
532
  // ytpFadeInAudio
570
533
  // ---------------------------------------------------------------------------
@@ -595,18 +558,10 @@ regenerate: true
595
558
  currentStep = 1;
596
559
 
597
560
  if (volumeSlider === undefined || volumeSlider === null) {
598
- logger.warn('\n' + 'no volume slider found at playerID: ' + settings.playerID);
561
+ logger.warn('no volume slider found at playerID: ' + settings.playerID);
599
562
  return;
600
563
  }
601
564
 
602
- // (ytPlayer.isMuted()) && ytPlayer.unMute();
603
-
604
- // skip fade-in when volume is already at target value
605
- // if (ytPlayer.getVolume() >= targetVolume) {
606
- // logger.warn('\n' + 'skipped fade-in for current video on volume: ', targetVolume);
607
- // return;
608
- // }
609
-
610
565
  // Start the players volume muted
611
566
  ytPlayer.setVolume(0);
612
567
 
@@ -651,7 +606,7 @@ regenerate: true
651
606
  currentStep = 0;
652
607
 
653
608
  if (volumeSlider === undefined || volumeSlider === null) {
654
- logger.warn('\n' + 'no volume slider found at playerID: ' + settings.playerID);
609
+ logger.warn('no volume slider found at playerID: ' + settings.playerID);
655
610
  return;
656
611
  }
657
612
 
@@ -675,7 +630,7 @@ regenerate: true
675
630
  function initYtAPI() {
676
631
  startTimeModule = Date.now();
677
632
 
678
- logger.info('\n' + 'Initialize plugin|tech (ytp) : started');
633
+ logger.info('Initialize plugin|tech (ytp) : started');
679
634
 
680
635
  // Load YT IFrame Player API asynchronously
681
636
  // -------------------------------------------------------------------------
@@ -712,7 +667,6 @@ regenerate: true
712
667
 
713
668
  ytpSongIndex = songIndex;
714
669
 
715
-
716
670
  // play sonng (video) in playlist
717
671
  if (songIndex <= songs.length - 1) {
718
672
  songMetaData = songs[songIndex];
@@ -723,8 +677,7 @@ regenerate: true
723
677
  j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
724
678
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytVideoID;
725
679
 
726
-
727
- logger.debug('\n' + `SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
680
+ logger.debug(`SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
728
681
  ytPlayer.loadVideoById(ytVideoID);
729
682
 
730
683
  // delay after switch video
@@ -742,7 +695,7 @@ regenerate: true
742
695
  loadCoverImage(songMetaData);
743
696
 
744
697
  // update meta data
745
- updatMetaContainers(songMetaData);
698
+ // ytpUpdatMetaContainers(songMetaData);
746
699
 
747
700
  // set song (video) active at index in playlist
748
701
  setSongActive(playlist, songIndex);
@@ -772,7 +725,7 @@ regenerate: true
772
725
  j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
773
726
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
774
727
 
775
- logger.debug('\n' + `SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
728
+ logger.debug(`SWITCH video on loadNextVideo at trackID|VideoID: ${trackID}|${ytVideoID}`);
776
729
  ytPlayer.loadVideoById(ytVideoID);
777
730
 
778
731
  // delay after switch video
@@ -787,11 +740,10 @@ regenerate: true
787
740
  loadCoverImage(songMetaData);
788
741
 
789
742
  // update meta data
790
- updatMetaContainers(songMetaData);
743
+ // ytpUpdatMetaContainers(songMetaData);
791
744
 
792
- // set AJS play_pause button paused
793
- var playPauseButtonClass = `large-player-play-pause-${playerID}`
794
- setPlayPauseButtonPaused(playPauseButtonClass);
745
+ var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
746
+ togglePlayPauseButton(playPauseButtonClass);
795
747
 
796
748
  // set song (video) active at index in playlist
797
749
  setSongActive(playlist, songIndex);
@@ -840,7 +792,7 @@ regenerate: true
840
792
  {% endif %}{% endfor %}
841
793
 
842
794
  clearInterval(dependencies_ytp_ready);
843
- logger.info('\n' + 'Initialize APIPlayers : ready');
795
+ logger.info('Initialize APIPlayers : ready');
844
796
  } // END if ready
845
797
 
846
798
  }, 10); // END dependencies_ytp_ready
@@ -887,8 +839,8 @@ regenerate: true
887
839
  var ytpHeight = ('{{player.yt_player.height}}'.length > 0) ? '{{player.yt_player.height}}' : '{{amplitude_defaults.player.yt_player.height}}';
888
840
  var ytpWidth = ('{{player.yt_player.width}}'.length > 0) ? '{{player.yt_player.width}}' : '{{amplitude_defaults.player.yt_player.width}}';
889
841
 
890
- logger.info('\n' + 'AJS YouTube iFrame API: ready');
891
- 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}}');
892
844
 
893
845
  // create a hidden YT Player iFrame container
894
846
  //
@@ -900,13 +852,15 @@ regenerate: true
900
852
  height: ytpHeight,
901
853
  width: ytpWidth,
902
854
  videoId: ytpVideoID,
855
+ // videoId: 'bloedsinn',
903
856
  playerVars: {
904
857
  autoplay: ytpAutoPlay,
905
858
  loop: ytpLoop
906
859
  },
907
860
  events: {
908
- 'onReady': {{player.id}}OnPlayerReady,
909
- 'onStateChange': {{player.id}}OnPlayerStateChange
861
+ 'onReady': {{player.id}}OnPlayerReady,
862
+ 'onStateChange': {{player.id}}OnPlayerStateChange,
863
+ 'onError': {{player.id}}OnPlayerErrors
910
864
  }
911
865
  });
912
866
 
@@ -937,19 +891,23 @@ regenerate: true
937
891
 
938
892
  } // END if playerExistsInPage()
939
893
 
940
- function checkPlayingStatus(player) {
941
- if (player.getPlayerState() === YT_PLAYER_STATE.PLAYING) {
942
- // code run after video is playing
943
- // console.debug("checkPlayingStatus: AJS YouTube Player state: PLAYING");
944
- // do nothing
945
- return;
946
- } else {
947
- // re-check player state required
948
- // console.debug("checkPlayingStatus: AJS YouTube Player state:", player.getPlayerState());
949
- }
950
- } // 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;
902
+
903
+ logger.error(`YT API Error '${YT_PLAYER_ERROR_NAMES[eventData]}' for VideoID: '${videoID}'`);
951
904
 
952
- // run AJS YouTube Player initialization
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
953
911
  // ---------------------------------------------------------------------
954
912
  function {{player.id}}OnPlayerReady(event) {
955
913
  var hours, minutes, seconds,
@@ -960,7 +918,7 @@ regenerate: true
960
918
  ytPlayerReady = true;
961
919
  playerVolumePreset = parseInt({{player.volume_slider.preset_value}});
962
920
 
963
- logger.debug('\n' + `FOUND video ready at ID: {{player.id}}`);
921
+ logger.debug(`FOUND video ready at ID: {{player.id}}`);
964
922
 
965
923
  // set video playback quality to a minimum
966
924
  ytPlayer.setPlaybackQuality('small');
@@ -985,13 +943,11 @@ regenerate: true
985
943
  }
986
944
  }
987
945
 
988
- logger.info('\n' + 'AJS YouTube Player on ID {{player.id}}: ready');
946
+ logger.info('AJS YouTube Player on ID {{player.id}}: ready');
989
947
 
990
948
  // save YT player GLOBAL data for later use (e.g. events)
991
949
  j1.adapter.amplitude.data.ytpGlobals['ytPlayerReady'] = ytPlayerReady;
992
-
993
- // save YT player data for later use (e.g. events)
994
- // j1.adapter.amplitude.data.ytPlayers.{{player.id}}.playerReady = ytPlayerReady;
950
+ j1.adapter.amplitude.data.ytpGlobals['ytApiError'] = 0;
995
951
 
996
952
  // get duration hours (if configured)
997
953
  if ({{player.display_hours}} ) {
@@ -1023,12 +979,12 @@ regenerate: true
1023
979
  // -------------------------------------------------------------------
1024
980
  endTimeModule = Date.now();
1025
981
 
1026
- logger.info('\n' + 'Initialize plugin|tech (ytp) : finished');
982
+ logger.info('Initialize plugin|tech (ytp) : finished');
1027
983
 
1028
984
  if (playerCounter > 0) {
1029
- logger.info('\n' + 'Found players of type video (YTP) in page: ' + playerCounter);
985
+ logger.info('Found players of type video (YTP) in page: ' + playerCounter);
1030
986
  } else {
1031
- logger.warn('\n' + 'Found NO players of type video (YTP) in page');
987
+ logger.warn('Found NO players of type video (YTP) in page');
1032
988
  }
1033
989
 
1034
990
  // update activeVideoElement data structure for the ACTIVE video
@@ -1038,7 +994,7 @@ regenerate: true
1038
994
  }, checkActiveVideoInterval);
1039
995
  // END checkActiveVideoElementYTP
1040
996
 
1041
- logger.info('\n' + 'plugin|tech initializing time: ' + (endTimeModule-startTimeModule) + 'ms');
997
+ logger.info('plugin|tech initializing time: ' + (endTimeModule-startTimeModule) + 'ms');
1042
998
 
1043
999
  } // END onPlayerReady()
1044
1000
 
@@ -1053,6 +1009,8 @@ regenerate: true
1053
1009
  // are being set; e.g. start|stop positions for a video (when)
1054
1010
  // configured.
1055
1011
  // ---------------------------------------------------------------------
1012
+ // AJS YouTube Player state changes fired by the YT API
1013
+ // ---------------------------------------------------------------------
1056
1014
  function {{player.id}}OnPlayerStateChange(event) {
1057
1015
  var currentTime, playlist, ytPlayer, ytVideoID,
1058
1016
  songs, songIndex, trackID, playerID, songMetaData;
@@ -1104,7 +1062,7 @@ regenerate: true
1104
1062
  processOnStateChangeEnded(event, playlist, songIndex);
1105
1063
  break;
1106
1064
  default:
1107
- logger.error('\n' + `UNKNOWN event on StateChange fired: ${event.data}`);
1065
+ logger.error(`UNKNOWN event on StateChange fired: ${event.data}`);
1108
1066
  } // END switch event.data
1109
1067
 
1110
1068
  } // END {{player.id}}OnPlayerStateChange
@@ -1114,7 +1072,6 @@ regenerate: true
1114
1072
 
1115
1073
  } // END onYouTubeIframeAPIReady
1116
1074
 
1117
-
1118
1075
  // ---------------------------------------------------------------------------
1119
1076
  // main
1120
1077
  // ===========================================================================
@@ -1133,28 +1090,27 @@ regenerate: true
1133
1090
  // ---------------------------------------------------------------------------
1134
1091
  initUiEventsForAJS();
1135
1092
 
1136
-
1137
1093
  // ---------------------------------------------------------------------------
1138
1094
  // Base AJS Player functions
1139
1095
  // ===========================================================================
1140
1096
 
1141
1097
  // ---------------------------------------------------------------------------
1142
- // updatMetaContainers(metaData)
1098
+ // ytpUpdatMetaContainers(metaData)
1143
1099
  //
1144
1100
  // update song name in meta-containers
1145
1101
  // ---------------------------------------------------------------------------
1146
- function updatMetaContainers(metaData) {
1147
- var playerID, playlist, songName, artistName, albumName,
1148
- largePlayerSongAudioRating;
1102
+ function ytpUpdatMetaContainers(metaData) {
1103
+ var playerID, playlist, trackID, rating;
1149
1104
 
1150
- playlist = metaData.playlist;
1151
- playerID = playlist + '_large';
1105
+ playlist = metaData.playlist;
1106
+ playerID = playlist + '_large';
1107
+ rating = metaData.rating;
1108
+ trackID = metaData.index + 1;
1152
1109
 
1153
- var trackID = metaData.index + 1;
1154
- 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}`);
1155
1111
 
1156
1112
  // update song name in meta-containers
1157
- songName = document.getElementsByClassName("song-name");
1113
+ var songName = document.getElementsByClassName("song-name");
1158
1114
  if (songName.length) {
1159
1115
  for (var i=0; i<songName.length; i++) {
1160
1116
  var currentPlaylist = songName[i].dataset.amplitudePlaylist;
@@ -1165,10 +1121,10 @@ regenerate: true
1165
1121
  }
1166
1122
 
1167
1123
  // update artist name in meta-containers
1168
- artistName = document.getElementsByClassName("artist");
1124
+ var artistName = document.getElementsByClassName("artist");
1169
1125
  if (artistName.length) {
1170
1126
  for (var i=0; i<artistName.length; i++) {
1171
- var currentPlaylist = songName[i].dataset.amplitudePlaylist;
1127
+ var currentPlaylist = artistName[i].dataset.amplitudePlaylist;
1172
1128
  if (currentPlaylist === playlist) {
1173
1129
  artistName[i].innerHTML = metaData.artist;
1174
1130
  }
@@ -1176,7 +1132,7 @@ regenerate: true
1176
1132
  }
1177
1133
 
1178
1134
  // update album name in meta-containers
1179
- albumName = document.getElementsByClassName("album");
1135
+ var albumName = document.getElementsByClassName("album");
1180
1136
  if (albumName.length) {
1181
1137
  for (var i=0; i<albumName.length; i++) {
1182
1138
  var currentPlaylist = songName[i].dataset.amplitudePlaylist;
@@ -1187,27 +1143,32 @@ regenerate: true
1187
1143
  }
1188
1144
 
1189
1145
  // update song rating in screen controls
1190
- largePlayerSongAudioRating = document.getElementsByClassName("audio-rating-screen-controls");
1191
- if (largePlayerSongAudioRating.length) {
1192
- for (var i=0; i<largePlayerSongAudioRating.length; i++) {
1193
- 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;
1194
1150
  if (currentPlaylist === playlist) {
1195
1151
  if (metaData.rating) {
1196
- var trackID = metaData.index + 1;
1197
-
1198
- // save YT player data for later use (e.g. events)
1199
- 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
1200
1157
 
1201
- logger.debug('\n' + `UPDATE song rating on updatMetaContainers for trackID|playlist at: ${trackID}|${playlist} with a value of: ${metaData.rating}`);
1202
- largePlayerSongAudioRating[i].innerHTML = '<img src="/assets/image/pattern/rating/scalable/' + metaData.rating + '-star.svg"' + 'alt="song rating">';
1203
- } else {
1204
- 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);
1205
1166
  }
1206
1167
  }
1207
1168
  }
1208
- } // END if largePlayerSongAudioRating
1169
+ } // END if songAudioInfo
1209
1170
 
1210
- } // END updatMetaContainers
1171
+ } // END ytpUpdatMetaContainers
1211
1172
 
1212
1173
  // ---------------------------------------------------------------------------
1213
1174
  // loadCoverImage(metaData)
@@ -1221,46 +1182,67 @@ regenerate: true
1221
1182
  selector = ".cover-image-" + metaData.playlist;
1222
1183
  coverImage = document.querySelector(selector);
1223
1184
  coverImage.src = metaData.cover_art_url;
1185
+
1224
1186
  } // END loadCoverImage
1225
1187
 
1226
1188
  // ---------------------------------------------------------------------------
1227
- // stopAllActivePlayers(exceptPlayer)
1189
+ // ytpStopParallelActivePlayers(exceptPlayer)
1228
1190
  //
1229
1191
  // if multiple players used on a page, stop ALL active AT|YT players
1230
- // running in parallel execpet the exceptPlayer
1192
+ // running in parallel skipping the exceptPlayer
1231
1193
  // ---------------------------------------------------------------------------
1232
- function stopAllActivePlayers(exceptPlayer) {
1194
+ function ytpStopParallelActivePlayers(exceptPlayer) {
1233
1195
 
1234
- // stop active AT players
1196
+ // stop active AT players running in parallel
1235
1197
  // -------------------------------------------------------------------------
1236
- var atpPlayerState = Amplitude.getPlayerState();
1237
- if (atpPlayerState === 'playing') {
1198
+ var atPlayerState = Amplitude.getPlayerState();
1199
+ if (atPlayerState === 'playing' || atPlayerState === 'paused') {
1238
1200
  Amplitude.stop();
1239
1201
  } // END stop active AT players
1240
1202
 
1241
- // stop active YT players
1203
+ // stop active YT players running in parallel
1242
1204
  // -------------------------------------------------------------------------
1243
1205
  const ytPlayers = Object.keys(j1.adapter.amplitude.data.ytPlayers);
1244
1206
  for (let i=0; i<ytPlayers.length; i++) {
1245
- const ytPlayerID = ytPlayers[i];
1246
- const playerProperties = j1.adapter.amplitude.data.ytPlayers[ytPlayerID];
1207
+ const ytPlayerID = ytPlayers[i];
1208
+ const playerProperties = j1.adapter.amplitude.data.ytPlayers[ytPlayerID];
1247
1209
 
1248
1210
  if (ytPlayerID !== exceptPlayer) {
1249
1211
  var player = j1.adapter.amplitude['data']['ytPlayers'][ytPlayerID]['player'];
1250
1212
  var playerState = (player.getPlayerState() > 0) ? player.getPlayerState() : 6;
1251
1213
  var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
1252
1214
 
1253
- // if (ytPlayerState === 'playing' || ytPlayerState === 'paused' || ytPlayerState === 'buffering' || ytPlayerState === 'cued' || ytPlayerState === 'unstarted') {
1254
- if (ytPlayerState === 'playing' || ytPlayerState === 'paused' || ytPlayerState === 'buffering' || ytPlayerState === 'cued' || ytPlayerState === 'unstarted') {
1255
- logger.debug('\n' + `STOP player at stopAllActivePlayers for id: ${ytPlayerID}`);
1256
- // 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}`);
1257
1219
  player.stopVideo();
1258
- j1.adapter.amplitude.data.ytpGlobals.activeIndex = 0;
1259
- }
1260
- }
1261
- } // 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
1236
+
1237
+ } // END if ytPlayerState
1238
+ } // END if ytPlayerID
1262
1239
 
1263
- } // END stopAllActivePlayers
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
1264
1246
 
1265
1247
  // ---------------------------------------------------------------------------
1266
1248
  // getSongPlayed
@@ -1313,7 +1295,7 @@ regenerate: true
1313
1295
  }
1314
1296
  }
1315
1297
 
1316
- } // END setSongPlayed
1298
+ } // END setSongActive
1317
1299
 
1318
1300
  // ---------------------------------------------------------------------------
1319
1301
  // getProgressBarSelectedPositionPercentage
@@ -1368,20 +1350,18 @@ regenerate: true
1368
1350
  activeVideoElement.album = activeSong.album;
1369
1351
  activeVideoElement.artist = activeSong.artist;
1370
1352
  activeVideoElement.audio_info = activeSong.audio_info;
1371
- activeVideoElement.audio_single = activeSong.audio_single;
1372
1353
  activeVideoElement.currentTime = parseFloat(activeVideoElement.player.getCurrentTime());
1373
1354
  activeVideoElement.cover_art_url = activeSong.cover_art_url;
1374
1355
  activeVideoElement.duration = activeSong.duration;
1375
- activeVideoElement.endSec = timestamp2seconds(activeSong.end);
1356
+ activeVideoElement.endSec = j1.adapter.amplitude.timestamp2seconds(activeSong.end);
1376
1357
  activeVideoElement.endTS = activeSong.end;
1377
1358
  activeVideoElement.name = activeSong.name;
1378
- activeVideoElement.rating = activeSong.album;
1379
- activeVideoElement.startSec = timestamp2seconds(activeSong.start);
1359
+ activeVideoElement.rating = activeSong.rating;
1360
+ activeVideoElement.startSec = j1.adapter.amplitude.timestamp2seconds(activeSong.start);
1380
1361
  activeVideoElement.startTS = activeSong.start;
1381
1362
  activeVideoElement.url = activeSong.url;
1382
1363
 
1383
1364
  var videoArray = activeSong.url.split('=');
1384
-
1385
1365
  activeVideoElement.videoID = videoArray[1];
1386
1366
 
1387
1367
  }
@@ -1440,7 +1420,7 @@ regenerate: true
1440
1420
  activeClass = 'large-player-progress-' + playlist;
1441
1421
 
1442
1422
  if (activePlayer === undefined) {
1443
- logger.error('\n' + 'YT player not defined');
1423
+ logger.error('YT player not defined');
1444
1424
  return;
1445
1425
  }
1446
1426
 
@@ -1481,14 +1461,6 @@ regenerate: true
1481
1461
  ytPlayer = activeSongSettings.player;
1482
1462
  activePlaylist = activeSongSettings.playlist;
1483
1463
 
1484
- // if (activeSongSettings) {
1485
- // ytPlayer = activeSongSettings.player;
1486
- // activePlaylist = activeSongSettings.playlist;
1487
- // } else {
1488
- // ytPlayer = player;
1489
- // activePlaylist = playlist;
1490
- // }
1491
-
1492
1464
  // get current hours|minutes|seconds
1493
1465
  // -------------------------------------------------------------------------
1494
1466
  hours = ytpGetDurationHours(ytPlayer);
@@ -1693,7 +1665,6 @@ regenerate: true
1693
1665
 
1694
1666
  } // END ytpSeekTo
1695
1667
 
1696
-
1697
1668
  // ---------------------------------------------------------------------------
1698
1669
  // ytpGetBuffered
1699
1670
  //
@@ -1719,7 +1690,6 @@ regenerate: true
1719
1690
  return activeIndex;
1720
1691
  } // END ytpGetActiveIndex
1721
1692
 
1722
-
1723
1693
  // ---------------------------------------------------------------------------
1724
1694
  // ytpSetActiveIndex
1725
1695
  //
@@ -1857,7 +1827,6 @@ regenerate: true
1857
1827
  }
1858
1828
  } // END ytpGetDurationMinutes
1859
1829
 
1860
-
1861
1830
  // ---------------------------------------------------------------------------
1862
1831
  // ytpGetDurationSeconds
1863
1832
  //
@@ -1980,10 +1949,6 @@ regenerate: true
1980
1949
  // setPlayPauseButtonPaused
1981
1950
  // ---------------------------------------------------------------------------
1982
1951
  function setPlayPauseButtonPaused(element) {
1983
- var button, htmlElement;
1984
-
1985
- // button = document.getElementsByClassName(elementClass);
1986
- // htmlElement = button[0];
1987
1952
 
1988
1953
  element.classList.remove('amplitude-playing');
1989
1954
  element.classList.add('amplitude-paused');
@@ -1993,14 +1958,10 @@ regenerate: true
1993
1958
  // ---------------------------------------------------------------------------
1994
1959
  // setPlayPauseButtonPlaying
1995
1960
  // ---------------------------------------------------------------------------
1996
- function setPlayPauseButtonPlaying(elementClass) {
1997
- var button, htmlElement;
1961
+ function setPlayPauseButtonPlaying(element) {
1998
1962
 
1999
- button = document.getElementsByClassName(elementClass);
2000
- htmlElement = button[0];
2001
-
2002
- htmlElement.classList.remove('amplitude-paused');
2003
- htmlElement.classList.add('amplitude-playing');
1963
+ element.classList.remove('amplitude-paused');
1964
+ element.classList.add('amplitude-playing');
2004
1965
 
2005
1966
  } // END setPlayPauseButtonPlaying
2006
1967
 
@@ -2080,8 +2041,9 @@ regenerate: true
2080
2041
 
2081
2042
  if (classString.includes(ytPlayerID)) {
2082
2043
  largePlayerPlayPauseButton[i].addEventListener('click', function(event) {
2083
- var activeSongSettings, songs, songMetaData, ytPlayer,
2084
- playlist, playerID, songIndex;
2044
+ var activeSongSettings, songs, songMetaData, playerData,
2045
+ ytPlayer, playerState, ytPlayerState, playlist,
2046
+ playerID, songIndex;
2085
2047
 
2086
2048
  playlist = this.getAttribute("data-amplitude-playlist");
2087
2049
  playerID = playlist + '_large';
@@ -2091,100 +2053,85 @@ regenerate: true
2091
2053
 
2092
2054
  // get active song settings (manually)
2093
2055
  activeSongSettings = getActiveSong();
2094
-
2095
- // TODO: Extend getSongIndex() for singleAudio
2096
- // var songIndex = (singleAudio) ? ytpSongIndex : getSongIndex(songs, ytVideoID);
2097
2056
  if (!activeSongSettings) {
2098
2057
  songIndex = 0;
2099
2058
  ytpSongIndex = 0;
2100
2059
  } else {
2101
-
2102
- // ytPlayerCurrentTime = activeSongSettings.currentTime;
2103
-
2104
2060
  if (activeSongSettings.playlist !== playlist) {
2105
2061
  songIndex = 0;
2106
2062
  ytpSongIndex = 0;
2107
2063
 
2108
2064
  // reset previous player settings
2109
- if (activeSongSettings.player !== undefined) {
2110
- activeSongSettings.player.stopVideo();
2111
- var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2112
- togglePlayPauseButton(playPauseButtonClass);
2113
- }
2065
+ // if (activeSongSettings.player !== undefined) {
2066
+ // activeSongSettings.player.stopVideo();
2067
+ // var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2068
+ // togglePlayPauseButton(playPauseButtonClass);
2069
+ // }
2114
2070
  } else {
2115
2071
  songIndex = ytpSongIndex;
2116
2072
  }
2117
- }
2118
-
2119
- // set song (video) active at index in playlist
2120
- setSongActive(playlist, songIndex);
2073
+ } // END if activeSongSettings
2121
2074
 
2122
- // reset progress bar settings
2123
- 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]}'`);
2124
2079
 
2125
- // scroll song active at index in player
2126
- if (playerAutoScrollSongElement) {
2127
- scrollToActiveElement(playlist);
2080
+ return;
2128
2081
  }
2129
2082
 
2130
2083
  // update activeAudio data (manually)
2131
2084
  checkActiveVideoElementYTP();
2132
2085
 
2133
2086
  // get active song settings (manually)
2134
- activeSongSettings = getActiveSong();
2087
+ // activeSongSettings = getActiveSong();
2135
2088
 
2136
- songs = activeSongSettings.songs;
2137
- songMetaData = songs[songIndex];
2138
- ytPlayer = activeSongSettings.player;
2089
+ playerData = j1.adapter.amplitude.data.ytPlayers[playerID];
2090
+ ytPlayer = playerData.player;
2091
+ songIndex = playerData.activeIndex;
2092
+ songs = playerData.songs;
2139
2093
 
2140
2094
  // update meta data
2141
- updatMetaContainers(songMetaData);
2095
+ // songMetaData = songs[songIndex];
2096
+ // ytpUpdatMetaContainers(songMetaData);
2142
2097
 
2143
2098
  // save player GLOBAL data for later use (e.g. events)
2144
2099
  j1.adapter.amplitude.data.activePlayer = 'ytp';
2145
2100
  j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2146
2101
  j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2147
2102
 
2148
- // YT play|pause video
2103
+ // toggle YT play|pause video
2149
2104
  // ---------------------------------------------------------------
2150
- var playerState = ytPlayer.getPlayerState();
2151
- if (playerState < 0) {
2152
- var ytPlayerState = YT_PLAYER_STATE_NAMES[6];
2153
- } else {
2154
- var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
2155
- }
2105
+ playerState = ytPlayer.getPlayerState();
2106
+ ytPlayerState = (playerState < 0) ? YT_PLAYER_STATE_NAMES[6] : YT_PLAYER_STATE_NAMES[playerState];
2156
2107
 
2157
- // var playPauseButtonsMini = document.getElementsByClassName('mini-player-play-pause');
2158
- // setPlayPauseButtonPaused(playPauseButtonsMini);
2108
+ // if (playerState < 0) {
2109
+ // var ytPlayerState = YT_PLAYER_STATE_NAMES[6];
2110
+ // } else {
2111
+ // var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
2112
+ // }
2159
2113
 
2114
+ // TOGGLE state 'playing' => 'paused'
2160
2115
  if (ytPlayerState === 'playing') {
2161
2116
  ytPlayer.pauseVideo();
2162
2117
 
2163
2118
  ytPlayerCurrentTime = ytPlayer.getCurrentTime();
2164
-
2165
- // var trackID = songIndex + 1;
2166
- // logger.debug('\n' + `PAUSE video for PlayPauseButton on playlist|trackID: ${playlist}|${trackID} at: ${ytPlayerCurrentTime}`);
2167
-
2168
- // var playPauseButtonsMini = document.getElementsByClassName('mini-player-play-pause');
2169
- // setPlayPauseButtonPaused(playPauseButtonsMini);
2170
2119
 
2171
- // var playPauseButtonClassCompact = `compact-player-play-pause -${ytPlayerID}`;
2172
- // togglePlayPauseButton(playPauseButtonClassCompact);
2173
- // //
2174
- // var playPauseButtonClassLarge = `large-player-play-pause-${ytPlayerID}`;
2175
- // togglePlayPauseButton(playPauseButtonClassLarge);
2120
+ var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2121
+ togglePlayPauseButton(playPauseButtonClass);
2176
2122
 
2177
2123
  // reset|update time settings
2178
2124
  resetCurrentTimeContainerYTP(ytPlayer, playlist);
2179
2125
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2180
2126
  }
2181
2127
 
2128
+ // TOGGLE state 'paused' => 'playing'
2182
2129
  if (ytPlayerState === 'paused') {
2183
2130
  ytPlayer.playVideo();
2184
2131
  ytpSeekTo(ytPlayer, ytPlayerCurrentTime, true);
2185
2132
 
2186
2133
  var trackID = songIndex + 1;
2187
- 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}`);
2188
2135
 
2189
2136
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2190
2137
  togglePlayPauseButton(playPauseButtonClass);
@@ -2192,43 +2139,62 @@ regenerate: true
2192
2139
  // reset|update time settings
2193
2140
  resetCurrentTimeContainerYTP(ytPlayer, playlist);
2194
2141
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2195
- }
2142
+ } // if ytPlayerState === 'paused'
2196
2143
 
2144
+ // load (cued) video
2197
2145
  if (ytPlayerState === 'cued') {
2198
2146
  ytPlayer.playVideo();
2199
- var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2200
- togglePlayPauseButton(playPauseButtonClass);
2201
2147
 
2202
- // set song at songIndex active in playlist
2203
- 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]}'`);
2204
2153
 
2205
- // scroll song active at index in player
2206
- if (playerAutoScrollSongElement) {
2207
- scrollToActiveElement(playlist);
2208
- }
2154
+ // do nothing on API errors
2155
+ return;
2156
+ }
2209
2157
 
2210
- // reset|update time settings
2211
- resetCurrentTimeContainerYTP(ytPlayer, playlist);
2212
- updateDurationTimeContainerYTP(ytPlayer, playlist);
2213
- }
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'
2214
2178
 
2215
2179
  // TODO: unclear why state 'unstarted' is generated
2216
2180
  // on LAST item
2217
2181
  // workaround sofar
2218
- if (ytPlayerState === 'unstarted') {
2219
- ytPlayer.playVideo();
2220
- // ytPlayer.mute();
2221
-
2222
- var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2223
- togglePlayPauseButton(playPauseButtonClass);
2224
- resetCurrentTimeContainerYTP(ytPlayer, playlist);
2225
- updateDurationTimeContainerYTP(ytPlayer, playlist);
2226
- }
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'
2227
2192
 
2228
2193
  // deactivate AJS events (if any)
2229
2194
  event.stopImmediatePropagation();
2230
- }); // END EventListener largePlayerPlayPauseButton 'click'
2231
- }
2195
+
2196
+ }); // END EventListener largePlayerPlayPauseButton 'click
2197
+ } // END if classString
2232
2198
  } // END for largePlayerPlayPauseButton
2233
2199
 
2234
2200
  // Overload AJS largePlayerSkipBackward button for YT
@@ -2252,7 +2218,7 @@ regenerate: true
2252
2218
  currentVideoTime = ytPlayer.getCurrentTime();
2253
2219
 
2254
2220
  if (playerState === YT_PLAYER_STATE.PLAYING || playerState === YT_PLAYER_STATE.PAUSED) {
2255
- logger.debug('\n' + `SKIP forward on Button skipForward for ${skipOffset} seconds`);
2221
+ logger.debug(`SKIP forward on Button skipForward for ${skipOffset} seconds`);
2256
2222
  ytpSeekTo(ytPlayer, currentVideoTime + skipOffset, true);
2257
2223
 
2258
2224
  }
@@ -2284,7 +2250,7 @@ regenerate: true
2284
2250
  currentVideoTime = ytPlayer.getCurrentTime();
2285
2251
 
2286
2252
  if (playerState === YT_PLAYER_STATE.PLAYING || playerState === YT_PLAYER_STATE.PAUSED) {
2287
- logger.debug('\n' + `SKIP backward on Button skipBackward for ${skipOffset} seconds`);
2253
+ logger.debug(`SKIP backward on Button skipBackward for ${skipOffset} seconds`);
2288
2254
  ytpSeekTo(ytPlayer, currentVideoTime - skipOffset, true);
2289
2255
  }
2290
2256
 
@@ -2315,12 +2281,17 @@ regenerate: true
2315
2281
  songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2316
2282
  ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2317
2283
 
2318
- if (ytPlayer === undefined) {
2319
- 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;
2320
2290
  }
2321
2291
 
2322
- // stop active AT|YT players except the current
2323
- // stopAllActivePlayers(playerID);
2292
+ if (ytPlayer === undefined) {
2293
+ logger.error('YT player not defined');
2294
+ }
2324
2295
 
2325
2296
  // select video
2326
2297
  if (songIndex < songs.length-1) {
@@ -2351,7 +2322,7 @@ regenerate: true
2351
2322
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2352
2323
 
2353
2324
  trackID = songIndex + 1;
2354
- logger.debug('\n' + `SWITCH video for PlayerNextButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2325
+ logger.debug(`SWITCH video for PlayerNextButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2355
2326
  ytPlayer.loadVideoById(ytpVideoID);
2356
2327
 
2357
2328
  // delay after switch video
@@ -2375,7 +2346,6 @@ regenerate: true
2375
2346
 
2376
2347
  // set AJS play_pause button paused
2377
2348
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2378
- // setPlayPauseButtonPlaying(playPauseButtonClass);
2379
2349
  togglePlayPauseButton(playPauseButtonClass);
2380
2350
  } else {
2381
2351
  // toggle AJS play_pause button
@@ -2392,7 +2362,7 @@ regenerate: true
2392
2362
  loadCoverImage(songMetaData);
2393
2363
 
2394
2364
  // update meta data
2395
- updatMetaContainers(songMetaData);
2365
+ // ytpUpdatMetaContainers(songMetaData);
2396
2366
 
2397
2367
  // set song at songIndex active in playlist
2398
2368
  setSongActive(playlist, songIndex);
@@ -2431,12 +2401,17 @@ regenerate: true
2431
2401
  songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2432
2402
  ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2433
2403
 
2434
- if (ytPlayer === undefined) {
2435
- 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;
2436
2410
  }
2437
2411
 
2438
- // stop active AT|YT players except the current
2439
- // stopAllActivePlayers(playerID);
2412
+ if (ytPlayer === undefined) {
2413
+ logger.error('YT player not defined');
2414
+ }
2440
2415
 
2441
2416
  // select video
2442
2417
  if (songIndex > 0 && songIndex <= songs.length - 1) {
@@ -2459,7 +2434,7 @@ regenerate: true
2459
2434
  j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2460
2435
  j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2461
2436
 
2462
- // load next video
2437
+ // load previous video
2463
2438
  // -----------------------------------------------------------------
2464
2439
 
2465
2440
  // save YT player data for later use (e.g. events)
@@ -2468,7 +2443,7 @@ regenerate: true
2468
2443
  j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2469
2444
 
2470
2445
  trackID = songIndex + 1;
2471
- logger.debug('\n' + `SWITCH video for PlayePreviousButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2446
+ logger.debug(`SWITCH video for PlayePreviousButton at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2472
2447
  ytPlayer.loadVideoById(ytpVideoID);
2473
2448
 
2474
2449
  // delay after switch video
@@ -2492,7 +2467,6 @@ regenerate: true
2492
2467
 
2493
2468
  // set AJS play_pause button paused
2494
2469
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2495
- // setPlayPauseButtonPlaying(playPauseButtonClass);
2496
2470
  togglePlayPauseButton(playPauseButtonClass);
2497
2471
  } else {
2498
2472
  // toggle AJS play_pause button
@@ -2509,7 +2483,7 @@ regenerate: true
2509
2483
  loadCoverImage(songMetaData);
2510
2484
 
2511
2485
  // update meta data
2512
- updatMetaContainers(songMetaData);
2486
+ // ytpUpdatMetaContainers(songMetaData);
2513
2487
 
2514
2488
  // set song at songIndex active in playlist
2515
2489
  setSongActive(playlist, songIndex);
@@ -2539,60 +2513,62 @@ regenerate: true
2539
2513
  largePlayerSongContainer[i].addEventListener('click', function(event) {
2540
2514
  var activeSongSettings, playlist, playerID, playerState,
2541
2515
  songs, songIndex, songName, singleAudio, trackID,
2542
- ytPlayer, ytpVideoID;
2516
+ ytPlayer, ytpVideoID, activeSongIndex, isSongIndexChanged;
2543
2517
 
2544
2518
  // set (current) playlist|song data
2545
- playlist = this.getAttribute("data-amplitude-playlist");
2546
- playerID = playlist + '_large';
2547
- songIndex = parseInt(this.getAttribute("data-amplitude-song-index"));
2548
- 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;
2549
2525
 
2550
2526
  // update active song settings (manually)
2551
2527
  checkActiveVideoElementYTP();
2552
2528
 
2553
- // get active song settings (manually)
2554
- activeSongSettings = getActiveSong();
2555
-
2556
- if (activeSongSettings) {
2557
- // ytpCurrentTime = activeSongSettings.currentTime;
2558
- if (activeSongSettings.playlist !== playlist) {
2559
- // set current player settings
2560
- songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2561
- ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2562
-
2563
- // reset previous player settings
2564
- if (activeSongSettings.player !== undefined) {
2565
- activeSongSettings.player.stopVideo();
2566
- var playPauseButtonClass = `large-player-play-pause-${activeSongSettings.playerID}`;
2567
- togglePlayPauseButton(playPauseButtonClass);
2568
- }
2569
- } else {
2570
- // set current player settings
2571
- songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2572
- ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2573
- }
2574
- } else {
2575
- // set current player settings
2576
- songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2577
- ytPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
2578
- }
2579
-
2580
2529
  // set (current) song meta data
2530
+ songs = j1.adapter.amplitude.data.ytPlayers[playerID].songs;
2581
2531
  songMetaData = songs[songIndex];
2582
2532
  songURL = songMetaData.url;
2583
2533
  ytpVideoID = songURL.split('=')[1];
2584
- 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();
2585
2543
 
2586
- // TOGGLE state 'playing'|'paused' if video (audio) NOT changed
2587
- var isItemChanged = (j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex !== songIndex) ? true : false;
2588
- 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
+ }
2589
2567
 
2590
- if (playerState === YT_PLAYER_STATE.PLAYING) {
2591
- ytPlayer.pauseVideo();
2592
2568
  ytPlayerCurrentTime = ytPlayer.getCurrentTime();
2593
2569
 
2594
2570
  var trackID = songIndex + 1;
2595
- 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}`);
2596
2572
 
2597
2573
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2598
2574
  togglePlayPauseButton(playPauseButtonClass);
@@ -2600,89 +2576,167 @@ regenerate: true
2600
2576
  // reset|update time settings
2601
2577
  resetCurrentTimeContainerYTP(ytPlayer, playlist);
2602
2578
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2603
- return;
2604
- }
2605
2579
 
2606
- 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) {
2607
2620
  ytPlayer.playVideo();
2608
2621
  ytpSeekTo(ytPlayer, ytPlayerCurrentTime, true);
2609
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
+
2610
2650
  var trackID = songIndex + 1;
2611
- 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}`);
2612
2652
 
2613
2653
  var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2614
2654
  togglePlayPauseButton(playPauseButtonClass);
2615
2655
 
2656
+ // update meta data
2657
+ // ytpUpdatMetaContainers(songMetaData);
2658
+
2616
2659
  // reset|update time settings
2617
2660
  resetCurrentTimeContainerYTP(ytPlayer, playlist);
2618
2661
  updateDurationTimeContainerYTP(ytPlayer, playlist);
2619
- return;
2620
- }
2621
2662
 
2622
- } // END !changedAudio
2663
+ // set song at songIndex active in playlist
2664
+ setSongActive(playlist, songIndex);
2623
2665
 
2624
- // update global song index (start at 0)
2625
- 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);
2626
2675
 
2627
- // stop active AT|YT players
2628
- // 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]}'`);
2629
2681
 
2630
- // save YT player GLOBAL data for later use (e.g. events)
2631
- j1.adapter.amplitude.data.activePlayer = 'ytp';
2632
- j1.adapter.amplitude.data.ytpGlobals['activeIndex'] = songIndex;
2633
- j1.adapter.amplitude.data.ytpGlobals['activePlaylist'] = playlist;
2682
+ // do nothing on API errors
2683
+ return;
2684
+ }
2634
2685
 
2635
- // save YT player data for later use (e.g. events)
2636
- j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2637
- j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2686
+ // update global song index (start at 0)
2687
+ ytpSongIndex = songIndex;
2638
2688
 
2639
- // reset|update current time settings
2640
- resetCurrentTimeContainerYTP(ytPlayer, playlist);
2641
- updateDurationTimeContainerYTP(ytPlayer, playlist);
2642
- 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;
2643
2693
 
2644
- // load the song cover image
2645
- 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;
2646
2697
 
2647
- // update meta data
2648
- updatMetaContainers(songMetaData);
2698
+ // reset|update current time settings
2699
+ resetCurrentTimeContainerYTP(ytPlayer, playlist);
2700
+ updateDurationTimeContainerYTP(ytPlayer, playlist);
2701
+ resetProgressBarYTP();
2649
2702
 
2650
- // set AJS play_pause button playing
2651
- var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2652
- setPlayPauseButtonPlaying(playPauseButtonClass)
2703
+ // load the song cover image
2704
+ loadCoverImage(songMetaData);
2653
2705
 
2654
- // set song at songIndex active in playlist
2655
- setSongActive(playlist, songIndex);
2706
+ // update meta data
2707
+ // ytpUpdatMetaContainers(songMetaData);
2656
2708
 
2657
- // scroll song active at index in player
2658
- if (playerAutoScrollSongElement) {
2659
- scrollToActiveElement(playlist);
2660
- }
2709
+ var playPauseButtonClass = `large-player-play-pause-${ytPlayerID}`;
2710
+ togglePlayPauseButton(playPauseButtonClass);
2661
2711
 
2662
- // save YT player data for later use (e.g. events)
2663
- j1.adapter.amplitude.data.ytPlayers[playerID].activeIndex = songIndex;
2664
- j1.adapter.amplitude.data.ytPlayers[playerID].videoID = ytpVideoID;
2712
+ // set song at songIndex active in playlist
2713
+ setSongActive(playlist, songIndex);
2665
2714
 
2666
- // load next video
2667
- // -------------------------------------------------------------------
2668
- trackID = songIndex + 1;
2669
- logger.debug('\n' + `SWITCH video for PlayerSongContainer at trackID|VideoID: ${trackID}|${ytpVideoID}`);
2670
- ytPlayer.loadVideoById(ytpVideoID);
2715
+ // scroll song active at index in player
2716
+ if (playerAutoScrollSongElement) {
2717
+ scrollToActiveElement(playlist);
2718
+ }
2671
2719
 
2672
- // mute sound after next video load
2673
- // -------------------------------------------------------------------
2674
- if (muteAfterVideoSwitchInterval) {
2675
- ytPlayer.mute();
2676
- setTimeout(() => {
2677
- ytPlayer.unMute();
2678
- }, muteAfterVideoSwitchInterval);
2679
- }
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
2680
2734
 
2681
- // deactivate AJS events (if any)
2682
- event.stopImmediatePropagation();
2683
- }); // END EventListener 'click' SongContainer
2684
- } // END ifSWITCH video
2685
- } // END for
2735
+ // deactivate AJS events (if any)
2736
+ event.stopImmediatePropagation();
2737
+ }); // END EventListener
2738
+ } // END if classString
2739
+ } // END for largePlayerSongContainer
2686
2740
 
2687
2741
  // add listeners to all progress bars found
2688
2742
  // TODO: Fix for multiple players in page
@@ -2768,7 +2822,9 @@ regenerate: true
2768
2822
  var playerID = sliderID.split('volume_slider_')[1];
2769
2823
 
2770
2824
  // save YT player data for later use (e.g. events)
2771
- // j1.adapter.amplitude.data.ytPlayers[playerID].volumeSlider = volumeSlider;
2825
+ if (volumeSlider.dataset.amplitudeSource === 'youtube') {
2826
+ j1.adapter.amplitude.data.ytPlayers[playerID].volumeSlider = volumeSlider;
2827
+ }
2772
2828
 
2773
2829
  volumeSliders[i].addEventListener('click', function(event) {
2774
2830
 
@@ -2820,9 +2876,6 @@ regenerate: true
2820
2876
  var sliderID = volumeMutes[i].id;
2821
2877
  var playerID = sliderID.split('amplitude-mute_')[1];
2822
2878
 
2823
- // save YT player data for later use (e.g. events)
2824
- // j1.adapter.amplitude.data.ytPlayers[playerID].volumMute = volumMute;
2825
-
2826
2879
  volumeMutes[i].addEventListener('click', function(event) {
2827
2880
 
2828
2881
  // update active song settings (manually)
@@ -2860,8 +2913,7 @@ regenerate: true
2860
2913
 
2861
2914
  } // END if playerSettings.type 'large'
2862
2915
 
2863
- }
2864
-
2916
+ } // END if j1.adapter.amplitude['data']['ytPlayers'][ytPlayerID] !== undefined
2865
2917
  } // END mimikYTPlayerUiEventsForAJS
2866
2918
 
2867
2919
  {%- endcapture -%}