j1-template 2024.3.14 → 2024.3.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/assets/data/amplitude.html +111 -58
  3. data/assets/data/cookieconsent.html +8 -8
  4. data/assets/data/panel.html +4 -3
  5. data/assets/data/speak2me.html +11 -11
  6. data/assets/data/translator.html +29 -29
  7. data/assets/theme/j1/adapter/js/amplitude.js +112 -88
  8. data/assets/theme/j1/adapter/js/j1.js +4 -4
  9. data/assets/theme/j1/adapter/js/masonry.js +2 -2
  10. data/assets/theme/j1/adapter/js/themes.js +42 -4
  11. data/assets/theme/j1/adapter/js/videojs.js +212 -0
  12. data/assets/theme/j1/core/css/icon-fonts/mdib.css +24 -4
  13. data/assets/theme/j1/core/css/icon-fonts/mdib.css.map +1 -1
  14. data/assets/theme/j1/core/css/icon-fonts/mdib.min.css +1 -1
  15. data/assets/theme/j1/core/css/icon-fonts/mdib.min.css.map +1 -1
  16. data/assets/theme/j1/core/css/themes/unolight/bootstrap.css +9 -6
  17. data/assets/theme/j1/core/css/themes/unolight/bootstrap.css.map +1 -1
  18. data/assets/theme/j1/core/css/themes/unolight/bootstrap.min.css +1 -1
  19. data/assets/theme/j1/core/css/themes/unolight/bootstrap.min.css.map +1 -1
  20. data/assets/theme/j1/core/js/template.js +262 -275
  21. data/assets/theme/j1/core/js/template.min.js +7 -7
  22. data/assets/theme/j1/core/js/template.min.js.map +1 -1
  23. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/amplitude.css +131 -24
  24. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/amplitude.min.css +1 -1
  25. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/compact.css +102 -76
  26. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/compact.min.css +1 -1
  27. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/large.css +109 -78
  28. data/assets/theme/j1/modules/amplitudejs/css/theme/uno/dark/player/large.min.css +1 -1
  29. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/artist.svg +78 -0
  30. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/mute.svg +52 -20
  31. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/next.svg +20 -39
  32. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/now-playing.svg +24 -38
  33. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/playlist-hide.svg +85 -0
  34. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/playlist-music.svg +85 -0
  35. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/playlist-show.svg +85 -0
  36. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/playlist.svg +85 -0
  37. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/previous.svg +18 -37
  38. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/skip-backward.svg +33 -30
  39. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/skip-forward.svg +33 -29
  40. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/small/next.svg +55 -14
  41. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/small/previous.svg +56 -14
  42. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/volume.svg +38 -21
  43. data/assets/theme/j1/modules/amplitudejs/js/amplitude.map +20 -20
  44. data/assets/theme/j1/modules/amplitudejs/js/tech/youtube_example.js +211 -0
  45. data/assets/theme/j1/modules/gemini/js/gemini.js.map +1 -1
  46. data/assets/theme/j1/modules/jquery/js/jquery.min.map +1 -1
  47. data/assets/theme/j1/modules/lightGallery/js/plugins/lg-video.js +206 -122
  48. data/assets/theme/j1/modules/videojs/assets/icons/custom-icons/next.svg +82 -0
  49. data/assets/theme/j1/modules/videojs/css/font/README.md +151 -0
  50. data/assets/theme/j1/modules/videojs/css/font/VideoJS.svg +150 -0
  51. data/assets/theme/j1/modules/videojs/css/font/video-js-cdn.css +2012 -0
  52. data/assets/theme/j1/modules/videojs/css/plugins/controls/skipbuttons.0.css +32 -0
  53. data/assets/theme/j1/modules/videojs/css/plugins/controls/skipbuttons.1.css +31 -0
  54. data/assets/theme/j1/modules/videojs/css/plugins/controls/skipbuttons.css +31 -0
  55. data/assets/theme/j1/modules/videojs/css/plugins/controls/skipbuttons.min.css +21 -0
  56. data/assets/theme/j1/modules/videojs/css/themes/uno.css +14 -3
  57. data/assets/theme/j1/modules/videojs/css/themes/uno.min.css +1 -1
  58. data/assets/theme/j1/modules/videojs/css/videojs.css +1 -0
  59. data/assets/theme/j1/modules/videojs/js/plugins/controls/autocaption/LICENSE +13 -0
  60. data/assets/theme/j1/modules/videojs/js/plugins/controls/autocaption/README.md +75 -0
  61. data/assets/theme/j1/modules/videojs/js/plugins/controls/autocaption/autocaption.js +149 -0
  62. data/assets/theme/j1/modules/videojs/js/plugins/controls/autocaption/autocaption.min.js +21 -0
  63. data/assets/theme/j1/modules/videojs/js/plugins/controls/hotkeys/README.md +76 -30
  64. data/assets/theme/j1/modules/videojs/js/plugins/controls/hotkeys/hotkeys.js +64 -53
  65. data/assets/theme/j1/modules/videojs/js/plugins/controls/hotkeys/hotkeys.min.js +1 -1
  66. data/assets/theme/j1/modules/videojs/js/plugins/controls/skipbuttons/README.md +133 -0
  67. data/assets/theme/j1/modules/videojs/js/plugins/controls/skipbuttons/skipbuttons.js +137 -0
  68. data/assets/theme/j1/modules/videojs/js/plugins/controls/skipbuttons/skipbuttons.min.js +21 -0
  69. data/assets/theme/j1/modules/videojs/js/plugins/controls/zoom/zoom.js +15 -12
  70. data/assets/theme/j1/modules/videojs/js/plugins/players/dm/dailymotion.js +2 -2
  71. data/assets/theme/j1/modules/videojs/js/plugins/players/yt/youtube.js +43 -16
  72. data/lib/j1/patches/rubygems/eventmachine-1.2.7-x64-mingw32/lib/3.3/fastfilereaderext.so +0 -0
  73. data/lib/j1/patches/rubygems/eventmachine-1.2.7-x64-mingw32/lib/3.3/rubyeventmachine.so +0 -0
  74. data/lib/j1/patches/rubygems/eventmachine-1.2.7-x64-mingw32/lib/3.4/fastfilereaderext.so +0 -0
  75. data/lib/j1/patches/rubygems/eventmachine-1.2.7-x64-mingw32/lib/3.4/rubyeventmachine.so +0 -0
  76. data/lib/j1/version.rb +1 -1
  77. data/lib/j1_app/j1_auth_manager/config.rb +0 -4
  78. data/lib/starter_web/Gemfile +45 -22
  79. data/lib/starter_web/README.md +5 -5
  80. data/lib/starter_web/_config.yml +4 -6
  81. data/lib/starter_web/_data/modules/amplitude.yml +67 -37
  82. data/lib/starter_web/_data/modules/defaults/amplitude.yml +1 -0
  83. data/lib/starter_web/_data/modules/defaults/gallery.yml +42 -0
  84. data/lib/starter_web/_data/modules/defaults/videojs.yml +107 -0
  85. data/lib/starter_web/_data/modules/gallery.yml +30 -14
  86. data/lib/starter_web/_data/modules/lazyLoader.yml +8 -8
  87. data/lib/starter_web/_data/modules/masonry.yml +15 -0
  88. data/lib/starter_web/_data/modules/masterslider.yml +6 -6
  89. data/lib/starter_web/_data/modules/videojs.yml +57 -0
  90. data/lib/starter_web/_data/resources.yml +9 -26
  91. data/lib/starter_web/_data/templates/feed.xml +1 -1
  92. data/lib/starter_web/_includes/tables/jekyll_variables.asciidoc +1 -0
  93. data/lib/starter_web/_plugins/asciidoctor/carousel-block.rb +2 -1
  94. data/lib/starter_web/_plugins/asciidoctor/dailymotion-block.rb +4 -1
  95. data/lib/starter_web/_plugins/asciidoctor/lightbox-block.rb +1 -1
  96. data/lib/starter_web/_plugins/asciidoctor/masterslider-block.rb +1 -1
  97. data/lib/starter_web/_plugins/asciidoctor/slick-block.rb +2 -1
  98. data/lib/starter_web/_plugins/asciidoctor/videojs-block.rb +145 -24
  99. data/lib/starter_web/_plugins/asciidoctor/vimeo-block.rb +4 -1
  100. data/lib/starter_web/_plugins/asciidoctor/wistia-block.rb +313 -0
  101. data/lib/starter_web/_plugins/asciidoctor/youtube-block.rb +192 -17
  102. data/lib/starter_web/_plugins/index/lunr.rb +1 -1
  103. data/lib/starter_web/assets/audio/cover/spontanorama/spontanorama.jpg +0 -0
  104. data/lib/starter_web/assets/audio/cover/spontanorama/src/spontanorama.png +0 -0
  105. data/lib/starter_web/assets/audio/cover/spontanorama/src/spontanorama.psd +0 -0
  106. data/lib/starter_web/package.json +1 -1
  107. data/lib/starter_web/pages/public/amplitude_yt_tester.adoc +20 -7
  108. data/lib/starter_web/pages/public/manuals/integrations/amplitudejs/amplitudejs-api.adoc +1 -1
  109. data/lib/starter_web/pages/public/manuals/integrations/videojs/youtube-api.adoc +1638 -0
  110. data/lib/starter_web/pages/public/tools/previewer/preview_bootstrap_theme.adoc +5 -6
  111. data/lib/starter_web/pages/public/tools/previewer/preview_videojs.adoc +203 -0
  112. data/lib/starter_web/pages/public/tour/asciidoc_extensions.adoc +1 -1
  113. data/lib/starter_web/pages/public/tour/bootstrap_themes.adoc +1 -1
  114. data/lib/starter_web/pages/public/tour/highlghter_rouge.adoc +1 -1
  115. data/lib/starter_web/pages/public/tour/modal_extentions.adoc +1 -1
  116. data/lib/starter_web/pages/public/tour/play_audio.adoc +30 -29
  117. data/lib/starter_web/pages/public/tour/play_video.adoc +65 -39
  118. data/lib/starter_web/pages/public/tour/present_images.adoc +17 -16
  119. data/lib/starter_web/pages/public/tour/quicksearch.adoc +1 -1
  120. data/lib/starter_web/pages/public/tour/responsive_tables.adoc +1 -1
  121. data/lib/starter_web/pages/public/tour/typography.adoc +1 -1
  122. metadata +37 -20
  123. data/assets/data/amplitude.28.html +0 -887
  124. data/assets/data/amplitude.29.html +0 -923
  125. data/assets/theme/j1/adapter/js/amplitude.23.js +0 -1165
  126. data/assets/theme/j1/adapter/js/amplitude.24.js +0 -1164
  127. data/assets/theme/j1/adapter/js/amplitude.25.js +0 -1268
  128. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/_pause.svg +0 -19
  129. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/_play.svg +0 -18
  130. data/assets/theme/j1/modules/amplitudejs/icons/player/dark/show-playlist.svg +0 -15
  131. data/assets/theme/j1/modules/jqueryScrollbar/LICENSE +0 -20
  132. data/assets/theme/j1/modules/jqueryScrollbar/README.md +0 -28
  133. data/assets/theme/j1/modules/jqueryScrollbar/css/scrollbar.css +0 -939
  134. data/assets/theme/j1/modules/jqueryScrollbar/css/scrollbar.min.css +0 -20
  135. data/assets/theme/j1/modules/jqueryScrollbar/js/scrollbar.js +0 -851
  136. data/assets/theme/j1/modules/jqueryScrollbar/js/scrollbar.min.js +0 -36
  137. data/assets/theme/j1/modules/jqueryScrollbar/sass/scrollbar.scss +0 -806
  138. data/assets/theme/j1/modules/lightGallery/js/plugins/lg-video.0.js +0 -794
  139. data/lib/starter_web/_data/modules/lazyLoader.0.yml +0 -118
