cloudinary-video-player 1.6.2-edge.13

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 (226) hide show
  1. package/.eslintignore +4 -0
  2. package/.snyk +19 -0
  3. package/.travis.yml +8 -0
  4. package/CHANGELOG.md +329 -0
  5. package/LICENSE +21 -0
  6. package/README.md +87 -0
  7. package/dist/cld-video-player.css +2110 -0
  8. package/dist/cld-video-player.js +5249 -0
  9. package/dist/cld-video-player.light.css +1766 -0
  10. package/dist/cld-video-player.light.js +1399 -0
  11. package/dist/cld-video-player.light.min.css +1 -0
  12. package/dist/cld-video-player.light.min.js +2 -0
  13. package/dist/cld-video-player.light.min.js.LICENSE.txt +23 -0
  14. package/dist/cld-video-player.min.css +1 -0
  15. package/dist/cld-video-player.min.js +2 -0
  16. package/dist/cld-video-player.min.js.LICENSE.txt +26 -0
  17. package/dist/fonts/cloudinary_icon_for_black_bg.svg +69 -0
  18. package/dist/fonts/cloudinary_icon_for_white_bg.svg +69 -0
  19. package/docs/360.html +102 -0
  20. package/docs/_template.html +93 -0
  21. package/docs/adaptive-streaming.html +297 -0
  22. package/docs/analytics.html +140 -0
  23. package/docs/api.html +302 -0
  24. package/docs/audio.html +136 -0
  25. package/docs/autoplay-fallback.html +138 -0
  26. package/docs/autoplay-on-scroll.html +107 -0
  27. package/docs/codec-fallback.html +158 -0
  28. package/docs/colors.html +135 -0
  29. package/docs/components.html +284 -0
  30. package/docs/custom-cld-errors.html +134 -0
  31. package/docs/floating-player.html +98 -0
  32. package/docs/fluid.html +117 -0
  33. package/docs/force-hls-subtitles-ios.html +159 -0
  34. package/docs/index.html +83 -0
  35. package/docs/interaction-area.html +398 -0
  36. package/docs/live-customer.html +128 -0
  37. package/docs/multiple-players.html +125 -0
  38. package/docs/playlist-by-tag-cap.html +182 -0
  39. package/docs/playlist-by-tag.html +133 -0
  40. package/docs/playlist.html +133 -0
  41. package/docs/poster.html +155 -0
  42. package/docs/raw-url.html +104 -0
  43. package/docs/recommendations.html +155 -0
  44. package/docs/scripts.js +156 -0
  45. package/docs/seek-thumbs.html +90 -0
  46. package/docs/shoppable.html +335 -0
  47. package/docs/subtitles-and-captions.html +267 -0
  48. package/docs/transformations.html +171 -0
  49. package/docs/ui-config.html +108 -0
  50. package/docs/vast-vpaid.html +149 -0
  51. package/env.example.js +6 -0
  52. package/env.js +6 -0
  53. package/jest-puppeteer.config.js +14 -0
  54. package/jest.config.js +196 -0
  55. package/package.json +99 -0
  56. package/sandbox.config.json +3 -0
  57. package/setupJest.js +1 -0
  58. package/src/assets/fonts/VideoJS.svg +120 -0
  59. package/src/assets/fonts/VideoJS.ttf +0 -0
  60. package/src/assets/fonts/VideoJS.woff +0 -0
  61. package/src/assets/fonts/icons.json +120 -0
  62. package/src/assets/icons/cloudinary_icon_for_black_bg.svg +69 -0
  63. package/src/assets/icons/cloudinary_icon_for_white_bg.svg +69 -0
  64. package/src/assets/icons/cloudinary_logo_for_dark_bg.svg +188 -0
  65. package/src/assets/icons/cloudinary_logo_for_white_bg.svg +188 -0
  66. package/src/assets/icons/info-circle.svg +17 -0
  67. package/src/assets/styles/ads-label.scss +16 -0
  68. package/src/assets/styles/components/interaction-areas.scss +158 -0
  69. package/src/assets/styles/components/playlist.scss +213 -0
  70. package/src/assets/styles/components/themedButton.scss +48 -0
  71. package/src/assets/styles/components/thumbnail.scss +94 -0
  72. package/src/assets/styles/components/title-bar.scss +67 -0
  73. package/src/assets/styles/components/triangle-volume-bar.scss +52 -0
  74. package/src/assets/styles/icons.scss +257 -0
  75. package/src/assets/styles/main.scss +324 -0
  76. package/src/assets/styles/mixins/aspect-ratio.scss +16 -0
  77. package/src/assets/styles/mixins/disable-transition.scss +3 -0
  78. package/src/assets/styles/mixins/mixins.scss +5 -0
  79. package/src/assets/styles/mixins/skin.scss +64 -0
  80. package/src/assets/styles/variables.scss +2 -0
  81. package/src/assets/styles/videojs-ima.scss +252 -0
  82. package/src/components/component-utils.js +20 -0
  83. package/src/components/index.js +21 -0
  84. package/src/components/interaction-area/interaction-area.const.js +30 -0
  85. package/src/components/interaction-area/interaction-area.service.js +223 -0
  86. package/src/components/interaction-area/interaction-area.utils.js +236 -0
  87. package/src/components/jumpButtons/jump-10-minus.js +21 -0
  88. package/src/components/jumpButtons/jump-10-plus.js +20 -0
  89. package/src/components/logoButton/logo-button.const.js +3 -0
  90. package/src/components/logoButton/logo-button.js +30 -0
  91. package/src/components/logoButton/logo-button.scss +15 -0
  92. package/src/components/playlist/components/playlist-button.js +34 -0
  93. package/src/components/playlist/components/playlist-next-button.js +18 -0
  94. package/src/components/playlist/components/playlist-previous-button.js +18 -0
  95. package/src/components/playlist/components/playlist.js +5 -0
  96. package/src/components/playlist/components/playlist.scss +15 -0
  97. package/src/components/playlist/components/upcoming-video-overlay.js +149 -0
  98. package/src/components/playlist/components/upcoming-video-overlay.scss +86 -0
  99. package/src/components/playlist/layout/playlist-layout-custom.js +21 -0
  100. package/src/components/playlist/layout/playlist-layout-horizontal.js +16 -0
  101. package/src/components/playlist/layout/playlist-layout-vertical.js +19 -0
  102. package/src/components/playlist/layout/playlist-layout.js +110 -0
  103. package/src/components/playlist/panel/playlist-panel-item.js +86 -0
  104. package/src/components/playlist/panel/playlist-panel.js +92 -0
  105. package/src/components/playlist/playlist-widget.js +119 -0
  106. package/src/components/playlist/playlist.const.js +14 -0
  107. package/src/components/playlist/playlist.js +413 -0
  108. package/src/components/playlist/thumbnail/thumbnail.js +69 -0
  109. package/src/components/progress-control-events-blocker/progress-control-events-blocker.js +17 -0
  110. package/src/components/qualitySelector/quality-selector.scss +10 -0
  111. package/src/components/qualitySelector/qualitySelector.js +152 -0
  112. package/src/components/recommendations-overlay/index.js +3 -0
  113. package/src/components/recommendations-overlay/recommendations-overlay-content.js +57 -0
  114. package/src/components/recommendations-overlay/recommendations-overlay-hide-button.js +18 -0
  115. package/src/components/recommendations-overlay/recommendations-overlay-item.js +35 -0
  116. package/src/components/recommendations-overlay/recommendations-overlay-primary-item.js +81 -0
  117. package/src/components/recommendations-overlay/recommendations-overlay-secondary-item.js +48 -0
  118. package/src/components/recommendations-overlay/recommendations-overlay-secondary-items-container.js +35 -0
  119. package/src/components/recommendations-overlay/recommendations-overlay.js +94 -0
  120. package/src/components/recommendations-overlay/recommendations-overlay.scss +182 -0
  121. package/src/components/shoppable-bar/layout/bar-layout.js +111 -0
  122. package/src/components/shoppable-bar/layout/shoppable-panel-toggle.js +64 -0
  123. package/src/components/shoppable-bar/layout/shoppable-products-overlay.js +87 -0
  124. package/src/components/shoppable-bar/panel/shoppable-panel-item.js +105 -0
  125. package/src/components/shoppable-bar/panel/shoppable-panel.js +172 -0
  126. package/src/components/shoppable-bar/shoppable-post-widget.js +110 -0
  127. package/src/components/shoppable-bar/shoppable-widget.const.js +52 -0
  128. package/src/components/shoppable-bar/shoppable-widget.js +111 -0
  129. package/src/components/shoppable-bar/shoppable-widget.scss +359 -0
  130. package/src/components/themeButton/themedButton.const.js +3 -0
  131. package/src/components/themeButton/themedButton.js +25 -0
  132. package/src/components/title-bar/title-bar.js +79 -0
  133. package/src/config/defaults.js +25 -0
  134. package/src/extended-events.js +228 -0
  135. package/src/index.js +18 -0
  136. package/src/mixins/eventable.js +54 -0
  137. package/src/mixins/playlistable.js +106 -0
  138. package/src/plugins/analytics/index.js +245 -0
  139. package/src/plugins/autoplay-on-scroll/index.js +86 -0
  140. package/src/plugins/cloudinary/common.js +216 -0
  141. package/src/plugins/cloudinary/event-handler-registry.js +46 -0
  142. package/src/plugins/cloudinary/index.js +345 -0
  143. package/src/plugins/cloudinary/models/audio-source/audio-source.const.js +11 -0
  144. package/src/plugins/cloudinary/models/audio-source/audio-source.js +82 -0
  145. package/src/plugins/cloudinary/models/base-source.js +107 -0
  146. package/src/plugins/cloudinary/models/image-source.js +26 -0
  147. package/src/plugins/cloudinary/models/video-source/video-source.const.js +32 -0
  148. package/src/plugins/cloudinary/models/video-source/video-source.js +239 -0
  149. package/src/plugins/cloudinary/models/video-source/video-source.utils.js +57 -0
  150. package/src/plugins/colors/index.js +303 -0
  151. package/src/plugins/context-menu/components/context-menu-item.js +12 -0
  152. package/src/plugins/context-menu/components/context-menu.js +63 -0
  153. package/src/plugins/context-menu/context-menu.scss +30 -0
  154. package/src/plugins/context-menu/contextMenuContent.js +53 -0
  155. package/src/plugins/context-menu/index.js +134 -0
  156. package/src/plugins/dash/index.js +26 -0
  157. package/src/plugins/dash/setup-audio-tracks.js +112 -0
  158. package/src/plugins/dash/setup-text-tracks.js +195 -0
  159. package/src/plugins/dash/videojs-dash.js +372 -0
  160. package/src/plugins/floating-player/floating-player.scss +74 -0
  161. package/src/plugins/floating-player/index.js +129 -0
  162. package/src/plugins/ima/index.js +1775 -0
  163. package/src/plugins/index.js +31 -0
  164. package/src/plugins/interactive-plugin/index.js +10 -0
  165. package/src/plugins/videojs-http-source-selector/components/SourceMenuButton.js +98 -0
  166. package/src/plugins/videojs-http-source-selector/components/SourceMenuItem.js +52 -0
  167. package/src/plugins/videojs-http-source-selector/plugin.js +82 -0
  168. package/src/plugins/videojs-http-source-selector/plugin.scss +9 -0
  169. package/src/plugins/vtt-thumbnails/index.js +526 -0
  170. package/src/plugins/vtt-thumbnails/vtt-thumbnails.scss +29 -0
  171. package/src/utils/api.js +32 -0
  172. package/src/utils/apply-with-props.js +32 -0
  173. package/src/utils/array.js +22 -0
  174. package/src/utils/assign.js +27 -0
  175. package/src/utils/attributes-normalizer.js +72 -0
  176. package/src/utils/cloudinary.js +165 -0
  177. package/src/utils/css-prefix.js +43 -0
  178. package/src/utils/dom.js +74 -0
  179. package/src/utils/find.js +28 -0
  180. package/src/utils/fontFace.js +25 -0
  181. package/src/utils/groupBy.js +12 -0
  182. package/src/utils/index.js +29 -0
  183. package/src/utils/matches.js +11 -0
  184. package/src/utils/mixin.js +5 -0
  185. package/src/utils/object.js +26 -0
  186. package/src/utils/playButton.js +9 -0
  187. package/src/utils/positioning.js +78 -0
  188. package/src/utils/querystring.js +12 -0
  189. package/src/utils/slicing.js +21 -0
  190. package/src/utils/string.js +15 -0
  191. package/src/utils/throttle.js +30 -0
  192. package/src/utils/time.js +77 -0
  193. package/src/utils/type-inference.js +35 -0
  194. package/src/validators/validators-functions.js +48 -0
  195. package/src/validators/validators-types.js +78 -0
  196. package/src/validators/validators.js +110 -0
  197. package/src/video-player.const.js +68 -0
  198. package/src/video-player.js +761 -0
  199. package/src/video-player.utils.js +123 -0
  200. package/test/adaptive-streaming.test.js +38 -0
  201. package/test/ads.test.js +35 -0
  202. package/test/analytics.test.js +111 -0
  203. package/test/api.test.js +111 -0
  204. package/test/autoplay.scroll.test.js +23 -0
  205. package/test/basic-ui.test.js +59 -0
  206. package/test/colors.test.js +58 -0
  207. package/test/components.test.js +21 -0
  208. package/test/custom-error.test.js +24 -0
  209. package/test/fluid.test.js +36 -0
  210. package/test/isValidConfig.test.js +224 -0
  211. package/test/mocks/cloudinary-core-mock.js +0 -0
  212. package/test/mocks/styleMock.js +1 -0
  213. package/test/multiplayer.test.js +25 -0
  214. package/test/playlist.test.js +60 -0
  215. package/test/puppeteer/vp-env.js +19 -0
  216. package/test/recommendations.test.js +38 -0
  217. package/test/title-bar.test.js +28 -0
  218. package/test/ui-conf.test.js +49 -0
  219. package/test/unit/cloudinaryConfig.test.js +22 -0
  220. package/test/unit/cloudinaryUtils.test.js +53 -0
  221. package/test/unit/utils.test.js +27 -0
  222. package/test/unit/videoSource.test.js +454 -0
  223. package/tsconfig.json +15 -0
  224. package/types/video-player-tests.js +12 -0
  225. package/types/video-player-tests.ts +31 -0
  226. package/types/video-player.d.ts +570 -0
