2
\$\begingroup\$

I'm trying to embed YouTube video's on a website in a privacy-friendly way.

The code doesn't load the iframes by default but shows a preview thumbnail overlayed with an info message instead. The user can load a single video by clicking the button in the info message. The overlay also contains a checkbox that, if checked, unblocks all YouTube iframes and remembers the user's preference by setting a cookie.

Some points of attention:

  • Embeds need to be responsive
  • In trying to minimize network request I don't hardcode the preview image in the html.
  • Loaded video is autoplayed, to avoid second click.
  • Code needs to support ie10.

Is the code indeed supported by ie10? Any input or thoughts on best practices or ways to organize my JS code are greatly appreciated.

HTML:

<div class="youtube-embed" data-id="-XB5y26XRSk">
  <div class="youtube-embed__notice">
    <p>Info and link to YouTube's privacy policy</p>
    <label><input type="checkbox" name="acceptall"> Accept YouTube content in the future.</label>
    <button>Load video</button>
  </div>
  <iframe class="youtube-embed__iframe" frameborder="0" allowfullscreen allow="autoplay"></iframe>
</div>

CSS

.youtube-embed {
  position: relative;
  overflow-y: auto;
  height: 0;
  padding-bottom: 56.25%;

  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

.youtube-embed__notice {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 100%;
}

.youtube-embed__iframe {
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.youtube-embed--active .youtube-embed__notice {
  display: none;
}

.youtube-embed--active .youtube-embed__iframe {
  display: block;
}

JS

var cookie = {
  name: 'cookie-consent',
  get: function() {
    var match = document.cookie.match(new RegExp('(?:^|;)\\s*' + this.name + '\\s*\\=\\s*([^;]*)'));
    return match ? match[1] : null;
  },
  set: function(value) {
    var expiryDate = new Date();
    expiryDate.setDate(expiryDate.getDate() + 365);

    document.cookie =
      this.name + '=' + value + '; expires=' + expiryDate.toUTCString() + '; path=/';
  }
};

function customEvent(name, detail) {
  var event;
  if (window.CustomEvent) {
    event = new CustomEvent(name, { detail: detail });
  } else {
    event = document.createEvent('CustomEvent');
    event.initCustomEvent(name, true, true, detail);
  }
  return event;
}

function YoutubeEmbed(container, state) {
  this.container = container;
  this.state = state;
  this.id = this.container.getAttribute('data-id');
  this.autoplay = false;
  this.notice = this.container.querySelector('.youtube-embed__notice');
  this.iframe = this.container.querySelector('.youtube-embed__iframe');
  this.acceptButton = this.container.querySelector('button');
  this.acceptAllCheckbox = this.container.querySelector('input[type=checkbox]');
  this.attachEvents();
  this.render();
}

YoutubeEmbed.prototype.setState = function(state) {
  this.state = state;
  this.render();
};

YoutubeEmbed.prototype.saveConsent = function(){
  cookie.set('youtube');
}

YoutubeEmbed.prototype.attachEvents = function() {
  var _this = this;

  this.acceptButton.addEventListener('click', function() {
    if (_this.acceptAllCheckbox.checked) {
      _this.saveConsent();
      var event = customEvent('consentchanged');
      document.dispatchEvent(event);
    }

    _this.autoplay = true;

    _this.setState(false);
  });
};

YoutubeEmbed.prototype.showNotice = function() {
  this.iframe.removeAttribute('src');
  var imageSrc = 'https://i.ytimg.com/vi/' + this.id + '/hqdefault.jpg';
  this.container.style.backgroundImage = 'url(' + imageSrc + ')';
  this.container.classList.remove('youtube-embed--active');
};

YoutubeEmbed.prototype.showIframe = function() {
  var iframeSrc = 'https://www.youtube-nocookie.com/embed/' + this.id;

  if (this.autoplay) {
    iframeSrc += '?autoplay=1';
  }

  this.iframe.src = iframeSrc;
  this.container.style.backgroundImage = 'none';
  this.container.classList.add('youtube-embed--active');
};

YoutubeEmbed.prototype.render = function() {
  if (this.state === 'blocked') {
    this.showNotice();
  } else {
    this.showIframe();
  }
};

function getState(){
  var consentCookie = cookie.get();
  var youtubeConsent = consentCookie && consentCookie.indexOf('youtube') !== -1;
  return youtubeConsent ? 'unblocked' : 'blocked';
}

var initialState = getState();

var youtubeEmbeds = document.querySelectorAll('.youtube-embed');
var youtubeEmbedObjects = [];
youtubeEmbeds.forEach(function(embed) {
  youtubeEmbedObjects.push(new YoutubeEmbed(embed, initialState));
});

document.addEventListener('consentchanged', function() {
  youtubeEmbedObjects.forEach(function(embedObject) {
    var newState = getState();
    embedObject.setState(newState);
  });
});
```
\$\endgroup\$
  • \$\begingroup\$ Adaptations made. \$\endgroup\$ – TheDancingCode Mar 24 at 12:50
  • \$\begingroup\$ Thank you I have retracted the close vote and will remove previous comments. \$\endgroup\$ – Blindman67 Mar 24 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.