cloudinary-video-player 3.12.1 → 3.12.2-edge.0
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.
- package/dist/134.min.js +8 -0
- package/dist/309.min.js +6 -0
- package/dist/adaptive-streaming.js +9 -9
- package/dist/adaptive-streaming.min.js +2 -2
- package/dist/chapters.js +4 -4
- package/dist/chapters.min.js +3 -3
- package/dist/cld-player-core.js +37 -0
- package/dist/cld-player-core.min.js +6 -0
- package/dist/cld-video-player-lazy.js +494 -0
- package/dist/cld-video-player-lazy.min.js +6 -0
- package/dist/cld-video-player.css +2 -2
- package/dist/cld-video-player.js +366 -332
- package/dist/cld-video-player.light.js +366 -332
- package/dist/cld-video-player.light.min.js +4 -4
- package/dist/cld-video-player.min.css +2 -2
- package/dist/cld-video-player.min.js +4 -4
- package/dist/colors.js +4 -4
- package/dist/colors.min.js +2 -2
- package/dist/dash.js +6 -6
- package/dist/dash.min.js +2 -2
- package/dist/debug.js +8 -8
- package/dist/debug.min.js +3 -3
- package/dist/ima.js +9 -9
- package/dist/ima.min.js +2 -2
- package/dist/interaction-areas.js +11 -11
- package/dist/interaction-areas.min.js +2 -2
- package/dist/node_modules_lodash_throttle_js.js +8 -8
- package/dist/playlist.js +31 -31
- package/dist/playlist.min.js +3 -3
- package/dist/recommendations-overlay.js +10 -10
- package/dist/recommendations-overlay.min.js +2 -2
- package/dist/schema.json +19 -0
- package/dist/share.js +5 -5
- package/dist/share.min.js +3 -3
- package/dist/shoppable.js +12 -12
- package/dist/shoppable.min.js +2 -2
- package/dist/utils_fetch-config_js.js +81 -0
- package/dist/video-player_js.js +3111 -0
- package/dist/visual-search.js +7 -7
- package/dist/visual-search.min.js +2 -2
- package/lib/_commonjsHelpers.js +7 -0
- package/lib/_videojs-proxy.js +30294 -0
- package/lib/abr-strategies.js +31 -0
- package/lib/adaptive-streaming.js +468 -2
- package/lib/all.js +25 -2
- package/lib/chapters.js +205 -1
- package/lib/cld-video-player.min.css +5 -22
- package/lib/colors.js +59 -1
- package/lib/{schema.json → config/configSchema.json} +19 -0
- package/lib/dash.js +69943 -2
- package/lib/debug.js +322 -1
- package/lib/document.js +770 -0
- package/lib/download-button.js +48 -0
- package/lib/fetch-config.js +93 -0
- package/lib/ima.js +6851 -1
- package/lib/index.js +27 -0
- package/lib/interaction-areas.const.js +24 -0
- package/lib/interaction-areas.service.js +469 -0
- package/lib/lazy.js +20 -0
- package/lib/noop.js +33 -0
- package/lib/player-api.js +469 -0
- package/lib/player.js +7 -2
- package/lib/playlist-panel.js +602 -0
- package/lib/playlist.js +637 -1
- package/lib/querystring.js +81 -0
- package/lib/recommendations-overlay.js +320 -1
- package/lib/share.js +129 -1
- package/lib/shoppable-post-widget.js +572 -0
- package/lib/shoppable-widget.js +77 -0
- package/lib/throttle.js +318 -0
- package/lib/toNumber.js +134 -0
- package/lib/validators-functions.js +485 -0
- package/lib/video-player.js +16241 -0
- package/lib/videoPlayer.js +7 -2
- package/lib/videojs-contrib-hlsjs.js +37638 -0
- package/lib/visual-search.js +235 -1
- package/package.json +31 -15
- package/lib/adaptive-streaming.js.LICENSE.txt +0 -3
- package/lib/all.js.LICENSE.txt +0 -25
- package/lib/cld-video-player.js +0 -2
- package/lib/cld-video-player.js.LICENSE.txt +0 -21
- package/lib/dash.js.LICENSE.txt +0 -1842
- package/lib/interaction-areas.js +0 -1
- package/lib/player.js.LICENSE.txt +0 -21
- package/lib/shoppable.js +0 -1
- package/lib/videoPlayer.js.LICENSE.txt +0 -21
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
import { _ as _vjs } from './_videojs-proxy.js';
|
|
2
|
+
import { P as PLAYER_EVENT, h as find, I as ImageSource } from './video-player.js';
|
|
3
|
+
import { t as throttle } from './throttle.js';
|
|
4
|
+
|
|
5
|
+
// Convert time string i.e. '2:40' to seconds number (160)
|
|
6
|
+
// Also allows h:m:s format and mm:ss, m:s etc.
|
|
7
|
+
const parseTime = function (hms) {
|
|
8
|
+
const [seconds, minutes, hours] = hms.split(':').reverse();
|
|
9
|
+
let sum = null;
|
|
10
|
+
if (!isNaN(seconds)) {
|
|
11
|
+
sum = (+hours || 0) * 60 * 60 + (+minutes || 0) * 60 + +seconds;
|
|
12
|
+
}
|
|
13
|
+
return sum;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const SHOPPABLE_WIDGET_OPTIONS_DEFAULTS = {
|
|
17
|
+
location: 'right',
|
|
18
|
+
toggleIcon: '',
|
|
19
|
+
width: '20%',
|
|
20
|
+
startState: 'openOnPlay',
|
|
21
|
+
autoClose: 2,
|
|
22
|
+
transformation: {
|
|
23
|
+
quality: 'auto',
|
|
24
|
+
width: 'auto',
|
|
25
|
+
fetch_format: 'auto',
|
|
26
|
+
crop: 'scale'
|
|
27
|
+
},
|
|
28
|
+
products: [],
|
|
29
|
+
showPostPlayOverlay: false
|
|
30
|
+
};
|
|
31
|
+
const SHOPPABLE_CLICK_ACTIONS = {
|
|
32
|
+
GO_TO: 'goto',
|
|
33
|
+
SEEk: 'seek'
|
|
34
|
+
};
|
|
35
|
+
const SHOPPABLE_HOVER_ACTIONS = {
|
|
36
|
+
OVERLAY: 'overlay'
|
|
37
|
+
};
|
|
38
|
+
const SHOPPABLE_PANEL_VISIBLE_CLASS = 'shoppable-panel-visible';
|
|
39
|
+
const SHOPPABLE_PANEL_HIDDEN_CLASS = 'shoppable-panel-hidden';
|
|
40
|
+
const SHOPPABLE_PRODUCTS_OVERLAY_CLASS = 'shoppable-products-overlay';
|
|
41
|
+
const CLD_SPBL_PANEL_CLASS = 'cld-spbl-panel';
|
|
42
|
+
const CLD_SPBL_TOGGLE_CLASS = 'cld-spbl-toggle';
|
|
43
|
+
const CLD_SPBL_TOGGLE_ICON_CLASS = 'cld-spbl-toggle-icon';
|
|
44
|
+
const CLD_SPBL_INNER_BAR = 'cld-spbl-bar-inner';
|
|
45
|
+
const CLD_SPBL_TOGGLE_CUSTOM_ICON_CLASS = 'cld-spbl-toggle-custom-icon';
|
|
46
|
+
const ICON_CART_CLASS = 'vjs-icon-cart';
|
|
47
|
+
const CLOSE_ICON_CLASS = 'vjs-icon-close';
|
|
48
|
+
const SHOPPABLE_ANIMATION_CLASS = 'animate';
|
|
49
|
+
const CLD_SPBL_ITEM = 'cld-spbl-item';
|
|
50
|
+
const CLD_SPBL_IMAGE = 'cld-spbl-img';
|
|
51
|
+
|
|
52
|
+
const dom$4 = _vjs.dom || _vjs;
|
|
53
|
+
const Component$2 = _vjs.getComponent('Component');
|
|
54
|
+
class ShoppableProductsOverlay extends Component$2 {
|
|
55
|
+
constructor(player) {
|
|
56
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
57
|
+
super(player, options);
|
|
58
|
+
this.options_ = options;
|
|
59
|
+
this.player_ = player;
|
|
60
|
+
this.player_.on(PLAYER_EVENT.SHOW_PRODUCTS_OVERLAY, this.renderProducts);
|
|
61
|
+
this.dispose = () => {
|
|
62
|
+
this.layout_.dispose();
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
renderProducts = () => {
|
|
66
|
+
// Close products side-panel
|
|
67
|
+
this.player_.removeClass(SHOPPABLE_PANEL_VISIBLE_CLASS);
|
|
68
|
+
this.player_.addClass(SHOPPABLE_PANEL_HIDDEN_CLASS);
|
|
69
|
+
this.player_.addClass(SHOPPABLE_PRODUCTS_OVERLAY_CLASS);
|
|
70
|
+
this.layout_.innerHTML = '';
|
|
71
|
+
|
|
72
|
+
// Filter products with appearance on currentTime
|
|
73
|
+
const currentTime = this.player_.currentTime();
|
|
74
|
+
const currentProducts = this.options_.products.filter(product => product.hotspots && product.hotspots.some(a => parseTime(a.time) === currentTime));
|
|
75
|
+
currentProducts.forEach(product => {
|
|
76
|
+
const hotspot = find(product.hotspots, hs => parseTime(hs.time) === currentTime);
|
|
77
|
+
const productName = dom$4.createEl('div', {
|
|
78
|
+
className: 'cld-spbl-product-hotspot-name'
|
|
79
|
+
}, {}, product.productName);
|
|
80
|
+
const productTooltip = dom$4.createEl('div', {
|
|
81
|
+
className: 'cld-spbl-product-tooltip cld-spbl-product-tooltip-' + hotspot.tooltipPosition
|
|
82
|
+
}, {}, productName);
|
|
83
|
+
const productHotSpot = dom$4.createEl('a', {
|
|
84
|
+
className: 'cld-spbl-product-hotspot accent-color-text',
|
|
85
|
+
href: hotspot.clickUrl,
|
|
86
|
+
target: '_blank'
|
|
87
|
+
}, {
|
|
88
|
+
style: 'left:' + hotspot.x + '; top:' + hotspot.y + ';'
|
|
89
|
+
}, productTooltip);
|
|
90
|
+
this.layout_.appendChild(productHotSpot);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Remove
|
|
94
|
+
this.player_.one(PLAYER_EVENT.SEEKING, this.clearLayout);
|
|
95
|
+
this.player_.one(PLAYER_EVENT.PLAY, this.clearLayout);
|
|
96
|
+
};
|
|
97
|
+
clearLayout = () => {
|
|
98
|
+
this.layout_.innerHTML = '';
|
|
99
|
+
this.player_.removeClass(SHOPPABLE_PRODUCTS_OVERLAY_CLASS);
|
|
100
|
+
};
|
|
101
|
+
createEl() {
|
|
102
|
+
const dimensions = this.player_.currentDimensions();
|
|
103
|
+
this.layout_ = dom$4.createEl('div', {
|
|
104
|
+
className: 'cld-spbl-products-overlay',
|
|
105
|
+
style: `padding-top: ${dimensions.height / dimensions.width * 100}%;`
|
|
106
|
+
});
|
|
107
|
+
return this.layout_;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
_vjs.registerComponent('ShoppableProductsOverlay', ShoppableProductsOverlay);
|
|
111
|
+
|
|
112
|
+
const dom$3 = _vjs.dom || _vjs;
|
|
113
|
+
const ClickableComponent$1 = _vjs.getComponent('ClickableComponent');
|
|
114
|
+
class ShoppablePanelToggle extends ClickableComponent$1 {
|
|
115
|
+
constructor(player, options) {
|
|
116
|
+
super(player, options);
|
|
117
|
+
this.options_ = options;
|
|
118
|
+
}
|
|
119
|
+
handleClick(event) {
|
|
120
|
+
event.preventDefault();
|
|
121
|
+
event.stopPropagation();
|
|
122
|
+
this.options_.clickHandler();
|
|
123
|
+
}
|
|
124
|
+
createEl() {
|
|
125
|
+
let iconProps = {};
|
|
126
|
+
let iconAttrs = {};
|
|
127
|
+
if (this.options_.toggleIcon) {
|
|
128
|
+
iconProps = {
|
|
129
|
+
className: `${CLD_SPBL_TOGGLE_ICON_CLASS} ${CLD_SPBL_TOGGLE_CUSTOM_ICON_CLASS} ${CLOSE_ICON_CLASS}`
|
|
130
|
+
};
|
|
131
|
+
iconAttrs = {
|
|
132
|
+
style: `background-image: url(${this.options_.toggleIcon})`
|
|
133
|
+
};
|
|
134
|
+
} else {
|
|
135
|
+
iconProps = {
|
|
136
|
+
className: `${CLD_SPBL_TOGGLE_ICON_CLASS} ${ICON_CART_CLASS}`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const icon = dom$3.createEl('span', iconProps, iconAttrs);
|
|
140
|
+
const el = super.createEl('a', {
|
|
141
|
+
className: `${CLD_SPBL_TOGGLE_CLASS} base-color-bg`
|
|
142
|
+
});
|
|
143
|
+
el.appendChild(icon);
|
|
144
|
+
this.player_.on(PLAYER_EVENT.PRODUCT_BAR_MIN, () => {
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
icon.classList.add(SHOPPABLE_ANIMATION_CLASS);
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
icon.classList.remove(SHOPPABLE_ANIMATION_CLASS);
|
|
149
|
+
}, 1000);
|
|
150
|
+
}, 500);
|
|
151
|
+
});
|
|
152
|
+
return el;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
_vjs.registerComponent('shoppablePanelToggle', ShoppablePanelToggle);
|
|
156
|
+
|
|
157
|
+
const dom$2 = _vjs.dom || _vjs;
|
|
158
|
+
const Component$1 = _vjs.getComponent('Component');
|
|
159
|
+
class ShoppableBarLayout extends Component$1 {
|
|
160
|
+
constructor(player, options) {
|
|
161
|
+
super(player, options);
|
|
162
|
+
this.player_ = player;
|
|
163
|
+
this.player().addClass('cld-shoppable-panel');
|
|
164
|
+
this.player().addClass(SHOPPABLE_PANEL_HIDDEN_CLASS);
|
|
165
|
+
this.contentWrpEl_ = dom$2.createEl('div', {
|
|
166
|
+
className: 'cld-spbl-bar'
|
|
167
|
+
});
|
|
168
|
+
this.contentBannerEl_ = dom$2.createEl('div', {
|
|
169
|
+
className: 'cld-spbl-banner-msg base-color-text'
|
|
170
|
+
}, {}, this.options_.bannerMsg || 'Shop the Video');
|
|
171
|
+
this.contentWrpEl_.appendChild(this.contentBannerEl_);
|
|
172
|
+
const productsOverlay = new ShoppableProductsOverlay(this.player_, this.options_);
|
|
173
|
+
this.contentWrpEl_.appendChild(productsOverlay.el_);
|
|
174
|
+
this.contentEl_ = dom$2.createEl('div', {
|
|
175
|
+
className: CLD_SPBL_INNER_BAR
|
|
176
|
+
});
|
|
177
|
+
this.contentWrpEl_.appendChild(this.contentEl_);
|
|
178
|
+
this.player().el().appendChild(this.contentWrpEl_);
|
|
179
|
+
this.addChild(new ShoppablePanelToggle(this.player_, {
|
|
180
|
+
toggleIcon: this.options_.toggleIcon,
|
|
181
|
+
clickHandler: () => {
|
|
182
|
+
this.togglePanel();
|
|
183
|
+
}
|
|
184
|
+
}));
|
|
185
|
+
this.addChild('ShoppablePanel', this.options_);
|
|
186
|
+
this.dispose = () => {
|
|
187
|
+
this.removeLayout();
|
|
188
|
+
super.dispose();
|
|
189
|
+
};
|
|
190
|
+
this.togglePanel = open => {
|
|
191
|
+
if (open === true) {
|
|
192
|
+
// Open
|
|
193
|
+
this.player().removeClass(SHOPPABLE_PANEL_HIDDEN_CLASS);
|
|
194
|
+
this.player().addClass(SHOPPABLE_PANEL_VISIBLE_CLASS);
|
|
195
|
+
} else if (open === false) {
|
|
196
|
+
// Close
|
|
197
|
+
this.player().removeClass(SHOPPABLE_PANEL_VISIBLE_CLASS);
|
|
198
|
+
this.player().addClass(SHOPPABLE_PANEL_HIDDEN_CLASS);
|
|
199
|
+
} else {
|
|
200
|
+
// Toggle
|
|
201
|
+
this.player().toggleClass(SHOPPABLE_PANEL_HIDDEN_CLASS);
|
|
202
|
+
this.player().toggleClass(SHOPPABLE_PANEL_VISIBLE_CLASS);
|
|
203
|
+
}
|
|
204
|
+
let eventName = this.player().hasClass(SHOPPABLE_PANEL_VISIBLE_CLASS) ? 'productBarMax' : 'productBarMin';
|
|
205
|
+
this.player().trigger(eventName);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// Open shoppable
|
|
209
|
+
if (this.options_.startState === 'open') {
|
|
210
|
+
this.togglePanel(true);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// On play start
|
|
214
|
+
this.player_.on(PLAYER_EVENT.PLAY, () => {
|
|
215
|
+
if (this.player_.currentTime() < 0.01) {
|
|
216
|
+
// Open shoppable on-play
|
|
217
|
+
if (this.options_.startState === 'openOnPlay') {
|
|
218
|
+
this.togglePanel(true, this.options_.autoClose);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Auto-close shoppable
|
|
222
|
+
if (this.options_.autoClose && this.options_.startState.indexOf('open') !== -1) {
|
|
223
|
+
setTimeout(() => {
|
|
224
|
+
// Keep it open while hovered
|
|
225
|
+
if (!this.contentEl_.matches(':hover')) {
|
|
226
|
+
this.togglePanel(false);
|
|
227
|
+
} else {
|
|
228
|
+
this.contentEl_.addEventListener('mouseleave', () => {
|
|
229
|
+
this.togglePanel(false);
|
|
230
|
+
}, {
|
|
231
|
+
once: true
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}, this.options_.autoClose * 1000);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
createEl() {
|
|
240
|
+
const el = super.createEl('div');
|
|
241
|
+
return el;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
_vjs.registerComponent('shoppableBarLayout', ShoppableBarLayout);
|
|
245
|
+
|
|
246
|
+
const ClickableComponent = _vjs.getComponent('ClickableComponent');
|
|
247
|
+
const dom$1 = _vjs.dom || _vjs;
|
|
248
|
+
const widthTransformation = {
|
|
249
|
+
width: 132
|
|
250
|
+
};
|
|
251
|
+
class ShoppablePanelItem extends ClickableComponent {
|
|
252
|
+
constructor(player, initOptions) {
|
|
253
|
+
super(player, initOptions);
|
|
254
|
+
this.options_ = initOptions;
|
|
255
|
+
this.isDragged = false;
|
|
256
|
+
}
|
|
257
|
+
handleClick(event) {
|
|
258
|
+
event.preventDefault();
|
|
259
|
+
event.stopPropagation();
|
|
260
|
+
if (!this.el_.matches(`.dragged .${CLD_SPBL_ITEM}`)) {
|
|
261
|
+
// Prevent click event if dragged
|
|
262
|
+
this.options_.clickHandler(event);
|
|
263
|
+
}
|
|
264
|
+
this.isDragged = false;
|
|
265
|
+
}
|
|
266
|
+
getTitle() {
|
|
267
|
+
return this.options_.conf.title;
|
|
268
|
+
}
|
|
269
|
+
createEl() {
|
|
270
|
+
const el = super.createEl('a', {
|
|
271
|
+
className: `${CLD_SPBL_ITEM} base-color-bg accent-color-text`,
|
|
272
|
+
href: '#'
|
|
273
|
+
});
|
|
274
|
+
el.setAttribute('data-product-id', this.options_.conf.productId || '');
|
|
275
|
+
el.setAttribute('data-product-name', this.options_.conf.productName || '');
|
|
276
|
+
if (this.options_.conf.onHover) {
|
|
277
|
+
addOnHover(el, this.options_.conf.onHover, this.options_.item.cloudinaryConfig());
|
|
278
|
+
}
|
|
279
|
+
if (this.options_.conf.onClick) {
|
|
280
|
+
addOnClick(el, this.options_.conf.onClick);
|
|
281
|
+
}
|
|
282
|
+
const img = super.createEl('img', {
|
|
283
|
+
className: CLD_SPBL_IMAGE
|
|
284
|
+
}, {
|
|
285
|
+
src: this.options_.item.url(widthTransformation)
|
|
286
|
+
});
|
|
287
|
+
el.appendChild(img);
|
|
288
|
+
if (this.getTitle()) {
|
|
289
|
+
const info = dom$1.createEl('div', {
|
|
290
|
+
className: 'cld-spbl-item-info base-color-semi-bg text-color-text'
|
|
291
|
+
});
|
|
292
|
+
const title = dom$1.createEl('span', {
|
|
293
|
+
className: 'cld-spbl-item-title'
|
|
294
|
+
}, {}, this.getTitle());
|
|
295
|
+
info.appendChild(title);
|
|
296
|
+
el.appendChild(info);
|
|
297
|
+
}
|
|
298
|
+
return el;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const addOnHover = (el, conf, cldConf) => {
|
|
302
|
+
el.setAttribute('data-hover-action', conf.action);
|
|
303
|
+
if (conf.action === SHOPPABLE_HOVER_ACTIONS.OVERLAY) {
|
|
304
|
+
const overlayText = dom$1.createEl('span', {
|
|
305
|
+
className: 'cld-spbl-overlay-text base-color-text'
|
|
306
|
+
}, {}, conf.args);
|
|
307
|
+
const overlay = dom$1.createEl('span', {
|
|
308
|
+
className: 'cld-spbl-overlay text-color-semi-bg base-color-text'
|
|
309
|
+
}, {
|
|
310
|
+
title: conf.args
|
|
311
|
+
}, overlayText);
|
|
312
|
+
el.appendChild(overlay);
|
|
313
|
+
} else {
|
|
314
|
+
const switchImgSource = new ImageSource(conf.args.publicId, {
|
|
315
|
+
cloudinaryConfig: cldConf,
|
|
316
|
+
transformation: conf.args.transformation
|
|
317
|
+
});
|
|
318
|
+
const hoverImg = dom$1.createEl('img', {
|
|
319
|
+
className: `${CLD_SPBL_IMAGE} cld-spbl-hover-img`
|
|
320
|
+
}, {
|
|
321
|
+
src: switchImgSource.url(widthTransformation)
|
|
322
|
+
});
|
|
323
|
+
el.appendChild(hoverImg);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
const addOnClick = (el, conf) => {
|
|
327
|
+
el.setAttribute('data-click-action', conf.action);
|
|
328
|
+
el.setAttribute('data-pause', conf.pause);
|
|
329
|
+
if (conf.action === SHOPPABLE_CLICK_ACTIONS.SEEk) {
|
|
330
|
+
el.setAttribute('data-seek', conf.args.time);
|
|
331
|
+
} else if (conf.action === SHOPPABLE_CLICK_ACTIONS.GO_TO) {
|
|
332
|
+
el.setAttribute('data-goto-url', conf.args.url);
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
_vjs.registerComponent('shoppablePanelItem', ShoppablePanelItem);
|
|
336
|
+
|
|
337
|
+
const Component = _vjs.getComponent('Component');
|
|
338
|
+
class ShoppablePanel extends Component {
|
|
339
|
+
constructor(player) {
|
|
340
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
341
|
+
super(player, options);
|
|
342
|
+
this.options = options;
|
|
343
|
+
const itemChangeHandler = () => {
|
|
344
|
+
this.render();
|
|
345
|
+
};
|
|
346
|
+
player.on(PLAYER_EVENT.SHOPPABLE_ITEM_CHANGED, itemChangeHandler);
|
|
347
|
+
this.render();
|
|
348
|
+
this.dispose = () => {
|
|
349
|
+
super.dispose();
|
|
350
|
+
player.off(PLAYER_EVENT.SHOPPABLE_ITEM_CHANGED, itemChangeHandler);
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
createEl() {
|
|
354
|
+
const el = super.createEl();
|
|
355
|
+
[CLD_SPBL_PANEL_CLASS, 'base-color-bg'].map(cls => el.classList.add(cls));
|
|
356
|
+
return el;
|
|
357
|
+
}
|
|
358
|
+
removeAll() {
|
|
359
|
+
const childrens = this.children();
|
|
360
|
+
for (let i = childrens.length - 1; i >= 0; --i) {
|
|
361
|
+
this.removeChild(childrens[i]);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
getItems() {
|
|
365
|
+
const cloudinaryConfig = this.player_.cloudinary.cloudinaryConfig();
|
|
366
|
+
return this.options.products.map(product => {
|
|
367
|
+
if (product.onHover && typeof product.onHover.args === 'object') {
|
|
368
|
+
product.onHover.args.transformation = Object.assign({}, this.options.transformation, product.onHover.args.transformation);
|
|
369
|
+
}
|
|
370
|
+
const conf = {
|
|
371
|
+
productId: product.productId,
|
|
372
|
+
productName: product.productName,
|
|
373
|
+
title: product.title,
|
|
374
|
+
onHover: product.onHover,
|
|
375
|
+
onClick: product.onClick,
|
|
376
|
+
startTime: product.startTime,
|
|
377
|
+
endTime: product.endTime
|
|
378
|
+
};
|
|
379
|
+
const imageSource = new ImageSource(product.publicId, {
|
|
380
|
+
cloudinaryConfig: cloudinaryConfig,
|
|
381
|
+
transformation: Object.assign({}, this.options.transformation, product.transformation)
|
|
382
|
+
});
|
|
383
|
+
return {
|
|
384
|
+
imageSrc: imageSource,
|
|
385
|
+
conf: conf
|
|
386
|
+
};
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
scrollToActiveItem() {
|
|
390
|
+
const activeItems = this.el_.getElementsByClassName('active');
|
|
391
|
+
if (activeItems.length > 0) {
|
|
392
|
+
const toScroll = activeItems[0].offsetTop - 12;
|
|
393
|
+
// Test for native scrollTo support (IE will fail)
|
|
394
|
+
if ('scrollBehavior' in document.documentElement.style) {
|
|
395
|
+
this.el_.scrollTo({
|
|
396
|
+
top: toScroll,
|
|
397
|
+
behavior: 'smooth'
|
|
398
|
+
});
|
|
399
|
+
} else {
|
|
400
|
+
this.el_.scrollTop = toScroll;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
render() {
|
|
405
|
+
this.removeAll();
|
|
406
|
+
const items = this.getItems();
|
|
407
|
+
const throttledScrollToActiveItem = throttle(() => this.scrollToActiveItem(), 1000);
|
|
408
|
+
items.forEach((item, index) => {
|
|
409
|
+
const shoppablePanelItem = new ShoppablePanelItem(this.player(), {
|
|
410
|
+
item: item.imageSrc,
|
|
411
|
+
conf: item.conf,
|
|
412
|
+
next: index === 1,
|
|
413
|
+
current: index === 0,
|
|
414
|
+
clickHandler: e => {
|
|
415
|
+
let target = e.currentTarget || e.target;
|
|
416
|
+
let evName = this.player_.ended() ? 'productClickPost' : 'productClick';
|
|
417
|
+
this.player_.trigger(evName, {
|
|
418
|
+
productId: target.dataset.productId,
|
|
419
|
+
productName: target.dataset.productName
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
// Go to URL, or seek video (set currentTime)
|
|
423
|
+
if (target.dataset.clickAction === SHOPPABLE_CLICK_ACTIONS.GO_TO) {
|
|
424
|
+
window.open(target.dataset.gotoUrl, '_blank');
|
|
425
|
+
} else if (target.dataset.clickAction === SHOPPABLE_CLICK_ACTIONS.SEEk) {
|
|
426
|
+
const gotoSecs = parseTime(target.dataset.seek);
|
|
427
|
+
if (gotoSecs !== null) {
|
|
428
|
+
this.player_.addClass('vjs-has-started'); // Hide the poster image
|
|
429
|
+
if (this.player_.postModal) {
|
|
430
|
+
this.player_.postModal.close();
|
|
431
|
+
}
|
|
432
|
+
this.player_.currentTime(gotoSecs);
|
|
433
|
+
// Close products side-panel
|
|
434
|
+
this.player_.removeClass(SHOPPABLE_PANEL_VISIBLE_CLASS);
|
|
435
|
+
this.player_.addClass(SHOPPABLE_PANEL_HIDDEN_CLASS);
|
|
436
|
+
this.player_.addClass(SHOPPABLE_PRODUCTS_OVERLAY_CLASS);
|
|
437
|
+
// Wait for the time update and show the tooltips
|
|
438
|
+
this.player_.one('seeked', () => this.player_.trigger('showProductsOverlay'));
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// pause - true (default), false, or number of seconds
|
|
443
|
+
if (target.dataset.pause !== 'false') {
|
|
444
|
+
this.player_.pause();
|
|
445
|
+
if (parseTime(target.dataset.pause)) {
|
|
446
|
+
setTimeout(() => {
|
|
447
|
+
this.player_.play();
|
|
448
|
+
}, parseTime(target.dataset.pause) * 1000);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
shoppablePanelItem.on('mouseover', e => {
|
|
454
|
+
let target = e.currentTarget || e.target;
|
|
455
|
+
let evName = this.player_.ended() ? 'productHoverPost' : 'productHover';
|
|
456
|
+
this.player_.trigger(evName, {
|
|
457
|
+
productId: target.dataset.productId,
|
|
458
|
+
productName: target.dataset.productName
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
if (typeof item.conf.startTime !== 'undefined' && typeof item.conf.endTime !== 'undefined') {
|
|
462
|
+
this.player_.on(PLAYER_EVENT.TIME_UPDATE, () => {
|
|
463
|
+
const time = this.player_.currentTime();
|
|
464
|
+
if (time >= item.conf.startTime && time < item.conf.endTime) {
|
|
465
|
+
shoppablePanelItem.el_.classList.add('active');
|
|
466
|
+
throttledScrollToActiveItem();
|
|
467
|
+
} else if (shoppablePanelItem.el_.classList.contains('active')) {
|
|
468
|
+
shoppablePanelItem.el_.classList.remove('active');
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
this.addChild(shoppablePanelItem);
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
_vjs.registerComponent('shoppablePanel', ShoppablePanel);
|
|
477
|
+
|
|
478
|
+
const dom = _vjs.dom || _vjs;
|
|
479
|
+
class ShoppablePostWidget {
|
|
480
|
+
constructor(player) {
|
|
481
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
482
|
+
this.options_ = {
|
|
483
|
+
...options,
|
|
484
|
+
postPlay: true
|
|
485
|
+
};
|
|
486
|
+
this.player_ = player;
|
|
487
|
+
this.render();
|
|
488
|
+
|
|
489
|
+
// Handle drag-to-scroll
|
|
490
|
+
this.handleDragToScroll();
|
|
491
|
+
this.dispose = () => {
|
|
492
|
+
this.layout_.dispose();
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
handleDragToScroll() {
|
|
496
|
+
const postModal = this.player_.postModal.el_;
|
|
497
|
+
const slider = postModal.querySelector(`.${CLD_SPBL_PANEL_CLASS}`);
|
|
498
|
+
let isDown = false;
|
|
499
|
+
let startX = 0;
|
|
500
|
+
let scrollLeft = 0;
|
|
501
|
+
slider.addEventListener('mousedown', e => {
|
|
502
|
+
isDown = true;
|
|
503
|
+
startX = e.pageX - slider.offsetLeft;
|
|
504
|
+
scrollLeft = slider.scrollLeft;
|
|
505
|
+
});
|
|
506
|
+
document.addEventListener('mouseup', e => {
|
|
507
|
+
isDown = false;
|
|
508
|
+
setTimeout(() => {
|
|
509
|
+
slider.classList.remove('dragged');
|
|
510
|
+
}, 300);
|
|
511
|
+
const x = e.pageX - slider.offsetLeft;
|
|
512
|
+
const walk = x - startX;
|
|
513
|
+
if (Math.abs(walk) > 5) {
|
|
514
|
+
e.preventDefault();
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
document.addEventListener('mousemove', e => {
|
|
518
|
+
if (!isDown) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
e.preventDefault();
|
|
522
|
+
const x = e.pageX - slider.offsetLeft;
|
|
523
|
+
const walk = x - startX;
|
|
524
|
+
slider.scrollLeft = scrollLeft - walk;
|
|
525
|
+
if (Math.abs(walk) > 5 && !slider.classList.contains('dragged')) {
|
|
526
|
+
slider.classList.add('dragged');
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
render() {
|
|
531
|
+
this.player_.postModal = null;
|
|
532
|
+
const el = dom.createEl('div', {
|
|
533
|
+
className: 'cld-spbl-post-play'
|
|
534
|
+
});
|
|
535
|
+
const panel = new ShoppablePanel(this.player_, this.options_);
|
|
536
|
+
const title = dom.createEl('div', {
|
|
537
|
+
className: 'cld-spbl-post-title base-color-text'
|
|
538
|
+
}, {}, this.options_.bannerMsg || 'Shop the Video');
|
|
539
|
+
|
|
540
|
+
// Background - poster + blur effect
|
|
541
|
+
const bgSrc = this.player_.cloudinary.currentPoster();
|
|
542
|
+
bgSrc.transformation([bgSrc.transformation().toOptions ? bgSrc.transformation().toOptions() : {}, {
|
|
543
|
+
effect: 'blur:3000'
|
|
544
|
+
}]);
|
|
545
|
+
const panelBg = dom.createEl('div', {
|
|
546
|
+
className: 'cld-spbl-post-play-bg',
|
|
547
|
+
style: `background-image: url("${bgSrc.url()}")`
|
|
548
|
+
});
|
|
549
|
+
const replayBtn = dom.createEl('button', {
|
|
550
|
+
className: 'cld-spbl-replay-btn base-color-bg vjs-icon-replay',
|
|
551
|
+
onclick: () => {
|
|
552
|
+
this.player_.trigger('replay');
|
|
553
|
+
this.player_.postModal.close();
|
|
554
|
+
this.player_.play();
|
|
555
|
+
}
|
|
556
|
+
}, {}, 'Replay');
|
|
557
|
+
el.appendChild(panelBg);
|
|
558
|
+
el.appendChild(title);
|
|
559
|
+
el.appendChild(panel.el());
|
|
560
|
+
el.appendChild(replayBtn);
|
|
561
|
+
this.player_.postModal = this.player_.createModal(el, {
|
|
562
|
+
name: 'postModal',
|
|
563
|
+
uncloseable: true
|
|
564
|
+
});
|
|
565
|
+
this.player_.addClass('cld-spbl-post-modal');
|
|
566
|
+
this.player_.postModal.on('beforemodalclose', () => {
|
|
567
|
+
this.player_.removeClass('cld-spbl-post-modal');
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export { CLD_SPBL_INNER_BAR as C, SHOPPABLE_WIDGET_OPTIONS_DEFAULTS as S, ShoppablePostWidget as a, SHOPPABLE_PANEL_VISIBLE_CLASS as b, CLD_SPBL_TOGGLE_CLASS as c, CLD_SPBL_PANEL_CLASS as d, ShoppableBarLayout as e };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { _ as _vjs } from './_videojs-proxy.js';
|
|
2
|
+
import { S as SHOPPABLE_WIDGET_OPTIONS_DEFAULTS, a as ShoppablePostWidget, C as CLD_SPBL_INNER_BAR, b as SHOPPABLE_PANEL_VISIBLE_CLASS, c as CLD_SPBL_TOGGLE_CLASS, d as CLD_SPBL_PANEL_CLASS, e as ShoppableBarLayout } from './shoppable-post-widget.js';
|
|
3
|
+
import { P as PLAYER_EVENT } from './video-player.js';
|
|
4
|
+
import './_commonjsHelpers.js';
|
|
5
|
+
import './throttle.js';
|
|
6
|
+
import './validators-functions.js';
|
|
7
|
+
import './toNumber.js';
|
|
8
|
+
import './querystring.js';
|
|
9
|
+
import './player-api.js';
|
|
10
|
+
|
|
11
|
+
class ShoppableWidget {
|
|
12
|
+
constructor(player) {
|
|
13
|
+
let initOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
14
|
+
this.options_ = _vjs.obj.merge(SHOPPABLE_WIDGET_OPTIONS_DEFAULTS, initOptions);
|
|
15
|
+
this.player_ = player;
|
|
16
|
+
if (this.options_.showPostPlayOverlay) {
|
|
17
|
+
this.player_.on(PLAYER_EVENT.ENDED, () => {
|
|
18
|
+
this.player_.addChild(new ShoppablePostWidget(this.player_, this.options_));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const width = this.options_.width;
|
|
22
|
+
this._injectCSS(`
|
|
23
|
+
.${CLD_SPBL_INNER_BAR} {
|
|
24
|
+
transform: translateX(${width});
|
|
25
|
+
}
|
|
26
|
+
.${SHOPPABLE_PANEL_VISIBLE_CLASS} .vjs-control-bar {
|
|
27
|
+
width: calc(100% - ${width});
|
|
28
|
+
}
|
|
29
|
+
.${CLD_SPBL_TOGGLE_CLASS} {
|
|
30
|
+
right: ${width};
|
|
31
|
+
}
|
|
32
|
+
.${CLD_SPBL_PANEL_CLASS}{
|
|
33
|
+
width: ${width};
|
|
34
|
+
}
|
|
35
|
+
`);
|
|
36
|
+
this._setListeners();
|
|
37
|
+
}
|
|
38
|
+
_setListeners() {
|
|
39
|
+
const resizeHandler = this._resizeHandler.bind(this);
|
|
40
|
+
this.player_.on(PLAYER_EVENT.RESIZE, resizeHandler);
|
|
41
|
+
window.addEventListener('resize', resizeHandler);
|
|
42
|
+
this.dispose = () => {
|
|
43
|
+
this.player_.off(PLAYER_EVENT.RESIZE, resizeHandler);
|
|
44
|
+
window.removeEventListener('resize', resizeHandler);
|
|
45
|
+
this.layout_.dispose();
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
_injectCSS(css) {
|
|
49
|
+
const style = document.createElement('style');
|
|
50
|
+
style.innerHTML = css;
|
|
51
|
+
this.player_.el_.appendChild(style);
|
|
52
|
+
}
|
|
53
|
+
_resizeHandler() {
|
|
54
|
+
const shoppableBarBreakpoints = [['sm', 0, 80], ['md', 81, 110], ['lg', 111, 170]];
|
|
55
|
+
const shoppableBarWidth = parseFloat(this.options_.width) / 100.0 * this.player_.el_.clientWidth;
|
|
56
|
+
let inRange = false;
|
|
57
|
+
if (shoppableBarWidth) {
|
|
58
|
+
for (const [name, min, max] of shoppableBarBreakpoints) {
|
|
59
|
+
if (shoppableBarWidth > min && shoppableBarWidth <= max) {
|
|
60
|
+
this.layout_.contentWrpEl_.setAttribute('size', name);
|
|
61
|
+
inRange = name;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!inRange) {
|
|
65
|
+
this.layout_.contentWrpEl_.removeAttribute('size');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
init() {
|
|
70
|
+
this.render();
|
|
71
|
+
}
|
|
72
|
+
render() {
|
|
73
|
+
this.layout_ = new ShoppableBarLayout(this.player_, this.options_);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { ShoppableWidget as default };
|