@@ -0,0 +1,526 @@
1
+ import videojs from 'video.js';
2
+ import Promise from 'promise-polyfill';
3
+
4
+ import './vtt-thumbnails.scss';
5
+
6
+ // Default options for the plugin.
7
+ let defaults = {};
8
+
9
+ // Cache for image elements
10
+ let cache = {};
11
+
12
+ /**
13
+ * Function to invoke when the player is ready.
14
+ *
15
+ * This is a great place for your plugin to initialize itself. When this
16
+ * function is called, the player will have its DOM and child components
17
+ * in place.
18
+ *
19
+ * @function onPlayerReady
20
+ * @param {Player} player
21
+ * A Video.js player object.
22
+ *
23
+ * @param {Object} [options={}]
24
+ * A plain object containing options for the plugin.
25
+ */
26
+ const onPlayerReady = function onPlayerReady(player, options) {
27
+ player.addClass('vjs-vtt-thumbnails');
28
+ player.vttThumbnails = new VttThumbnailsPlugin(player, options);
29
+ };
30
+
31
+ /**
32
+ * A video.js plugin.
33
+ *
34
+ * In the plugin function, the value of `this` is a video.js `Player`
35
+ * instance. You cannot rely on the player being in a "ready" state here,
36
+ * depending on how the plugin is invoked. This may or may not be important
37
+ * to you; if not, remove the wait for "ready"!
38
+ *
39
+ * @function vttThumbnails
40
+ * @param {Object} [options={}]
41
+ * An object of options left to the plugin author to define.
42
+ */
43
+ const vttThumbnails = function vttThumbnails(options) {
44
+ let _this = this;
45
+
46
+ this.ready(function () {
47
+ onPlayerReady(_this, videojs.mergeOptions(defaults, options));
48
+ });
49
+ };
50
+
51
+ /**
52
+ * VTT Thumbnails class.
53
+ *
54
+ * This class performs all functions related to displaying the vtt
55
+ * thumbnails.
56
+ */
57
+ const VttThumbnailsPlugin = (function () {
58
+
59
+ /**
60
+ * Plugin class constructor, called by videojs on
61
+ * ready event.
62
+ *
63
+ * @function constructor
64
+ * @param {Player} player
65
+ * A Video.js player object.
66
+ *
67
+ * @param {Object} [options={}]
68
+ * A plain object containing options for the plugin.
69
+ */
70
+ function VttThumbnailsPlugin(player, options) {
71
+ this.player = player;
72
+ this.options = options;
73
+ this.listenForDurationChange();
74
+ this.initializeThumbnails();
75
+ this.registeredEvents = {};
76
+ return this;
77
+ }
78
+
79
+ VttThumbnailsPlugin.prototype.src = function src(source) {
80
+ this.resetPlugin();
81
+ this.options.src = source;
82
+ this.initializeThumbnails();
83
+ };
84
+
85
+ VttThumbnailsPlugin.prototype.detach = function detach() {
86
+ this.resetPlugin();
87
+ };
88
+
89
+ VttThumbnailsPlugin.prototype.resetPlugin = function resetPlugin() {
90
+ if (this.thumbnailHolder) {
91
+ this.thumbnailHolder.parentNode.removeChild(this.thumbnailHolder);
92
+ }
93
+ if (this.progressBar) {
94
+ this.progressBar.removeEventListener(
95
+ 'mouseenter',
96
+ this.registeredEvents.progressBarMouseEnter
97
+ );
98
+ this.progressBar.removeEventListener(
99
+ 'mouseleave',
100
+ this.registeredEvents.progressBarMouseLeave
101
+ );
102
+ this.progressBar.removeEventListener(
103
+ 'mousemove',
104
+ this.registeredEvents.progressBarMouseMove
105
+ );
106
+ }
107
+ delete this.registeredEvents.progressBarMouseEnter;
108
+ delete this.registeredEvents.progressBarMouseLeave;
109
+ delete this.registeredEvents.progressBarMouseMove;
110
+ delete this.progressBar;
111
+ delete this.vttData;
112
+ delete this.thumbnailHolder;
113
+ delete this.lastStyle;
114
+ };
115
+
116
+ VttThumbnailsPlugin.prototype.listenForDurationChange = function listenForDurationChange() {
117
+ this.player.on('durationchange', function () {
118
+ // ToDo
119
+ });
120
+ };
121
+
122
+ /**
123
+ * Bootstrap the plugin.
124
+ */
125
+
126
+ VttThumbnailsPlugin.prototype.initializeThumbnails = function initializeThumbnails() {
127
+ let _this2 = this;
128
+
129
+ if (!this.options.src) {
130
+ return;
131
+ }
132
+ let baseUrl = this.getBaseUrl();
133
+ let url = this.getFullyQualifiedUrl(this.options.src, baseUrl);
134
+
135
+ this.getVttFile(url).then(function (data) {
136
+ _this2.vttData = _this2.processVtt(data);
137
+ _this2.setupThumbnailElement();
138
+ });
139
+ };
140
+
141
+ /**
142
+ * Builds a base URL should we require one.
143
+ *
144
+ * @returns {string}
145
+ */
146
+
147
+ VttThumbnailsPlugin.prototype.getBaseUrl = function getBaseUrl() {
148
+ return [
149
+ window.location.protocol,
150
+ '//',
151
+ window.location.hostname,
152
+ window.location.port ? ':' + window.location.port : '',
153
+ window.location.pathname
154
+ ]
155
+ .join('')
156
+ .split(/([^\/]*)$/gi)
157
+ .shift();
158
+ };
159
+
160
+ /**
161
+ * Grabs the contents of the VTT file.
162
+ *
163
+ * @param url
164
+ * @returns {Promise}
165
+ */
166
+
167
+ VttThumbnailsPlugin.prototype.getVttFile = function getVttFile(url) {
168
+ let _this3 = this;
169
+
170
+ return new Promise(function (resolve) {
171
+ let req = new XMLHttpRequest();
172
+ req.data = {
173
+ resolve: resolve
174
+ };
175
+ req.addEventListener('load', _this3.vttFileLoaded);
176
+ req.open('GET', url);
177
+ req.send();
178
+ });
179
+ };
180
+
181
+ /**
182
+ * Callback for loaded VTT file.
183
+ */
184
+
185
+ VttThumbnailsPlugin.prototype.vttFileLoaded = function vttFileLoaded() {
186
+ this.data.resolve(this.responseText);
187
+ };
188
+
189
+ VttThumbnailsPlugin.prototype.setupThumbnailElement = function setupThumbnailElement() {
190
+ let _this4 = this;
191
+
192
+ let mouseDisplay = this.player.$('.vjs-mouse-display');
193
+ this.progressBar = this.player.$('.vjs-progress-control');
194
+ let thumbHolder = document.createElement('div');
195
+ thumbHolder.setAttribute('class', 'vjs-vtt-thumbnail-display');
196
+ this.progressBar.appendChild(thumbHolder);
197
+ this.thumbnailHolder = thumbHolder;
198
+ let timeHolder = document.createElement('div');
199
+ timeHolder.setAttribute('class', 'vjs-vtt-time-display');
200
+ this.thumbnailHolder.appendChild(timeHolder);
201
+ this.timeHolder = timeHolder;
202
+ if (mouseDisplay) {
203
+ mouseDisplay.classList.add('vjs-hidden');
204
+ }
205
+ this.registeredEvents.progressBarMouseEnter = function () {
206
+ return _this4.onBarMouseenter();
207
+ };
208
+ this.registeredEvents.progressBarMouseLeave = function () {
209
+ return _this4.onBarMouseleave();
210
+ };
211
+ this.progressBar.addEventListener(
212
+ 'mouseenter',
213
+ this.registeredEvents.progressBarMouseEnter
214
+ );
215
+ this.progressBar.addEventListener(
216
+ 'mouseleave',
217
+ this.registeredEvents.progressBarMouseLeave
218
+ );
219
+ };
220
+
221
+ VttThumbnailsPlugin.prototype.onBarMouseenter = function onBarMouseenter() {
222
+ let _this5 = this;
223
+
224
+ if (this.progressBar.offsetWidth < 400) {
225
+ // Don't show in small players
226
+ return;
227
+ }
228
+
229
+ this.mouseMoveCallback = function (e) {
230
+ _this5.onBarMousemove(e);
231
+ };
232
+ this.registeredEvents.progressBarMouseMove = this.mouseMoveCallback;
233
+ this.progressBar.addEventListener(
234
+ 'mousemove',
235
+ this.registeredEvents.progressBarMouseMove
236
+ );
237
+ this.showThumbnailHolder();
238
+ };
239
+
240
+ VttThumbnailsPlugin.prototype.onBarMouseleave = function onBarMouseleave() {
241
+ if (this.registeredEvents.progressBarMouseMove) {
242
+ this.progressBar.removeEventListener(
243
+ 'mousemove',
244
+ this.registeredEvents.progressBarMouseMove
245
+ );
246
+ }
247
+ this.hideThumbnailHolder();
248
+ };
249
+
250
+ VttThumbnailsPlugin.prototype.getXCoord = function getXCoord(bar, mouseX) {
251
+ let rect = bar.getBoundingClientRect();
252
+ let docEl = document.documentElement;
253
+ return (
254
+ mouseX - (rect.left + (window.pageXOffset || docEl.scrollLeft || 0))
255
+ );
256
+ };
257
+
258
+ VttThumbnailsPlugin.prototype.onBarMousemove = function onBarMousemove(
259
+ event
260
+ ) {
261
+ this.updateThumbnailStyle(
262
+ videojs.dom.getPointerPosition(this.progressBar, event).x,
263
+ this.progressBar.offsetWidth
264
+ );
265
+ };
266
+
267
+ VttThumbnailsPlugin.prototype.getStyleForTime = function getStyleForTime(
268
+ time
269
+ ) {
270
+ for (let i = 0; i < this.vttData.length; ++i) {
271
+ let item = this.vttData[i];
272
+ if (time >= item.start && time < item.end) {
273
+ // Cache miss
274
+ if (item.css.url && !cache[item.css.url]) {
275
+ let image = new Image();
276
+ image.src = item.css.url;
277
+ cache[item.css.url] = image;
278
+ }
279
+
280
+ return item.css;
281
+ }
282
+ }
283
+ };
284
+
285
+ VttThumbnailsPlugin.prototype.showThumbnailHolder = function showThumbnailHolder() {
286
+ this.thumbnailHolder.style.opacity = '1';
287
+ };
288
+
289
+ VttThumbnailsPlugin.prototype.hideThumbnailHolder = function hideThumbnailHolder() {
290
+ this.thumbnailHolder.style.opacity = '0';
291
+ };
292
+
293
+ VttThumbnailsPlugin.prototype.updateThumbnailStyle = function updateThumbnailStyle(
294
+ percent,
295
+ width
296
+ ) {
297
+ let duration = this.player.duration();
298
+ let time = percent * duration;
299
+ let currentStyle = this.getStyleForTime(time);
300
+
301
+ if (!currentStyle) {
302
+ return this.hideThumbnailHolder();
303
+ }
304
+
305
+ let xPos = percent * width;
306
+ let thumbnailWidth = parseInt(currentStyle.width, 10);
307
+ let halfthumbnailWidth = thumbnailWidth / 2;
308
+ let marginRight = width - (xPos + halfthumbnailWidth);
309
+ let marginLeft = xPos - halfthumbnailWidth;
310
+ if (marginLeft > 0 && marginRight > 0) {
311
+ this.thumbnailHolder.style.transform =
312
+ 'translateX(' + (xPos - halfthumbnailWidth) + 'px)';
313
+ } else if (marginLeft <= 0) {
314
+ this.thumbnailHolder.style.transform = 'translateX(' + 0 + 'px)';
315
+ } else if (marginRight <= 0) {
316
+ this.thumbnailHolder.style.transform =
317
+ 'translateX(' + (width - thumbnailWidth) + 'px)';
318
+ }
319
+
320
+ this.timeHolder.innerHTML = this.getTimestampFromSeconds(time);
321
+
322
+ if (this.lastStyle && this.lastStyle === currentStyle) {
323
+ return;
324
+ }
325
+ this.lastStyle = currentStyle;
326
+
327
+ for (let style in currentStyle) {
328
+ if (Object.prototype.hasOwnProperty.call(currentStyle, style)) {
329
+ this.thumbnailHolder.style[style] = currentStyle[style];
330
+ }
331
+ }
332
+ };
333
+
334
+ VttThumbnailsPlugin.prototype.processVtt = function processVtt(data) {
335
+ let _this6 = this;
336
+
337
+ let processedVtts = [];
338
+ let vttDefinitions = data.split(/[\r\n][\r\n]/i);
339
+ vttDefinitions.forEach(function (vttDef) {
340
+ if (
341
+ vttDef.match(
342
+ /([0-9]{2}:)?([0-9]{2}:)?[0-9]{2}(.[0-9]{3})?( ?--> ?)([0-9]{2}:)?([0-9]{2}:)?[0-9]{2}(.[0-9]{3})?[\r\n]{1}.*/gi
343
+ )
344
+ ) {
345
+ let vttDefSplit = vttDef.split(/[\r\n]/i);
346
+ let vttTiming = vttDefSplit[0];
347
+ let vttTimingSplit = vttTiming.split(/ ?--> ?/i);
348
+ let vttTimeStart = vttTimingSplit[0];
349
+ let vttTimeEnd = vttTimingSplit[1];
350
+
351
+ let vttImageFullPath = vttDefSplit[1];
352
+ let vttImageDef = vttImageFullPath.split('\/').pop();
353
+ let vttCssDef = _this6.getVttCss(vttImageDef);
354
+
355
+ processedVtts.push({
356
+ start: _this6.getSecondsFromTimestamp(vttTimeStart),
357
+ end: _this6.getSecondsFromTimestamp(vttTimeEnd),
358
+ css: vttCssDef
359
+ });
360
+ }
361
+ });
362
+ return processedVtts;
363
+ };
364
+
365
+ VttThumbnailsPlugin.prototype.getFullyQualifiedUrl = function getFullyQualifiedUrl(
366
+ path,
367
+ base
368
+ ) {
369
+ // ToDo: remove this? also remove trim?
370
+ if (path.indexOf('//') >= 0) {
371
+ // We have a fully qualified path.
372
+ return path;
373
+ } else if (base.indexOf('//') === 0) {
374
+ // We don't have a fully qualified path, but need to
375
+ // be careful with trimming.
376
+ return [base.replace(/\/$/gi, ''), this.trim(path, '/')].join('/');
377
+ } else if (base.indexOf('//') > 0) {
378
+ // We don't have a fully qualified path, and should
379
+ // trim both sides of base and path.
380
+ return [this.trim(base, '/'), this.trim(path, '/')].join('/');
381
+ }
382
+
383
+ // If all else fails.
384
+ return path;
385
+ };
386
+
387
+ VttThumbnailsPlugin.prototype.getPropsFromDef = function getPropsFromDef(
388
+ def
389
+ ) {
390
+ let imageDefSplit = def.split(/#xywh=/i);
391
+ let imageUrl = imageDefSplit[0];
392
+ let imageCoords = imageDefSplit[1];
393
+ let splitCoords = imageCoords.match(/[0-9]+/gi);
394
+ return {
395
+ x: splitCoords[0],
396
+ y: splitCoords[1],
397
+ w: splitCoords[2],
398
+ h: splitCoords[3],
399
+ image: imageUrl
400
+ };
401
+ };
402
+
403
+ VttThumbnailsPlugin.prototype.getVttCss = function getVttCss(vttImageDef) {
404
+ let cssObj = {};
405
+
406
+ // If there isn't a protocol, use the VTT source URL.
407
+ let baseSplit = '';
408
+ if (this.options.src.indexOf('//') >= 0) {
409
+ baseSplit = this.options.src.split(/([^\/]*)$/gi).shift();
410
+ } else {
411
+ baseSplit =
412
+ this.getBaseUrl() + this.options.src.split(/([^\/]*)$/gi).shift();
413
+ }
414
+
415
+ vttImageDef = this.getFullyQualifiedUrl(vttImageDef, baseSplit);
416
+
417
+ if (!vttImageDef.match(/#xywh=/i)) {
418
+ cssObj.background = 'url("' + vttImageDef + '")';
419
+ return cssObj;
420
+ }
421
+
422
+ let imageProps = this.getPropsFromDef(vttImageDef);
423
+ cssObj.background =
424
+ 'url("' +
425
+ imageProps.image +
426
+ '") no-repeat -' +
427
+ imageProps.x +
428
+ 'px -' +
429
+ imageProps.y +
430
+ 'px';
431
+ cssObj.width = imageProps.w + 'px';
432
+ cssObj.height = imageProps.h + 'px';
433
+ cssObj.url = imageProps.image;
434
+
435
+ return cssObj;
436
+ };
437
+
438
+ VttThumbnailsPlugin.prototype.doconstructTimestamp = function doconstructTimestamp(
439
+ timestamp
440
+ ) {
441
+ let splitStampMilliseconds = timestamp.split('.');
442
+ let timeParts = splitStampMilliseconds[0];
443
+ let timePartsSplit = timeParts.split(':');
444
+ return {
445
+ milliseconds: parseInt(splitStampMilliseconds[1], 10) || 0,
446
+ seconds: parseInt(timePartsSplit.pop(), 10) || 0,
447
+ minutes: parseInt(timePartsSplit.pop(), 10) || 0,
448
+ hours: parseInt(timePartsSplit.pop(), 10) || 0
449
+ };
450
+ };
451
+
452
+ VttThumbnailsPlugin.prototype.getSecondsFromTimestamp = function getSecondsFromTimestamp(
453
+ timestamp
454
+ ) {
455
+ let timestampParts = this.doconstructTimestamp(timestamp);
456
+ return parseInt(
457
+ timestampParts.hours * (60 * 60) +
458
+ timestampParts.minutes * 60 +
459
+ timestampParts.seconds +
460
+ timestampParts.milliseconds / 1000
461
+ , 10);
462
+ };
463
+
464
+ VttThumbnailsPlugin.prototype.getTimestampFromSeconds = function getTimestampFromSeconds(
465
+ totalSeconds
466
+ ) {
467
+ let minutes = Math.floor(totalSeconds / 60);
468
+ let seconds = Math.floor(totalSeconds % 60);
469
+ if (seconds < 10) {
470
+ seconds = '0' + seconds;
471
+ }
472
+ return minutes + ':' + seconds;
473
+ };
474
+
475
+ VttThumbnailsPlugin.prototype.trim = function trim(str, charlist) {
476
+ let whitespace = [
477
+ ' ',
478
+ '\n',
479
+ '\r',
480
+ '\t',
481
+ '\f',
482
+ '\x0b',
483
+ '\xa0',
484
+ '\u2000',
485
+ '\u2001',
486
+ '\u2002',
487
+ '\u2003',
488
+ '\u2004',
489
+ '\u2005',
490
+ '\u2006',
491
+ '\u2007',
492
+ '\u2008',
493
+ '\u2009',
494
+ '\u200A',
495
+ '\u200B',
496
+ '\u2028',
497
+ '\u2029',
498
+ '\u3000'
499
+ ].join('');
500
+ let l = 0;
501
+ let i = 0;
502
+ str += '';
503
+ if (charlist) {
504
+ whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1');
505
+ }
506
+ l = str.length;
507
+ for (i = 0; i < l; i++) {
508
+ if (whitespace.indexOf(str.charAt(i)) === -1) {
509
+ str = str.substring(i);
510
+ break;
511
+ }
512
+ }
513
+ l = str.length;
514
+ for (i = l - 1; i >= 0; i--) {
515
+ if (whitespace.indexOf(str.charAt(i)) === -1) {
516
+ str = str.substring(0, i + 1);
517
+ break;
518
+ }
519
+ }
520
+ return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
521
+ };
522
+
523
+ return VttThumbnailsPlugin;
524
+ }());
525
+
526
+ export default vttThumbnails;
@@ -0,0 +1,29 @@
1
+ .vjs-vtt-thumbnail-display {
2
+ position: absolute;
3
+ left: 0;
4
+ bottom: 15px;
5
+ z-index: 1;
6
+ opacity: 0;
7
+ transition: opacity 0.2s;
8
+ bottom: 3em;
9
+ pointer-events: none;
10
+ border: 3px solid #fff;
11
+ // border: 3px solid var(--color-base);
12
+ border-radius: 3px;
13
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);
14
+ }
15
+
16
+ .vjs-vtt-time-display {
17
+ position: absolute;
18
+ bottom: -1.7em;
19
+ left: 0;
20
+ right: 0;
21
+ margin: auto;
22
+ color: #fff;
23
+ // color: var(--color-base);
24
+ text-shadow: 0 0 3px #000;
25
+ }
26
+
27
+ .vjs-vtt-thumbnails .vjs-time-tooltip {
28
+ display: none !important;
29
+ }
@@ -0,0 +1,32 @@
1
+ import { isPlainObject } from 'utils/type-inference';
2
+ import { camelize } from 'utils/string';
3
+ import { parseISO8601 } from 'utils/time';
4
+
5
+ const TIME_FIELDS = ['created_at', 'updated_at'];
6
+
7
+ const normalizeJsonResponse = (obj) => {
8
+ const agg = {};
9
+
10
+ if (isPlainObject(obj)) {
11
+ Object.keys(obj).reduce((agg, key) => {
12
+ const newKey = camelize(key);
13
+
14
+ if (TIME_FIELDS.indexOf(key) !== -1) {
15
+ agg[newKey] = new Date(parseISO8601(obj[key]));
16
+ } else {
17
+ agg[newKey] = normalizeJsonResponse(obj[key]);
18
+ }
19
+
20
+ return agg;
21
+ }, agg);
22
+
23
+ return agg;
24
+ } else if (Array.isArray(obj)) {
25
+ return obj.map((item) => normalizeJsonResponse(item));
26
+ } else {
27
+ return obj;
28
+ }
29
+ };
30
+
31
+
32
+ export { normalizeJsonResponse };
@@ -0,0 +1,32 @@
1
+ import { assign } from './assign';
2
+ import { isFunction } from './type-inference';
3
+
4
+ function applyWithProps(context, obj, { order = null } = {}) {
5
+ let _obj = obj;
6
+
7
+ const apply = (key) => {
8
+ const value = obj[key];
9
+ if (value === undefined) {
10
+ return;
11
+ }
12
+
13
+ if (context[key] && isFunction(context[key])) {
14
+ context[key](value);
15
+ }
16
+ };
17
+
18
+ if (order) {
19
+ _obj = assign({}, obj);
20
+
21
+ order.forEach((key) => {
22
+ apply(key);
23
+ delete _obj[key];
24
+ });
25
+ }
26
+
27
+ Object.keys(_obj).forEach((key => {
28
+ apply(key);
29
+ }));
30
+ }
31
+
32
+ export { applyWithProps };
@@ -0,0 +1,22 @@
1
+
2
+ export const castArray = (value) => Array.isArray(value) ? value : [value];
3
+
4
+ export const forEach = (value, callback) => {
5
+ if (Array.isArray(value) && value.length) {
6
+ value.forEach(callback);
7
+ }
8
+ };
9
+
10
+ export const some = (value, callback) => {
11
+ if (Array.isArray(value) && value.length) {
12
+ return value.some(callback);
13
+ }
14
+
15
+ return false;
16
+ };
17
+
18
+ export const map = (value, callback) => {
19
+ if (Array.isArray(value) && value.length) {
20
+ return value.map(callback);
21
+ }
22
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Object.assign-style object shallow merge/extend.
3
+ *
4
+ * @param {Object} target
5
+ * @param {Object} ...sources
6
+ * @return {Object}
7
+ */
8
+ function assign(target, ...sources) {
9
+ if (Object.assign) {
10
+ return Object.assign(target, ...sources);
11
+ }
12
+
13
+ sources.forEach(source => {
14
+ if (!source) {
15
+ return;
16
+ }
17
+
18
+ Object.keys(source).forEach((key) => {
19
+ const value = source[key];
20
+ target[key] = value;
21
+ });
22
+ });
23
+
24
+ return target;
25
+ }
26
+
27
+ export { assign };