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,359 @@
1
+ $width: 20%;
2
+ .cld-spbl-bar {
3
+ position: absolute;
4
+ top: 0;
5
+ right: 0;
6
+ bottom: 0;
7
+ left: 0;
8
+ pointer-events: none;
9
+ overflow: hidden;
10
+ z-index: 1;
11
+ }
12
+ .cld-spbl-bar-inner {
13
+ position: absolute;
14
+ top: 0;
15
+ right: 0;
16
+ bottom: 0;
17
+ left: 0;
18
+ transform: translateX($width);
19
+ transition: transform .3s;
20
+ }
21
+ .cld-video-player .vjs-control-bar {
22
+ transition: width .3s;
23
+ }
24
+ .shoppable-panel-visible {
25
+ .cld-spbl-bar-inner {
26
+ transform: translateX(0);
27
+ }
28
+ .vjs-control-bar {
29
+ width: 100% - $width;
30
+ }
31
+ .cld-spbl-toggle-icon:before {
32
+ content: "\f119";
33
+ }
34
+ }
35
+ .cld-spbl-banner-msg {
36
+ position: absolute;
37
+ font-size: 2em;
38
+ text-shadow: 0 0 5px rgba(#000, .5);
39
+ left: 0;
40
+ top: calc(50% + 3em);
41
+ width: 100%;
42
+ text-align: center;
43
+ .cld-video-player.vjs-has-started &,
44
+ .cld-video-player.vjs-error & {
45
+ display: none;
46
+ }
47
+ }
48
+ .cld-spbl-toggle {
49
+ position: absolute;
50
+ top: 3%;
51
+ right: $width;
52
+ color: inherit;
53
+ border-radius: 6px 0 0 6px;
54
+ width: 40px;
55
+ height: 40px;
56
+ line-height: 40px;
57
+ font-size: 24px;
58
+ text-align: center;
59
+ cursor: pointer;
60
+ pointer-events: all;
61
+ text-decoration: none;
62
+ &:hover {
63
+ color: inherit;
64
+ text-decoration: none;
65
+ }
66
+ &:focus {
67
+ outline: none;
68
+ }
69
+ }
70
+ .cld-spbl-toggle-icon {
71
+
72
+ // Custom toggle icon
73
+ &.cld-spbl-toggle-custom-icon {
74
+ position: absolute;
75
+ top: 0;
76
+ right: 0;
77
+ bottom: 0;
78
+ left: 0;
79
+ background-position: center;
80
+ background-repeat: no-repeat;
81
+ background-size: 75%;
82
+ .shoppable-panel-hidden & {
83
+ &:before {
84
+ display: none;
85
+ }
86
+ }
87
+ .shoppable-panel-visible & {
88
+ background-image: none !important;
89
+ }
90
+ }
91
+
92
+ // Animate
93
+ display: block;
94
+ animation-duration: 1s;
95
+ animation-fill-mode: both;
96
+ &.animate,
97
+ .shoppable-panel-hidden &:hover {
98
+ animation-name: tada;
99
+ animation-iteration-count: infinite;
100
+ }
101
+
102
+ }
103
+ .cld-spbl-panel {
104
+ position: absolute;
105
+ top: 0;
106
+ right: 0;
107
+ bottom: 0;
108
+ width: $width;
109
+ overflow: auto;
110
+ pointer-events: all;
111
+
112
+ // Hide scrollbar
113
+ -ms-overflow-style: none; // Internet Explorer 10+
114
+ scrollbar-width: none; // Firefox
115
+ &::-webkit-scrollbar {
116
+ display: none; // Safari and Chrome
117
+ }
118
+ }
119
+ .cld-spbl-item {
120
+ display: block;
121
+ position: relative;
122
+ margin: 12px 8px;
123
+ color: inherit;
124
+ transform: scale(0.98);
125
+ transition: transform .3s;
126
+
127
+ .cld-spbl-bar[size="md"] & {
128
+ font-size: 10px;
129
+ }
130
+ .cld-spbl-bar[size="sm"] & {
131
+ font-size: 8px;
132
+ }
133
+
134
+ &:before,
135
+ &:after {
136
+ content: "";
137
+ position: absolute;
138
+ top: 0;
139
+ right: 0;
140
+ bottom: 0;
141
+ left: 0;
142
+ z-index: 0;
143
+ pointer-events: none;
144
+ box-shadow: 0 0 0;
145
+ transition: box-shadow .3s;
146
+ border-radius: 3px;
147
+ }
148
+ &.active {
149
+ transform: scale(1);
150
+ &:before {
151
+ opacity: .5;
152
+ box-shadow: 0 0 0 4px;
153
+ }
154
+ &:after {
155
+ box-shadow: 0 0 0 2px;
156
+ }
157
+
158
+ }
159
+ &:hover {
160
+ color: inherit;
161
+ }
162
+ }
163
+ .cld-spbl-img {
164
+ max-width: 100%;
165
+ height: auto;
166
+ }
167
+ .cld-spbl-hover-img {
168
+ display: none;
169
+ }
170
+ .cld-spbl-item-info {
171
+ position: absolute;
172
+ right: 0;
173
+ bottom: 0;
174
+ left: 0;
175
+ max-height: 100%;
176
+ overflow: hidden;
177
+ padding: 6%;
178
+ }
179
+ .cld-spbl-overlay {
180
+ display: inline-flex;
181
+ position: absolute;
182
+ top: 0;
183
+ right: 0;
184
+ bottom: 0;
185
+ left: 0;
186
+ line-height: 1.3;
187
+ font-size: 120%;
188
+ text-align: center;
189
+ padding: 10%;
190
+ z-index: 1;
191
+ opacity: 0;
192
+
193
+ .cld-spbl-overlay-text {
194
+ margin: auto;
195
+ }
196
+ }
197
+ .cld-spbl-item:hover {
198
+ .cld-spbl-overlay {
199
+ opacity: 1;
200
+ ~ .cld-spbl-item-info {
201
+ display: none;
202
+ }
203
+ }
204
+ .cld-spbl-hover-img {
205
+ display: block;
206
+ + {
207
+ .cld-spbl-img {
208
+ display: none;
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ .cld-spbl-post-play {
215
+ .cld-spbl-post-play-bg {
216
+ position: absolute;
217
+ top: 0;
218
+ left: 0;
219
+ bottom: 0;
220
+ right: 0;
221
+ background-size: cover;
222
+ }
223
+ .cld-spbl-post-title {
224
+ position: absolute;
225
+ font-size: 1.5em;
226
+ text-shadow: 0 0 5px rgba(#000, .5);
227
+ left: 0;
228
+ top: 0.8em;
229
+ width: 100%;
230
+ text-align: center;
231
+ }
232
+ .cld-spbl-panel {
233
+ width: 100%;
234
+ top: 16%;
235
+ height: 60%;
236
+ padding: 10px 8px;
237
+ white-space: nowrap;
238
+ background: none !important;
239
+
240
+ cursor: grab;
241
+ &:active {
242
+ cursor: grabbing;
243
+ }
244
+ }
245
+ .cld-spbl-item {
246
+ display: inline-block;
247
+ width: 28%;
248
+ padding-top: 28%;
249
+ margin: 0 8px;
250
+ white-space: normal;
251
+ vertical-align: top;
252
+ border-radius: 10px;
253
+ overflow: hidden;
254
+ box-shadow: 0 4px 6px 1.2px rgba(0,0,0,0.24), 0 6px 8px 4px rgba(0,0,0,0.24);
255
+ transform: none;
256
+ }
257
+ .cld-spbl-img {
258
+ max-width: 100%;
259
+ max-height: 100%;
260
+ position: absolute;
261
+ top: 0;
262
+ left: 0;
263
+ bottom: 0;
264
+ right: 0;
265
+ margin: 0 auto auto;
266
+ }
267
+ .cld-spbl-replay-btn {
268
+ position: absolute;
269
+ left: 5%;
270
+ bottom: 10%;
271
+ font-family: inherit;
272
+ padding: 8px 15px;
273
+ border-radius: 5px;
274
+ &:before {
275
+ font-family: VideoJS;
276
+ vertical-align: bottom;
277
+ margin-right: 4px;
278
+ }
279
+ }
280
+ }
281
+
282
+ .cld-spbl-post-modal {
283
+ .cld-spbl-bar,
284
+ .vjs-big-play-button,
285
+ .vjs-recommendations-overlay {
286
+ display: none;
287
+ }
288
+ }
289
+
290
+ @keyframes tada {
291
+ 0% {
292
+ transform: scale3d(1, 1, 1);
293
+ }
294
+ 10%, 20% {
295
+ transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
296
+ }
297
+ 30%, 50%, 70%, 90% {
298
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
299
+ }
300
+ 40%, 60%, 80% {
301
+ transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
302
+ }
303
+ 100% {
304
+ transform: scale3d(1, 1, 1);
305
+ }
306
+ }
307
+
308
+ // cld-spbl-products-overlay
309
+ .shoppable-products-overlay {
310
+ .vjs-title-bar,
311
+ .vjs-big-play-button {
312
+ display: none !important;
313
+ }
314
+ }
315
+ .cld-spbl-product-hotspot {
316
+ pointer-events: all;
317
+ position: absolute;
318
+ cursor: pointer;
319
+ padding: 15px;
320
+ &:after {
321
+ content: '';
322
+ display: block;
323
+ width: 8px;
324
+ height: 8px;
325
+ background: #fff;
326
+ box-shadow: 0 0 0 4px #0078FF, 0 0 0 8px rgba(0,120,255,0.24);
327
+ border-radius: 18px;
328
+ }
329
+
330
+ &:hover .cld-spbl-product-tooltip {
331
+ display: block;
332
+ }
333
+ }
334
+ .cld-spbl-product-tooltip {
335
+ display: none;
336
+ position: absolute;
337
+ white-space: nowrap;
338
+ padding: 4px 6px;
339
+ border-radius: 4px;
340
+ top: 100%;
341
+ left: 50%;
342
+ transform: translateX(-50%);
343
+ &.cld-spbl-product-tooltip-top {
344
+ top: auto;
345
+ bottom: 100%;
346
+ }
347
+ &.cld-spbl-product-tooltip-left {
348
+ top: 50%;
349
+ right: 100%;
350
+ left: auto;
351
+ transform: translateY(-50%);
352
+ }
353
+ &.cld-spbl-product-tooltip-right {
354
+ top: 50%;
355
+ left: 100%;
356
+ transform: translateY(-50%);
357
+ }
358
+
359
+ }
@@ -0,0 +1,3 @@
1
+ export const BUTTON_THEME = {
2
+ TRANSPARENT_WHITE: 'transparent-white'
3
+ };
@@ -0,0 +1,25 @@
1
+ import { elementsCreator } from '../../utils/dom';
2
+
3
+
4
+ export const themedButton = ({ text, onClick, theme = '', loadingDelay = 0 }) => {
5
+ return elementsCreator({
6
+ tag: 'button',
7
+ attr: { class: `vp-theme-button theme-${theme}` },
8
+ onClick,
9
+ children: [
10
+ {
11
+ tag: 'div',
12
+ attr: { class: 'vp-loading-bar' },
13
+ style: {
14
+ 'animation-duration': `${loadingDelay}ms`
15
+ }
16
+ },
17
+ {
18
+ tag: 'div',
19
+ attr: { class: 'content' },
20
+ children: text
21
+ }
22
+ ]
23
+ });
24
+ };
25
+
@@ -0,0 +1,79 @@
1
+ import videojs from 'video.js';
2
+ import 'assets/styles/components/title-bar.scss';
3
+ import componentUtils from '../component-utils';
4
+
5
+ // support VJS5 & VJS6 at the same time
6
+ const dom = videojs.dom || videojs;
7
+
8
+ const Component = videojs.getComponent('Component');
9
+
10
+ class TitleBar extends Component {
11
+
12
+ constructor(player, options = {}) {
13
+ super(player, options);
14
+
15
+ this.on(player, 'cldsourcechanged', (_, { source }) => this.setItem(source));
16
+ }
17
+
18
+ setItem(source) {
19
+ if (!source) {
20
+ this.setTitle('');
21
+ this.setSubtitle('');
22
+
23
+ return;
24
+ }
25
+
26
+ const info = source.info();
27
+
28
+ this.setTitle(info.title);
29
+ this.setSubtitle(info.subtitle);
30
+ }
31
+
32
+ setTitle(text) {
33
+ componentUtils.setText(this.titleEl, text);
34
+ this.refresh();
35
+ return text;
36
+ }
37
+
38
+ setSubtitle(text) {
39
+ componentUtils.setText(this.subtitleEl, text);
40
+ this.refresh();
41
+ return text;
42
+ }
43
+
44
+ refresh() {
45
+ const titleValue = () => this.titleEl.innerText;
46
+ const subtitleValue = () => this.subtitleEl.innerText;
47
+
48
+ if (!titleValue() && !subtitleValue()) {
49
+ this.hide();
50
+ return;
51
+ }
52
+
53
+ this.show();
54
+ }
55
+
56
+ createEl() {
57
+ this.titleEl = dom.createEl('div', {
58
+ className: 'vjs-title-bar-title'
59
+ });
60
+
61
+ this.subtitleEl = dom.createEl('div', {
62
+ className: 'vjs-title-bar-subtitle'
63
+ });
64
+
65
+ const el = super.createEl('div', {
66
+ append: this.titleEl,
67
+ className: 'vjs-title-bar'
68
+ });
69
+
70
+ el.appendChild(this.titleEl);
71
+ el.appendChild(this.subtitleEl);
72
+
73
+ return el;
74
+ }
75
+ }
76
+
77
+ videojs.registerComponent('titleBar', TitleBar);
78
+
79
+ export default TitleBar;
@@ -0,0 +1,25 @@
1
+ import contextMenuContent from '../plugins/context-menu/contextMenuContent';
2
+ import { FLOATING_TO, PRELOAD } from '../video-player.const';
3
+
4
+ export default {
5
+ logoOnclickUrl: 'https://cloudinary.com/',
6
+ showLogo: true,
7
+ showJumpControls: false,
8
+ skin: 'dark',
9
+ controls: false,
10
+ controlBar: {
11
+ 'pictureInPictureToggle': false
12
+ },
13
+ preload: PRELOAD.AUTO,
14
+ loop: false,
15
+ muted: false,
16
+ posterOptions: {},
17
+ sourceTypes: ['webm/vp9', 'mp4/h265', 'mp4'],
18
+ contextMenu: {
19
+ content: contextMenuContent
20
+ },
21
+ floatingWhenNotVisible: FLOATING_TO.NONE,
22
+ hideContextMenu: false,
23
+ analytics: false,
24
+ playedEventPercents: [25, 50, 75, 100]
25
+ };
@@ -0,0 +1,228 @@
1
+ import videojs from 'video.js';
2
+ import EventEmitter from 'events';
3
+ import { assign } from 'utils/assign';
4
+ import { isPlainObject } from 'utils/type-inference';
5
+
6
+ const EVENT_DEFAULTS = {
7
+ percentsplayed: {
8
+ percents: [25, 50, 75, 100]
9
+ }
10
+ };
11
+
12
+ const DEFAULT_EVENTS = [
13
+ 'percentsplayed',
14
+ 'pausenoseek',
15
+ 'seek',
16
+ 'mute',
17
+ 'unmute',
18
+ 'qualitychanged'
19
+ ];
20
+
21
+ const DEFAULT_OPTIONS = {
22
+ events: DEFAULT_EVENTS
23
+ };
24
+
25
+ // Emits the following additional events:
26
+ // percentsplayed, timeplayed, pausenoseek, seek, mute, unmute
27
+ class ExtendedEvents extends EventEmitter {
28
+
29
+ constructor(player, initOptions = {}) {
30
+ super();
31
+ this.player = player;
32
+ const options = videojs.mergeOptions(DEFAULT_OPTIONS, initOptions);
33
+
34
+ let _muteData = { lastState: undefined };
35
+ let _seekStart = 0;
36
+ let _seekEnd = 0;
37
+ let _seeking = false;
38
+ let _percentsTracked = [];
39
+ let _timesTracked = [];
40
+ let _currentSource = null;
41
+ let _ended = false;
42
+
43
+ const volumechange = (event) => {
44
+ if (this.player.muted() && _muteData.lastState !== 'muted') {
45
+ _muteData.lastState = 'muted';
46
+ this.emit('mute', event);
47
+ } else if (!this.player.muted() && _muteData.lastState !== 'unmuted') {
48
+ _muteData.lastState = 'unmuted';
49
+ this.emit('unmute', event);
50
+ }
51
+ };
52
+
53
+ const timeupdate = (event) => {
54
+ const currentTime = this.player.currentTime();
55
+ const duration = this.player.duration();
56
+
57
+ const _emit = (type, data) => {
58
+ data.originalType = 'timeupdate';
59
+ this.emit(type, event, data);
60
+ };
61
+
62
+ if (this.events.percentsplayed) {
63
+ this.events.percentsplayed.percents.forEach((percent) => {
64
+ if (playedAtPercentage(currentTime, duration, percent) && _percentsTracked.indexOf(percent) === -1) {
65
+ _percentsTracked.push(percent);
66
+ _emit('percentsplayed', { percent });
67
+ }
68
+ });
69
+ }
70
+
71
+ if (this.events.timeplayed) {
72
+ const timeplayed = this.events.timeplayed;
73
+ const times = timeplayed.interval ? [Math.floor(currentTime / timeplayed.interval) * timeplayed.interval] : timeplayed.times;
74
+
75
+ times.forEach((time) => {
76
+ if (playedAtTime(currentTime, time) && _timesTracked.indexOf(time) === -1) {
77
+ _timesTracked.push(time);
78
+ _emit('timeplayed', { time });
79
+ }
80
+ });
81
+ }
82
+
83
+ if (this.events.seek) {
84
+ _seekStart = _seekEnd;
85
+ _seekEnd = currentTime;
86
+
87
+ if (Math.abs(_seekStart - _seekEnd) > 1) {
88
+ _seeking = true;
89
+
90
+ // should empty _timesTracked array on seek, needed for 'timeplayed' event
91
+ resetPerVideoState();
92
+ _emit('seek', { seekStart: _seekStart, seekEnd: _seekEnd });
93
+ }
94
+ }
95
+ };
96
+
97
+ const pause = (event) => {
98
+ const currentTime = Math.round(this.player.currentTime());
99
+ const duration = Math.round(this.player.duration());
100
+
101
+ if (currentTime !== duration && !_seeking) {
102
+ this.emit('pausenoseek', event);
103
+ }
104
+ };
105
+
106
+ const play = () => {
107
+ _seeking = false;
108
+ };
109
+ const replay = () => {
110
+ if (_ended) {
111
+ this.player.trigger('replay');
112
+ _ended = false;
113
+ }
114
+ };
115
+
116
+ const loadedmetadata = () => {
117
+ if (this.player.currentSource().src !== _currentSource) {
118
+ resetPerVideoState();
119
+ _currentSource = this.player.currentSource().src;
120
+ }
121
+ };
122
+
123
+ const adaptiveEvents = (event) => {
124
+ let ee = this;
125
+ let tracks = this.player.textTracks();
126
+ let segmentMetadataTrack = null;
127
+ for (let i = 0; i < tracks.length; i++) {
128
+ if (tracks[i].label === 'segment-metadata') {
129
+ segmentMetadataTrack = tracks[i];
130
+ }
131
+
132
+ }
133
+ let previousResolution = null;
134
+
135
+ if (segmentMetadataTrack) {
136
+ segmentMetadataTrack.on('cuechange', function() {
137
+ let activeCue = segmentMetadataTrack.activeCues[0];
138
+
139
+ if (activeCue) {
140
+ let currentRes = activeCue.value.resolution;
141
+ if (previousResolution !== currentRes) {
142
+ let data = {
143
+ from: previousResolution,
144
+ to: currentRes
145
+ };
146
+ ee.emit('qualitychanged', event, data);
147
+ }
148
+ previousResolution = currentRes;
149
+ }
150
+ });
151
+ }
152
+
153
+
154
+ };
155
+
156
+ const resetState = () => {
157
+ _muteData = { lastState: undefined };
158
+ _seekStart = _seekEnd = 0;
159
+ _seeking = false;
160
+ resetPerVideoState();
161
+ };
162
+
163
+ const resetPerVideoState = () => {
164
+ _percentsTracked = [];
165
+ _timesTracked = [];
166
+ };
167
+
168
+ const ended = () => {
169
+ _ended = true;
170
+ };
171
+
172
+ this.events = normalizeEventsParam(options.events, EVENT_DEFAULTS);
173
+ resetState();
174
+
175
+ this.player.on('play', replay.bind(this));
176
+ this.player.on('ended', ended.bind(this));
177
+ if (this.events.percentsplayed || this.events.timeplayed ||
178
+ this.events.seek || this.events.totaltimeplayed) {
179
+
180
+ this.player.on('timeupdate', timeupdate.bind(this));
181
+ }
182
+
183
+ if (this.events.mute || this.events.unmute) {
184
+ this.player.on('volumechange', volumechange.bind(this));
185
+ }
186
+
187
+ if (this.events.pausenoseek) {
188
+ this.player.on('pause', pause.bind(this));
189
+ this.player.on('play', play.bind(this));
190
+ }
191
+
192
+ this.player.on('loadedmetadata', loadedmetadata.bind(this));
193
+ this.player.on('loadeddata', adaptiveEvents.bind(this));
194
+
195
+ }
196
+ }
197
+
198
+ const normalizeEventsParam = (events, defaults) => {
199
+ let normalized = events;
200
+
201
+ if (events.constructor.name === 'Array') {
202
+ normalized = events.reduce((agg, item) => {
203
+ const eventDefaults = defaults[item] || {};
204
+
205
+ if (isPlainObject(item)) {
206
+ agg[item.type] = assign({}, eventDefaults, item);
207
+ } else {
208
+ agg[item] = eventDefaults;
209
+ }
210
+
211
+ return agg;
212
+ }, {});
213
+ }
214
+
215
+ return normalized;
216
+ };
217
+
218
+ const playedAtPercentage = (currentTime, duration, percentageCheckpoint, graceRangeSeconds = 0.5) => {
219
+ const checkPoint = duration * percentageCheckpoint / 100;
220
+ return playedAtTime(currentTime, checkPoint, graceRangeSeconds);
221
+ };
222
+
223
+ const playedAtTime = (currentTime, checkpoint, graceRangeSeconds = 0.5) =>
224
+ (currentTime <= checkpoint + graceRangeSeconds &&
225
+ currentTime >= checkpoint - graceRangeSeconds);
226
+
227
+ export { normalizeEventsParam };
228
+ export default ExtendedEvents;