Author: | orestbida |
---|---|
Views Total: | 818 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