| Author: | orestbida |
|---|---|
| Views Total: | 831 views |
| Official Page: | Go to website |
| Last Update: | September 8, 2024 |
| License: | MIT |
Preview:

Description:
A lightweight, GDPR-compliant iframe manager that delays the loading of iframe content (like Youtube videos) until you agree to certain Privacy Policy and Terms.
More Features:
- Auto resize the iframe to fit its container.
- Custom thumbnail before loading the iframe content.
- Supports any service which uses iframes: Youtube, Vimeo, Twitch, etc.
- Easy to integrate with any cookie consent solution.
- Lazily load iframes & thumbnails to improve page speed.
How to use it:
1. Load the iframemanager’s JavaScript and Stylesheet in the document.
<link rel="stylesheet" href="dist/iframemanager.css" /> <script src="dist/iframemanager.js"></script>
2. Initialize the iframe manager.
var manager = iframemanager();
3. Add services to the iframe manager.
iframemanager.run({
services : {
// Youtube
youtube : {
embedUrl: 'https://www.youtube-nocookie.com/embed/{data-id}',
iframe : {
allow : 'accelerometer; encrypted-media; gyroscope; picture-in-picture; fullscreen;',
},
cookie : {
name : 'cc_youtube'
},
languages : {
'en' : {
notice: 'This content is hosted by a third party. By showing the external content you accept the <a rel="noreferrer" href="https://www.youtube.com/t/terms" title="Terms and conditions" target="_blank">terms and conditions</a> of youtube.com.',
loadBtn: 'Load video',
loadAllBtn: 'Don\'t ask again'
}
}
},
// Vimeo
vimeo: {
embedUrl: 'https://player.vimeo.com/video/{data-id}',
iframe: {
allow : 'fullscreen; picture-in-picture, allowfullscreen;',
},
thumbnailUrl: async (dataId, setThumbnail) => {
const url = `https://vimeo.com/api/v2/video/${dataId}.json`;
const response = await (await fetch(url)).json();
const thumbnailUrl = response[0]?.thumbnail_large;
thumbnailUrl && setThumbnail(thumbnailUrl);
},
languages: {
en: {
notice: 'This content is hosted by a third party. By showing the external content you accept the <a rel="noreferrer noopener" href="https://vimeo.com/terms" target="_blank">terms and conditions</a> of vimeo.com.',
loadBtn: 'Load video',
loadAllBtn: "Don't ask again"
}
}
},
// Daily Motion
dailymotion : {
embedUrl: 'https://www.dailymotion.com/embed/video/{data-id}',
// Use dailymotion api to obtain thumbnail
thumbnailUrl: function(id, callback){
var url = "https://api.dailymotion.com/video/" + id + "?fields=thumbnail_large_url";
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var src = JSON.parse(this.response).thumbnail_large_url;
callback(src);
}
};
xhttp.open("GET", url, true);
xhttp.send();
},
iframe : {
allow : 'accelerometer; encrypted-media; gyroscope; picture-in-picture; fullscreen;'
},
cookie : {
name : 'cc_dailymotion'
},
languages : {
'en' : {
notice: 'This content is hosted by a third party. By showing the external content you accept the <a rel="noreferrer" href="#link_dailymotion" title="Terms and conditions" target="_blank">terms and conditions</a> of dailymotion.com.',
loadBtn: 'Load video',
loadAllBtn: 'Don\'t ask again'
}
}
},
// Google maps
googlemaps: {
embedUrl: 'https://www.google.com/maps/embed/v1/place?key=API_KEY&q={data-id}',
iframe: {
allow: 'picture-in-picture; fullscreen;'
},
languages: {
en: {
notice: 'This content is hosted by a third party. By showing the external content you accept the <a rel="noreferrer noopener" href="https://cloud.google.com/maps-platform/terms" target="_blank">terms and conditions</a> of Google Maps.',
loadBtn: 'Load map',
loadAllBtn: "Don't ask again"
}
}
},
// Twitch
"twitch" : {
embedUrl: 'https://player.twitch.tv/?{data-id}&parent=localhost',
iframe : {
allow : 'accelerometer; encrypted-media; gyroscope; picture-in-picture; fullscreen;',
params: '',// optional
},
cookie : {
name : 'cc_twitch'
},
languages : {
'en' : {
notice: 'This content is hosted by a third party. By showing the external content you accept the <a rel="noreferrer" href="#link_twitch" title="Terms and conditions" target="_blank">terms and conditions</a> of twitch.com.',
loadBtn: 'Load stream',
loadAllBtn: 'Don\'t ask again'
}
}
}
}
});4. Create a DIV container to hold the iframe manager and config the iframe content with the following data attributes:
- data-service: Service name
- data-id: Video ID
- data-params: Additional parameters
- data-thumbnail: Path to the thumbnail image
- data-thumbnailpreload: Determine whether to preload the thumbnail image
- data-autoscale: Determine whether to auto resize the iframe content
- data-ratio: Custom ratio: 1:1, 2:1, 3:2, 5:2, 4:3, 16:9, 16:10, 20:9, 21:9, 9:16, 9:20
- data-widget: Ignore the default aspect ratio; specify when implementing a custom widget with explicit width and height
- data-iframe-id: Iframe ID attribute
- data-iframe-loading: Iframe loading attribute
- data-iframe-frameborder: Iframe border attribute
<div data-service="youtube"
data-id="VIDEO ID"
data-params="start=21&mute=1"
data-thumbnail="/path/to/poster.jpg"
data-thumbnailpreload
data-autoscale >
</div>5. Available configuration options.
iframemanager.run({
currLang: 'en',
autoLang: false,
services : {
myservice : {
embedUrl: 'https://myservice_embed_url>/{data-id}',
// set valid url for automatic thumbnails [OPTIONAL]
thumbnailUrl: 'https://<myservice_embed_thumbnail_url>/{data-id}',
// global iframe settings (apply to all iframes relative to current service) [OPTIONAL]
iframe : {
allow : 'fullscreen',
params : 'mute=1&start=21'
// function run for each iframe configured with current service
onload : function(data_id, callback){
console.log("loaded iframe with data-id=" + data_id);
}
},
// cookie is set if the current service is accepted
cookie : {
name : 'cc_youtube',
path : '/',
samesite : 'lax',
domain : location.hostname
},
languages : {
en : {
notice: 'Html <b>notice</b> message',
loadBtn: 'Load video',
loadAllBtn: 'Don\'t ask again'
}
}
},
anotherservice : {
...
}
}
});6. API methods.
// accept specific service
manager.acceptService('youtube');
// accept all services
manager.acceptService('all');
// reject specific service
manager.rejectService('youtube');
// reject all services
manager.rejectService('all');
// get the entire config object
manager.getConfig();
// get the current state (enabled/disabled services)
manager.getState();7. Add a custom widget.
<div
data-service="twitter"
data-widget
style="width: 300px; height: 501px"
>
<div data-placeholder>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Sunsets don't get much better than this one over <a href="https://twitter.com/GrandTetonNPS?ref_src=twsrc%5Etfw">@GrandTetonNPS</a>. <a href="https://twitter.com/hashtag/nature?src=hash&ref_src=twsrc%5Etfw">#nature</a> <a href="https://twitter.com/hashtag/sunset?src=hash&ref_src=twsrc%5Etfw">#sunset</a> <a href="http://t.co/YuKy2rcjyU">pic.twitter.com/YuKy2rcjyU</a></p>— US Department of the Interior (@Interior) <a href="https://twitter.com/Interior/status/463440424141459456?ref_src=twsrc%5Etfw">May 5, 2014</a></blockquote>
</div>
</div>manager.run({
services: {
twitter: {
onAccept: async (div, setIframe) => {
// Using cookieconsent v3
await CookieConsent.loadScript('https://platform.twitter.com/widgets.js');
// Make sure the "window.twttr" property exists
await im.childExists({childProperty: 'twttr'}) && await twttr.widgets.load(div);
// Make sure the "iframe" element exists
await im.childExists({parent: div}) && setIframe(div.querySelector('iframe'));
},
onReject: (iframe) => {
iframe && iframe.parentElement.remove();
}
}
}
})Changelog:
v1.3.0 (09/08/2024)
- Add .reset() function to fix re-render issues (react/svelte …)
- Allow usage of the {data-id} placeholder inside the notice text
- Allow usage of optional callback in embedUrl
- Bug Fixes
v1.2.5 (05/21/2023)
- Fix issue with visibility in v1.2.4 where buttons/links remain clickable despite notice being hidden
v1.2.4 (05/20/2023)
- Fix compatibility issues with Safari 10-13
- Use em/rem units instead of px
v1.2.3 (04/03/2023)
- Fix iframes outside viewport are not reset via rejectService(‘<specific_service>’)
v1.2.2 (03/31/2023)
- Fix uncaught exception when service div is no longer present
v1.2.1 (02/08/2023)
- Bugfixes
v1.2.0 (01/19/2023)
- Add .getState() to retrieve the current state such as accepted/rejected services
- Add .getConfig() to retrieve any config. value/prop.
- Add onChange callback, executed whenever a service’s state is changed
- Add support for custom widgets generated by external API (twitter, facebook, instagram …)
- Add css variables for easier customization
- Improve support for custom placeholders when javascript is not enabled
- Make buttons optional (you can now have 0, 1 or 2 buttons)
- Use service name as default cookie name if no explicit cookie.name is provided: ‘im_<service>’
- Bug Fixes
v1.1.0 (11/15/2022)
- Add support for custom aspect ratios via data-ratio=”x:y” 8680851
- Allow any attribute on the iframe element via data-iframe-<attribute>
- Allow any attribute on the iframe element via the internal iframe object
- Bugfixes







