1

I'm using a Learning Management System where users can add YouTube videos, which are then embedded using the iframe tag. They are not embedded responsively automatically. However, I found this JavaScript to wrap the YouTube videos in a div to make them embed responsive:

var embedItem = document.querySelectorAll('iframe[src*="youtube"]');
  embedItem.forEach(function(eachEmbed){
    let wrapper = document.createElement('div');
    wrapper.classList.add('embed-responsive');
    wrapper.classList.add('embed-responsive-16by9');
    wrapper.appendChild(eachEmbed.cloneNode(true));
    eachEmbed.replaceWith(wrapper);
});

This result in a YouTube video being wrapped as follow in HTML:

<div class="embed-responsive embed-responsive-16by9">
     <iframe class="embed-responsive-item" src="https://www.youtube.com/embed/jTwdtMzZMds" allowfullscreen="true" title="YouTube video">
     </iframe>
</div>

This works great, but now, I want to wrap this element in another div <div class="video-wrapper rounded">

Basically the output I want for the original iframe tag is:

<div class="video-wrapper rounded">
      <div class="embed-responsive embed-responsive-16by9">
            <iframe class="embed-responsive-item" src="https://www.youtube.com/embed/jTwdtMzZMds"
                     allowfullscreen="true" title="YouTube video"></iframe>
      </div>
</div>

But I cannot figure out how I can tweak the javascript I found to perform this function automatically. Can anyone adapt the javascript code to perform this function? Does anyone know how to do this?

Hagelslag
  • 85
  • 8
  • FYI, those classes require [version 4 of the Bootstrap library](https://getbootstrap.com/docs/4.6/utilities/embed/#aspect-ratios) to make things embedded (or at least the appropriate CSS). They don't do anything on their own. – isherwood Sep 15 '22 at 18:41
  • Does this answer your question? [https://stackoverflow.com/q/6838104/1264804](https://stackoverflow.com/questions/6838104/pure-javascript-method-to-wrap-content-in-a-div) – isherwood Sep 15 '22 at 18:45
  • @isherwood You're right. The templates I use, use Bootstrap 4.3.1, among other things. – Hagelslag Sep 15 '22 at 19:33
  • That means you also have jQuery available, which would make this whole thing much simpler. If you care to use that, tag accordingly. – isherwood Sep 15 '22 at 19:49

2 Answers2

1

I've assumed that you're using Bootstrap 4 on your website based on the class names.

As you can see here, you don't actually need another div. You can apply the new classes to the div created in your existing code to achieve the rounded corners.

Note that I've added overflow-hidden to the class list. This is necessary to apply the border radius to the inner elements.

body {
  padding: 3rem; /* for demo only */
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

<div class="embed-responsive embed-responsive-16by9 video-wrapper rounded overflow-hidden">
  <iframe class="embed-responsive-item" src="https://www.youtube.com/embed/jTwdtMzZMds" allowfullscreen="true" title="YouTube video"></iframe>
</div>

Then, no need to call classList.add() repeatedly. Just put all the classes in a list.

I've updated variable names here. They weren't particularly semantic (singular vs. plural), and the repeat made things a bit confusing.

const embedItems = document.querySelectorAll('iframe[src*="youtube"]');

embedItems.forEach(function(item) {
  let wrapper = document.createElement('div');

  wrapper.classList.add(
    'embed-responsive',
    'embed-responsive-16by9',
    'video-wrapper',
    'rounded',
    'overflow-hidden'
  );

  wrapper.appendChild(item.cloneNode(true));
  item.replaceWith(wrapper);
});
body {
  padding: 3rem; /* for demo only */
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

<iframe class="embed-responsive-item" src="https://www.youtube.com/embed/jTwdtMzZMds" allowfullscreen="true" title="YouTube video"></iframe>

Now, if you actually do need another element for reasons I'm not aware of, you can work in another level of wrapping.

const embedItems = document.querySelectorAll('iframe[src*="youtube"]');

embedItems.forEach(function(item) {
  let innerWrapper = document.createElement('div');
  innerWrapper.classList.add(
    'embed-responsive',
    'embed-responsive-16by9'
  );
  innerWrapper.appendChild(item.cloneNode(true));

  let outerWrapper = document.createElement('div');
  outerWrapper.classList.add(
    'video-wrapper',
    'rounded',
    'overflow-hidden'
  );

  outerWrapper.appendChild(innerWrapper);
  item.replaceWith(outerWrapper);
});
body {
  padding: 3rem;
  /* for demo only */
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

<iframe class="embed-responsive-item" src="https://www.youtube.com/embed/jTwdtMzZMds" allowfullscreen="true" title="YouTube video"></iframe>

Since you are using Bootstrap, and therefore have the jQuery library available, I'll offer a simple replacement for all this as an alternative.

$('iframe[src*="youtube"]').each(function() {
  $(this) // <-- refers to the currently looped element
    // note the outside-in order here
    .wrap('<div class="video-wrapper rounded overflow-hidden"></div>')
    .wrap('<div class="embed-responsive embed-responsive-16by9"></div>');
});
body {
  padding: 3rem;
  /* for demo only */
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

<iframe class="embed-responsive-item" src="https://www.youtube.com/embed/jTwdtMzZMds" allowfullscreen="true" title="YouTube video"></iframe>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
isherwood
  • 58,414
  • 16
  • 114
  • 157
0

var embedItem = document.querySelectorAll('iframe[src*="youtube"]');
  embedItem.forEach(function(eachEmbed){
    const container = document.createElement('div');
    container.classList.add('video-wrapper');
    container.classList.add('rounded');
    const wrapper = document.createElement('div');
    wrapper.classList.add('embed-responsive');
    wrapper.classList.add('embed-responsive-16by9');
    wrapper.appendChild(eachEmbed.cloneNode(true));
    container.appendChild(wrapper)
    eachEmbed.replaceWith(container);
});
Robert
  • 2,538
  • 1
  • 9
  • 17
  • i know that someone will paste this... nothing to explain just read the code. Guy just copy code from net and this don't work. so he don't ask about explanation.... he needs working code to copy it :P – Robert Sep 15 '22 at 18:56