Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .config/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['test/unit/setup.js'],
include: ['test/unit/**/*.test.js'],
exclude: [
'test/*.test.js',
Expand Down
3 changes: 2 additions & 1 deletion docs/es-modules/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@ <h3 class="mt-4">Code examples:</h3>
<li><a href="./force-hls-subtitles.html">Force HLS Subtitles</a></li>
<li><a href="./hdr.html">HDR</a></li>
<li><a href="./interaction-area.html">Interaction Area</a></li>
<li><a href="./lazy-player.html">Lazy player</a></li>
<li><a href="./multiple-players.html">Multiple Players</a></li>
<li><a href="./playlist.html">Playlist</a></li>
<li><a href="./playlist-by-tag.html">Playlist by Tag</a></li>
<li><a href="./poster.html">Poster Options</a></li>
<li><a href="./profiles.html">Profiles</a></li>
<li><a href="./raw-url.html">Raw URL</a></li>
<li><a href="./recommendations.html">Recommendations</a></li>
<li><a href="./schedule.html">Schedule (weekly time slots)</a></li>
<li><a href="./schedule.html">Schedule</a></li>
<li><a href="./seek-thumbs.html">Seek Thumbnails</a></li>
<li><a href="./share-plugin.html">Share &amp; Download</a></li>
<li><a href="./shoppable.html">Shoppable Videos</a></li>
Expand Down
119 changes: 119 additions & 0 deletions docs/es-modules/lazy-player.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Cloudinary Video Player - Lazy player (ESM)</title>
<link
href="https://res.cloudinary.com/cloudinary-marketing/image/upload/f_auto,q_auto/c_scale,w_32,e_hue:290/creative_staging/cloudinary_internal/Website/Brand%20Updates/Favicon/cloudinary_web_favicon_192x192.png"
rel="icon"
type="image/png"
/>
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div class="container p-4 col-12 col-md-9 col-xl-6">
<nav class="nav mb-2">
<a href="/index.html">&#60;&#60; Back to examples index</a>
</nav>
<h1>Cloudinary Video Player</h1>
<h3 class="mb-3">Lazy player (with poster URL)</h3>
<p class="text-muted small mb-2">Uses an explicit <code>poster</code> URL. Custom accent color and logo configured.</p>

<video
id="player"
playsinline
controls
muted
class="cld-video-player cld-fluid"
width="500"
></video>

<button type="button" id="btn-load" class="btn btn-sm btn-outline-primary mt-2 mb-3">Load Player</button>
<p class="text-muted small mb-3">
Click the player or the button above to initialize. The button calls <code>player.loadPlayer()</code>.
</p>

<h3 class="mt-4">Scroll to load (auto-built poster)</h3>
<p class="text-muted small mb-2">No <code>poster</code> URL - built automatically from <code>cloudName</code> and <code>publicId</code>. Custom colors configured.</p>
<p class="text-muted small mb-3">
Scroll down - the player loads automatically when it enters the viewport.
</p>

<div style="height: 80vh; display: flex; color: #aaa; font-size: 2rem;">
&darr; &darr; &darr; &darr; &darr; &darr; &darr;
</div>

<video
id="player-scroll"
playsinline
controls
muted
loop
class="cld-video-player cld-fluid"
width="500"
></video>

<h3 class="mt-4">Example code:</h3>
<pre><code class="language-javascript">
import { player as createPlayer } from 'cloudinary-video-player/lazy';
import 'cloudinary-video-player/cld-video-player.min.css';

// With explicit poster URL
const player = await createPlayer('my-video', {
cloudName: 'demo',
publicId: 'sea_turtle',
poster: 'https://res.cloudinary.com/demo/video/upload/so_0,f_auto,q_auto/sea_turtle.jpg',
lazy: true,
colors: { accent: '#ff4081' }
});
// await player.loadPlayer();

// Auto-built poster from cloudName + publicId
createPlayer('my-video', {
cloudName: 'demo',
publicId: 'sea_turtle',
lazy: { loadOnScroll: true },
colors: { base: '#0d1b2a', accent: '#00b4d8' }
});
</code></pre>
</div>

<script type="module">
import { player as createPlayer } from 'cloudinary-video-player/lazy';
import 'cloudinary-video-player/cld-video-player.min.css';

(async () => {
const player = await createPlayer('player', {
cloudName: 'demo',
publicId: 'sea_turtle',
poster: 'https://res.cloudinary.com/demo/video/upload/so_0,f_auto,q_auto/sea_turtle.jpg',
lazy: true,
colors: { accent: '#ff4081' },
logoImageUrl: 'https://res.cloudinary.com/demo/image/upload/c_scale,w_100/cloudinary_logo.png',
logoOnclickUrl: 'https://cloudinary.com'
});

document.getElementById('btn-load').addEventListener('click', () => {
if (player && typeof player.loadPlayer === 'function') {
player.loadPlayer();
}
});

createPlayer('player-scroll', {
cloudName: 'demo',
publicId: 'sea_turtle',
lazy: { loadOnScroll: true },
colors: { base: '#0d1b2a', accent: '#00b4d8' }
});
})();
</script>

<link
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
crossorigin="anonymous"
/>
</body>
</html>
4 changes: 2 additions & 2 deletions docs/es-modules/schedule.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ <h4 class="mb-2" id="schedule-label">Schedule</h4>

<h3 class="mt-4">Example Code (ESM):</h3>
<pre><code class="language-javascript">
import { videoPlayer } from 'cloudinary-video-player';
import { player } from 'cloudinary-video-player';
import 'cloudinary-video-player/cld-video-player.min.css';

videoPlayer('player', {
player('player', {
cloudName: 'demo',
publicId: 'sea_turtle',
schedule: {
Expand Down
3 changes: 2 additions & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ <h3 class="mt-4">Some code examples:</h3>
<li><a href="./force-hls-subtitles-ios.html">Force HLS Subtitles</a></li>
<li><a href="./hdr.html">HDR</a></li>
<li><a href="./interaction-area.html">Interaction Area</a></li>
<li><a href="./lazy-player.html">Lazy player</a></li>
<li><a href="./live-streaming.html">Live Streaming</a></li>
<li><a href="./multiple-players.html">Multiple Players</a></li>
<li><a href="./playlist.html">Playlist</a></li>
Expand All @@ -76,7 +77,7 @@ <h3 class="mt-4">Some code examples:</h3>
<li><a href="./profiles.html">Profiles</a></li>
<li><a href="./raw-url.html">Raw URL</a></li>
<li><a href="./recommendations.html">Recommendations</a></li>
<li><a href="./schedule.html">Schedule (weekly time slots)</a></li>
<li><a href="./schedule.html">Schedule</a></li>
<li><a href="./seek-thumbs.html">Seek Thumbnails</a></li>
<li><a href="./share-plugin.html">Share &amp; Download</a></li>
<li><a href="./shoppable.html">Shoppable Videos</a></li>
Expand Down
120 changes: 120 additions & 0 deletions docs/lazy-player.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Cloudinary Video Player - Lazy player</title>
<link href="https://res.cloudinary.com/cloudinary-marketing/image/upload/f_auto,q_auto/c_scale,w_32/v1597183771/creative_staging/cloudinary_internal/Website/Brand%20Updates/Favicon/cloudinary_web_favicon_192x192.png" rel="icon" type="image/png">

<!-- Bootstrap -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

<!-- highlight.js -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/solarized-light.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

<script type="text/javascript" src="./scripts.js?lazy"></script>

<script type="text/javascript">
(function () {
var player = null;

async function initLazyPlayer() {
player = await cloudinary.player('player', {
cloudName: 'demo',
publicId: 'sea_turtle',
poster: 'https://res.cloudinary.com/demo/video/upload/so_0,f_auto,q_auto/sea_turtle.jpg',
lazy: true,
colors: { accent: '#ff4081' },
logoImageUrl: 'https://res.cloudinary.com/demo/image/upload/c_scale,w_100/cloudinary_logo.png',
logoOnclickUrl: 'https://cloudinary.com'
});

cloudinary.player('player-scroll', {
cloudName: 'demo',
publicId: 'sea_turtle',
lazy: { loadOnScroll: true },
colors: { accent: '#ff4081' }
});
}

window.addEventListener('load', function () {
initLazyPlayer();
document.getElementById('btn-load').addEventListener('click', function () {
if (player && typeof player.loadPlayer === 'function') {
player.loadPlayer();
}
});
});
})();
</script>
</head>
<body>
<div class="container p-4 col-12 col-md-9 col-xl-6">
<nav class="nav mb-2">
<a href="./index.html">&#60;&#60; Back to examples index</a>
</nav>
<h1>Cloudinary Video Player</h1>
<h3 class="mb-3">Lazy player (with poster URL)</h3>
<p class="text-muted small mb-2">Uses an explicit <code>poster</code> URL. Custom accent color and logo configured.</p>

<video
id="player"
playsinline
controls
muted
class="cld-video-player cld-fluid"
width="500">
</video>

<button type="button" id="btn-load" class="btn btn-sm btn-outline-primary mt-2 mb-3">Load Player</button>
<p class="text-muted small mb-3">
Click the player or the button above to initialize. The button calls <code>player.loadPlayer()</code>.
</p>

<h3 class="mt-4">Scroll to load (auto-built poster)</h3>
<p class="text-muted small mb-2">No <code>poster</code> URL - built automatically from <code>cloudName</code> and <code>publicId</code>. Custom colors configured.</p>
<p class="text-muted small mb-3">
Scroll down - the player loads automatically when it enters the viewport.
</p>

<div style="height: 80vh; display: flex; color: #aaa; font-size: 2rem;">
&darr; &darr; &darr; &darr; &darr; &darr; &darr;
</div>

<video
id="player-scroll"
playsinline
controls
muted
loop
class="cld-video-player cld-fluid"
width="500">
</video>

<h3 class="mt-4">Example code:</h3>
<pre>
<code class="language-javascript">
// With explicit poster URL
const player = await cloudinary.player('my-video', {
cloudName: 'demo',
publicId: 'sea_turtle',
poster: 'https://res.cloudinary.com/demo/video/upload/so_0,f_auto,q_auto/sea_turtle.jpg',
lazy: true,
colors: { accent: '#ff4081' }
});
// await player.loadPlayer();

// Auto-built poster from cloudName + publicId
cloudinary.player('my-video', {
cloudName: 'demo',
publicId: 'sea_turtle',
lazy: { loadOnScroll: true },
colors: { base: '#0d1b2a', accent: '#00b4d8' }
});
</code>
</pre>
</div>
</body>
</html>
2 changes: 1 addition & 1 deletion docs/schedule.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ <h4 class="mb-2" id="schedule-label">Schedule</h4>

<h3 class="mt-4">Example Code:</h3>
<pre><code class="language-javascript">
cloudinary.videoPlayer('player', {
cloudinary.player('player', {
cloudName: 'demo',
publicId: 'sea_turtle',
schedule: {
Expand Down
5 changes: 5 additions & 0 deletions src/assets/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ $icon-font-path: '../icon-font' !default;
text-shadow: none;
}

&.cld-lazy-player {
width: auto;
height: auto;
}

&.cld-fluid {
width: 100%;
max-width: 100%;
Expand Down
16 changes: 16 additions & 0 deletions src/config/configSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,22 @@
},
"default": {}
},
"lazy": {
"oneOf": [
{
"type": "boolean",
"default": false
},
{
"type": "object",
"properties": {
"loadOnScroll": { "type": "boolean", "default": false }
},
"additionalProperties": false
}
],
"default": false
},
"videoSources": {
"type": "array",
"items": {
Expand Down
12 changes: 12 additions & 0 deletions src/utils/cloudinary-config-from-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import pick from 'lodash/pick';
import { CLOUDINARY_CONFIG_PARAM } from '../video-player.const';
import { convertKeysToSnakeCase } from './object';

export const getCloudinaryConfigFromOptions = (options) => {
if (options.cloudinaryConfig) {
return options.cloudinaryConfig;
}

const snakeCaseCloudinaryConfig = pick(convertKeysToSnakeCase(options), CLOUDINARY_CONFIG_PARAM);
return Object.assign({}, snakeCaseCloudinaryConfig);
};
13 changes: 1 addition & 12 deletions src/utils/fetch-config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import pick from 'lodash/pick';
import { defaultProfiles } from 'cloudinary-video-player-profiles';
import { isRawUrl, getCloudinaryUrlPrefix } from '../plugins/cloudinary/url-helpers';
import { CLOUDINARY_CONFIG_PARAM } from '../video-player.const';
import { utf8ToBase64 } from '../utils/utf8Base64';
import { appendQueryParams } from './querystring';
import { convertKeysToSnakeCase } from './object';
import { getCloudinaryConfigFromOptions } from './cloudinary-config-from-options';

const isDefaultProfile = (profileName) => !!defaultProfiles.find(({ name }) => profileName === name);

Expand All @@ -18,15 +16,6 @@ const getDefaultProfileConfig = (profileName) => {
return profile.config;
};

const getCloudinaryConfigFromOptions = (options) => {
if (options.cloudinaryConfig) {
return options.cloudinaryConfig;
}

const snakeCaseCloudinaryConfig = pick(convertKeysToSnakeCase(options), CLOUDINARY_CONFIG_PARAM);
return Object.assign({}, snakeCaseCloudinaryConfig);
};

const fetchConfig = async (options) => {
const { profile, publicId, type = 'upload', videoConfig, allowUsageReport = true } = options;

Expand Down
4 changes: 4 additions & 0 deletions src/utils/get-analytics-player-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ export const getAnalyticsFromPlayerOptions = (playerOptions) => filterDefaultsAn
debug: playerOptions.debug,
type: playerOptions.type,
schedule: hasConfig(playerOptions.schedule?.weekly),
lazy: playerOptions.lazy === true || (playerOptions.lazy && typeof playerOptions.lazy === 'object'),
lazyLoadOnScroll: (playerOptions.lazy && typeof playerOptions.lazy === 'object' && playerOptions.lazy.loadOnScroll === true)
? true
: undefined,

colors: hasConfig(playerOptions.colors),
controlBar: hasConfig(playerOptions.controlBar),
Expand Down
Loading
Loading