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/adapter/js/amplitude.38.js
9
+ # ~/assets/theme/j1/adapter/js/amplitude.41.js
10
10
  # Liquid template to adapt J1 AmplitudeJS Apps
11
11
  #
12
12
  # Product/Info:
@@ -63,7 +63,7 @@ regenerate: true
63
63
 
64
64
  /*
65
65
  # -----------------------------------------------------------------------------
66
- # ~/assets/theme/j1/adapter/js/amplitude.38.js
66
+ # ~/assets/theme/j1/adapter/js/amplitude.41.js
67
67
  # J1 Adapter for the amplitude module
68
68
  #
69
69
  # Product/Info:
@@ -87,34 +87,39 @@ regenerate: true
87
87
 
88
88
  j1.adapter.amplitude = ((j1, window) => {
89
89
 
90
- // global settings
90
+ const isDev = (j1.env === "development" || j1.env === "dev") ? true : false;
91
+
92
+ // Adapter GLOBAL settings
91
93
  // ---------------------------------------------------------------------------
92
94
  var environment = '{{environment}}';
93
95
  var cookie_names = j1.getCookieNames();
94
96
  var user_state = j1.readCookie(cookie_names.user_state);
95
97
  var state = 'not_started';
96
98
 
97
- // module settings
98
99
  // ---------------------------------------------------------------------------
99
-
100
100
  // control|logging
101
- // ---------------------------------------------------------------------------
101
+ // ------------------------------------
102
+ var consoleFilterSettings = {};
102
103
  var _this;
103
104
  var logger;
104
105
  var logText;
105
106
  var toJSON;
106
107
  var toText;
107
108
 
109
+ // --------------------------------------------------------------------------
108
110
  // date|time monitoring
109
- //----------------------------------------------------------------------------
111
+ // ------------------------------------
110
112
  var startTime;
111
113
  var endTime;
112
114
  var startTimeModule;
113
115
  var endTimeModule;
114
116
  var timeSeconds;
115
117
 
116
- // AmplitudeJS API settings
117
- // ---------------------------------------------------------------------------
118
+ // --------------------------------------------------------------------------
119
+ // AmplitudeJS GLOBAL settings
120
+ // ----------------------------------
121
+ const requiredForATP = false;
122
+
118
123
  const AT_PLAYER_STATE = {
119
124
  ENDED: 0,
120
125
  PLAYING: 1,
@@ -135,12 +140,16 @@ j1.adapter.amplitude = ((j1, window) => {
135
140
  6: "changed",
136
141
  };
137
142
 
138
- var playLists = {};
139
- var playersUILoaded = { state: false };
140
- var apiInitialized = { state: false };
141
-
142
- var isFadingIn = false;
143
- var isFadingOut = false;
143
+ var playLists = {};
144
+ var playersUILoaded = { state: false };
145
+ var apiInitialized = { state: false };
146
+ var playerCounter = 0;
147
+ var load_dependencies = {};
148
+ var playersProcessed = [];
149
+ var playersHtmlLoaded = false;
150
+ var processingPlayersFinished = false;
151
+ var isFadingIn = false;
152
+ var isFadingOut = false;
144
153
 
145
154
  var amplitudePlayerState;
146
155
  var amplitudeDefaults;
@@ -156,40 +165,49 @@ j1.adapter.amplitude = ((j1, window) => {
156
165
  var pluginManagerEnabled;
157
166
  var playerExistsInPage;
158
167
 
159
- // AmplitudeJS Player DEFAULT settings
168
+
169
+ // AmplitudeJS DEFAULT settings
160
170
  // ---------------------------------------------------------------------------
161
- var playerCounter = 0;
162
- var load_dependencies = {};
163
- var playersProcessed = [];
164
- var playersHtmlLoaded = false;
165
- var processingPlayersFinished = false;
166
171
 
167
- var playerSongElementHeigthDesktop = {{amplitude_defaults.player.song_element_heigt_desktop}};
168
- var playerSongElementHeigthMobile = {{amplitude_defaults.player.song_element_heigth_mobile}};
172
+ // PLAYER settings
173
+ // ------------------------------------
174
+ var playerDefaultPluginManager = {{amplitude_defaults.player.plugin_manager.enabled}};
175
+ var playerDefaultType = '{{amplitude_defaults.player.type}}';
176
+ var playerDefaultVolume = {{amplitude_defaults.player.volume_slider.preset_value}};
177
+ var playerVolumeSliderStep = {{amplitude_defaults.player.volume_slider.slider_step}};
178
+ var playerRepeat = {{amplitude_defaults.player.player_repeat}};
179
+ var playerShuffle = {{amplitude_defaults.player.player_shuffle}};
180
+ var playerPlayNextTitle = {{amplitude_defaults.player.play_next_title}};
181
+ var playerPauseNextTitle = {{amplitude_defaults.player.pause_next_title}};
182
+ var playerDelayNextTitle = {{amplitude_defaults.player.delay_next_title}};
183
+ var playerForwardBackwardSkipSeconds = {{amplitude_defaults.player.forward_backward_skip_seconds}};
184
+ var playerHoverPageScrollDisabled = {{amplitude_defaults.player.player_hover_page_scroll_disabled}};
185
+
186
+ var playerSongElementHeigthMobile = {{amplitude_defaults.player.player_song_element_heigth_mobile}};
187
+ var playerSongElementHeigthDesktop = {{amplitude_defaults.player.player_song_element_heigt_desktop}};
188
+ var playerScrollerSongElementMin = {{amplitude_defaults.player.player_scroller_song_element_min}};
189
+ var playerScrollControl = {{amplitude_defaults.player.player_scroll_control}};
169
190
  var playerAutoScrollSongElement = {{amplitude_defaults.player.player_auto_scroll_song_element}};
170
191
 
171
- var playerAudioInfo = ('{{amplitude_defaults.playlist.audio_info}}' === 'true') ? true : false;
172
- var playerDefaultPluginManager = ('{{amplitude_defaults.player.plugin_manager.enabled}}' === 'true') ? true : false;
173
- var playerDefaultType = '{{amplitude_defaults.player.type}}';
174
- var playerVolumeValue = '{{amplitude_defaults.player.volume_slider.preset_value}}';
175
- var playerVolumeSliderStep = '{{amplitude_defaults.player.volume_slider.slider_step}}';
176
- var playerRepeat = ('{{amplitude_defaults.player.repeat}}' === 'true') ? true : false;
177
- var playerShuffle = ('{{amplitude_defaults.player.shuffle}}' === 'true') ? true : false;
178
- var playerPlayNextTitle = ('{{amplitude_defaults.player.play_next_title}}' === 'true') ? true : false;
179
- var playerPauseNextTitle = ('{{amplitude_defaults.player.pause_next_title}}' === 'true') ? true : false;
180
- var playerDelayNextTitle = '{{amplitude_defaults.player.delay_next_title}}';
181
- var playerForwardBackwardSkipSeconds = '{{amplitude_defaults.player.forward_backward_skip_seconds}}';
182
-
183
- // AmplitudeJS settings curently NOT used
184
192
  // ---------------------------------------------------------------------------
185
- var playerWaveformsEnabled = '{{amplitude_defaults.player.waveforms.enabled}}';
186
- var playerWaveformsSampleRate = '{{amplitude_defaults.player.waveforms.sample_rate}}';
187
- var playerVisualizationEnabled = '{{amplitude_defaults.player.visualization.enabled}}';
188
- var playerVisualizationName = '{{amplitude_defaults.player.visualization.name}}';
193
+ // PLAYLIST settings
194
+ // ------------------------------------
195
+ var playlistAudioInfo = {{amplitude_defaults.playlist.audio_info}};
196
+
197
+ // ---------------------------------------------------------------------------
198
+ // UNUSED settings
199
+ // ------------------------------------
200
+ var playerWaveformsEnabled = {{amplitude_defaults.player.waveforms.enabled}};
201
+ var playerWaveformsSampleRate = {{amplitude_defaults.player.waveforms.sample_rate}};
202
+ var playerVisualizationEnabled = {{amplitude_defaults.player.visualization.enabled}};
203
+ var playerVisualizationName = '{{amplitude_defaults.player.visualization.name}}';
189
204
 
190
205
  // ---------------------------------------------------------------------------
191
206
  // helper functions
192
207
  // ---------------------------------------------------------------------------
208
+ function forceJsError() {
209
+ throw new Error("GENERATED JavaScript error!");
210
+ }
193
211
 
194
212
  // ---------------------------------------------------------------------------
195
213
  // main
@@ -201,6 +219,20 @@ j1.adapter.amplitude = ((j1, window) => {
201
219
  // -------------------------------------------------------------------------
202
220
  init: (options) => {
203
221
 
222
+ // -----------------------------------------------------------------------
223
+ // set console log filters (early)
224
+ // -----------------------------------------------------------------------
225
+ // consoleFilterSettings = {
226
+ // debug: false,
227
+ // };
228
+ // j1.api.consoleFilters.filter(consoleFilterSettings);
229
+ j1.api.consoleFilters.filter();
230
+
231
+ // -----------------------------------------------------------------------
232
+ // set error log filters (JS early)
233
+ // -----------------------------------------------------------------------
234
+ // j1.api.errorFilters.filter();
235
+
204
236
  // -----------------------------------------------------------------------
205
237
  // default module settings
206
238
  // -----------------------------------------------------------------------
@@ -217,6 +249,11 @@ j1.adapter.amplitude = ((j1, window) => {
217
249
  amplitudePlaylists = $.extend({}, {{amplitude_playlists | replace: 'nil', 'null' | replace: '=>', ':' }});
218
250
  amplitudeOptions = $.extend(true, {}, amplitudeDefaults, amplitudePlayers, amplitudePlaylists);
219
251
 
252
+ // save AJS player setiings for later use (e.g. the AJS plugins)
253
+ // j1.adapter.amplitude['amplitudeDefaults'] = amplitudeDefaults;
254
+ // j1.adapter.amplitude['amplitudeSettings'] = amplitudeSettings;
255
+ // j1.adapter.amplitude['amplitudeOptions'] = amplitudeOptions;
256
+
220
257
  // -----------------------------------------------------------------------
221
258
  // control|logging settings
222
259
  // -----------------------------------------------------------------------
@@ -230,8 +267,8 @@ j1.adapter.amplitude = ((j1, window) => {
230
267
  j1.adapter.amplitude.data.ytPlayers = {};
231
268
 
232
269
  // (initial) YT player data for later use (e.g. events)
270
+ j1.adapter.amplitude.data.playerSongElementHeigth = playerSongElementHeigthDesktop;
233
271
  j1.adapter.amplitude.data.activePlayer = 'not_set';
234
- j1.adapter.amplitude.data.playerSongElementHeigth = 'not_set';
235
272
  j1.adapter.amplitude.data.atpGlobals.activePlayerType = 'not_set';
236
273
  j1.adapter.amplitude.data.atpGlobals.ytpInstalled = false;
237
274
  j1.adapter.amplitude.data.ytpGlobals.activePlayerType = 'not_set';
@@ -249,11 +286,19 @@ j1.adapter.amplitude = ((j1, window) => {
249
286
  startTimeModule = Date.now();
250
287
 
251
288
  _this.setState('started');
252
- logger.debug('\n' + 'module state: ' + _this.getState());
253
- logger.info('\n' + 'module is being initialized');
289
+ logger.debug('module state: ' + _this.getState());
290
+ logger.info('module is being initialized');
254
291
 
255
- // set default viewport setting
256
- j1.adapter.amplitude.data.playerSongElementHeigth = playerSongElementHeigthDesktop;
292
+ // test data for console filters
293
+ // -------------------------------------------------------------------
294
+ // console.warn("consoleFilters: Diese WARNUNG wird gefiltert.");
295
+ // isDev && logger.warn("consoleFilters: Diese WARNUNG wird gefiltert.");
296
+ // console.warn("consoleFilters: Diese Meldung wird nicht gefiltert.");
297
+ // isDev && logger.warn("consoleFilters: Diese Meldung wird nicht gefiltert.");
298
+
299
+ // test data for error filters
300
+ // -------------------------------------------------------------------
301
+ // forceJsError();
257
302
 
258
303
  // -------------------------------------------------------------------
259
304
  // create global playlist (songs)
@@ -292,20 +337,20 @@ j1.adapter.amplitude = ((j1, window) => {
292
337
  // initialize viewPort specific (GLOBAL) settings
293
338
  $(window).bind('resizeEnd', function() {
294
339
  var viewPortSize = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
295
- //do something, window hasn't changed size in 500ms
296
- if (viewPortSize > 578) {
297
- j1.adapter.amplitude.data.playerSongElementHeigth = playerSongElementHeigthDesktop;
298
- } else {
299
- j1.adapter.amplitude.data.playerSongElementHeigth = playerSongElementHeigthMobile;
300
- }
340
+ //do something, window hasn't changed size in 500ms
341
+ if (viewPortSize > 578) {
342
+ j1.adapter.amplitude.data.playerSongElementHeigth = playerSongElementHeigthDesktop;
343
+ } else {
344
+ j1.adapter.amplitude.data.playerSongElementHeigth = playerSongElementHeigthMobile;
345
+ }
301
346
  });
302
347
 
303
348
  $(window).resize(function() {
304
- if(this.resizeTO) clearTimeout(this.resizeTO);
305
- this.resizeTO = setTimeout(function() {
306
- $(this).trigger('resizeEnd');
307
- }, 500);
308
- });
349
+ if (this.resizeTO) clearTimeout(this.resizeTO);
350
+ this.resizeTO = setTimeout(function() {
351
+ $(this).trigger('resizeEnd');
352
+ }, 500);
353
+ });
309
354
 
310
355
  clearInterval(dependencies_met_page_ready);
311
356
  } // END pageVisible
@@ -318,7 +363,7 @@ j1.adapter.amplitude = ((j1, window) => {
318
363
  // -------------------------------------------------------------------------
319
364
  songLoader: (songs) => {
320
365
 
321
- logger.info('\n' + 'creating global playlist (API): started');
366
+ logger.info('creating global playlist (API): started');
322
367
 
323
368
  // -----------------------------------------------------------------------
324
369
  // initialize amplitude songs
@@ -354,9 +399,21 @@ j1.adapter.amplitude = ((j1, window) => {
354
399
  continue;
355
400
  } else if (key === 'rating') {
356
401
  song.rating = item[key];
357
- continue;
402
+ continue;
403
+ } else if (key === 'playlist') {
404
+ song.playlist = item[key];
405
+ continue;
358
406
  } else if (key === 'shuffle') {
359
- song.shuffle = item[key];
407
+ song.shuffle = ((!!item[key]) === false) ? playerShuffle : item[key];
408
+ continue;
409
+ } else if (key === 'repeat') {
410
+ song.repeat = ((!!item[key]) === false) ? playerRepeat : item[key];
411
+ continue;
412
+ } else if (key === 'start') {
413
+ song.start = ((!!item[key]) === false) ? '00:00:00' : item[key];
414
+ continue;
415
+ } else if (key === 'end') {
416
+ song.end = ((!!item[key]) === false) ? '00:00:00' : item[key];
360
417
  continue;
361
418
  } else {
362
419
  song[key] = item[key];
@@ -369,7 +426,7 @@ j1.adapter.amplitude = ((j1, window) => {
369
426
 
370
427
  {% endif %} {% endfor %}
371
428
 
372
- logger.info('\n' + 'creating global playlist (API): finished');
429
+ logger.info('creating global playlist (API): finished');
373
430
  }, // END songLoader
374
431
 
375
432
  // -------------------------------------------------------------------------
@@ -381,7 +438,7 @@ j1.adapter.amplitude = ((j1, window) => {
381
438
  // -----------------------------------------------------------------------
382
439
  // initialize HTML portion (UI) for all players configured|enabled
383
440
  // -----------------------------------------------------------------------
384
- logger.info('\n' + 'loading player HTML components (UI): started');
441
+ logger.info('loading player HTML components (UI): started');
385
442
 
386
443
  {% for player in amplitude_options.players %} {% if player.enabled %}
387
444
  {% assign xhr_data_path = amplitude_options.xhr_data_path %}
@@ -392,7 +449,7 @@ j1.adapter.amplitude = ((j1, window) => {
392
449
  playerExistsInPage = ($('#' + '{{xhr_container_id}}')[0] !== undefined) ? true : false;
393
450
  if (playerExistsInPage) {
394
451
  playerCounter++;
395
- logger.debug('\n' + 'load player UI on ID #{{player.id}}: started');
452
+ logger.debug('load player UI on ID #{{player.id}}: started');
396
453
 
397
454
  j1.loadHTML({
398
455
  xhr_container_id: '{{xhr_container_id}}',
@@ -416,7 +473,7 @@ j1.adapter.amplitude = ((j1, window) => {
416
473
 
417
474
  if (xhrLoadState === 'success') {
418
475
  playersProcessed.push('{{xhr_container_id}}');
419
- logger.debug('\n' + 'load player UI on ID #{{player.id}}: finished');
476
+ logger.debug('load player UI on ID #{{player.id}}: finished');
420
477
 
421
478
  clearInterval(load_dependencies['dependencies_met_html_loaded_{{player.id}}']);
422
479
  }
@@ -432,7 +489,7 @@ j1.adapter.amplitude = ((j1, window) => {
432
489
  }
433
490
 
434
491
  if (processingPlayersFinished) {
435
- logger.info('\n' + 'loading player HTML components (UI): finished');
492
+ logger.info('loading player HTML components (UI): finished');
436
493
 
437
494
  clearInterval(load_dependencies['dependencies_met_players_loaded']);
438
495
  playersLoaded.state = true;
@@ -446,7 +503,7 @@ j1.adapter.amplitude = ((j1, window) => {
446
503
  // -------------------------------------------------------------------------
447
504
  initApi: (songlist) => {
448
505
 
449
- logger.info('\n' + 'initialze API: started');
506
+ logger.info('initialze API: started');
450
507
 
451
508
  {% comment %} collect playlists
452
509
  -------------------------------------------------------------------------- {% endcomment %}
@@ -468,7 +525,6 @@ j1.adapter.amplitude = ((j1, window) => {
468
525
  {% capture song_item %}
469
526
  {
470
527
  "name": "{{item.title}}",
471
- // "track": "{{item.track}}",
472
528
  "artist": "{{item.artist}}",
473
529
  "playlist": "{{item.playlist}}",
474
530
  "album": "{{item.name}}",
@@ -478,6 +534,7 @@ j1.adapter.amplitude = ((j1, window) => {
478
534
  "start": "{{item.start}}",
479
535
  "end": "{{item.end}}",
480
536
  "shuffle": "{{item.shuffle}}",
537
+ "repeat": "{{item.repeat}}",
481
538
  "duration": "{{item.duration}}",
482
539
  // "audio_fade_in": "{{item.audio_fade_in}}",
483
540
  // "audio_fade_out": "{{item.audio_fade_out}}",
@@ -529,14 +586,14 @@ j1.adapter.amplitude = ((j1, window) => {
529
586
  callbacks: {
530
587
  initialized: function() {
531
588
  var amplitudeConfig = Amplitude.getConfig();
532
- logger.info('\n' + 'initialze API: finished');
589
+ logger.info('initialze API: finished');
533
590
  // indicate api successfully initialized
534
591
  apiInitialized.state = true;
535
592
  },
536
593
  onInitError: function() {
537
594
  // indicate api failed on initialization
538
595
  apiInitialized.state = false;
539
- console.error('\n' + 'Amplitude API failed on initialization');
596
+ console.error('Amplitude API failed on initialization');
540
597
  },
541
598
  play: function() {
542
599
  // make sure the player is playing
@@ -572,7 +629,7 @@ j1.adapter.amplitude = ((j1, window) => {
572
629
  var currentState = Amplitude.getPlayerState();
573
630
  onPlayerStateChange(4);
574
631
  if (playerDelayNextTitle) {
575
- logger.debug('\n' + 'delay on previous title: ' + songMetaData.name + ' with titleIndex ' + songMetaData.index);
632
+ logger.debug('delay on previous title: ' + songMetaData.name + ' with titleIndex ' + songMetaData.index);
576
633
  }
577
634
 
578
635
  if (playerPauseNextTitle) {
@@ -580,7 +637,7 @@ j1.adapter.amplitude = ((j1, window) => {
580
637
  if (amplitudePlayerState === 'playing' || amplitudePlayerState === 'stopped' ) {
581
638
  setTimeout(() => {
582
639
  // pause playback of next title
583
- logger.debug('\n' + 'paused on next title: ' + songMetaData.name);
640
+ logger.debug('paused on next title: ' + songMetaData.name);
584
641
  Amplitude.pause();
585
642
  }, 150);
586
643
  } // END if playing
@@ -591,7 +648,7 @@ j1.adapter.amplitude = ((j1, window) => {
591
648
  next: function() {
592
649
  onPlayerStateChange(5);
593
650
  if (playerDelayNextTitle) {
594
- logger.debug('\n' + 'delay on next title: ' + songMetaData.name + ' with titleIndex ' + songMetaData.index);
651
+ logger.debug('delay on next title: ' + songMetaData.name + ' with titleIndex ' + songMetaData.index);
595
652
  }
596
653
 
597
654
  if (playerPauseNextTitle) {
@@ -599,7 +656,7 @@ j1.adapter.amplitude = ((j1, window) => {
599
656
  if (amplitudePlayerState === 'playing' || amplitudePlayerState === 'stopped' ) {
600
657
  setTimeout(() => {
601
658
  // pause playback of next title
602
- logger.debug('\n' + 'paused on next title: ' + songMetaData.name);
659
+ logger.debug('paused on next title: ' + songMetaData.name);
603
660
  Amplitude.pause();
604
661
  }, 150);
605
662
  } // END if playing
@@ -618,64 +675,12 @@ j1.adapter.amplitude = ((j1, window) => {
618
675
  // },
619
676
 
620
677
  continue_next: playerPlayNextTitle,
621
- volume: playerVolumeValue,
678
+ volume: playerDefaultVolume,
622
679
  volume_decrement: playerVolumeSliderStep,
623
680
  volume_increment: playerVolumeSliderStep
624
681
 
625
682
  }); // END Amplitude init
626
683
 
627
- // -----------------------------------------------------------------------
628
- // timestamp2seconds
629
- //
630
- // TODO: Add support for timestamp w/o hours like mm:ss
631
- // -----------------------------------------------------------------------
632
- function timestamp2seconds(timestamp) {
633
- // split timestamp
634
- const parts = timestamp.split(':');
635
-
636
- // check timestamp format
637
- if (parts.length !== 3) {
638
- // return "invalid timestamp";
639
- return false;
640
- }
641
-
642
- // convert parts to integers
643
- const hours = parseInt(parts[0], 10);
644
- const minutes = parseInt(parts[1], 10);
645
- const seconds = parseInt(parts[2], 10);
646
-
647
- // check valid timestamp values
648
- if (isNaN(hours) || isNaN(minutes) || isNaN(seconds) ||
649
- hours < 0 || hours > 23 ||
650
- minutes < 0 || minutes > 59 ||
651
- seconds < 0 || seconds > 59) {
652
- return "invalid timestamp";
653
- }
654
-
655
- const totalSeconds = (hours * 3600) + (minutes * 60) + seconds;
656
-
657
- return totalSeconds;
658
- } // END timestamp2seconds
659
-
660
- // -----------------------------------------------------------------------
661
- // seconds2timestamp
662
- // -----------------------------------------------------------------------
663
- function seconds2timestamp(seconds) {
664
-
665
- if (isNaN(seconds)) {
666
- return false;
667
- }
668
-
669
- const hours = Math.floor(seconds / 3600);
670
- const minutes = Math.floor((seconds % 3600) / 60);
671
- const remainSeconds = seconds % 60;
672
- const tsHours = hours.toString().padStart(2, '0');
673
- const tsMinutes = minutes.toString().padStart(2, '0');
674
- const tsSeconds = remainSeconds.toString().padStart(2, '0');
675
-
676
- return `${tsHours}:${tsMinutes}:${tsSeconds}`;
677
- } // END seconds2timestamp
678
-
679
684
  // -----------------------------------------------------------------------
680
685
  // atpFadeInAudio
681
686
  // -----------------------------------------------------------------------
@@ -708,7 +713,7 @@ j1.adapter.amplitude = ((j1, window) => {
708
713
  currentStep = 1;
709
714
 
710
715
  if (volumeSlider === undefined || volumeSlider === null) {
711
- logger.warn('\n' + 'no volume slider found at playerID: ' + settings.playerID);
716
+ isDev && logger.warn('no volume slider found at playerID: ' + settings.playerID);
712
717
  return;
713
718
  }
714
719
 
@@ -785,7 +790,7 @@ j1.adapter.amplitude = ((j1, window) => {
785
790
  songs = Amplitude.getSongsInPlaylist(playlist);
786
791
 
787
792
  if (songIndex === songs.length-1) {
788
- logger.debug('\n' + 'restore player volume on last trackID|volume at: ' + trackID + '|' + defaultVolume);
793
+ logger.debug('restore player volume on last trackID|volume at: ' + trackID + '|' + defaultVolume);
789
794
  volumeSlider.value = defaultVolume;
790
795
  }
791
796
 
@@ -798,196 +803,115 @@ j1.adapter.amplitude = ((j1, window) => {
798
803
  } // END atpFadeAudioOut
799
804
 
800
805
  // -----------------------------------------------------------------------
801
- // onPlayerStateChange
806
+ // doNothingOnStateChange(state)
802
807
  //
803
- // update AT player on state change
808
+ // wrraper for states that are not processed
804
809
  // -----------------------------------------------------------------------
805
- function onPlayerStateChange(state) {
806
- var playerID, playlist, songs, songIndex, songIndex, trackID,
807
- songStart, songEnd, songStartSec, songEndSec,
808
- songStartTS, songEndTS, songMetaData, currentVolume,
809
- activeSongMetadata, fadeAudio;
810
-
811
- activeSongMetadata = Amplitude.getActiveSongMetadata();
810
+ function doNothingOnStateChange(state) {
811
+ var playlist, playerID, songMetaData,
812
+ songIndex, trackID;
813
+
812
814
  playlist = Amplitude.getActivePlaylist();
813
- // playlist = activeSongMetadata.playlist
814
815
  playerID = playlist + '_large';
815
- songs = Amplitude.getSongsInPlaylist(playlist);
816
816
  songMetaData = Amplitude.getActiveSongMetadata();
817
817
  songIndex = songMetaData.index;
818
818
  trackID = songIndex + 1;
819
819
 
820
- if (state === AT_PLAYER_STATE.UNSTARTED) {
821
- // logger.debug('\n' + 'current audio state: unstarted');
822
- return;
823
- }
820
+ isDev && logger.warn(`DO NOTHING on StateChange for playlist: ${playlist} at trackID|state: ${trackID}|${AT_PLAYER_STATE_NAMES[state]}`);
824
821
 
825
- if (state === AT_PLAYER_STATE.STOPPED) {
826
- logger.debug('\n' + 'audio player on playlist: ' + playlist + ' at trackID|state: ' + trackID + '|' + AT_PLAYER_STATE_NAMES[state]);
827
- return;
828
- }
822
+ } // END doNothingOnStateChange
829
823
 
830
- if (state === AT_PLAYER_STATE.PAUSED) {
831
- logger.debug('\n' + 'audio player on playlist: ' + playlist + ' at trackID|state: ' + trackID + '|' + AT_PLAYER_STATE_NAMES[state]);
832
- return;
833
- }
824
+ // -----------------------------------------------------------------------
825
+ // processOnStateChangePlaying()
826
+ //
827
+ // wrraper to process the ACTIVE player on state PLAYING
828
+ // -----------------------------------------------------------------------
829
+ function processOnStateChangePlaying(state) {
830
+ var songMetaData, songIndex, playList, trackID;
834
831
 
835
- if (state === AT_PLAYER_STATE.PREVIOUS) {
836
- logger.debug('\n' + 'audio player on playlist: ' + playlist + ' at trackID|state: ' + trackID + '|' + AT_PLAYER_STATE_NAMES[state]);
837
- return;
838
- }
832
+ songMetaData = Amplitude.getActiveSongMetadata();
833
+ songIndex = songMetaData.index;
834
+ playList = Amplitude.getActivePlaylist();
835
+ trackID = songIndex + 1;
839
836
 
840
- if (state === AT_PLAYER_STATE.NEXT) {
841
- logger.debug('\n' + 'audio player on playlist: ' + playlist + ' at trackID|state: ' + trackID + '|' + AT_PLAYER_STATE_NAMES[state]);
842
- return;
843
- }
837
+ logger.debug(`PLAY audio on ATP at playlist|trackID: ${playList}|${trackID}`);
838
+ // logger.debug(`PLAY audio on processOnStateChangePlaying for playlist \'${playList}\' at trackID|state: ${trackID}|${AT_PLAYER_STATE_NAMES[state]}`);
844
839
 
845
- if (state === AT_PLAYER_STATE.CHANGED) {
846
- logger.debug('\n' + 'audio player on playlist: ' + playlist + ' at trackID|state: ' + trackID + '|' + AT_PLAYER_STATE_NAMES[state]);
847
- return;
848
- }
840
+ // save player GLOBAL data for later use (e.g. events)
841
+ j1.adapter.amplitude.data.activePlayer = 'atp';
849
842
 
850
- if (state === AT_PLAYER_STATE.PLAYING) {
851
- var playList, activePlayist, playerID, playerType,
852
- activePlayerType, startVolume, songIndex,
853
- ratingIndex, rating, ratingElement,
854
- screenControlRatingElements, screenControlRating;
843
+ // set song (manually) active at index in playlist
844
+ _this.setSongActive(playList, songIndex);
855
845
 
856
- songMetaData = Amplitude.getActiveSongMetadata();
857
- songIndex = songMetaData.index;
858
- playList = songMetaData.playlist;
859
- playList = Amplitude.getActivePlaylist();
860
- trackID = songIndex + 1;
846
+ // stop active YT players
847
+ // ---------------------------------------------------------------------
848
+ _this.atpStopParallelActivePlayers(j1.adapter.amplitude.data.ytPlayers);
861
849
 
862
- songStartTS = songMetaData.start;
863
- songEndTS = songMetaData.end;
864
- songStartSec = timestamp2seconds(songStartTS);
865
- songEndSec = timestamp2seconds(songEndTS);
866
- startVolume = Amplitude.getVolume();
850
+ // update song rating in playlist-screen|meta-container
851
+ // ---------------------------------------------------------------------
852
+ _this.atpUpdatMetaContainers(songMetaData);
867
853
 
868
- logger.debug('\n' + 'audio player on playlist: ' + playList + ' at trackID|state: ' + trackID + '|' + AT_PLAYER_STATE_NAMES[state]);
854
+ // scroll active song in players playlist
855
+ // ---------------------------------------------------------------------
856
+ _this.atPlayerScrollToActiveElement(songMetaData);
869
857
 
870
- // update song rating in playlist-screen|meta-container
871
- // -------------------------------------------------------------------
858
+ // process audio for AT players at configured START position
859
+ // ---------------------------------------------------------------------
860
+ _this.atpProcessAudioStartPosition();
872
861
 
873
- // search for ACTIVE screenControlRatingElement
874
- screenControlRating = null;
875
- screenControlRatingElements = document.getElementsByClassName('audio-rating-screen-controls');
876
- for (let i=0; i<screenControlRatingElements.length; i++) {
877
- ratingElement = screenControlRatingElements[i];
878
- rating = parseInt(songMetaData.rating);
879
- playerType = ratingElement.dataset.playerType;
880
- activePlayerType = j1.adapter.amplitude.data.atpGlobals.activePlayerType;
881
- activePlayist = songMetaData.playlist
882
-
883
- if (ratingElement.dataset.amplitudePlaylist === activePlayist && playerType === activePlayerType) {
884
- ratingIndex = i;
885
- screenControlRating = ratingElement;
886
- break;
887
- }
888
- }
862
+ // process audio for AT players at configured END position
863
+ // ---------------------------------------------------------------------
864
+ _this.atpProcessAudioEndPosition();
889
865
 
890
- // set the rating for ACTIVE screenControlRatingElements
891
- if (screenControlRating) {
892
- if (rating) {
893
- screenControlRatingElements[ratingIndex].innerHTML = '<img src="/assets/image/pattern/rating/scalable/' + rating + '-star.svg"' + 'alt="song rating">';
894
- } else {
895
- screenControlRatingElements[ratingIndex].innerHTML = '';
896
- }
897
- } // END if screenControlRating
898
-
899
- // process audio for configured START position
900
- // -------------------------------------------------------------------
901
- var checkIsFading = setInterval (() => {
902
- if (!isFadingIn) {
903
- var currentAudioTime = Amplitude.getSongPlayedSeconds();
904
- if (songStartSec && currentAudioTime <= songStartSec) {
905
- var songDurationSec = timestamp2seconds(songMetaData.duration);
906
-
907
- // seek audio to configured START position
908
- // NOTE: use setSongPlayedPercentage for seeking to NOT
909
- // generation any addition state changes like stopped
910
- // or playing
911
- logger.debug('\n' + 'seek audio in on playlist: ' + playList + ' at|to trackID|timestamp: ' + trackID + '|' + songStartTS);
912
- Amplitude.setSongPlayedPercentage((songStartSec / songDurationSec) * 100);
913
-
914
- // fade-in audio (if enabled)
915
- var fadeAudioIn = (songMetaData.audio_fade_in === 'true') ? true : false;
916
- if (fadeAudioIn) {
917
- logger.debug('\n' + 'faden audio in on playlist: ' + playList + ' at|to trackID|timestamp: ' + trackID + '|' + songStartTS);
918
- atpFadeInAudio({ playerID: playerID });
919
- } // END if fadeAudio
920
-
921
- } // END if songStartSec
922
-
923
- clearInterval(checkIsFading);
924
- }
925
- }, 100); // END checkIsFading
926
-
927
- // check|process audio for configured END position
928
- // -------------------------------------------------------------------
929
- if (songEndSec > songStartSec) {
930
- var checkIsOnVideoEnd = setInterval(() => {
931
-
932
- if (!isFadingOut) {
933
- var currentAudioTime = Amplitude.getSongPlayedSeconds();
934
- var songMetaData = Amplitude.getActiveSongMetadata();
935
- var songEndTS = songMetaData.end;
936
- var songEndSec = timestamp2seconds(songEndTS);
937
-
938
- if (currentAudioTime > songEndSec) {
939
- songMetaData = Amplitude.getActiveSongMetadata();
940
- songIndex = songMetaData.index;
941
- trackID = songIndex + 1;
942
-
943
- // seek audio out to total end END position
944
- // NOTE: use setSongPlayedPercentage for seeking to NOT
945
- // generation any addition state changes like stopped
946
- // or playing
947
- logger.debug('\n' + 'seek audio out to end on playlist: ' + playList + ' at trackID|timestamp: ' + trackID + '|' + songEndTS);
948
- Amplitude.setSongPlayedPercentage(99.99);
949
-
950
- // fade-out audio (if enabled)
951
- var fadeAudioOut = (songMetaData.audio_fade_out === 'true') ? true : false;
952
- if (fadeAudioOut) {
953
- logger.debug('\n' + 'fade audio out on playlist: ' + playList + ' at|to trackID|timestamp: ' + trackID + '|' + songEndTS);
954
- atpFadeAudioOut({ playerID: playerID });
955
- } // END if fadeAudio
956
-
957
- clearInterval(checkIsOnVideoEnd);
958
- } // END if currentAudioTime
959
-
960
- } // END if !isFading
961
-
962
- }, 100); // END checkIsOnVideoEnd
963
- } // END if songEndSec
964
-
965
- // stop active YT players running in parallel
966
- // -------------------------------------------------------------------
967
- const ytPlayers = Object.keys(j1.adapter.amplitude.data.ytPlayers);
968
- for (let i=0; i<ytPlayers.length; i++) {
969
- const ytPlayerID = ytPlayers[i];
970
- const playerProperties = j1.adapter.amplitude.data.ytPlayers[ytPlayerID];
971
-
972
- var player = j1.adapter.amplitude['data']['ytPlayers'][ytPlayerID]['player'];
973
- var playerState = (player.getPlayerState() > 0) ? player.getPlayerState() : 6;
974
- var ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
975
-
976
- // if (ytPlayerState === 'playing' || ytPlayerState === 'paused' || ytPlayerState === 'buffering' || ytPlayerState === 'cued' || ytPlayerState === 'unstarted') {
977
- if (ytPlayerState === 'playing' || ytPlayerState === 'paused') {
978
- logger.debug('\n' + `STOP YT player at onPlayerStateChange for id: ${ytPlayerID}`);
979
- player.stopVideo();
980
- j1.adapter.amplitude.data.ytpGlobals.activeIndex = 0;
981
- }
866
+ // save YT player data for later use (e.g. events)
867
+ // ---------------------------------------------------------------------
868
+ j1.adapter.amplitude.data.activePlayer = 'atp';
869
+ j1.adapter.amplitude.data.atpGlobals.activePlayerType = 'large';
982
870
 
983
- } // END stop active YT players
871
+ }; // END processOnStateChangePlaying
984
872
 
985
- } // END state AT_PLAYER_STATE PLAYING
986
-
987
- if (state === AT_PLAYER_STATE.ENDED) {
988
- // Amplitude.setVolume(50);
989
- } // END state AT_PLAYER_STATE.ENDED
873
+ // -----------------------------------------------------------------------
874
+ // onPlayerStateChange
875
+ //
876
+ // process all AT Player specific state changes
877
+ // -----------------------------------------------------------------------
878
+ // NOTE:
879
+ // The AT API fires a lot of INTERMEDIATE states. MOST of them gets
880
+ // ignored (do nothing). Currently, only state PLAYING is actively
881
+ // processed.
882
+ // -----------------------------------------------------------------------
883
+ function onPlayerStateChange(state) {
990
884
 
885
+ // process all state changes fired by AT API
886
+ // ---------------------------------------------------------------------
887
+ switch(state) {
888
+ case AT_PLAYER_STATE.UNSTARTED:
889
+ doNothingOnStateChange(AT_PLAYER_STATE.UNSTARTED);
890
+ break;
891
+ case AT_PLAYER_STATE.STOPPED:
892
+ doNothingOnStateChange(AT_PLAYER_STATE.STOPPED);
893
+ break;
894
+ case AT_PLAYER_STATE.PAUSED:
895
+ doNothingOnStateChange(AT_PLAYER_STATE.PAUSED);
896
+ break;
897
+ case AT_PLAYER_STATE.PREVIOUS:
898
+ doNothingOnStateChange(AT_PLAYER_STATE.PREVIOUS);
899
+ break;
900
+ case AT_PLAYER_STATE.NEXT:
901
+ doNothingOnStateChange(AT_PLAYER_STATE.NEXT);
902
+ break;
903
+ case AT_PLAYER_STATE.CHANGED:
904
+ doNothingOnStateChange(AT_PLAYER_STATE.CHANGED);
905
+ break;
906
+ case AT_PLAYER_STATE.PLAYING:
907
+ processOnStateChangePlaying(AT_PLAYER_STATE.PLAYING);
908
+ break;
909
+ case AT_PLAYER_STATE.ENDED:
910
+ doNothingOnStateChange(AT_PLAYER_STATE.ENDED);
911
+ break;
912
+ default:
913
+ logger.error(`UNKNOWN state on StateChange fired: ${state}`);
914
+ } // END switch state
991
915
  } // END onPlayerStateChange
992
916
 
993
917
  }, // END initApi
@@ -996,30 +920,30 @@ j1.adapter.amplitude = ((j1, window) => {
996
920
  // monitorPlayerActiveElementChanges
997
921
  //
998
922
  // -------------------------------------------------------------------------
999
- monitorPlayerActiveElementChanges: () => {
1000
- // var playerSongContainers = document.getElementsByClassName("large-player-title-list");
1001
- var playerSongContainers = document.getElementsByClassName("large-player-title-list");
1002
- for (var i=0; i<playerSongContainers.length; i++) {
1003
- var scrollableList = document.getElementById(playerSongContainers[0].id);
1004
- var observer = new MutationObserver((mutationsList, observer) => {
1005
- for (const mutation of mutationsList) {
1006
- if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
1007
- // Überprüfen, ob das geänderte Element jetzt die aktive Klasse besitzt
1008
- if (mutation.target.classList.contains('amplitude-active-song-container')) {
1009
- scrollableList.scrollTop = mutation.target.offsetTop;
1010
- }
1011
- }
1012
- }
1013
- }); // END observer
1014
-
1015
- // Optionen für den Observer: Nur Änderungen an Attributen beobachten
1016
- observer.observe(scrollableList, {
1017
- attributes: true,
1018
- subtree: true
1019
- }); // END observer options
1020
-
1021
- } // END for playerSongContainers
1022
- }, // END monitorPlayerActiveElementChanges
923
+ // monitorPlayerActiveElementChanges: () => {
924
+ // // var playerSongContainers = document.getElementsByClassName("large-player-title-list");
925
+ // var playerSongContainers = document.getElementsByClassName("large-player-title-list");
926
+ // for (var i=0; i<playerSongContainers.length; i++) {
927
+ // var scrollableList = document.getElementById(playerSongContainers[0].id);
928
+ // var observer = new MutationObserver((mutationsList, observer) => {
929
+ // for (const mutation of mutationsList) {
930
+ // if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
931
+ // // Überprüfen, ob das geänderte Element jetzt die aktive Klasse besitzt
932
+ // if (mutation.target.classList.contains('amplitude-active-song-container')) {
933
+ // scrollableList.scrollTop = mutation.target.offsetTop;
934
+ // }
935
+ // }
936
+ // }
937
+ // }); // END observer
938
+
939
+ // // Optionen für den Observer: Nur Änderungen an Attributen beobachten
940
+ // observer.observe(scrollableList, {
941
+ // attributes: true,
942
+ // subtree: true
943
+ // }); // END observer options
944
+
945
+ // } // END for playerSongContainers
946
+ // }, // END monitorPlayerActiveElementChanges
1023
947
 
1024
948
  // -------------------------------------------------------------------------
1025
949
  // initPlayerUiEvents
@@ -1031,7 +955,7 @@ j1.adapter.amplitude = ((j1, window) => {
1031
955
  var parentContainer = (document.getElementById('{{xhr_container_id}}') !== null) ? true : false;
1032
956
  var parentContainerExist = ($('#' + '{{xhr_container_id}}')[0] !== undefined) ? true : false;
1033
957
 
1034
- logger.info('\n' + 'initialize player specific UI events: started');
958
+ logger.info('initialize player specific UI events: started');
1035
959
 
1036
960
  {% for player in amplitude_options.players %} {% if player.enabled %}
1037
961
  {% assign xhr_data_path = amplitude_options.xhr_data_path %}
@@ -1056,36 +980,59 @@ j1.adapter.amplitude = ((j1, window) => {
1056
980
  var playListName = '{{player.playlist.name}}';
1057
981
  var playListTitle = '{{player.playlist.title}}';
1058
982
 
1059
- logger.debug('\n' + 'initialize audio player instance on id: {{player.id}}');
983
+ logger.debug('initialize audio player instance on id: {{player.id}}');
1060
984
 
1061
985
  // set song (title) specific audio info links
1062
986
  // -------------------------------------------------------------
1063
- if (playerAudioInfo) {
987
+ if (playlistAudioInfo) {
1064
988
  var infoLinks = document.getElementsByClassName('audio-info-link');
1065
989
  _this.setAudioInfo(infoLinks);
1066
990
  }
1067
991
 
1068
992
  // set player specific UI events
1069
993
  // -------------------------------------------------------------
1070
- logger.debug('\n' + 'setup audio player specific UI events on ID #{{player.id}}: started');
994
+ logger.debug('setup audio player specific UI events on ID #{{player.id}}: started');
1071
995
 
1072
996
  var dependencies_met_api_initialized = setInterval (() => {
1073
997
  if (apiInitialized.state) {
1074
998
  amplitudePlayerState = Amplitude.getPlayerState();
1075
999
 
1000
+ {% comment %} process UI events for all MINI Players
1001
+ ============================================================ {% endcomment %}
1076
1002
  {% if player.id contains 'mini' %}
1077
- // ---------------------------------------------------------
1078
- // START mini player UI events
1079
- //
1080
1003
  if (document.getElementById('{{player.id}}') !== null) {
1081
1004
 
1082
- // add listeners to all progress bars found (mini-player)
1083
- // getElementsByClassName returns an Array-like object
1005
+ {% comment %} PREPARED event listener for LATER use
1006
+ ----------------------------------------------------------
1007
+ // click on play_pause button (MINI player)
1008
+ var miniPlayerPlayPauseButton = document.getElementsByClassName('mini-player-play-pause');
1009
+ for (var i=0; i<miniPlayerPlayPauseButton.length; i++) {
1010
+ if (miniPlayerPlayPauseButton[i].dataset.amplitudeSource === 'youtube') {
1011
+ // do nothing (managed by plugin)
1012
+ } else {
1013
+ // var currentPlaylist = compactPlayerPlayPauseButton[i].dataset.amplitudePlaylist;
1014
+ // if (currentPlaylist === playListName) {
1015
+ if (miniPlayerPlayPauseButton[i].id === 'mini_player_play_pause_{{player.id}}') {
1016
+ miniPlayerPlayPauseButton[i].addEventListener('click', function(event) {
1017
+ var ytpPlayer;
1018
+
1019
+ // save YT player data for later use (e.g. events)
1020
+ j1.adapter.amplitude.data.activePlayer = 'atp';
1021
+ j1.adapter.amplitude.data.atpGlobals.activePlayerType = 'mini';
1022
+
1023
+ }); // addEventListener END
1024
+ } // END if miniPlayerPlayPauseButton
1025
+ } // END if ATP
1026
+ } // END for miniPlayerPlayPauseButton
1027
+ ----------------------------------------------------------
1028
+ {% endcomment %}
1029
+
1030
+ // add listeners to all progress bars found (MINI Player)
1084
1031
  // -------------------------------------------------------
1085
1032
  var progressBars = document.getElementsByClassName("mini-player-progress");
1086
1033
  for (var i=0; i<progressBars.length; i++) {
1087
1034
  if (progressBars[i].dataset.amplitudeSource === 'youtube') {
1088
- // do nothing
1035
+ // do nothing for YTP (managed by plugin)
1089
1036
  } else {
1090
1037
  progressBars[i].addEventListener('click', function(event) {
1091
1038
  var offset = this.getBoundingClientRect();
@@ -1093,43 +1040,29 @@ j1.adapter.amplitude = ((j1, window) => {
1093
1040
 
1094
1041
  Amplitude.setSongPlayedPercentage(
1095
1042
  (parseFloat(xpos)/parseFloat(this.offsetWidth))*100);
1096
- }); // END EventListener 'click'
1097
- }
1098
- } // END for
1099
1043
 
1100
- // click on play_pause button (MINI player)
1101
- var miniPlayerPlayPauseButton = document.getElementsByClassName('mini-player-play-pause');
1102
- for (var i=0; i<miniPlayerPlayPauseButton.length; i++) {
1103
- if (miniPlayerPlayPauseButton[i].dataset.amplitudeSource === 'youtube') {
1104
- // do nothing
1105
- } else {
1106
- var currentPlaylist = miniPlayerPlayPauseButton[i].dataset.amplitudePlaylist;
1107
- if (currentPlaylist === playList) {
1108
- miniPlayerPlayPauseButton[i].addEventListener('click', function(event) {
1109
- // do nothing
1110
- });
1111
- }
1112
- }
1113
- } // END play_pause button (MINI player)
1044
+ }); // END addEventListener
1045
+ } // END if progressBars
1046
+ } // END for progressBars
1114
1047
 
1115
1048
  } // END mini player UI events
1116
1049
  {% endif %}
1117
1050
 
1118
- {% if player.id contains 'compact' %}
1119
- // ---------------------------------------------------------
1120
- // START compact player UI events
1121
- //
1051
+
1052
+ {% comment %} process UI events for all COMPACT Players
1053
+ ============================================================ {% endcomment %}
1054
+ {% if player.id contains 'compact' %}
1122
1055
  if (document.getElementById('{{player.id}}') !== null) {
1123
1056
 
1124
1057
  // show|hide scrollbar in playlist (compact player)
1125
1058
  // -------------------------------------------------------
1126
1059
  const songsInPlaylist = Amplitude.getSongsInPlaylist(playListName);
1127
- if (songsInPlaylist.length <= 8) {
1060
+ if (songsInPlaylist.length <= playerScrollerSongElementMin) {
1128
1061
  const titleListCompactPlayer = document.getElementById('compact_player_title_list_' + playListName);
1129
1062
  if (titleListCompactPlayer !== null) {
1130
1063
  titleListCompactPlayer.classList.add('hide-scrollbar');
1131
1064
  }
1132
- }
1065
+ } // END if songsInPlaylist
1133
1066
 
1134
1067
  // show playlist
1135
1068
  // -------------------------------------------------------
@@ -1159,7 +1092,8 @@ j1.adapter.amplitude = ((j1, window) => {
1159
1092
  $('body').addClass('stop-scrolling');
1160
1093
  }
1161
1094
  }
1162
- }); // END EventListener 'click' (compact player|show playlist)
1095
+
1096
+ }); // END EventListener
1163
1097
  } // END if showPlaylist
1164
1098
 
1165
1099
  // hide playlist
@@ -1170,7 +1104,7 @@ j1.adapter.amplitude = ((j1, window) => {
1170
1104
  var playlistScreen = document.getElementById("playlist_screen_{{player.id}}");
1171
1105
 
1172
1106
  playlistScreen.classList.remove('slide-in-top');
1173
- playlistScreen.classList.add('slislide-out-top');
1107
+ playlistScreen.classList.add('slide-out-top');
1174
1108
  playlistScreen.style.display = "none";
1175
1109
  playlistScreen.style.zIndex = "1";
1176
1110
 
@@ -1178,17 +1112,16 @@ j1.adapter.amplitude = ((j1, window) => {
1178
1112
  if ($('body').hasClass('stop-scrolling')) {
1179
1113
  $('body').removeClass('stop-scrolling');
1180
1114
  }
1181
- }); // END EventListener 'click' (compact player|show playlist)
1182
- } // END if hidePlaylist
1183
1115
 
1116
+ }); // END addEventListener
1117
+ } // END if hidePlaylist
1184
1118
 
1185
1119
  // add listeners to all progress bars found (compact-player)
1186
- // getElementsByClassName returns an Array-like object
1187
1120
  // -------------------------------------------------------
1188
1121
  var progressBars = document.getElementsByClassName("compact-player-progress");
1189
1122
  for (var i=0; i<progressBars.length; i++) {
1190
1123
  if (progressBars[i].dataset.amplitudeSource === 'youtube') {
1191
- // do nothing
1124
+ // do nothing for YTP (managed by plugin)
1192
1125
  } else {
1193
1126
  progressBars[i].addEventListener('click', function(event) {
1194
1127
  var offset = this.getBoundingClientRect();
@@ -1196,56 +1129,99 @@ j1.adapter.amplitude = ((j1, window) => {
1196
1129
 
1197
1130
  Amplitude.setSongPlayedPercentage(
1198
1131
  (parseFloat(xpos)/parseFloat(this.offsetWidth))*100);
1199
- }); // END EventListener 'click'
1200
- }
1201
- } // END for
1202
1132
 
1133
+ }); // END EventListener 'click'
1134
+ } // END if progressBars
1135
+ } // END for progressBars
1203
1136
 
1204
- // click on Next|Previous Buttons (COMPACT player)
1137
+ // add listeners to all Next Buttons found (COMPACT player)
1205
1138
  // -------------------------------------------------------
1206
1139
 
1207
- // add listeners to all Next Buttons found
1208
- var largeNextButtons = document.getElementsByClassName("compact-player-next");
1209
- for (var i=0; i<largeNextButtons.length; i++) {
1210
- if (largeNextButtons[i].dataset.amplitudeSource === 'youtube') {
1211
- // do nothing
1140
+ {% comment %} PREPARED event listener for LATER use
1141
+ ----------------------------------------------------------
1142
+ var compactNextButtons = document.getElementsByClassName("compact-player-next");
1143
+ for (var i=0; i<compactNextButtons.length; i++) {
1144
+ if (compactNextButtons[i].dataset.amplitudeSource === 'youtube') {
1145
+ // do nothing for YTP (managed by plugin)
1212
1146
  } else {
1213
- if (largeNextButtons[i].id === 'compact_player_next_{{player.id}}') {
1214
- largeNextButtons[i].addEventListener('click', function(event) {
1215
- // do nothing
1147
+ if (compactNextButtons[i].id === 'compact_player_next_{{player.id}}' || compactNextButtons[i].id === 'compact_player_list_next_{{player.id}}') {
1148
+ compactNextButtons[i].addEventListener('click', function(event) {
1149
+ var atpPlayerID = this.id;
1150
+ var atpPlayerActive = atpPlayerID.split('_');
1151
+
1152
+ j1.adapter.amplitude.data.atpGlobals.activePlayerType = 'compact';
1153
+
1216
1154
  }); // END EventListener 'click'
1217
1155
  } // END if ID
1218
1156
  }
1219
1157
  } // END Next Buttons (COMPACT player)
1158
+ ----------------------------------------------------------
1159
+ {% endcomment %}
1220
1160
 
1161
+ {% comment %} PREPARED event listener for LATER use
1162
+ ----------------------------------------------------------
1221
1163
  // add listeners to all Previous Buttons found
1222
1164
  var compactPreviousButtons = document.getElementsByClassName("compact-player-previous");
1223
1165
  for (var i=0; i<compactPreviousButtons.length; i++) {
1224
1166
  if (compactPreviousButtons[i].dataset.amplitudeSource === 'youtube') {
1225
- // do nothing
1167
+ // do nothing for YTP (managed by plugin)
1226
1168
  } else {
1227
- if (compactPreviousButtons[i].id === 'compact_player_previous_{{player.id}}') {
1169
+ if (compactPreviousButtons[i].id === 'compact_player_previous_{{player.id}}' || compactPreviousButtons[i].id === 'compact_player_list_previous_{{player.id}}') {
1228
1170
  compactPreviousButtons[i].addEventListener('click', function(event) {
1229
- // do nothing
1171
+ var atpPlayerID = this.id;
1172
+ var atpPlayerActive = atpPlayerID.split('_');
1173
+
1174
+ j1.adapter.amplitude.data.atpGlobals.activePlayerType = 'compact';
1175
+
1230
1176
  }); // END EventListener 'click'
1231
1177
  } // END if ID
1232
1178
  }
1233
1179
  } // END Previous Buttons (COMPACT player)
1180
+ ----------------------------------------------------------
1181
+ {% endcomment %}
1234
1182
 
1183
+ {% comment %} PREPARED event listener for LATER use
1184
+ ----------------------------------------------------------
1235
1185
  // click on play_pause button (COMPACT player)
1236
1186
  var compactPlayerPlayPauseButton = document.getElementsByClassName('compact-player-play-pause');
1237
1187
  for (var i=0; i<compactPlayerPlayPauseButton.length; i++) {
1238
1188
  if (compactPlayerPlayPauseButton[i].dataset.amplitudeSource === 'youtube') {
1239
1189
  // do nothing (managed by plugin)
1240
1190
  } else {
1241
- var currentPlaylist = compactPlayerPlayPauseButton[i].dataset.amplitudePlaylist;
1242
- if (currentPlaylist === playList) {
1191
+ // var currentPlaylist = compactPlayerPlayPauseButton[i].dataset.amplitudePlaylist;
1192
+ // if (currentPlaylist === playListName) {
1193
+ if (compactPlayerPlayPauseButton[i].id === 'compact_player_play_pause_{{player.id}}' || compactPlayerPlayPauseButton[i].id === 'compact_player_list_play_pause_{{player.id}}') {
1243
1194
  compactPlayerPlayPauseButton[i].addEventListener('click', function(event) {
1244
- // do nothing
1245
- });
1195
+ var ytpPlayer;
1196
+ var ytpPlayerState;
1197
+ var playerState;
1198
+
1199
+ // stop active YT players
1200
+ const ytPlayers = Object.keys(j1.adapter.amplitude.data.ytPlayers);
1201
+ for (let i=0; i<ytPlayers.length; i++) {
1202
+ const playerID = ytPlayers[i];
1203
+ const playerProperties = j1.adapter.amplitude.data.ytPlayers[playerID];
1204
+ logger.debug('process player id: ' + playerID);
1205
+ ytpPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
1206
+ playerState = ytpPlayer.getPlayerState();
1207
+ ytpPlayerState = YT_PLAYER_STATE_NAMES[playerState];
1208
+
1209
+ if (ytpPlayerState === 'playing' || ytpPlayerState === 'paused' || ytpPlayerState === 'buffering') {
1210
+ logger.debug('process player id: ' + playerID + ' stopped');
1211
+ ytpPlayer.stopVideo();
1212
+ }
1213
+ }
1214
+
1215
+ // save YT player data for later use (e.g. events)
1216
+ j1.adapter.amplitude.data.activePlayer = 'atp';
1217
+ j1.adapter.amplitude.data.atpGlobals.activePlayerType = 'compact';
1218
+
1219
+ });
1246
1220
  }
1247
1221
  }
1248
1222
  } // END play_pause button (COMPACT player)
1223
+ ----------------------------------------------------------
1224
+ {% endcomment %}
1249
1225
 
1250
1226
  // click on skip forward|backward (COMPACT player)
1251
1227
  // See: https://github.com/serversideup/amplitudejs/issues/384
@@ -1255,10 +1231,14 @@ j1.adapter.amplitude = ((j1, window) => {
1255
1231
  var compactPlayerSkipForwardButtons = document.getElementsByClassName("compact-player-skip-forward");
1256
1232
  for (var i=0; i<compactPlayerSkipForwardButtons.length; i++) {
1257
1233
  if (compactPlayerSkipForwardButtons[i].dataset.amplitudeSource === 'youtube') {
1258
- // do nothing
1234
+ // do nothing for YTP (managed by plugin)
1259
1235
  } else {
1260
1236
  if (compactPlayerSkipForwardButtons[i].id === 'skip-forward_{{player.id}}') {
1261
1237
  compactPlayerSkipForwardButtons[i].addEventListener('click', function(event) {
1238
+
1239
+ // load player settings
1240
+ // playerForwardBackwardSkipSeconds = (playerSettings.forward_backward_skip_seconds === undefined) ? playerForwardBackwardSkipSeconds: playerSettings.forward_backward_skip_seconds;
1241
+
1262
1242
  const skipOffset = parseFloat(playerForwardBackwardSkipSeconds);
1263
1243
  const duration = Amplitude.getSongDuration();
1264
1244
  const currentTime = parseFloat(Amplitude.getSongPlayedSeconds());
@@ -1267,6 +1247,7 @@ j1.adapter.amplitude = ((j1, window) => {
1267
1247
  if (currentTime > 0) {
1268
1248
  Amplitude.setSongPlayedPercentage((targetTime / duration) * 100);
1269
1249
  }
1250
+
1270
1251
  }); // END EventListener 'click'
1271
1252
  } // END if ID
1272
1253
  }
@@ -1276,10 +1257,14 @@ j1.adapter.amplitude = ((j1, window) => {
1276
1257
  var compactPlayerSkipBackwardButtons = document.getElementsByClassName("compact-player-skip-backward");
1277
1258
  for (var i=0; i<compactPlayerSkipBackwardButtons.length; i++) {
1278
1259
  if (compactPlayerSkipBackwardButtons[i].dataset.amplitudeSource === 'youtube') {
1279
- // do nothing
1260
+ // do nothing for YTP (managed by plugin)
1280
1261
  } else {
1281
1262
  if (compactPlayerSkipBackwardButtons[i].id === 'skip-backward_{{player.id}}') {
1282
1263
  compactPlayerSkipBackwardButtons[i].addEventListener('click', function(event) {
1264
+
1265
+ // load player settings
1266
+ // playerForwardBackwardSkipSeconds = (playerSettings.forward_backward_skip_seconds === undefined) ? playerForwardBackwardSkipSeconds: playerSettings.forward_backward_skip_seconds;
1267
+
1283
1268
  const skipOffset = parseFloat(playerForwardBackwardSkipSeconds);
1284
1269
  const duration = Amplitude.getSongDuration();
1285
1270
  const currentTime = parseFloat(Amplitude.getSongPlayedSeconds());
@@ -1288,6 +1273,7 @@ j1.adapter.amplitude = ((j1, window) => {
1288
1273
  if (currentTime > 0) {
1289
1274
  Amplitude.setSongPlayedPercentage((targetTime / duration) * 100);
1290
1275
  }
1276
+
1291
1277
  }); // END EventListener 'click'
1292
1278
  } // END if ID
1293
1279
  }
@@ -1300,6 +1286,7 @@ j1.adapter.amplitude = ((j1, window) => {
1300
1286
  var shuffleState = (document.getElementById('compact_player_shuffle').className.includes('amplitude-shuffle-on')) ? true : false;
1301
1287
 
1302
1288
  Amplitude.setShuffle(shuffleState)
1289
+
1303
1290
  }); // END EventListener 'click'
1304
1291
  } // END PlayerShuffleButton (COMPACT player)
1305
1292
 
@@ -1310,73 +1297,112 @@ j1.adapter.amplitude = ((j1, window) => {
1310
1297
  var repeatState = (document.getElementById('compact_player_repeat').className.includes('amplitude-repeat-on')) ? true : false;
1311
1298
 
1312
1299
  Amplitude.setRepeat(repeatState)
1300
+
1313
1301
  }); // END EventListener 'click'
1314
1302
  } // END PlayerRepeatButton (COMPACT player)
1315
1303
 
1316
1304
  } // END compact player UI events
1317
1305
  {% endif %}
1318
1306
 
1307
+
1308
+ {% comment %} process UI events for all LARGE Players
1309
+ ============================================================ {% endcomment %}
1319
1310
  {% if player.id contains 'large' %}
1320
- // START large player UI events
1321
- // ---------------------------------------------------------
1311
+
1322
1312
  if (document.getElementById('{{player.id}}') !== null) {
1323
1313
  // var playlist = '{{player.id}}_yt';
1324
1314
  var playlistInfo = {{player.playlist | replace: 'nil', 'null' | replace: '=>', ':'}};
1325
1315
  var playList = playlistInfo.name;
1326
1316
 
1327
- // NOTE: listener overloads for video managed by plugin
1328
- // -------------------------------------------------------
1329
- var largetPlayerSongContainer = document.getElementsByClassName("amplitude-song-container");
1330
- for (var i=0; i<largetPlayerSongContainer.length; i++) {
1331
- if (largetPlayerSongContainer[i].dataset.amplitudeSource === 'youtube') {
1332
- // do nothing
1317
+ {% comment %} PREPARED event listener for LATER use
1318
+ ----------------------------------------------------------
1319
+ // add listeners to all SongContainers found (LARGE player)
1320
+ // -------------------------------------------------------
1321
+ var largePlayerSongContainer = document.getElementsByClassName("amplitude-song-container");
1322
+ for (var i=0; i<largePlayerSongContainer.length; i++) {
1323
+ if (largePlayerSongContainer[i].dataset.amplitudeSource === 'youtube') {
1324
+ // do nothing for YTP (managed by plugin)
1333
1325
  } else {
1334
- var currentPlaylist = largetPlayerSongContainer[i].dataset.amplitudePlaylist;
1326
+ var currentPlaylist = largePlayerSongContainer[i].dataset.amplitudePlaylist;
1335
1327
  if (currentPlaylist === playList) {
1336
- largetPlayerSongContainer[i].addEventListener('click', function(event) {
1337
- var ytpPlayer, ytpPlayerState, ytpPlayerState, playerState,
1338
- classArray, atpPlayerActive, playlist;
1328
+ // if (largePlayerSongContainer[i].id === 'large-player-play-pause_{{player.id}}' || largePlayerSongContainer[i].id === 'large-player-play-pause_{{player.id}}') {
1329
+ largePlayerSongContainer[i].addEventListener('click', function(event) {
1330
+ var ytpPlayer, ytpPlayerState, ytpPlayerState, atpPlayerState,
1331
+ playerState, classArray, atpPlayerActive, metaData,
1332
+ playlist, playlistIndex;
1339
1333
 
1340
1334
  classArray = [].slice.call(this.classList, 0);
1341
1335
  atpPlayerActive = classArray[0].split('-');
1342
1336
  playlist = this.getAttribute("data-amplitude-playlist");
1343
-
1344
- // scroll song active at index in player
1345
- if (playerAutoScrollSongElement) {
1346
- j1.adapter.amplitude.atPlayerScrollToActiveElement(playlist);
1337
+ playlistIndex = parseInt(this.getAttribute("data-amplitude-song-index"));
1338
+ metaData = Amplitude.getActiveSongMetadata();
1339
+ atpPlayerState = Amplitude.getPlayerState();
1340
+
1341
+ // stop active YT players
1342
+ // -----------------------------------------------
1343
+ const ytPlayers = Object.keys(j1.adapter.amplitude.data.ytPlayers);
1344
+ for (let i=0; i<ytPlayers.length; i++) {
1345
+ const playerID = ytPlayers[i];
1346
+ const playerProperties = j1.adapter.amplitude.data.ytPlayers[playerID];
1347
+ logger.debug('process player id: ' + playerID);
1348
+ ytpPlayer = j1.adapter.amplitude.data.ytPlayers[playerID].player;
1349
+ playerState = ytpPlayer.getPlayerState();
1350
+ ytpPlayerState = YT_PLAYER_STATE_NAMES[playerState];
1351
+
1352
+ if (ytpPlayerState === 'playing' || ytpPlayerState === 'paused' || ytpPlayerState === 'buffering') {
1353
+ logger.debug('process player id: ' + playerID + ' stopped');
1354
+ ytpPlayer.stopVideo();
1355
+ }
1347
1356
  }
1348
- });
1349
- }
1350
- }
1351
- } // END player SongContainer
1357
+
1358
+ // save YT player data for later use (e.g. events)
1359
+ // -----------------------------------------------
1360
+ j1.adapter.amplitude.data.activePlayer = 'atp';
1361
+ j1.adapter.amplitude.data.atpGlobals.activePlayerType = atpPlayerActive[3];
1362
+
1363
+ }); // END add EventListener
1364
+ } // END if currentPlaylist
1365
+ } // ENF if largePlayerSongContainer
1366
+ } // END for largePlayerSongContainer
1367
+ ----------------------------------------------------------
1368
+ {% endcomment %}
1352
1369
 
1353
1370
  // click on prev button
1354
1371
  var largePlayerPreviousButton = document.getElementById('large_player_previous');
1355
1372
  if (largePlayerPreviousButton && largePlayerPreviousButton.getAttribute("data-amplitude-source") === 'youtube') {
1356
- // do nothing (managed by plugin)
1373
+ // do nothing for YTP (managed by plugin)
1357
1374
  }
1358
1375
 
1359
- // click on play_pause button (LARGE player)
1376
+ {% comment %} PREPARED event listener for LATER use
1377
+ ----------------------------------------------------------
1378
+ // add listeners to all PlayPause Buttons found (LARGE player)
1379
+ // -------------------------------------------------------
1360
1380
  var largePlayerPlayPauseButton = document.getElementsByClassName('large-player-play-pause');
1361
1381
  for (var i=0; i<largePlayerPlayPauseButton.length; i++) {
1362
1382
  if (largePlayerPlayPauseButton[i].dataset.amplitudeSource === 'youtube') {
1363
- // do nothing (managed by YTP plugin)
1383
+ // do nothing for YTP (managed by plugin)
1364
1384
  } else {
1365
- var currentPlaylist = largePlayerPlayPauseButton[i].dataset.amplitudePlaylist;
1366
- if (currentPlaylist === playList) {
1385
+ var currentPlaylist = largePlayerPlayPauseButton[i].dataset.amplitudePlaylist;
1386
+ if (currentPlaylist === playList) {
1367
1387
  largePlayerPlayPauseButton[i].addEventListener('click', function(event) {
1368
- // do nothing
1388
+ var ytpPlayer, ytpPlayerState, playlist, metaData, playerState;
1389
+
1390
+ metaData = Amplitude.getActiveSongMetadata();
1391
+ playlist = this.getAttribute("data-amplitude-playlist");
1392
+
1369
1393
  });
1370
1394
  }
1371
1395
  }
1372
1396
  } // END play_pause button (LARGE player)
1397
+ ----------------------------------------------------------
1398
+ {% endcomment %}
1373
1399
 
1374
1400
  // add listeners to all progress bars found (LARGE player)
1375
1401
  // -------------------------------------------------------
1376
1402
  var progressBars = document.getElementsByClassName("large-player-progress");
1377
1403
  for (var i=0; i<progressBars.length; i++) {
1378
1404
  if (progressBars[i].dataset.amplitudeSource === 'youtube') {
1379
- // do nothing (managed by plugin)
1405
+ // do nothing for YTP (managed by plugin)
1380
1406
  } else {
1381
1407
  progressBars[i].addEventListener('click', function(event) {
1382
1408
  var offset = this.getBoundingClientRect();
@@ -1385,75 +1411,100 @@ j1.adapter.amplitude = ((j1, window) => {
1385
1411
  if (Amplitude.getPlayerState() === 'playing') {
1386
1412
  Amplitude.setSongPlayedPercentage((parseFloat(xpos)/parseFloat(this.offsetWidth))*100);
1387
1413
  }
1414
+
1388
1415
  }); // END EventListener 'click'
1389
1416
  }
1390
1417
  } // END for
1391
1418
 
1392
-
1393
- // click on Next|Previous Buttons (LARGE player)
1394
- // -------------------------------------------------------
1395
-
1396
- // add listeners to all Next Buttons found
1419
+ {% comment %} PREPARED event listener for LATER use
1420
+ ----------------------------------------------------------
1421
+ // add listeners to all Next Buttons found (LARGE player)
1422
+ // -------------------------------------------------------
1397
1423
  var largeNextButtons = document.getElementsByClassName("large-player-next");
1398
1424
  for (var i=0; i<largeNextButtons.length; i++) {
1399
1425
  if (largeNextButtons[i].dataset.amplitudeSource === 'youtube') {
1400
- // do nothing (managed by plugin)
1426
+ // do nothing for YTP (managed by plugin)
1401
1427
  } else {
1402
1428
  if (largeNextButtons[i].id === 'large_player_next_{{player.id}}') {
1403
1429
  largeNextButtons[i].addEventListener('click', function(event) {
1404
- var atpPlayerID = this.id;
1405
- var atpPlayerActive = atpPlayerID.split('_');
1406
- var playlist = this.getAttribute("data-amplitude-playlist");
1407
-
1408
- // scroll song active at index in player
1409
- if (playerAutoScrollSongElement) {
1410
- j1.adapter.amplitude.atPlayerScrollToActiveElement(playlist);
1411
- }
1430
+ var atpPlayerID, atpPlayerActive, metaData, playlist;
1431
+
1432
+ atpPlayerID = this.id;
1433
+ atpPlayerActive = atpPlayerID.split('_');
1434
+ playlist = this.getAttribute("data-amplitude-playlist");
1435
+ metaData = Amplitude.getActiveSongMetadata();
1412
1436
 
1413
- // save YT player data for later use (e.g. events)
1414
- j1.adapter.amplitude.data.activePlayer = 'atp';
1415
- j1.adapter.amplitude.data.atpGlobals.activePlayerType = atpPlayerActive[0];
1416
1437
  }); // END EventListener 'click'
1417
- } // END if ID
1418
- }
1438
+ } // END addEventListener
1439
+ } // END if largeNextButtons
1419
1440
  } // END for Next Buttons
1441
+ ----------------------------------------------------------
1442
+ {% endcomment %}
1420
1443
 
1444
+ {% comment %} PREPARED event listener for LATER use
1445
+ ----------------------------------------------------------
1421
1446
  // add listeners to all Previous Buttons found
1447
+ // -------------------------------------------------------
1422
1448
  var largePreviousButtons = document.getElementsByClassName("large-player-previous");
1423
1449
  for (var i=0; i<largePreviousButtons.length; i++) {
1424
1450
  if (largePreviousButtons[i].dataset.amplitudeSource === 'youtube') {
1425
- // do nothing (managed by plugin)
1451
+ // do nothing for YTP (managed by plugin)
1426
1452
  } else {
1427
1453
  if (largePreviousButtons[i].id === 'large_player_previous_{{player.id}}') {
1428
1454
  largePreviousButtons[i].addEventListener('click', function(event) {
1429
- var atpPlayerID = this.id;
1430
- var atpPlayerActive = atpPlayerID.split('_');
1431
- var playlist = this.getAttribute("data-amplitude-playlist");
1455
+ var atpPlayerID, atpPlayerActive, metaData, playlist;
1456
+
1457
+ atpPlayerID = this.id;
1458
+ atpPlayerActive = atpPlayerID.split('_');
1459
+ playlist = this.getAttribute("data-amplitude-playlist");
1460
+ metaData = Amplitude.getActiveSongMetadata();
1461
+
1462
+ // update song rating in screen controls
1463
+ var largePlayerSongAudioRating = document.getElementsByClassName("audio-rating-screen-controls");
1464
+ if (largePlayerSongAudioRating.length) {
1465
+ for (var i=0; i<largePlayerSongAudioRating.length; i++) {
1466
+ var currentPlaylist = largePlayerSongAudioRating[i].dataset.amplitudePlaylist;
1467
+ if (currentPlaylist === playlist) {
1468
+ if (metaData.rating) {
1469
+ var trackID = metaData.index + 1;
1470
+ logger.debug(`UPDATE song rating on updatMetaContainers for trackID|playlist at: ${trackID}|${playlist} with a value of: ${metaData.rating}`);
1471
+ largePlayerSongAudioRating[i].innerHTML = '<img src="/assets/image/pattern/rating/scalable/' + metaData.rating + '-star.svg"' + 'alt="song rating">';
1472
+ } else {
1473
+ largePlayerSongAudioRating[i].innerHTML = '';
1474
+ }
1475
+ }
1476
+ }
1477
+ } // END if largePlayerSongAudioRating
1432
1478
 
1433
1479
  // scroll song active at index in player
1434
1480
  if (playerAutoScrollSongElement) {
1435
- j1.adapter.amplitude.atPlayerScrollToActiveElement(playlist);
1481
+ j1.adapter.amplitude.atPlayerScrollToActiveElement(Amplitude.getActiveSongMetadata());
1482
+ }
1483
+
1484
+ // scroll song active at index in player
1485
+ if (playerAutoScrollSongElement) {
1486
+ j1.adapter.amplitude.atPlayerScrollToActiveElement(Amplitude.getActiveSongMetadata());
1436
1487
  }
1437
1488
 
1438
1489
  // save YT player data for later use (e.g. events)
1439
1490
  j1.adapter.amplitude.data.activePlayer = 'atp';
1440
1491
  j1.adapter.amplitude.data.atpGlobals.activePlayerType = atpPlayerActive[0];
1441
- }); // END EventListener 'click'
1442
- } // END if ID
1443
- }
1444
- } // END for Previous Buttons
1445
1492
 
1493
+ }); // END addEventListener
1494
+ } // END if largePreviousButtons
1495
+ } // END if largePreviousButtons
1496
+ } // END for Previous Buttons
1497
+ ----------------------------------------------------------
1498
+ {% endcomment %}
1446
1499
 
1447
- // click on skip forward|backward (large player)
1500
+ // add listeners to all SkipForward Buttons found
1448
1501
  // See: https://github.com/serversideup/amplitudejs/issues/384
1449
1502
  // -------------------------------------------------------
1450
-
1451
- // add listeners to all SkipForwardButtons found
1452
1503
  var largePlayerSkipForwardButtons = document.getElementsByClassName("large-player-skip-forward");
1453
1504
  for (var i=0; i<largePlayerSkipForwardButtons.length; i++) {
1454
1505
  if (largePlayerSkipForwardButtons[i].id === 'skip-forward_{{player.id}}') {
1455
1506
  if (largePlayerSkipForwardButtons[i].dataset.amplitudeSource === 'youtube') {
1456
- // do nothing (managed by plugin)
1507
+ // do nothing for YTP (managed by plugin)
1457
1508
  } else {
1458
1509
  largePlayerSkipForwardButtons[i].addEventListener('click', function(event) {
1459
1510
  const skipOffset = parseFloat(playerForwardBackwardSkipSeconds);
@@ -1462,19 +1513,21 @@ j1.adapter.amplitude = ((j1, window) => {
1462
1513
  const targetTime = parseFloat(currentTime + skipOffset);
1463
1514
 
1464
1515
  if (currentTime > 0) {
1516
+ logger.debug(`SKIP forward on Button skipForward for ${skipOffset} seconds`);
1465
1517
  Amplitude.setSongPlayedPercentage((targetTime / duration) * 100);
1466
1518
  }
1467
- }); // END EventListener 'click'
1468
- } // END else
1469
- } // END if ID
1519
+ }); // END addEventListener
1520
+ } // END largePlayerSkipForwardButtons
1521
+ } // END if largePlayerSkipForwardButtons
1470
1522
  } // END for SkipForwardButtons
1471
1523
 
1472
- // add listeners to all SkipBackwardButtons found
1524
+ // add listeners to all SkipBackward Buttons found
1525
+ // -------------------------------------------------------
1473
1526
  var largePlayerSkipBackwardButtons = document.getElementsByClassName("large-player-skip-backward");
1474
1527
  for (var i=0; i<largePlayerSkipBackwardButtons.length; i++) {
1475
1528
  if (largePlayerSkipBackwardButtons[i].id === 'skip-backward_{{player.id}}') {
1476
1529
  if (largePlayerSkipBackwardButtons[i].dataset.amplitudeSource === 'youtube') {
1477
- // do nothing (managed by plugin)
1530
+ // do nothing for YTP (managed by plugin)
1478
1531
  } else {
1479
1532
  largePlayerSkipBackwardButtons[i].addEventListener('click', function(event) {
1480
1533
  const skipOffset = parseFloat(playerForwardBackwardSkipSeconds);
@@ -1483,11 +1536,12 @@ j1.adapter.amplitude = ((j1, window) => {
1483
1536
  const targetTime = parseFloat(currentTime - skipOffset);
1484
1537
 
1485
1538
  if (currentTime > 0) {
1539
+ logger.debug(`SKIP backward on Button skipForward for ${skipOffset} seconds`);
1486
1540
  Amplitude.setSongPlayedPercentage((targetTime / duration) * 100);
1487
1541
  }
1488
- }); // END EventListener 'click'
1542
+ }); // END addEventListener
1489
1543
  } // END else
1490
- } // END if ID
1544
+ } // END if largePlayerSkipBackwardButtons
1491
1545
  } // END for SkipBackwardButtons
1492
1546
 
1493
1547
  // click on shuffle button
@@ -1495,34 +1549,37 @@ j1.adapter.amplitude = ((j1, window) => {
1495
1549
  if (largePlayerShuffleButton) {
1496
1550
  largePlayerShuffleButton.addEventListener('click', function(event) {
1497
1551
  var shuffleState = (document.getElementById('large_player_shuffle').className.includes('amplitude-shuffle-on')) ? true : false;
1552
+ logger.debug(`Set shuffle state to: ${shuffleState}`);
1498
1553
  Amplitude.setShuffle(shuffleState)
1499
- }); // END EventListener 'click'
1500
- } // END largePlayerShuffleButton
1554
+ }); // END addEventListener
1555
+ } // END if largePlayerShuffleButton
1501
1556
 
1502
1557
  // click on repeat button
1503
1558
  var largePlayerRepeatButton = document.getElementById('large_player_repeat');
1504
1559
  if (largePlayerRepeatButton) {
1505
1560
  largePlayerRepeatButton.addEventListener('click', function(event) {
1506
1561
  var repeatState = (document.getElementById('large_player_repeat').className.includes('amplitude-repeat-on')) ? true : false;
1562
+ logger.debug(`Set repeat state to: ${repeatState}`);
1507
1563
  Amplitude.setRepeat(repeatState)
1508
- }); // END EventListener 'click'
1564
+ }); // END addEventListener
1509
1565
  } // END if largePlayerRepeatButton
1510
1566
 
1511
- // enable|disable scrolling on playlist (large player)
1567
+ // enable|disable PAGE scrolling on players playlist (LARGE player)
1512
1568
  // -------------------------------------------------------
1513
- if (document.getElementById('large_player_right') !== null) {
1569
+ // if (playerHoverPageScrollDisabled && document.getElementById('large_player_right') !== null) {
1570
+ if (playerHoverPageScrollDisabled) {
1514
1571
 
1515
1572
  // show|hide scrollbar in playlist
1516
1573
  // -----------------------------------------------------
1517
- var songsInPlaylist = Amplitude.getSongsInPlaylist(playListName);
1518
- if (songsInPlaylist.length <= 8) {
1574
+ const songsInPlaylist = Amplitude.getSongsInPlaylist(playListName);
1575
+ if (songsInPlaylist.length <= playerScrollerSongElementMin) {
1519
1576
  const titleListLargePlayer = document.getElementById('large_player_title_list_' + playListName);
1520
1577
  if (titleListLargePlayer !== null) {
1521
1578
  titleListLargePlayer.classList.add('hide-scrollbar');
1522
1579
  }
1523
- }
1580
+ } // END show|hide scrollbar in playlist
1524
1581
 
1525
- // scroll to player top position (large player)
1582
+ // scroll player to top position (LARGE player)
1526
1583
  //
1527
1584
  // Bootstrap grid breakpoints
1528
1585
  // SN: 576px Mobile
@@ -1538,21 +1595,21 @@ j1.adapter.amplitude = ((j1, window) => {
1538
1595
  var playlistHeader = document.getElementById("playlist_header_{{player.id}}");
1539
1596
  var scrollOffset = (window.innerWidth >= 992) ? -130 : -44;
1540
1597
 
1541
- // scroll player|playlist to top position (large player)
1542
- //
1598
+ // scroll player|playlist to top position (LARGE player)
1599
+ // NOTE: depending on WINDOW SIZE the relation changes to TOP POSITION (targetDivPosition)
1600
+ // -- ------------------------------------------------
1543
1601
  const targetDivPlayerRight = playerRight;
1544
1602
  const targetDivPositionPlayerRight = targetDivPlayerRight.offsetTop;
1545
1603
  const targetDivPlaylistHeader = playlistHeader;
1546
1604
  const targetDivPositionplaylistHeader = targetDivPlaylistHeader.offsetTop;
1547
1605
 
1548
- // NOTE: depending on WINDOW SIZE the relation changes to TOP POSITION (targetDivPosition)
1549
- //
1550
1606
  if (targetDivPositionPlayerRight > targetDivPositionplaylistHeader) {
1551
1607
  window.scrollTo(0, targetDivPositionPlayerRight + targetDivPlaylistHeader.offsetParent.firstElementChild.clientHeight + scrollOffset);
1552
1608
  } else {
1553
1609
  window.scrollTo(0, targetDivPositionplaylistHeader + scrollOffset);
1554
1610
  }
1555
- }); // END EventListener 'click' largePlayerTitleHeader
1611
+
1612
+ }); // END addEventListener
1556
1613
 
1557
1614
  var largePlayerPlaylistHeader = document.getElementById("playlist_header_{{player.id}}");
1558
1615
  largePlayerPlaylistHeader.addEventListener('click', function(event) {
@@ -1560,7 +1617,7 @@ j1.adapter.amplitude = ((j1, window) => {
1560
1617
  var playlistHeader = document.getElementById("playlist_header_{{player.id}}");
1561
1618
  var scrollOffset = (window.innerWidth >= 992) ? -130 : -44;
1562
1619
 
1563
- // scroll player|playlist to top position (large player)
1620
+ // scroll player|playlist to top position (LARGE player)
1564
1621
  //
1565
1622
  const targetDivPlayerRight = playerRight;
1566
1623
  const targetDivPositionPlayerRight = targetDivPlayerRight.offsetTop;
@@ -1575,7 +1632,7 @@ j1.adapter.amplitude = ((j1, window) => {
1575
1632
  window.scrollTo(0, targetDivPositionplaylistHeader + scrollOffset);
1576
1633
  }
1577
1634
 
1578
- }); // END EventListener 'click' largePlayerPlaylistHeader
1635
+ }); // END addEventListener
1579
1636
 
1580
1637
  // disable scrolling (if window viewport >= BS Medium and above)
1581
1638
  document.getElementById('large_player_right').addEventListener('mouseenter', function() {
@@ -1586,16 +1643,16 @@ j1.adapter.amplitude = ((j1, window) => {
1586
1643
  $('body').addClass('stop-scrolling');
1587
1644
  }
1588
1645
  }
1589
- }); // END EventListener 'mouseenter'
1646
+ }); // END addEventListener
1590
1647
 
1591
1648
  // enable scrolling
1592
1649
  document.getElementById('large_player_right').addEventListener('mouseleave', function() {
1593
1650
  if ($('body').hasClass('stop-scrolling')) {
1594
1651
  $('body').removeClass('stop-scrolling');
1595
1652
  }
1596
- }); // END EventListener 'mouseleave'
1653
+ }); // END addEventListener
1597
1654
 
1598
- } // END enable|disable scrolling on playlist
1655
+ } // END enable|disable PAGE scrolling on players playlist
1599
1656
 
1600
1657
  // set volume slider presets (for the player when exists|enabled)
1601
1658
  //
@@ -1616,14 +1673,16 @@ j1.adapter.amplitude = ((j1, window) => {
1616
1673
 
1617
1674
  } // END large player UI events
1618
1675
  {% endif %}
1676
+ {% comment %} END process UI events for all LARGE Players
1677
+ ============================================================ {% endcomment %}
1619
1678
 
1620
1679
  // ---------------------------------------------------------
1621
1680
  // START configured player features
1622
1681
 
1623
- logger.debug('\n' + 'set play next title: ' + playerPlayNextTitle);
1624
- logger.debug('\n' + 'set delay between titles: ' + playerDelayNextTitle + 'ms');
1625
- logger.debug('\n' + 'set repeat (album): ' + playerRepeat);
1626
- logger.debug('\n' + 'set shuffle (album): ' + playerShuffle);
1682
+ logger.debug('set play next title: ' + playerPlayNextTitle);
1683
+ logger.debug('set delay between titles: ' + playerDelayNextTitle + 'ms');
1684
+ logger.debug('set repeat (album): ' + playerRepeat);
1685
+ logger.debug('set shuffle (album): ' + playerShuffle);
1627
1686
 
1628
1687
  // set delay between titles (songs)
1629
1688
  Amplitude.setDelay(playerDelayNextTitle);
@@ -1637,8 +1696,8 @@ j1.adapter.amplitude = ((j1, window) => {
1637
1696
 
1638
1697
  // finished messages
1639
1698
  // ---------------------------------------------------------
1640
- logger.debug('\n' + 'current player state: ' + amplitudePlayerState);
1641
- logger.debug('\n' + 'setup player specific UI events on ID #{{player.id}}: finished');
1699
+ logger.debug('current player state: ' + amplitudePlayerState);
1700
+ logger.debug('setup player specific UI events on ID #{{player.id}}: finished');
1642
1701
 
1643
1702
  clearInterval(dependencies_met_api_initialized);
1644
1703
  } // END if apiInitialized
@@ -1658,14 +1717,14 @@ j1.adapter.amplitude = ((j1, window) => {
1658
1717
 
1659
1718
  {% endif %} {% endfor %}
1660
1719
 
1661
- logger.info('\n' + 'initialize player specific UI events: finished');
1720
+ logger.info('initialize player specific UI events: finished');
1662
1721
 
1663
1722
  _this.setState('finished');
1664
- logger.debug('\n' + 'module state: ' + _this.getState());
1665
- logger.info('\n' + 'module initialized successfully');
1723
+ logger.debug('module state: ' + _this.getState());
1724
+ logger.info('module initialized successfully');
1666
1725
 
1667
1726
  endTimeModule = Date.now();
1668
- logger.info('\n' + 'module initializing time: ' + (endTimeModule-startTimeModule) + 'ms');
1727
+ logger.info('module initializing time: ' + (endTimeModule-startTimeModule) + 'ms');
1669
1728
 
1670
1729
  clearInterval(dependencies_met_player_instances_initialized);
1671
1730
  } // END if apiInitialized
@@ -1689,7 +1748,7 @@ j1.adapter.amplitude = ((j1, window) => {
1689
1748
  // songEvents
1690
1749
  // -------------------------------------------------------------------------
1691
1750
  songEvents: (songs) => {
1692
- logger.debug('\n' + 'initializing title events for player on ID ' + '#' + playerID + ': started');
1751
+ logger.debug('initializing title events for player on ID ' + '#' + playerID + ': started');
1693
1752
 
1694
1753
  for (var i = 0; i < songs.length; i++) {
1695
1754
  // ensure that on mouseover, CSS styles don't get messed up for active songs
@@ -1717,7 +1776,7 @@ j1.adapter.amplitude = ((j1, window) => {
1717
1776
  }); // END EventListener 'click' (songlist)
1718
1777
  }
1719
1778
 
1720
- logger.debug('\n' + 'initializing title events for player on ID ' + '#' + playerID + ': finished');
1779
+ logger.debug('initializing title events for player on ID ' + '#' + playerID + ': finished');
1721
1780
  }, // END songEvents
1722
1781
 
1723
1782
  // -------------------------------------------------------------------------
@@ -1751,7 +1810,7 @@ j1.adapter.amplitude = ((j1, window) => {
1751
1810
  }
1752
1811
 
1753
1812
  if (plugin !== '' && isPluginLoaded(plugin)) {
1754
- logger.debug('\n' + 'plugin loaded: ' + plugin);
1813
+ logger.debug('plugin loaded: ' + plugin);
1755
1814
 
1756
1815
  // make sure the plugin installed only ONCE
1757
1816
  j1.adapter.amplitude.data.atpGlobals.ytpInstalled = true;
@@ -1759,30 +1818,363 @@ j1.adapter.amplitude = ((j1, window) => {
1759
1818
  }, // END pluginManager
1760
1819
 
1761
1820
  // -------------------------------------------------------------------------
1762
- // atPlayerScrollToActiveElement(activePlaylist)
1821
+ // atPlayerScrollToActiveElement(metaData)
1763
1822
  // -------------------------------------------------------------------------
1764
- atPlayerScrollToActiveElement: (activePlaylist) => {
1765
- var scrollableList, songIndex,
1766
- activeElement, activeElementOffsetTop;
1823
+ atPlayerScrollToActiveElement: (metaData) => {
1824
+ var scrollableList, songIndex, playlist,
1825
+ activeElement, activeElementOffsetTop, numSongs,
1826
+ songElementMin, playerSongElementHeigthCompact;
1767
1827
 
1768
- scrollableList = document.getElementById('large_player_title_list_' + activePlaylist);
1828
+ if (!playerAutoScrollSongElement) {
1829
+ // do nothing if playerAutoScrollSongElement is false
1830
+ return;
1831
+ }
1832
+
1833
+ songIndex = metaData.index;
1834
+ songElementMin = playerScrollerSongElementMin;
1835
+ playlist = metaData.playlist;
1836
+ scrollableList = document.getElementById('large_player_title_list_' + playlist);
1769
1837
  activeElement = scrollableList.querySelector('.amplitude-active-song-container');
1838
+ numSongs = Amplitude.getSongsInPlaylist(playlist).length;
1770
1839
 
1771
1840
  if (activeElement === null || scrollableList === null) {
1772
- // do nothing if NO scrollableList or active element found (failsafe)
1841
+ // do nothing if NO scrollableList or ACTIVE element found (failsafe)
1773
1842
  return;
1774
1843
  }
1775
1844
 
1776
- songIndex = parseInt(activeElement.getAttribute("data-amplitude-song-index"));
1777
- activeElementOffsetTop = songIndex * j1.adapter.amplitude.data.playerSongElementHeigth;
1778
- scrollableList.scrollTop = activeElementOffsetTop;
1779
-
1780
- if (songIndex === 0) {
1781
- var bla = 'puups';
1845
+ // LARGE players
1846
+ // -----------------------------------------------------------------------
1847
+ if (songIndex > 0 && numSongs >= songElementMin) {
1848
+ activeElementOffsetTop = songIndex * j1.adapter.amplitude.data.playerSongElementHeigth;
1849
+ scrollableList.scrollTop = activeElementOffsetTop;
1850
+ } else {
1851
+ // do nothing if songIndex is 0 or less than songElementMin
1852
+ return;
1782
1853
  }
1783
1854
 
1855
+ // COMPACT players (WIP)
1856
+ // -----------------------------------------------------------------------
1857
+ // playerSongElementHeigthCompact = 74.00;
1858
+ // if (songIndex > 0 && numSongs >= songElementMin) {
1859
+ // // scrollableList = document.getElementById('compact_player_title_list_' + metaData.playlist);
1860
+ // // activeElement = scrollableList.querySelector('.amplitude-active-song-container');
1861
+ // activeElementOffsetTop = (songIndex * playerSongElementHeigthCompact);
1862
+ // scrollableList.scrollTop = activeElementOffsetTop;
1863
+ // } else {
1864
+ // // do nothing if songIndex is 0 or less than songElementMin
1865
+ // return;
1866
+ // }
1867
+
1784
1868
  }, // END atPlayerScrollToActiveElement
1785
1869
 
1870
+ // -------------------------------------------------------------------------
1871
+ // atpUpdatMetaContainers(playlist, rating)
1872
+ //
1873
+ // update song rating in playlist-screen|meta-container
1874
+ // for all (compact|large) players
1875
+ // -------------------------------------------------------------------------
1876
+ atpUpdatMetaContainers: (metaData) => {
1877
+ var activePlayist = metaData.playlist;
1878
+ var rating = parseInt(metaData.rating);
1879
+ var trackID = metaData.index + 1;
1880
+ const notRequiredForATP = true
1881
+
1882
+ logger.debug(`UPDATE metadata on atpUpdatMetaContainers for trackID|playlist at: ${trackID}|${activePlayist}`);
1883
+
1884
+ // properties automatically set by AT API
1885
+ if (requiredForATP) {
1886
+ // update SONG NAME in meta-containers
1887
+ var songName = document.getElementsByClassName("song-name");
1888
+ if (songName.length) {
1889
+ for (var i=0; i<songName.length; i++) {
1890
+ var currentPlaylist = songName[i].dataset.amplitudePlaylist;
1891
+ if (currentPlaylist === activePlayist) {
1892
+ songName[i].innerHTML = metaData.name;
1893
+ }
1894
+ }
1895
+ }
1896
+ }
1897
+
1898
+ // properties automatically set by AT API
1899
+ if (requiredForATP) {
1900
+ // update SONG ARTIST name in meta-containers
1901
+ var artistName = document.getElementsByClassName("artist");
1902
+ if (artistName.length) {
1903
+ for (var i=0; i<artistName.length; i++) {
1904
+ var currentPlaylist = songName[i].dataset.amplitudePlaylist;
1905
+ if (currentPlaylist === activePlayist) {
1906
+ artistName[i].innerHTML = metaData.artist;
1907
+ }
1908
+ }
1909
+ }
1910
+ }
1911
+
1912
+ // properties automatically set by AT API
1913
+ if (requiredForATP) {
1914
+ // update SONG ALBUM name in meta-containers
1915
+ var albumName = document.getElementsByClassName("album");
1916
+ if (albumName.length) {
1917
+ for (var i=0; i<albumName.length; i++) {
1918
+ var currentPlaylist = albumName[i].dataset.amplitudePlaylist;
1919
+ if (currentPlaylist === activePlayist) {
1920
+ albumName[i].innerHTML = metaData.album;
1921
+ }
1922
+ }
1923
+ }
1924
+ }
1925
+
1926
+ // update SONG RATING in screen controls
1927
+ var screenControlRatingElements = document.getElementsByClassName('audio-rating-screen-controls');
1928
+ if (rating) {
1929
+ for (let i=0; i<screenControlRatingElements.length; i++) {
1930
+ var ratingElement = screenControlRatingElements[i];
1931
+ if (ratingElement.dataset.amplitudePlaylist === activePlayist && ratingElement.classList.contains('audio-rating-screen-controls')) {
1932
+ ratingElement.innerHTML = '<img src="/assets/image/pattern/rating/scalable/' + rating + '-star.svg"' + 'alt="song rating">';
1933
+ }
1934
+ }
1935
+ }
1936
+
1937
+ // update SONG INFO in screen controls
1938
+ var songAudioInfo = document.getElementsByClassName("audio-info-link-screen-controls");
1939
+ if (songAudioInfo.length) {
1940
+ for (var i=0; i<songAudioInfo.length; i++) {
1941
+ var currentPlaylist = songAudioInfo[i].dataset.amplitudePlaylist;
1942
+ if (currentPlaylist === activePlayist) {
1943
+ if (metaData.audio_info) {
1944
+ songAudioInfo[i].setAttribute("href", metaData.audio_info);
1945
+ }
1946
+ }
1947
+ }
1948
+ } // END if songAudioInfo
1949
+
1950
+ }, // END atpUpdatMetaContainers
1951
+
1952
+ // -------------------------------------------------------------------------
1953
+ // atpStopParallelActivePlayers(players)
1954
+ //
1955
+ // stop active YT players (running in parallel to AT players)
1956
+ // -------------------------------------------------------------------------
1957
+ atpStopParallelActivePlayers: (players) => {
1958
+ var ytPlayer, playerState, ytPlayerState;
1959
+
1960
+ const ytPlayers = Object.keys(players);
1961
+ for (var i=0; i<ytPlayers.length; i++) {
1962
+ const ytPlayerID = ytPlayers[i];
1963
+
1964
+ ytPlayer = players[ytPlayerID].player;
1965
+ playerState = ytPlayer.getPlayerState();
1966
+ ytPlayerState = YT_PLAYER_STATE_NAMES[playerState];
1967
+
1968
+ // stop YT players running in parallel
1969
+ // ---------------------------------------------------------------------
1970
+ if (ytPlayerState === 'playing' || ytPlayerState === 'paused' || ytPlayerState === 'buffering') {
1971
+ logger.debug(`STOP YT player on id: ${playerID}`);
1972
+ ytPlayer.stopVideo();
1973
+ }
1974
+
1975
+ // toggle PlayPause buttons playing => puased
1976
+ // ---------------------------------------------------------------------
1977
+ var ytpButtonPlayerPlayPause = document.getElementsByClassName("large-player-play-pause-" + ytPlayerID);
1978
+ for (var j=0; j<ytpButtonPlayerPlayPause.length; j++) {
1979
+
1980
+ var htmlElement = ytpButtonPlayerPlayPause[j];
1981
+ if (htmlElement.dataset.amplitudeSource === 'youtube') {
1982
+ if (htmlElement.classList.contains('amplitude-playing')) {
1983
+ htmlElement.classList.remove('amplitude-playing');
1984
+ htmlElement.classList.add('amplitude-paused');
1985
+ }
1986
+ }
1987
+ } // END for ytpButtonPlayerPlayPause
1988
+
1989
+ } // END for ytPlayers
1990
+ }, // END atpStopParallelActivePlayers
1991
+
1992
+ // -------------------------------------------------------------------------
1993
+ // atpProcessAudioStartPosition()
1994
+ //
1995
+ // process audio for configured START position
1996
+ // -------------------------------------------------------------------------
1997
+ atpProcessAudioStartPosition: () => {
1998
+ var songMetaData, songIndex, playList,
1999
+ songStartSec, songStartTS, trackID;
2000
+
2001
+ songMetaData = Amplitude.getActiveSongMetadata();
2002
+ songIndex = songMetaData.index;
2003
+ songStartTS = songMetaData.start;
2004
+ songStartSec = _this.timestamp2seconds(songStartTS);
2005
+ playList = Amplitude.getActivePlaylist();
2006
+ trackID = songIndex + 1;
2007
+
2008
+ if (!songStartSec) {
2009
+ return;
2010
+ }
2011
+
2012
+ var checkIsFading = setInterval (() => {
2013
+ if (!isFadingIn) {
2014
+ var currentAudioTime = Amplitude.getSongPlayedSeconds();
2015
+ if (songStartSec && currentAudioTime <= songStartSec) {
2016
+ var songDurationSec = _this.timestamp2seconds(songMetaData.duration);
2017
+
2018
+ // seek audio to configured START position
2019
+ // NOTE: use setSongPlayedPercentage for seeking to NOT
2020
+ // generation any addition state changes like stopped
2021
+ // or playing
2022
+ logger.debug('seek audio in on playlist: ' + playList + ' at|to trackID|timestamp: ' + trackID + '|' + songStartTS);
2023
+ Amplitude.setSongPlayedPercentage((songStartSec / songDurationSec) * 100);
2024
+
2025
+ // fade-in audio (if enabled)
2026
+ var fadeAudioIn = (songMetaData.audio_fade_in === 'true') ? true : false;
2027
+ if (fadeAudioIn) {
2028
+ logger.debug('faden audio in on playlist: ' + playList + ' at|to trackID|timestamp: ' + trackID + '|' + songStartTS);
2029
+ atpFadeInAudio({ playerID: playerID });
2030
+ } // END if fadeAudio
2031
+
2032
+ } // END if songStartSec
2033
+
2034
+ clearInterval(checkIsFading);
2035
+ }
2036
+ }, 100); // END checkIsFading
2037
+ }, // END atpProcessAudioStartPosition
2038
+
2039
+ // -------------------------------------------------------------------------
2040
+ // atpProcessAudioEndPosition()
2041
+ //
2042
+ // process audio for configured END position
2043
+ // -------------------------------------------------------------------------
2044
+ atpProcessAudioEndPosition: () => {
2045
+ var songMetaData, songIndex, playList,
2046
+ songStartSec, songStartTS, songEndSec, songEndTS,
2047
+ trackID;
2048
+
2049
+ songMetaData = Amplitude.getActiveSongMetadata();
2050
+ songIndex = songMetaData.index;
2051
+ songStartTS = songMetaData.start;
2052
+ songStartSec = _this.timestamp2seconds(songStartTS);
2053
+ songEndTS = songMetaData.end;
2054
+ songEndSec = _this.timestamp2seconds(songEndTS);
2055
+ playList = Amplitude.getActivePlaylist();
2056
+ trackID = songIndex + 1;
2057
+
2058
+ if (songEndSec > songStartSec) {
2059
+ var checkIsOnVideoEnd = setInterval(() => {
2060
+ if (!isFadingOut) {
2061
+ var currentAudioTime = Amplitude.getSongPlayedSeconds();
2062
+ if (currentAudioTime >= songEndSec) {
2063
+ songMetaData = Amplitude.getActiveSongMetadata();
2064
+ songIndex = songMetaData.index;
2065
+ trackID = songIndex + 1;
2066
+
2067
+ // seek audio out to END position
2068
+ // NOTE:
2069
+ // ---------------------------------------------------------------
2070
+ // use setSongPlayedPercentage for seeking to NOT
2071
+ // generation any addition state changes like stopped
2072
+ // or playing
2073
+ logger.debug('seek audio to end on playlist: ' + playList + ' at trackID|timestamp: ' + trackID + '|' + songEndTS);
2074
+ Amplitude.setSongPlayedPercentage(99.99);
2075
+
2076
+ // fade-out audio (if enabled)
2077
+ var fadeAudioOut = (songMetaData.audio_fade_out === 'true') ? true : false;
2078
+ if (fadeAudioOut) {
2079
+ logger.debug('fade audio out on playlist: ' + playList + ' at|to trackID|timestamp: ' + trackID + '|' + songEndTS);
2080
+ atpFadeAudioOut({ playerID: playerID });
2081
+ } // END if fadeAudio
2082
+
2083
+ clearInterval(checkIsOnVideoEnd);
2084
+ } // END if currentAudioTime
2085
+ } // END if !isFading
2086
+ }, 100); // END checkIsOnVideoEnd
2087
+ } // END if songEndSec
2088
+
2089
+ }, // END atpProcessAudioEndPosition
2090
+
2091
+ // -------------------------------------------------------------------------
2092
+ // setSongActive(currentPlayList, currentIndex)
2093
+ //
2094
+ // set song active at index in playlist
2095
+ // -------------------------------------------------------------------------
2096
+ setSongActive: (currentPlayList, currentIndex) => {
2097
+ var playlist, songContainers, songIndex;
2098
+
2099
+ songIndex = currentIndex;
2100
+
2101
+ // clear ALL active song containers
2102
+ // -------------------------------------------------------------------------
2103
+ songContainers = document.getElementsByClassName("amplitude-song-container");
2104
+ for (var i=0; i<songContainers.length; i++) {
2105
+ songContainers[i].classList.remove("amplitude-active-song-container");
2106
+ }
2107
+
2108
+ // find current song container and activate the element
2109
+ // -------------------------------------------------------------------------
2110
+ songContainers = document.querySelectorAll('.amplitude-song-container[data-amplitude-song-index="' + songIndex + '"]');
2111
+ for (var i=0; i<songContainers.length; i++) {
2112
+ if (songContainers[i].hasAttribute("data-amplitude-playlist")) {
2113
+ playlist = songContainers[i].getAttribute("data-amplitude-playlist");
2114
+ if (playlist === currentPlayList) {
2115
+ songContainers[i].classList.add("amplitude-active-song-container");
2116
+ }
2117
+ }
2118
+ }
2119
+
2120
+ }, // END setSongActive
2121
+
2122
+ // -------------------------------------------------------------------------
2123
+ // timestamp2seconds(timestamp)
2124
+ //
2125
+ // converts a timestamp of hh:mm:ss into seconds
2126
+ // -------------------------------------------------------------------------
2127
+ // TODO:
2128
+ // Add support for timestamp w/o hours like mm:ss
2129
+ // -------------------------------------------------------------------------
2130
+ timestamp2seconds: (timestamp) => {
2131
+ // split timestamp
2132
+ const parts = timestamp.split(':');
2133
+
2134
+ // check timestamp format
2135
+ if (parts.length !== 3) {
2136
+ // return "invalid timestamp";
2137
+ return false;
2138
+ }
2139
+
2140
+ // convert parts to integers
2141
+ const hours = parseInt(parts[0], 10);
2142
+ const minutes = parseInt(parts[1], 10);
2143
+ const seconds = parseInt(parts[2], 10);
2144
+
2145
+ // check valid timestamp values
2146
+ if (isNaN(hours) || isNaN(minutes) || isNaN(seconds) ||
2147
+ hours < 0 || hours > 23 ||
2148
+ minutes < 0 || minutes > 59 ||
2149
+ seconds < 0 || seconds > 59) {
2150
+ return "invalid timestamp";
2151
+ }
2152
+
2153
+ const totalSeconds = (hours * 3600) + (minutes * 60) + seconds;
2154
+
2155
+ return totalSeconds;
2156
+ }, // END timestamp2seconds
2157
+
2158
+ // -------------------------------------------------------------------------
2159
+ // seconds2timestamp(seconds)
2160
+ //
2161
+ // converts seconds into a timestamp of hh:mm:ss
2162
+ // -------------------------------------------------------------------------
2163
+ seconds2timestamp: (seconds) => {
2164
+ if (isNaN(seconds)) {
2165
+ return false;
2166
+ }
2167
+
2168
+ const hours = Math.floor(seconds / 3600);
2169
+ const minutes = Math.floor((seconds % 3600) / 60);
2170
+ const remainSeconds = seconds % 60;
2171
+ const tsHours = hours.toString().padStart(2, '0');
2172
+ const tsMinutes = minutes.toString().padStart(2, '0');
2173
+ const tsSeconds = remainSeconds.toString().padStart(2, '0');
2174
+
2175
+ return `${tsHours}:${tsMinutes}:${tsSeconds}`;
2176
+ }, // END seconds2timestamp
2177
+
1786
2178
  // -------------------------------------------------------------------------
1787
2179
  // messageHandler()
1788
2180
  // manage messages send from other J1 modules
@@ -1790,7 +2182,7 @@ j1.adapter.amplitude = ((j1, window) => {
1790
2182
  messageHandler: (sender, message) => {
1791
2183
  var json_message = JSON.stringify(message, undefined, 2);
1792
2184
 
1793
- logText = '\n' + 'received message from ' + sender + ': ' + json_message;
2185
+ logText = 'received message from ' + sender + ': ' + json_message;
1794
2186
  logger.debug(logText);
1795
2187
 
1796
2188
  // -----------------------------------------------------------------------
@@ -1802,7 +2194,7 @@ j1.adapter.amplitude = ((j1, window) => {
1802
2194
  // place handling of command|action here
1803
2195
  //
1804
2196
 
1805
- logger.info('\n' + message.text);
2197
+ logger.info(message.text);
1806
2198
  }
1807
2199
 
1808
2200
  //