@@ -0,0 +1,313 @@
1
+ # ------------------------------------------------------------------------------
2
+ # ~/_plugins/asciidoctor-extensions/wistia-block.rb
3
+ # Asciidoctor extension for Vimeo Video
4
+ #
5
+ # Product/Info:
6
+ # https://jekyll.one
7
+ #
8
+ # Copyright (C) 2023, 2024 Juergen Adams
9
+ #
10
+ # J1 Template is licensed under the MIT License.
11
+ # See: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE
12
+ # ------------------------------------------------------------------------------
13
+ require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
14
+ include Asciidoctor
15
+
16
+ # ------------------------------------------------------------------------------
17
+ # A block macro that embeds a video from the Vimeo platform
18
+ # into the output document
19
+ #
20
+ # Usage:
21
+ #
22
+ # wistia::video_id[theme="vjs_theme_name" role="CSS classes"]
23
+ #
24
+ # Example:
25
+ #
26
+ # .Video title
27
+ # wistia::179528528[theme="city" role="mt-5 mb-5"]
28
+ #
29
+ # ------------------------------------------------------------------------------
30
+ # See:
31
+ # https://www.tutorialspoint.com/creating-a-responsive-video-player-using-video-js
32
+ # ------------------------------------------------------------------------------
33
+
34
+ Asciidoctor::Extensions.register do
35
+
36
+ class WistiaBlockMacro < Extensions::BlockMacroProcessor
37
+ use_dsl
38
+
39
+ named :wistia
40
+ name_positional_attributes 'caption', 'start','poster', 'theme', 'custom_buttons', 'role'
41
+ default_attrs 'caption' => 'true',
42
+ 'start' => '00:00:00',
43
+ 'poster' => '/assets/videos/poster/wistia/wistia-blue.jpg',
44
+ 'theme' => 'uno',
45
+ 'custom_buttons' => true,
46
+ 'role' => 'mt-3 mb-3'
47
+
48
+ def process parent, target, attributes
49
+
50
+ # ========================================================================
51
+ # load VideoJS configuration data
52
+ # ------------------------------------------------------------------------
53
+ # NOTE:
54
+ # Settings folder _data is NOT available in the website
55
+ #-------------------------------------------------------------------------
56
+ current_path = File.expand_path(Dir.getwd)
57
+ default_config_path = File.join(current_path, '/_data/modules/defaults')
58
+ user_config_path = File.join(current_path, '/_data/modules')
59
+
60
+ videojs_config_file_name = 'videojs.yml'
61
+ videojs_default_config_file = File.join(default_config_path, videojs_config_file_name)
62
+ videojs_user_config_file = File.join(user_config_path, videojs_config_file_name)
63
+
64
+ videojsDefaultSettings = YAML::load(File.open(videojs_default_config_file))
65
+ videojsUserSettings = YAML::load(File.open(videojs_user_config_file))
66
+ videojsDefaultSettingsJson = videojsDefaultSettings.to_json;
67
+ videojsUserSettingsJson = videojsUserSettings.to_json;
68
+
69
+ # ========================================================================
70
+ # set plugin specific data
71
+ # ------------------------------------------------------------------------
72
+ #
73
+ chars = [('a'..'z'), ('A'..'Z'), ('0'..'9')].map(&:to_a).flatten
74
+ video_id = (0...11).map { chars[rand(chars.length)] }.join
75
+
76
+ title_html = (attributes.has_key? 'title') ? %(<div class="video-title">#{attributes['title']}</div>\n) : nil
77
+ poster_image = (poster = attributes['poster']) ? %(#{poster}) : nil
78
+ theme_name = (theme = attributes['theme']) ? %(#{theme}) : nil
79
+ caption_enabled = (caption = attributes['caption']) ? true : false
80
+ custom_buttons = (custom_buttons = attributes['custom_buttons']) ? %(#{custom_buttons}) : nil
81
+ poster_attr = %(poster="#{poster_image}")
82
+
83
+ if attributes['poster'] == 'auto'
84
+ poster_attr = ''
85
+ end
86
+
87
+ html = %(
88
+ <div class="wistia-player #{attributes['role']}">
89
+ #{title_html}
90
+ <video
91
+ id="#{video_id}"
92
+ class="video-js vjs-theme-#{theme_name}"
93
+ width="640" height="360"
94
+ #{poster_attr}
95
+ aria-label="#{attributes['title']}"
96
+ data-setup='{
97
+ "fluid" : true,
98
+ "techOrder": [
99
+ "wistia", "html5"
100
+ ],
101
+ "sources": [{
102
+ "type": "video/wistia",
103
+ "src": "#{target}"
104
+ }],
105
+ "wistia": {
106
+ "playback_css_class": "wistia_embed wistia_async_29b0fbf547",
107
+ "autoplay": false
108
+ },
109
+ "controlBar": {
110
+ "pictureInPictureToggle": false,
111
+ "volumePanel": {
112
+ "inline": false
113
+ }
114
+ }
115
+ }'
116
+ > </video>
117
+ </div>
118
+
119
+ <script>
120
+ $(function() {
121
+
122
+ // =================================================================
123
+ // take over VideoJS configuration data (JSON data from Ruby)
124
+ // -----------------------------------------------------------------
125
+ var videojsDefaultConfigJson = '#{videojsDefaultSettingsJson}';
126
+ var videojsUserConfigJson = '#{videojsUserSettingsJson}';
127
+
128
+ // =================================================================
129
+ // create config objects from JSON data
130
+ // -----------------------------------------------------------------
131
+ var videojsDefaultSettings = JSON.parse(videojsDefaultConfigJson);
132
+ var videojsUserSettings = JSON.parse(videojsUserConfigJson);
133
+
134
+ // merge config objects (jQuery)
135
+ var videojsConfig = $.extend(true, {}, videojsDefaultSettings.defaults, videojsUserSettings.settings);
136
+
137
+ // =================================================================
138
+ // VideoJS player settings
139
+ // -----------------------------------------------------------------
140
+ const vjsPlayerType = 'ytp';
141
+ const vjsPlaybackRates = videojsConfig.playbackRates.values;
142
+
143
+ // =================================================================
144
+ // VideoJS plugin settings
145
+ // -----------------------------------------------------------------
146
+ const piAutoCaption = videojsConfig.plugins.autoCaption;
147
+ const piHotKeys = videojsConfig.plugins.hotKeys;
148
+ const piSkipButtons = videojsConfig.plugins.skipButtons;
149
+ const piZoomButtons = videojsConfig.plugins.zoomButtons;
150
+
151
+ // =================================================================
152
+ // helper functions
153
+ // -----------------------------------------------------------------
154
+ function addCaptionAfterImage(imageSrc) {
155
+ const image = document.querySelector(`img[src="${imageSrc}"]`);
156
+
157
+ if (image) {
158
+ // create div|caption container
159
+ const newDiv = document.createElement('div');
160
+ newDiv.classList.add('caption');
161
+ newDiv.textContent = '#{attributes['title']}';
162
+
163
+ // insert div|caption container AFTER the image
164
+ image.parentNode.insertBefore(newDiv, image.nextSibling);
165
+ } else {
166
+ console.error(`Kein Bild mit src="${imageSrc}" gefunden.`);
167
+ }
168
+ }
169
+
170
+ // =================================================================
171
+ // initialize the VideoJS player (on page ready)
172
+ // -----------------------------------------------------------------
173
+ var dependencies_met_page_ready = setInterval (function (options) {
174
+ var pageState = $('#content').css("display");
175
+ var pageVisible = (pageState == 'block') ? true : false;
176
+ var j1CoreFinished = (j1.getState() === 'finished') ? true : false;
177
+
178
+ if (j1CoreFinished && pageVisible) {
179
+ var vjs_player = document.getElementById("#{video_id}");
180
+
181
+ // add|skip captions (on poster image)
182
+ if ('#{caption_enabled}' === 'true') {
183
+ addCaptionAfterImage('#{poster_image}');
184
+ }
185
+
186
+ // scroll page to the players top position
187
+ // -------------------------------------------------------------
188
+ vjs_player.addEventListener('click', function(event) {
189
+ const targetDiv = document.getElementById("#{video_id}");
190
+ const targetDivPosition = targetDiv.offsetTop;
191
+ var scrollOffset = (window.innerWidth >= 720) ? -130 : -110;
192
+
193
+ // scroll player to top position
194
+ window.scrollTo(0, targetDivPosition + scrollOffset);
195
+ }); // END EventListener 'click'
196
+
197
+ clearInterval(dependencies_met_page_ready);
198
+ }
199
+ }, 10);
200
+
201
+ // customize the yt player (already) created
202
+ // -----------------------------------------------------------------
203
+ var dependencies_met_vjs_player_exist = setInterval (function (options) {
204
+ var vjsPlayerExist = document.getElementById("#{video_id}") ? true : false;
205
+ var vjsPlayerCustomButtons = ("#{custom_buttons}" === 'true') ? true : false;
206
+
207
+ if (vjsPlayerExist && vjsPlayerCustomButtons) {
208
+ // apply player customization on 'player ready'
209
+ videojs("#{video_id}").ready(function() {
210
+ var vjsPlayer = this;
211
+
212
+ // add|skip playbackRates
213
+ //
214
+ if (videojsConfig.playbackRates.enabled) {
215
+ vjsPlayer.playbackRates(vjsPlaybackRates);
216
+ }
217
+
218
+ // add|skip hotKeys plugin
219
+ //
220
+ if (piHotKeys.enabled) {
221
+ vjsPlayer.hotKeys({
222
+ volumeStep: piHotKeys.volumeStep,
223
+ seekStep: piHotKeys.seekStep,
224
+ enableMute: piHotKeys.enableMute,
225
+ enableFullscreen: piHotKeys.enableFullscreen,
226
+ enableNumbers: piHotKeys.enableNumbers,
227
+ enableVolumeScroll: piHotKeys.enableVolumeScroll,
228
+ enableHoverScroll: piHotKeys.enableHoverScroll,
229
+ alwaysCaptureHotkeys: piHotKeys.alwaysCaptureHotkeys,
230
+ captureDocumentHotkeys: piHotKeys.captureDocumentHotkeys,
231
+ documentHotkeysFocusElementFilter: e => e.tagName.toLowerCase() === "body",
232
+
233
+ // Mimic VLC seek behavior (default to: 15)
234
+ seekStep: function(e) {
235
+ if (e.ctrlKey && e.altKey) {
236
+ return 5*60;
237
+ } else if (e.ctrlKey) {
238
+ return 60;
239
+ } else if (e.altKey) {
240
+ return 10;
241
+ } else {
242
+ return 15;
243
+ }
244
+ },
245
+
246
+ // Enhance existing simple hotkey by complex hotkeys
247
+ fullscreenKey: function(e) {
248
+ // fullscreen with the F key or Ctrl+Enter
249
+ return ((e.which === 70) || (e.ctrlKey && e.which === 13));
250
+ },
251
+
252
+ }); // END VideoJS hotKeys plugin
253
+ }
254
+
255
+ // add|skip skipButtons plugin
256
+ if (piSkipButtons.enabled) {
257
+ var backwardIndex = piSkipButtons.backward;
258
+ var forwardIndex = piSkipButtons.forwardIndex;
259
+
260
+ // property 'surroundPlayButton' takes precendence
261
+ //
262
+ if (piSkipButtons.surroundPlayButton) {
263
+ var backwardIndex = 0;
264
+ var forwardIndex = 1;
265
+ }
266
+
267
+ vjsPlayer.skipButtons({
268
+ backwardIndex: backwardIndex,
269
+ forwardIndex: forwardIndex,
270
+ backward: piSkipButtons.backward,
271
+ forward: piSkipButtons.forward,
272
+ });
273
+ }
274
+
275
+ // add|skip zoomButtons plugin
276
+ if (piZoomButtons.enabled && vjsPlayerType === 'native') {
277
+ vjsPlayer.zoomButtons({
278
+ moveX: piZoomButtons.moveX,
279
+ moveY: piZoomButtons.moveY,
280
+ rotate: piZoomButtons.rotate,
281
+ zoom: piZoomButtons.zoom
282
+ });
283
+ }
284
+
285
+ // set start position of current video (on play)
286
+ // -----------------------------------------------------------
287
+ var appliedOnce = false;
288
+ vjsPlayer.on("play", function() {
289
+ var startFromSecond = new Date('1970-01-01T' + "#{attributes['start']}" + 'Z').getTime() / 1000;
290
+ if (!appliedOnce) {
291
+ vjsPlayer.currentTime(startFromSecond);
292
+ appliedOnce = true;
293
+ }
294
+ });
295
+
296
+ }); // END yt player ready (set custom controls)
297
+
298
+ clearInterval(dependencies_met_vjs_player_exist);
299
+ } // END if 'vjsPlayerExist'
300
+
301
+ }, 10); // END 'dependencies_met_vjs_player_exist'
302
+
303
+ }); // END 'document ready'
304
+
305
+ </script>
306
+ )
307
+
308
+ create_pass_block parent, html, attributes, subs: nil
309
+ end
310
+ end
311
+
312
+ block_macro WistiaBlockMacro
313
+ end
@@ -1,6 +1,6 @@
1
1
  # ------------------------------------------------------------------------------
2
2
  # ~/_plugins/asciidoctor-extensions/youtube-block.rb
3
- # Asciidoctor extension for YouTube Video
3
+ # Asciidoctor extension for YouTube Videos
4
4
  #
5
5
  # Product/Info:
6
6
  # https://jekyll.one
@@ -10,6 +10,9 @@
10
10
  # J1 Template is licensed under the MIT License.
11
11
  # See: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE
12
12
  # ------------------------------------------------------------------------------
13
+
14
+ # Require Asciidoctor Extensions
15
+ # ------------------------------------------------------------------------------
13
16
  require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
14
17
  include Asciidoctor
15
18
 
@@ -40,25 +43,55 @@ include Asciidoctor
40
43
  # See: https://www.datenschutz.org/youtube-nocookie/
41
44
  # ------------------------------------------------------------------------------
42
45
 
46
+ # Register the Asciidoctor Extension
47
+ # ------------------------------------------------------------------------------
43
48
  Asciidoctor::Extensions.register do
44
49
 
45
50
  class YouTubeBlockMacro < Extensions::BlockMacroProcessor
46
51
  use_dsl
47
52
 
48
53
  named :youtube
49
- name_positional_attributes 'poster', 'theme', 'role'
50
- default_attrs 'poster' => '/assets/image/icons/videojs/videojs-poster.png',
54
+ name_positional_attributes 'caption', 'start','poster', 'theme', 'custom_buttons', 'role'
55
+ default_attrs 'caption' => 'true',
56
+ 'start' => '00:00:00',
57
+ 'poster' => '/assets/image/icons/videojs/videojs-poster.png',
51
58
  'theme' => 'uno',
52
- 'role' => 'mt-3 mb-3'
59
+ 'custom_buttons' => true,
60
+ 'role' => 'mt-4 mb-5'
53
61
 
54
62
  def process parent, target, attributes
55
63
 
56
- chars = [('a'..'z'), ('A'..'Z'), ('0'..'9')].map(&:to_a).flatten
57
- video_id = (0...11).map { chars[rand(chars.length)] }.join
64
+ # ========================================================================
65
+ # load VideoJS configuration data
66
+ # ------------------------------------------------------------------------
67
+ # NOTE:
68
+ # Settings folder _data is NOT available in the website
69
+ #-------------------------------------------------------------------------
70
+ current_path = File.expand_path(Dir.getwd)
71
+ default_config_path = File.join(current_path, '/_data/modules/defaults')
72
+ user_config_path = File.join(current_path, '/_data/modules')
73
+
74
+ videojs_config_file_name = 'videojs.yml'
75
+ videojs_default_config_file = File.join(default_config_path, videojs_config_file_name)
76
+ videojs_user_config_file = File.join(user_config_path, videojs_config_file_name)
77
+
78
+ videojsDefaultSettings = YAML::load(File.open(videojs_default_config_file))
79
+ videojsUserSettings = YAML::load(File.open(videojs_user_config_file))
80
+ videojsDefaultSettingsJson = videojsDefaultSettings.to_json;
81
+ videojsUserSettingsJson = videojsUserSettings.to_json;
58
82
 
59
- title_html = (attributes.has_key? 'title') ? %(<div class="video-title"> <i class="mdib mdib-youtube-tv mdib-24px mr-2"></i> #{attributes['title']} </div>\n) : nil
60
- poster_image = (poster = attributes['poster']) ? %(#{poster}) : nil
61
- theme_name = (theme = attributes['theme']) ? %(#{theme}) : nil
83
+ # ========================================================================
84
+ # set plugin specific data
85
+ # ------------------------------------------------------------------------
86
+ #
87
+ chars = [('a'..'z'), ('A'..'Z'), ('0'..'9')].map(&:to_a).flatten
88
+ video_id = (0...11).map { chars[rand(chars.length)] }.join
89
+
90
+ title_html = (attributes.has_key? 'title') ? %(<div class="video-title"> <i class="mdib mdib-video mdib-24px mr-2"></i> #{attributes['title']} </div>\n) : nil
91
+ poster_image = (poster = attributes['poster']) ? %(#{poster}) : nil
92
+ theme_name = (theme = attributes['theme']) ? %(#{theme}) : nil
93
+ custom_buttons = (custom_buttons = attributes['custom_buttons']) ? %(#{custom_buttons}) : nil
94
+ caption_enabled = (caption = attributes['caption']) ? true : false
62
95
 
63
96
  html = %(
64
97
  <div class="youtube-player bottom #{attributes['role']}">
@@ -93,6 +126,38 @@ Asciidoctor::Extensions.register do
93
126
  <script>
94
127
  $(function() {
95
128
 
129
+ // =================================================================
130
+ // take over VideoJS configuration data (JSON data from Ruby)
131
+ // -----------------------------------------------------------------
132
+ var videojsDefaultConfigJson = '#{videojsDefaultSettingsJson}';
133
+ var videojsUserConfigJson = '#{videojsUserSettingsJson}';
134
+
135
+ // =================================================================
136
+ // create config objects from JSON data
137
+ // -----------------------------------------------------------------
138
+ var videojsDefaultSettings = JSON.parse(videojsDefaultConfigJson);
139
+ var videojsUserSettings = JSON.parse(videojsUserConfigJson);
140
+
141
+ // merge config objects (jQuery)
142
+ var videojsConfig = $.extend(true, {}, videojsDefaultSettings.defaults, videojsUserSettings.settings);
143
+
144
+ // =================================================================
145
+ // VideoJS player settings
146
+ // -----------------------------------------------------------------
147
+ const vjsPlayerType = 'ytp';
148
+ const vjsPlaybackRates = videojsConfig.playbackRates.values;
149
+
150
+ // =================================================================
151
+ // VideoJS plugin settings
152
+ // -----------------------------------------------------------------
153
+ const piAutoCaption = videojsConfig.plugins.autoCaption;
154
+ const piHotKeys = videojsConfig.plugins.hotKeys;
155
+ const piSkipButtons = videojsConfig.plugins.skipButtons;
156
+ const piZoomButtons = videojsConfig.plugins.zoomButtons;
157
+
158
+ // =================================================================
159
+ // helper functions
160
+ // -----------------------------------------------------------------
96
161
  function addCaptionAfterImage(imageSrc) {
97
162
  const image = document.querySelector(`img[src="${imageSrc}"]`);
98
163
 
@@ -109,31 +174,141 @@ Asciidoctor::Extensions.register do
109
174
  }
110
175
  }
111
176
 
177
+ // =================================================================
178
+ // initialize the VideoJS player (on page ready)
179
+ // -----------------------------------------------------------------
112
180
  var dependencies_met_page_ready = setInterval (function (options) {
113
181
  var pageState = $('#content').css("display");
114
182
  var pageVisible = (pageState == 'block') ? true : false;
115
183
  var j1CoreFinished = (j1.getState() === 'finished') ? true : false;
116
184
 
117
185
  if (j1CoreFinished && pageVisible) {
118
- addCaptionAfterImage('#{poster_image}');
186
+ var vjs_player = document.getElementById("#{video_id}");
119
187
 
120
- // scroll to player top position
121
- // -------------------------------------------------------------
122
- var vjs_player = document.getElementById("#{video_id}");
188
+ // add|skip captions (on poster image)
189
+ if ('#{caption_enabled}' === 'true') {
190
+ addCaptionAfterImage('#{poster_image}');
191
+ }
123
192
 
193
+ // scroll page to the players top position
194
+ // -------------------------------------------------------------
124
195
  vjs_player.addEventListener('click', function(event) {
125
- var scrollOffset = (window.innerWidth >= 720) ? -130 : -110;
126
-
127
- // scroll player to top position
128
196
  const targetDiv = document.getElementById("#{video_id}");
129
197
  const targetDivPosition = targetDiv.offsetTop;
198
+ var scrollOffset = (window.innerWidth >= 720) ? -130 : -110;
199
+
200
+ // scroll player to top position
130
201
  window.scrollTo(0, targetDivPosition + scrollOffset);
131
202
  }); // END EventListener 'click'
132
203
 
133
204
  clearInterval(dependencies_met_page_ready);
134
205
  }
135
206
  }, 10);
136
- });
207
+
208
+ // customize the yt player (already) created
209
+ // -----------------------------------------------------------------
210
+ var dependencies_met_vjs_player_exist = setInterval (function (options) {
211
+ var vjsPlayerExist = document.getElementById("#{video_id}") ? true : false;
212
+ var vjsPlayerCustomButtons = ("#{custom_buttons}" === 'true') ? true : false;
213
+
214
+ if (vjsPlayerExist && vjsPlayerCustomButtons) {
215
+ // apply player customization on 'player ready'
216
+ videojs("#{video_id}").ready(function() {
217
+ var vjsPlayer = this;
218
+
219
+ // add|skip playbackRates
220
+ //
221
+ if (videojsConfig.playbackRates.enabled) {
222
+ vjsPlayer.playbackRates(vjsPlaybackRates);
223
+ }
224
+
225
+ // add|skip hotKeys plugin
226
+ //
227
+ if (piHotKeys.enabled) {
228
+ vjsPlayer.hotKeys({
229
+ volumeStep: piHotKeys.volumeStep,
230
+ seekStep: piHotKeys.seekStep,
231
+ enableMute: piHotKeys.enableMute,
232
+ enableFullscreen: piHotKeys.enableFullscreen,
233
+ enableNumbers: piHotKeys.enableNumbers,
234
+ enableVolumeScroll: piHotKeys.enableVolumeScroll,
235
+ enableHoverScroll: piHotKeys.enableHoverScroll,
236
+ alwaysCaptureHotkeys: piHotKeys.alwaysCaptureHotkeys,
237
+ captureDocumentHotkeys: piHotKeys.captureDocumentHotkeys,
238
+ documentHotkeysFocusElementFilter: e => e.tagName.toLowerCase() === "body",
239
+
240
+ // Mimic VLC seek behavior (default to: 15)
241
+ seekStep: function(e) {
242
+ if (e.ctrlKey && e.altKey) {
243
+ return 5*60;
244
+ } else if (e.ctrlKey) {
245
+ return 60;
246
+ } else if (e.altKey) {
247
+ return 10;
248
+ } else {
249
+ return 15;
250
+ }
251
+ },
252
+
253
+ // Enhance existing simple hotkey by complex hotkeys
254
+ fullscreenKey: function(e) {
255
+ // fullscreen with the F key or Ctrl+Enter
256
+ return ((e.which === 70) || (e.ctrlKey && e.which === 13));
257
+ },
258
+
259
+ }); // END VideoJS hotKeys plugin
260
+ }
261
+
262
+ // add|skip skipButtons plugin
263
+ if (piSkipButtons.enabled) {
264
+ var backwardIndex = piSkipButtons.backward;
265
+ var forwardIndex = piSkipButtons.forwardIndex;
266
+
267
+ // property 'surroundPlayButton' takes precendence
268
+ //
269
+ if (piSkipButtons.surroundPlayButton) {
270
+ var backwardIndex = 0;
271
+ var forwardIndex = 1;
272
+ }
273
+
274
+ vjsPlayer.skipButtons({
275
+ backwardIndex: backwardIndex,
276
+ forwardIndex: forwardIndex,
277
+ backward: piSkipButtons.backward,
278
+ forward: piSkipButtons.forward,
279
+ });
280
+ }
281
+
282
+ // add|skip zoomButtons plugin
283
+ if (piZoomButtons.enabled && vjsPlayerType === 'native') {
284
+ vjsPlayer.zoomButtons({
285
+ moveX: piZoomButtons.moveX,
286
+ moveY: piZoomButtons.moveY,
287
+ rotate: piZoomButtons.rotate,
288
+ zoom: piZoomButtons.zoom
289
+ });
290
+ }
291
+
292
+ // set start position of current video (on play)
293
+ // -----------------------------------------------------------
294
+ var appliedOnce = false;
295
+ vjsPlayer.on("play", function() {
296
+ var startFromSecond = new Date('1970-01-01T' + "#{attributes['start']}" + 'Z').getTime() / 1000;
297
+ if (!appliedOnce) {
298
+ vjsPlayer.currentTime(startFromSecond);
299
+ appliedOnce = true;
300
+ }
301
+ });
302
+
303
+ }); // END yt player ready (set custom controls)
304
+
305
+ clearInterval(dependencies_met_vjs_player_exist);
306
+ } // END if 'vjsPlayerExist'
307
+
308
+ }, 10); // END 'dependencies_met_vjs_player_exist'
309
+
310
+ }); // END 'document ready'
311
+
137
312
  </script>
138
313
  )
139
314
 
@@ -394,6 +394,6 @@ end
394
394
 
395
395
  module Jekyll
396
396
  module J1LunrSearch
397
- VERSION = '2024.3.14'
397
+ VERSION = '2024.3.16'
398
398
  end
399
399
  end
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": true,
3
3
  "name": "j1",
4
- "version": "2024.3.14",
4
+ "version": "2024.3.16",
5
5
  "description": "J1 Template",
6
6
  "homepage": "https://your.site",
7
7
  "author": {