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.
- package/.eslintignore +4 -0
- package/.snyk +19 -0
- package/.travis.yml +8 -0
- package/CHANGELOG.md +329 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/cld-video-player.css +2110 -0
- package/dist/cld-video-player.js +5249 -0
- package/dist/cld-video-player.light.css +1766 -0
- package/dist/cld-video-player.light.js +1399 -0
- package/dist/cld-video-player.light.min.css +1 -0
- package/dist/cld-video-player.light.min.js +2 -0
- package/dist/cld-video-player.light.min.js.LICENSE.txt +23 -0
- package/dist/cld-video-player.min.css +1 -0
- package/dist/cld-video-player.min.js +2 -0
- package/dist/cld-video-player.min.js.LICENSE.txt +26 -0
- package/dist/fonts/cloudinary_icon_for_black_bg.svg +69 -0
- package/dist/fonts/cloudinary_icon_for_white_bg.svg +69 -0
- package/docs/360.html +102 -0
- package/docs/_template.html +93 -0
- package/docs/adaptive-streaming.html +297 -0
- package/docs/analytics.html +140 -0
- package/docs/api.html +302 -0
- package/docs/audio.html +136 -0
- package/docs/autoplay-fallback.html +138 -0
- package/docs/autoplay-on-scroll.html +107 -0
- package/docs/codec-fallback.html +158 -0
- package/docs/colors.html +135 -0
- package/docs/components.html +284 -0
- package/docs/custom-cld-errors.html +134 -0
- package/docs/floating-player.html +98 -0
- package/docs/fluid.html +117 -0
- package/docs/force-hls-subtitles-ios.html +159 -0
- package/docs/index.html +83 -0
- package/docs/interaction-area.html +398 -0
- package/docs/live-customer.html +128 -0
- package/docs/multiple-players.html +125 -0
- package/docs/playlist-by-tag-cap.html +182 -0
- package/docs/playlist-by-tag.html +133 -0
- package/docs/playlist.html +133 -0
- package/docs/poster.html +155 -0
- package/docs/raw-url.html +104 -0
- package/docs/recommendations.html +155 -0
- package/docs/scripts.js +156 -0
- package/docs/seek-thumbs.html +90 -0
- package/docs/shoppable.html +335 -0
- package/docs/subtitles-and-captions.html +267 -0
- package/docs/transformations.html +171 -0
- package/docs/ui-config.html +108 -0
- package/docs/vast-vpaid.html +149 -0
- package/env.example.js +6 -0
- package/env.js +6 -0
- package/jest-puppeteer.config.js +14 -0
- package/jest.config.js +196 -0
- package/package.json +99 -0
- package/sandbox.config.json +3 -0
- package/setupJest.js +1 -0
- package/src/assets/fonts/VideoJS.svg +120 -0
- package/src/assets/fonts/VideoJS.ttf +0 -0
- package/src/assets/fonts/VideoJS.woff +0 -0
- package/src/assets/fonts/icons.json +120 -0
- package/src/assets/icons/cloudinary_icon_for_black_bg.svg +69 -0
- package/src/assets/icons/cloudinary_icon_for_white_bg.svg +69 -0
- package/src/assets/icons/cloudinary_logo_for_dark_bg.svg +188 -0
- package/src/assets/icons/cloudinary_logo_for_white_bg.svg +188 -0
- package/src/assets/icons/info-circle.svg +17 -0
- package/src/assets/styles/ads-label.scss +16 -0
- package/src/assets/styles/components/interaction-areas.scss +158 -0
- package/src/assets/styles/components/playlist.scss +213 -0
- package/src/assets/styles/components/themedButton.scss +48 -0
- package/src/assets/styles/components/thumbnail.scss +94 -0
- package/src/assets/styles/components/title-bar.scss +67 -0
- package/src/assets/styles/components/triangle-volume-bar.scss +52 -0
- package/src/assets/styles/icons.scss +257 -0
- package/src/assets/styles/main.scss +324 -0
- package/src/assets/styles/mixins/aspect-ratio.scss +16 -0
- package/src/assets/styles/mixins/disable-transition.scss +3 -0
- package/src/assets/styles/mixins/mixins.scss +5 -0
- package/src/assets/styles/mixins/skin.scss +64 -0
- package/src/assets/styles/variables.scss +2 -0
- package/src/assets/styles/videojs-ima.scss +252 -0
- package/src/components/component-utils.js +20 -0
- package/src/components/index.js +21 -0
- package/src/components/interaction-area/interaction-area.const.js +30 -0
- package/src/components/interaction-area/interaction-area.service.js +223 -0
- package/src/components/interaction-area/interaction-area.utils.js +236 -0
- package/src/components/jumpButtons/jump-10-minus.js +21 -0
- package/src/components/jumpButtons/jump-10-plus.js +20 -0
- package/src/components/logoButton/logo-button.const.js +3 -0
- package/src/components/logoButton/logo-button.js +30 -0
- package/src/components/logoButton/logo-button.scss +15 -0
- package/src/components/playlist/components/playlist-button.js +34 -0
- package/src/components/playlist/components/playlist-next-button.js +18 -0
- package/src/components/playlist/components/playlist-previous-button.js +18 -0
- package/src/components/playlist/components/playlist.js +5 -0
- package/src/components/playlist/components/playlist.scss +15 -0
- package/src/components/playlist/components/upcoming-video-overlay.js +149 -0
- package/src/components/playlist/components/upcoming-video-overlay.scss +86 -0
- package/src/components/playlist/layout/playlist-layout-custom.js +21 -0
- package/src/components/playlist/layout/playlist-layout-horizontal.js +16 -0
- package/src/components/playlist/layout/playlist-layout-vertical.js +19 -0
- package/src/components/playlist/layout/playlist-layout.js +110 -0
- package/src/components/playlist/panel/playlist-panel-item.js +86 -0
- package/src/components/playlist/panel/playlist-panel.js +92 -0
- package/src/components/playlist/playlist-widget.js +119 -0
- package/src/components/playlist/playlist.const.js +14 -0
- package/src/components/playlist/playlist.js +413 -0
- package/src/components/playlist/thumbnail/thumbnail.js +69 -0
- package/src/components/progress-control-events-blocker/progress-control-events-blocker.js +17 -0
- package/src/components/qualitySelector/quality-selector.scss +10 -0
- package/src/components/qualitySelector/qualitySelector.js +152 -0
- package/src/components/recommendations-overlay/index.js +3 -0
- package/src/components/recommendations-overlay/recommendations-overlay-content.js +57 -0
- package/src/components/recommendations-overlay/recommendations-overlay-hide-button.js +18 -0
- package/src/components/recommendations-overlay/recommendations-overlay-item.js +35 -0
- package/src/components/recommendations-overlay/recommendations-overlay-primary-item.js +81 -0
- package/src/components/recommendations-overlay/recommendations-overlay-secondary-item.js +48 -0
- package/src/components/recommendations-overlay/recommendations-overlay-secondary-items-container.js +35 -0
- package/src/components/recommendations-overlay/recommendations-overlay.js +94 -0
- package/src/components/recommendations-overlay/recommendations-overlay.scss +182 -0
- package/src/components/shoppable-bar/layout/bar-layout.js +111 -0
- package/src/components/shoppable-bar/layout/shoppable-panel-toggle.js +64 -0
- package/src/components/shoppable-bar/layout/shoppable-products-overlay.js +87 -0
- package/src/components/shoppable-bar/panel/shoppable-panel-item.js +105 -0
- package/src/components/shoppable-bar/panel/shoppable-panel.js +172 -0
- package/src/components/shoppable-bar/shoppable-post-widget.js +110 -0
- package/src/components/shoppable-bar/shoppable-widget.const.js +52 -0
- package/src/components/shoppable-bar/shoppable-widget.js +111 -0
- package/src/components/shoppable-bar/shoppable-widget.scss +359 -0
- package/src/components/themeButton/themedButton.const.js +3 -0
- package/src/components/themeButton/themedButton.js +25 -0
- package/src/components/title-bar/title-bar.js +79 -0
- package/src/config/defaults.js +25 -0
- package/src/extended-events.js +228 -0
- package/src/index.js +18 -0
- package/src/mixins/eventable.js +54 -0
- package/src/mixins/playlistable.js +106 -0
- package/src/plugins/analytics/index.js +245 -0
- package/src/plugins/autoplay-on-scroll/index.js +86 -0
- package/src/plugins/cloudinary/common.js +216 -0
- package/src/plugins/cloudinary/event-handler-registry.js +46 -0
- package/src/plugins/cloudinary/index.js +345 -0
- package/src/plugins/cloudinary/models/audio-source/audio-source.const.js +11 -0
- package/src/plugins/cloudinary/models/audio-source/audio-source.js +82 -0
- package/src/plugins/cloudinary/models/base-source.js +107 -0
- package/src/plugins/cloudinary/models/image-source.js +26 -0
- package/src/plugins/cloudinary/models/video-source/video-source.const.js +32 -0
- package/src/plugins/cloudinary/models/video-source/video-source.js +239 -0
- package/src/plugins/cloudinary/models/video-source/video-source.utils.js +57 -0
- package/src/plugins/colors/index.js +303 -0
- package/src/plugins/context-menu/components/context-menu-item.js +12 -0
- package/src/plugins/context-menu/components/context-menu.js +63 -0
- package/src/plugins/context-menu/context-menu.scss +30 -0
- package/src/plugins/context-menu/contextMenuContent.js +53 -0
- package/src/plugins/context-menu/index.js +134 -0
- package/src/plugins/dash/index.js +26 -0
- package/src/plugins/dash/setup-audio-tracks.js +112 -0
- package/src/plugins/dash/setup-text-tracks.js +195 -0
- package/src/plugins/dash/videojs-dash.js +372 -0
- package/src/plugins/floating-player/floating-player.scss +74 -0
- package/src/plugins/floating-player/index.js +129 -0
- package/src/plugins/ima/index.js +1775 -0
- package/src/plugins/index.js +31 -0
- package/src/plugins/interactive-plugin/index.js +10 -0
- package/src/plugins/videojs-http-source-selector/components/SourceMenuButton.js +98 -0
- package/src/plugins/videojs-http-source-selector/components/SourceMenuItem.js +52 -0
- package/src/plugins/videojs-http-source-selector/plugin.js +82 -0
- package/src/plugins/videojs-http-source-selector/plugin.scss +9 -0
- package/src/plugins/vtt-thumbnails/index.js +526 -0
- package/src/plugins/vtt-thumbnails/vtt-thumbnails.scss +29 -0
- package/src/utils/api.js +32 -0
- package/src/utils/apply-with-props.js +32 -0
- package/src/utils/array.js +22 -0
- package/src/utils/assign.js +27 -0
- package/src/utils/attributes-normalizer.js +72 -0
- package/src/utils/cloudinary.js +165 -0
- package/src/utils/css-prefix.js +43 -0
- package/src/utils/dom.js +74 -0
- package/src/utils/find.js +28 -0
- package/src/utils/fontFace.js +25 -0
- package/src/utils/groupBy.js +12 -0
- package/src/utils/index.js +29 -0
- package/src/utils/matches.js +11 -0
- package/src/utils/mixin.js +5 -0
- package/src/utils/object.js +26 -0
- package/src/utils/playButton.js +9 -0
- package/src/utils/positioning.js +78 -0
- package/src/utils/querystring.js +12 -0
- package/src/utils/slicing.js +21 -0
- package/src/utils/string.js +15 -0
- package/src/utils/throttle.js +30 -0
- package/src/utils/time.js +77 -0
- package/src/utils/type-inference.js +35 -0
- package/src/validators/validators-functions.js +48 -0
- package/src/validators/validators-types.js +78 -0
- package/src/validators/validators.js +110 -0
- package/src/video-player.const.js +68 -0
- package/src/video-player.js +761 -0
- package/src/video-player.utils.js +123 -0
- package/test/adaptive-streaming.test.js +38 -0
- package/test/ads.test.js +35 -0
- package/test/analytics.test.js +111 -0
- package/test/api.test.js +111 -0
- package/test/autoplay.scroll.test.js +23 -0
- package/test/basic-ui.test.js +59 -0
- package/test/colors.test.js +58 -0
- package/test/components.test.js +21 -0
- package/test/custom-error.test.js +24 -0
- package/test/fluid.test.js +36 -0
- package/test/isValidConfig.test.js +224 -0
- package/test/mocks/cloudinary-core-mock.js +0 -0
- package/test/mocks/styleMock.js +1 -0
- package/test/multiplayer.test.js +25 -0
- package/test/playlist.test.js +60 -0
- package/test/puppeteer/vp-env.js +19 -0
- package/test/recommendations.test.js +38 -0
- package/test/title-bar.test.js +28 -0
- package/test/ui-conf.test.js +49 -0
- package/test/unit/cloudinaryConfig.test.js +22 -0
- package/test/unit/cloudinaryUtils.test.js +53 -0
- package/test/unit/utils.test.js +27 -0
- package/test/unit/videoSource.test.js +454 -0
- package/tsconfig.json +15 -0
- package/types/video-player-tests.js +12 -0
- package/types/video-player-tests.ts +31 -0
- package/types/video-player.d.ts +570 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { camelize } from './string';
|
|
2
|
+
|
|
3
|
+
const CLD_ATTR_REGEX = /^(data-cld-)(\w+)/;
|
|
4
|
+
|
|
5
|
+
const normalizers = {};
|
|
6
|
+
|
|
7
|
+
function coerce(string) {
|
|
8
|
+
let val = null;
|
|
9
|
+
|
|
10
|
+
// Boolean
|
|
11
|
+
if (string === '') {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Complex object
|
|
16
|
+
try {
|
|
17
|
+
val = JSON.parse(string);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
// Continue execution in case str is not parsable
|
|
20
|
+
}
|
|
21
|
+
if (val) {
|
|
22
|
+
return val;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Number
|
|
26
|
+
val = Number(string);
|
|
27
|
+
if (val) {
|
|
28
|
+
return val;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// TODO: Parse date?
|
|
32
|
+
//
|
|
33
|
+
return string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const normalizeDefault = (value) => coerce(value);
|
|
37
|
+
|
|
38
|
+
const normalizeAttributes = (elem) => {
|
|
39
|
+
const obj = {};
|
|
40
|
+
|
|
41
|
+
if (elem && elem.attributes && elem.attributes.length > 0) {
|
|
42
|
+
const attrs = elem.attributes;
|
|
43
|
+
|
|
44
|
+
for (let i = attrs.length - 1; i >= 0; i--) {
|
|
45
|
+
let attrName = attrs[i].name;
|
|
46
|
+
let attrVal = attrs[i].value;
|
|
47
|
+
|
|
48
|
+
if (attrName.match(CLD_ATTR_REGEX)) {
|
|
49
|
+
attrName = camelize(attrName.replace(CLD_ATTR_REGEX, '$2'));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// check for known booleans
|
|
53
|
+
// the matching element property will return a value for typeof
|
|
54
|
+
// if (typeof elem[attrName] === 'boolean' || KNOWN_BOOLEANS[attrName]) {
|
|
55
|
+
if (typeof elem[attrName] === 'boolean') {
|
|
56
|
+
// the value of an included boolean attribute is typically an empty
|
|
57
|
+
// string ('') which would equal false if we just check for a false value.
|
|
58
|
+
// we also don't want support bad code like autoplay='false'
|
|
59
|
+
attrVal = (attrVal !== null);
|
|
60
|
+
} else {
|
|
61
|
+
const normalizer = normalizers[attrName] || normalizeDefault;
|
|
62
|
+
attrVal = normalizer(attrVal);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
obj[attrName] = attrVal;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return obj;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export { normalizeAttributes };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import Promise from 'promise-polyfill';
|
|
2
|
+
import fetchPF from 'fetch-ponyfill/build/fetch-browser';
|
|
3
|
+
import { cloudinaryErrorsConverter, ERROR_CODE } from '../plugins/cloudinary/common';
|
|
4
|
+
import { find } from 'utils/find';
|
|
5
|
+
|
|
6
|
+
const { fetch } = fetchPF({ Promise });
|
|
7
|
+
|
|
8
|
+
const GET_ERROR_DEFAULT_REQUEST = { method: 'head' };
|
|
9
|
+
const ERROR_WITH_GET_REQUEST = { method: 'get', credentials: 'include', headers: { 'Content-Range': 'bytes=0-0' } };
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const getGoodSrcs = (srcs, parsedUris) => {
|
|
13
|
+
return srcs.filter((s) => {
|
|
14
|
+
const origUrl = parseUri(s.src);
|
|
15
|
+
return parsedUris.indexOf(origUrl.host + origUrl.path) !== -1 && s.try !== true;
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const getParsedUris = (res) => {
|
|
21
|
+
return res.reduce((acc, r) => {
|
|
22
|
+
if (r.status >= 200 && r.status < 399 && r.url !== '') {
|
|
23
|
+
const parsedUri = parseUri(r.url);
|
|
24
|
+
acc.push(parsedUri.host + parsedUri.path);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return acc;
|
|
28
|
+
}, []);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const setError = (that, res) => {
|
|
32
|
+
that.videojs.error(cloudinaryErrorsConverter({
|
|
33
|
+
errorMsg: res.headers.get('x-cld-error') || '',
|
|
34
|
+
publicId: that.currentPublicId(),
|
|
35
|
+
cloudName: that.cloudinaryConfig().config().cloud_name,
|
|
36
|
+
error: res,
|
|
37
|
+
statusCode: res.status
|
|
38
|
+
}));
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const setVideoSrc = (that, srcs) => {
|
|
42
|
+
console.log('Trying urls: ' + JSON.stringify(srcs));
|
|
43
|
+
srcs.forEach(s => {
|
|
44
|
+
s.try = true;
|
|
45
|
+
});
|
|
46
|
+
that.videojs.autoplay(that.videojs.autoplay() || that.playWasCalled);
|
|
47
|
+
that.videojs.src(srcs);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleCldError = (that, options) => {
|
|
51
|
+
const opts = options.fetchErrorUsingGet ? ERROR_WITH_GET_REQUEST : GET_ERROR_DEFAULT_REQUEST;
|
|
52
|
+
const srcs = that.videojs.cloudinary.getCurrentSources();
|
|
53
|
+
|
|
54
|
+
if (srcs.length > 0) {
|
|
55
|
+
Promise.all(srcs.map((s) => fetch(s.src, opts))).then((res) => {
|
|
56
|
+
const parsedUris = getParsedUris(res);
|
|
57
|
+
const firstRes = res[0];
|
|
58
|
+
if (!parsedUris.length) {
|
|
59
|
+
setError(that, firstRes);
|
|
60
|
+
} else {
|
|
61
|
+
const goodSrcs = getGoodSrcs(srcs, parsedUris);
|
|
62
|
+
|
|
63
|
+
if (goodSrcs && goodSrcs.length) {
|
|
64
|
+
setVideoSrc(that, goodSrcs);
|
|
65
|
+
} else {
|
|
66
|
+
console.log('No urls left to try so stopping');
|
|
67
|
+
that.videojs.error({ code: ERROR_CODE.NO_SUPPORTED_MEDIA, message: 'No supported media sources', statusCode: res.status });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
.catch(error => {
|
|
72
|
+
that.videojs.error({
|
|
73
|
+
code: 7,
|
|
74
|
+
message: error && error.message ? error.message : 'Failed to test sources'
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
that.videojs.error({ code: ERROR_CODE.NO_SUPPORTED_MEDIA, message: 'No supported media sources' });
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// for IE 11
|
|
83
|
+
function parseUri(str) {
|
|
84
|
+
const o = {
|
|
85
|
+
strictMode: false,
|
|
86
|
+
key: ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'],
|
|
87
|
+
q: {
|
|
88
|
+
name: 'queryKey',
|
|
89
|
+
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
|
|
90
|
+
},
|
|
91
|
+
parser: {
|
|
92
|
+
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
|
|
93
|
+
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const m = o.parser[o.strictMode ? 'strict' : 'loose'].exec(str);
|
|
97
|
+
const uri = {};
|
|
98
|
+
let i = 14;
|
|
99
|
+
|
|
100
|
+
while (i--) {
|
|
101
|
+
uri[o.key[i]] = m[i] || '';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
uri[o.q.name] = {};
|
|
105
|
+
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
|
|
106
|
+
if ($1) {
|
|
107
|
+
uri[o.q.name][$1] = $2;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return uri;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function getCloudinaryInstanceOf(Klass, obj) {
|
|
115
|
+
if (Array.isArray(obj)) {
|
|
116
|
+
return obj.map(e => getCloudinaryInstanceOf(Klass, e));
|
|
117
|
+
}
|
|
118
|
+
if (obj instanceof Klass) {
|
|
119
|
+
return obj;
|
|
120
|
+
} else {
|
|
121
|
+
return new Klass(obj);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Check if key exist in transformation
|
|
127
|
+
* @param transformation
|
|
128
|
+
* @param key
|
|
129
|
+
* @returns true if key exists in transformation, false otherwise
|
|
130
|
+
*/
|
|
131
|
+
const isKeyInTransformation = (transformation, key) => {
|
|
132
|
+
if (!transformation || !key) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// transformation is an array so run this function for each item
|
|
137
|
+
if (Array.isArray(transformation)) {
|
|
138
|
+
return !!find(transformation, (t) => isKeyInTransformation(t, key));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// transformation is a Transformation object so use getValue() to check key
|
|
142
|
+
if (transformation.getValue) {
|
|
143
|
+
return !!transformation.getValue(key);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// transformation is an Object so just check for key existence in object
|
|
147
|
+
return !!transformation[key];
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const filterAndAddTextTracks = (tracks, videojs) => {
|
|
151
|
+
tracks.forEach(track => {
|
|
152
|
+
fetch(track.src, GET_ERROR_DEFAULT_REQUEST).then(r => {
|
|
153
|
+
if (r.status >= 200 && r.status <= 399) {
|
|
154
|
+
videojs.addRemoteTextTrack(track, true);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export {
|
|
161
|
+
getCloudinaryInstanceOf,
|
|
162
|
+
handleCldError,
|
|
163
|
+
isKeyInTransformation,
|
|
164
|
+
filterAndAddTextTracks
|
|
165
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { startsWith } from './string';
|
|
2
|
+
import defaults from '../config/defaults';
|
|
3
|
+
import { find } from './find';
|
|
4
|
+
|
|
5
|
+
const CLASS_PREFIX = 'cld-video-player';
|
|
6
|
+
const SKIN_CLASS_PREFIX = `${CLASS_PREFIX}-skin-`;
|
|
7
|
+
|
|
8
|
+
const playerClassPrefix = (componentInstance) => `${CLASS_PREFIX}-${componentInstance.id_}`;
|
|
9
|
+
|
|
10
|
+
const skinClass = (skin) => `${SKIN_CLASS_PREFIX}${skin}`;
|
|
11
|
+
|
|
12
|
+
const skinClassPrefix = (componentInstance) => find(componentInstance.el().classList, (cls) => startsWith(cls, SKIN_CLASS_PREFIX));
|
|
13
|
+
|
|
14
|
+
const setSkinClassPrefix = (componentInstance, name) => {
|
|
15
|
+
const currentSkinPrefix = skinClassPrefix(componentInstance);
|
|
16
|
+
const skinName = name ? name.replace(SKIN_CLASS_PREFIX, '') : false;
|
|
17
|
+
|
|
18
|
+
let newSkinPrefix = '';
|
|
19
|
+
if (skinName) {
|
|
20
|
+
// From html class
|
|
21
|
+
newSkinPrefix = skinClass(skinName);
|
|
22
|
+
} else if (componentInstance.options_.skin) {
|
|
23
|
+
// From JS config
|
|
24
|
+
newSkinPrefix = skinClass(componentInstance.options_.skin);
|
|
25
|
+
} else {
|
|
26
|
+
// Defult
|
|
27
|
+
newSkinPrefix = skinClass(defaults.skin);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (newSkinPrefix !== currentSkinPrefix) {
|
|
31
|
+
if (currentSkinPrefix) {
|
|
32
|
+
componentInstance.removeClass(currentSkinPrefix);
|
|
33
|
+
}
|
|
34
|
+
componentInstance.addClass(newSkinPrefix);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (skinName && componentInstance.options_.skin !== skinName) {
|
|
38
|
+
componentInstance.options_.skin = skinName;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { CLASS_PREFIX, playerClassPrefix, skinClassPrefix, skinClass, setSkinClassPrefix };
|
package/src/utils/dom.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { castArray } from './array';
|
|
2
|
+
import { isElement } from './type-inference';
|
|
3
|
+
|
|
4
|
+
const wrap = (el, wrapper) => {
|
|
5
|
+
el.parentNode.insertBefore(wrapper, el);
|
|
6
|
+
wrapper.appendChild(el);
|
|
7
|
+
|
|
8
|
+
return wrapper;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const createElement = (elementName, attributes = {}, children) => {
|
|
12
|
+
const element = document.createElement(elementName);
|
|
13
|
+
|
|
14
|
+
for (let key in attributes) {
|
|
15
|
+
if (Object.prototype.hasOwnProperty.call(attributes, key)) {
|
|
16
|
+
element.setAttribute(key, attributes[key]);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
castArray(children).forEach(child => appendChild(child, element));
|
|
21
|
+
|
|
22
|
+
return element;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const appendChild = (child, element) => {
|
|
26
|
+
if (isElement(child)) {
|
|
27
|
+
element.appendChild(child);
|
|
28
|
+
} else if (child && typeof child !== 'object') {
|
|
29
|
+
const text = document.createTextNode(child);
|
|
30
|
+
element.appendChild(text);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const styleElement = (element, style) => {
|
|
35
|
+
for (let key in style) {
|
|
36
|
+
if (Object.prototype.hasOwnProperty.call(style, key)) {
|
|
37
|
+
element.style[key] = style[key];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return element;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const elementsCreator = (item) => {
|
|
45
|
+
const children = Array.isArray(item.children) ? item.children.map(elementsCreator) : item.children;
|
|
46
|
+
|
|
47
|
+
const element = isElement(item) ? item : createElement(item.tag, item.attr, children);
|
|
48
|
+
|
|
49
|
+
if (item.onClick) {
|
|
50
|
+
item.event = { name: 'click', callback: item.onClick };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (item.event) {
|
|
54
|
+
element.addEventListener(item.event.name, item.event.callback, false);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (item.style) {
|
|
58
|
+
styleElement(element, item.style);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return element;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
const addEventListener = (element, name, cb) => {
|
|
66
|
+
element.addEventListener(name, cb, false);
|
|
67
|
+
|
|
68
|
+
return () => {
|
|
69
|
+
element.removeEventListener(name, cb, false);
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
export { wrap, createElement, elementsCreator, addEventListener };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
function find(list, callback) {
|
|
2
|
+
if (Array.prototype.find && Array.isArray(list)) {
|
|
3
|
+
return list.find(callback);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
return findElementAndIndex(list, callback)[0];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function findIndex(list, callback) {
|
|
10
|
+
if (Array.prototype.findIndex) {
|
|
11
|
+
return list.findIndex(callback);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return findElementAndIndex(list, callback)[1];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function findElementAndIndex(list, callback) {
|
|
18
|
+
for (let i = 0; i < list.length; i++) {
|
|
19
|
+
const element = list[i];
|
|
20
|
+
if (callback(element, i, list)) {
|
|
21
|
+
return [element, i];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return [undefined, -1];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { find, findIndex, findElementAndIndex };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import WebFont from 'webfontloader';
|
|
2
|
+
|
|
3
|
+
const FONT_FAMILY = 'Fira Sans';
|
|
4
|
+
|
|
5
|
+
const fontFace = (elem, options) => {
|
|
6
|
+
let fontFace = options.cloudinary.fontFace;
|
|
7
|
+
|
|
8
|
+
// Default font-face is "Fira sans"
|
|
9
|
+
if (typeof fontFace === 'undefined') {
|
|
10
|
+
fontFace = FONT_FAMILY;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (fontFace && fontFace !== 'inherit') {
|
|
14
|
+
WebFont.load({
|
|
15
|
+
google: {
|
|
16
|
+
families: [fontFace]
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
elem.style.fontFamily = fontFace;
|
|
20
|
+
} else if (fontFace === 'inherit') {
|
|
21
|
+
elem.style.fontFamily = 'inherit';
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { fontFace };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
const groupBy = (collection, iteratee) => collection.reduce((result, value, key) => {
|
|
3
|
+
key = iteratee(value);
|
|
4
|
+
if (Object.prototype.hasOwnProperty.call(result, key)) {
|
|
5
|
+
result[key].push(value);
|
|
6
|
+
} else {
|
|
7
|
+
result[key] = [value];
|
|
8
|
+
}
|
|
9
|
+
return result;
|
|
10
|
+
}, {});
|
|
11
|
+
|
|
12
|
+
export { groupBy };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as assign from './assign';
|
|
2
|
+
import * as slicing from './slicing';
|
|
3
|
+
import * as positioning from './positioning';
|
|
4
|
+
import * as string from './string';
|
|
5
|
+
import * as cloudinaryUtils from './cloudinary';
|
|
6
|
+
import * as applyWithProps from './apply-with-props';
|
|
7
|
+
import * as groupBy from './groupBy';
|
|
8
|
+
import * as mixin from './mixin';
|
|
9
|
+
import * as fontFace from './fontFace';
|
|
10
|
+
import * as playButton from './playButton';
|
|
11
|
+
import * as cssPrefix from './css-prefix';
|
|
12
|
+
import * as normalizeAttributes from './attributes-normalizer';
|
|
13
|
+
|
|
14
|
+
const Utils = assign.assign({},
|
|
15
|
+
assign,
|
|
16
|
+
slicing,
|
|
17
|
+
positioning,
|
|
18
|
+
string,
|
|
19
|
+
cloudinaryUtils,
|
|
20
|
+
fontFace,
|
|
21
|
+
playButton,
|
|
22
|
+
groupBy,
|
|
23
|
+
applyWithProps,
|
|
24
|
+
mixin,
|
|
25
|
+
cssPrefix,
|
|
26
|
+
normalizeAttributes
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export default Utils;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
// Test for matches()/
|
|
3
|
+
const elMatches = (el, selector) => {
|
|
4
|
+
let p = Element.prototype;
|
|
5
|
+
let f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function (s) {
|
|
6
|
+
return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
|
|
7
|
+
};
|
|
8
|
+
return f.call(el, selector);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export { elMatches };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* a nested value from an object
|
|
4
|
+
* @param {object} value - a object you want to get a nested value from
|
|
5
|
+
* @param {string} path - path to the nested value, key separated by . (dots)
|
|
6
|
+
* @param {any} defaultValue - a default Value in case the value is not defined
|
|
7
|
+
* @returns a nested value from an object / array
|
|
8
|
+
*/
|
|
9
|
+
export const get = (value, path, defaultValue) => {
|
|
10
|
+
if (value && typeof value === 'object') {
|
|
11
|
+
const keysArray = path.split('.');
|
|
12
|
+
let getValue = value;
|
|
13
|
+
|
|
14
|
+
for (let objectValue of keysArray) {
|
|
15
|
+
if (Object.prototype.hasOwnProperty.call(getValue, objectValue) && getValue[objectValue] !== undefined) {
|
|
16
|
+
getValue = getValue[objectValue];
|
|
17
|
+
} else {
|
|
18
|
+
return defaultValue;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return getValue;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return defaultValue;
|
|
26
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
function getElementPosition(el) {
|
|
2
|
+
const box = el.getBoundingClientRect();
|
|
3
|
+
|
|
4
|
+
const body = document.body;
|
|
5
|
+
const docEl = document.documentElement;
|
|
6
|
+
|
|
7
|
+
const scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
|
|
8
|
+
const scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
|
|
9
|
+
|
|
10
|
+
const clientTop = docEl.clientTop || body.clientTop || 0;
|
|
11
|
+
const clientLeft = docEl.clientLeft || body.clientLeft || 0;
|
|
12
|
+
|
|
13
|
+
const top = box.top + scrollTop - clientTop;
|
|
14
|
+
const left = box.left + scrollLeft - clientLeft;
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
top: Math.round(top),
|
|
18
|
+
left: Math.round(left)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get pointer position in element
|
|
24
|
+
* Returns an object with x and y coordinates.
|
|
25
|
+
* The base on the coordinates are the bottom left of the element.
|
|
26
|
+
*
|
|
27
|
+
* @function getPointerPosition
|
|
28
|
+
* @param {Element} el Element on which to get the pointer position on
|
|
29
|
+
* @param {Event} event Event object
|
|
30
|
+
* @return {Object}
|
|
31
|
+
* This object will have x and y coordinates corresponding to the
|
|
32
|
+
* mouse position
|
|
33
|
+
*/
|
|
34
|
+
function getPointerPosition(el, event) {
|
|
35
|
+
const position = {};
|
|
36
|
+
const box = getElementPosition(el);
|
|
37
|
+
const boxW = el.offsetWidth;
|
|
38
|
+
const boxH = el.offsetHeight;
|
|
39
|
+
const boxY = box.top;
|
|
40
|
+
const boxX = box.left;
|
|
41
|
+
let pageY = event.pageY;
|
|
42
|
+
let pageX = event.pageX;
|
|
43
|
+
|
|
44
|
+
if (event.changedTouches) {
|
|
45
|
+
pageX = event.changedTouches[0].pageX;
|
|
46
|
+
pageY = event.changedTouches[0].pageY;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
position.y = Math.max(0, Math.min(1, ((boxY - pageY) + boxH) / boxH));
|
|
50
|
+
position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));
|
|
51
|
+
|
|
52
|
+
return position;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isElementInViewport(el, { fraction }) {
|
|
56
|
+
const topLeft = getElementPosition(el);
|
|
57
|
+
const x = topLeft.left;
|
|
58
|
+
const y = topLeft.top;
|
|
59
|
+
const h = el.offsetHeight;
|
|
60
|
+
const w = el.offsetWidth;
|
|
61
|
+
const r = x + w;
|
|
62
|
+
const b = y + h;
|
|
63
|
+
const visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x,
|
|
64
|
+
r - window.pageXOffset));
|
|
65
|
+
const visibleY = Math.max(0, Math.min(w, window.pageYOffset + window.innerHeight - y,
|
|
66
|
+
b - window.pageYOffset));
|
|
67
|
+
|
|
68
|
+
const visible = visibleX * visibleY / (w * h);
|
|
69
|
+
|
|
70
|
+
return visible > fraction;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function setPosition(el, left, top) {
|
|
74
|
+
el.style.left = `${left}px`;
|
|
75
|
+
el.style.top = `${top}px`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { getElementPosition, getPointerPosition, isElementInViewport, setPosition };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function _sliceProperties(obj, isUnset, ...props) {
|
|
2
|
+
return props.reduce((acc, prop) => {
|
|
3
|
+
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
|
|
4
|
+
acc[prop] = obj[prop];
|
|
5
|
+
if (isUnset) {
|
|
6
|
+
delete obj[prop];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function sliceProperties(obj, ...props) {
|
|
14
|
+
return _sliceProperties(obj, false, ...props);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function sliceAndUnsetProperties(obj, ...props) {
|
|
18
|
+
return _sliceProperties(obj, true, ...props);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { sliceProperties, sliceAndUnsetProperties };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
function camelize(str) {
|
|
3
|
+
return str.replace(/[_.-](\w|$)/g, (_, x) => x.toUpperCase());
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function startsWith(str, searchStr, position) {
|
|
7
|
+
if (String.prototype.startsWith) {
|
|
8
|
+
return str.startsWith(searchStr, position);
|
|
9
|
+
} else {
|
|
10
|
+
let position = position || 0;
|
|
11
|
+
return str.indexOf(searchStr, position) === position;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { camelize, startsWith };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps the given function, `fn`, with a new function that only invokes `fn`
|
|
3
|
+
* at most once per every `wait` milliseconds.
|
|
4
|
+
*
|
|
5
|
+
* @function
|
|
6
|
+
* @param {Function} fn
|
|
7
|
+
* The function to be throttled.
|
|
8
|
+
*
|
|
9
|
+
* @param {number} wait
|
|
10
|
+
* The number of milliseconds by which to throttle.
|
|
11
|
+
*
|
|
12
|
+
* @return {Function}
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
function throttle(fn, wait) {
|
|
16
|
+
let last = window.performance.now();
|
|
17
|
+
|
|
18
|
+
const throttled = function(...args) {
|
|
19
|
+
const now = window.performance.now();
|
|
20
|
+
|
|
21
|
+
if (now - last >= wait) {
|
|
22
|
+
fn(...args);
|
|
23
|
+
last = now;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return throttled;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { throttle };
|