41

I'm very new to javascript and trying to use Twitter bootstrap to get a good looking website up and running quickly. I know this has something to do with jquery, but I'm not sure how to stop my video when I push the close button or the close icon.

Can someone explain how I can get my video to stop playing because even when I close the window, I can still hear it in the background.

<!-- Button to trigger modal -->
    <a href="#myModal" role="button" class="btn" data-toggle="modal"><img src="img/play.png"></a>

<!-- Modal -->
  <div id="myModal" class="modal hide fade" tabindex="-1" role=labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-header">
      <button type="button" class="close" data-dismiss="modal" aria>×</button>
      <h3 id="myModalLabel">I am the header</h3>
    </div>
    <div class="modal-body">
      <p><iframe width="100%" height="315" src="http:com/embed/662KGcqjT5Q" frameborder="0" allowfullscreen></iframe></p>
    </div>
    <div class="modal-footer">
      <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    </div>
  </div>
catchmikey
  • 1,739
  • 4
  • 20
  • 20

22 Answers22

82

I know I'm 2+ years late, but since then, a couple of things have changed, with B3 the new way to perform this out of the box is this:

$("#myModal").on('hidden.bs.modal', function (e) {
    $("#myModal iframe").attr("src", $("#myModal iframe").attr("src"));
});

Have fun with Bootstrap!

gmslzr
  • 1,211
  • 1
  • 10
  • 15
42

There is a nice proper way of doing this - see the comments in the approved answer to this post.

Couldn't get that working first time round myself though, and was in a rush, so I did a rather horrible hacky bit of code which does the trick.

This snippet 'refreshes' the src of the embed iframe, causing it to reload:

jQuery(".modal-backdrop, #myModal .close, #myModal .btn").live("click", function() {
        jQuery("#myModal iframe").attr("src", jQuery("#myModal iframe").attr("src"));
});
Community
  • 1
  • 1
RobCalvert123
  • 452
  • 5
  • 3
  • Thanks @rob. I need to look more into this along with javascript to understand how these function. I tried inserting the code you mentioned above between some – catchmikey Dec 10 '12 at 12:36
  • 1
    Sorry was being a little lazy - have changed the above markup to match your HTML; should work now – RobCalvert123 Dec 10 '12 at 14:36
  • Thanks @rob, this worked great. I'm not sure where to post followups in the comments, but I also wanted to apply this to the close button. I add the following and it worked. – catchmikey Dec 10 '12 at 15:07
  • Aye that'll do it, but a slightly neater way is to target all three at once with that original function - see above, I've edited to also include '#myModal .btn' in that first part. If I were you I'd also look at that post I referenced (which Ruslanas is referring to below) - that's a better way to do it. – RobCalvert123 Dec 10 '12 at 17:46
  • 1
    This method works in Firefox, but not in Chrome. Any suggestions? – alyus Mar 07 '13 at 22:10
  • .live is deprecated in latest jquery so use .on instead – Shiv Jan 19 '16 at 11:41
  • guillesalazar's which uses bootstrap 3 function is a much better way of doing it. – LZH Jul 16 '16 at 17:45
19

If someone still has the problem, try this, it worked for me:

$(document).ready(function(){
    $('.modal').each(function(){
            var src = $(this).find('iframe').attr('src');

        $(this).on('click', function(){

            $(this).find('iframe').attr('src', '');
            $(this).find('iframe').attr('src', src);

        });
    });
});
ckpepper02
  • 3,297
  • 5
  • 29
  • 43
knightkiddo
  • 191
  • 1
  • 3
  • 1
    Awesome! this snippet has saved me from head banging against desk trauma, thanks! – Nsokyi Nov 11 '15 at 18:19
  • 1
    You saved me a big headache and best solution on Stack! – Woody Jul 09 '17 at 22:22
  • 2
    This should be the accepted answer!! With this approach, you don't have to pass through ID's or anything, since it goes through all the modals on the page. – Zeth Oct 23 '18 at 00:57
13

Here is a simple way I've found for having a video play in a modal window, and then stop playing on close.

Use the .html to load the iFrame with your video into the modal-body, when the modal is shown, and then replace the modal-body with nothing when it is hidden.

$('#myModal').on('show', function () { 
 $('div.modal-body').html('YouTube iFrame goes here');  
});
$('#myModal').on('hide', function () {
 $('div.modal-body').html('');
});

Here is a jsfiddle example:

http://jsfiddle.net/WrrM3/87/

13

Here, I generalize @guillesalazar's answer.

This will reset any iFrame within any bootstrap modal (when the modal is closed):

$(function(){
  $("body").on('hidden.bs.modal', function (e) {
    var $iframes = $(e.target).find("iframe");
    $iframes.each(function(index, iframe){
      $(iframe).attr("src", $(iframe).attr("src"));
    });
  });
});

Add this to your layout and you're set.

UPDATE: Code modified for modals with multiple iFrames.

thekingoftruth
  • 1,711
  • 1
  • 25
  • 24
  • 1
    Added this function to a js file and included it in the html using ``. I have multiple modals, some with multiple videos, and this works with embedded videos. Very nice. – Vincent Jul 03 '15 at 19:47
  • @Vincent This should not work for modals which have multiple videos. For that you will have to loop over all the iFrames referenced in the `$iframe` var. Ex: `$($iframe).each(function(item){$(item).attr("src", $iframe.attr("src"));})`. – thekingoftruth Jul 06 '15 at 21:33
  • @Vincent I've updated my answer to be even more generalized, so as to catch the case where you have multiple iFrames within your modals. – thekingoftruth Jul 06 '15 at 21:41
  • Hmmm. The pervious version seemed to do that just fine already. Will try out the new version as well. – Vincent Jul 07 '15 at 01:18
  • @Vincent The previous version would seem to work but what would actually be happening is: the first iFrame's `src` attribute would replace all of the iFrames' `src` attributes in a given modal. – thekingoftruth Jul 08 '15 at 19:09
  • I tried the new function and it does not seem to stop either one or more videos running in a modal. The previous function did. – Vincent Jul 08 '15 at 22:39
  • @Vincent Hey, I found some minor bugs, which have been fixed in the latest edit. – thekingoftruth Jul 09 '15 at 22:40
  • Works! Thanks @thekingoftruth Do you perhaps have something similar for changing to another page via a navbar when the video is embedded in the body? I tried // see http://jsfiddle.net/o4eebLp4/17/ but no luck. – Vincent Jul 10 '15 at 00:13
  • @Vincent Your jsfiddle works fine for me. Not sure what the problem is. – thekingoftruth Jul 10 '15 at 04:01
  • Sorry. I wasn't very clear. That jsfiddle works for tabs but not for a navbar for some reason. – Vincent Jul 10 '15 at 04:31
  • FYI Wrapped js code in a function from the jsfiddle like you had above and it works now. – Vincent Jul 12 '15 at 21:21
  • @Vincent Ah. Since `$(function(){...});` runs the code once the page has finished loading, it avoids some issues. I guess that must have been the problem. – thekingoftruth Jul 14 '15 at 07:56
6

You should empty iframe src first and then set it up again.

So my working answer:

$('#myModal').on('hidden.bs.modal', function () {
    var src = $(this).find('iframe').attr('src');
    $(this).find('iframe').attr('src', '');
    $(this).find('iframe').attr('src', src);
});

October, 2014. For Bootstrap 3.

littlealien
  • 429
  • 4
  • 11
4

Here is my solution, it solves the following using bootstrap event calls:

  1. Autoplay movie when showing the modal
  2. Stop movie when modal is hidden

HTML carousel inside modal, first active item is the iframe video

<button class="btn btn-primary" data-toggle="modal" data-target="#myModal">Modal</button>

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-body">
                <div id="myCarousel" class="carousel slide carousel-fade" data-ride="carousel">
                    <div class="carousel-inner" role="listbox">
                        <div class="item active">
                            <div class="fill">
                                <iframe id="videoIframe" width="100%" height="100%" src="https://www.youtube.com/embed/UVAjm8b7YFg?rel=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Javascript autoplay when displaying modal, then reset the URL and apply it to iframe src again

$('#myModal').on('show.bs.modal', function() {
    $("#videoIframe")[0].src += "&autoplay=1";
});
$('#myModal').on('hidden.bs.modal', function(e) {
    var rawVideoURL = $("#videoIframe")[0].src;
    rawVideoURL = rawVideoURL.replace("&autoplay=1", "");
    $("#videoIframe")[0].src = rawVideoURL;
});
Brandon Franklin
  • 363
  • 3
  • 11
2

This one does it perfectly:

$("#myModal").on("hidden.bs.modal", function(t) {
   var o = $(t.target).find("iframe");
   o.each(function(t, o) {
      $(o).attr("src", $(o).attr("src"))
   });
});

If you however want to have it start when modal opens / stop when it closes use this code:

But make sure to add enablejsapi=1 in your src, like this for example:

<iframe src="https://www.youtube.com/embed/YOUR_VIDEO_CODE?rel=0&amp;controls=0&amp;showinfo=0&enablejsapi=1" frameborder="0" allowfullscreen></iframe>


function playStopVideo() {
    var youtubeFunc ='';
    var outerDiv = $("#myModal");
    var youtubeIframe = outerDiv.find("iframe")[0].contentWindow;
    outerDiv.on('hidden.bs.modal', function (e) {
        youtubeFunc = 'stopVideo';
        youtubeIframe.postMessage('{"event":"command","func":"' + youtubeFunc + '","args":""}', '*');
    });
    outerDiv.on('shown.bs.modal', function (e) {
        youtubeFunc = 'playVideo';
        youtubeIframe.postMessage('{"event":"command","func":"' + youtubeFunc + '","args":""}', '*');
    });
}

playStopVideo();
nikola_wd
  • 607
  • 5
  • 9
2

A much easier way than all of these answers is just replacing the whole src. This works for all modals and you can adjust iframe class as required.

$('.modal').on('hidden.bs.modal', function(e) {
    var closestIframe = $(e.currentTarget).find('iframe');
    var rawVideoURL = $("iframe")[0].src;

    closestIframe[0].src = "";
    closestIframe[0].src = rawVideoURL;
  });
Jonathan Bird
  • 313
  • 5
  • 19
2

Reload any iframe in bootstrap modal on hide.bs.modal event.

The setTimeout delay added for fixing iframe rendering after src reset.

$('.modal').on('hidden.bs.modal', function (event){
    let iframes = event.target.getElementsByTagName('iframe');
    for (let i = 0; i < iframes.length; i++) {
        let src_tmp = iframes[i].src;
        iframes[i].src = '';
        setTimeout(() => {
            iframes[i].src = src_tmp;
        }, 100);
    }
});
Arthur Shlain
  • 961
  • 10
  • 23
1

I used a combination of Ruslanas Balčiūnas and Nathan McFarland's answers to code something that worked well for me.

$('#myModal').on('hide',function(){
   $('.modal-body iframe').attr('src','');
});

So basically this sets the src attribute of the iframe to nothing when the close modal event is triggered. Short and sweet.

Community
  • 1
  • 1
ckpepper02
  • 3,297
  • 5
  • 29
  • 43
1

My solution to this that works for Bootstrap 3 and the modern YouTube embed format is as follows.

Assuming your video is embedded within a standard Bootstrap 3 Modal with id="#video-modal", this simple bit of Javascript will do the job.

$(document).ready(function(){
  $("#video-modal").on('hide.bs.modal', function(evt){
    var player = $(evt.target).find('iframe'),
        vidSrc = player.prop('src');
    player.prop('src', ''); // to force it to pause
    player.prop('src', vidSrc);
  });
});

I've seen proposed solutions to this issue involving use of the YouTube API, but if your site is not an https site, or your video is embedded using the modern format recommended by YouTube, or if you have the no-cookies option set, then those solutions don't work and you get the "TV set to a dead channel" effect instead of your video.

I've tested the above on every browser I could lay my hands on and it works very reliably.

Dave Sag
  • 13,266
  • 14
  • 86
  • 134
1

Expanding on Guille's answer above, this is a drop-in function that will work with Bootstrap 3, the latest version of youtube as of Aug 14, and works for multiple videos /modals in one page.

$(".modal").on('hidden.bs.modal', function(e) {
    $iframe = $(this).find( "iframe" );
    $iframe.attr("src", $iframe.attr("src"));
}); 
spiral
  • 598
  • 3
  • 10
1

Had a modal with many videos. Updated the code by @guillesalazar to close multiple videos in the modal.

$("#myModal").on('hidden.bs.modal', function (e) {
            $("#myModal iframe").each(function () {
                $(this).attr("src", '');
            });
        });
Lee Harris
  • 521
  • 4
  • 12
  • This doesnt work with with multiple links opening video ina modal window., when you close the modal window, the video still plays in the background – user244394 May 05 '16 at 13:51
1

7 years after, we still need to solve this.

We found a best way to fix it (Inspired by RobCalvert123 answer)

  jQuery(".modal-backdrop, .modal.open .close,.modal.open .btn").live("click", function() {  
         // Get iframe opened 
         var iframe_open = jQuery('.modal.open');     
         // Get src from opened iframe 
         var src = iframe_open.attr('src');
         // replace src by src to stop it that's the tips
        iframe_open.attr("src", src);
});
Vincent Guesné
  • 776
  • 5
  • 13
  • 28
1

1. Embed Youtube on your Page (html)

Add the Youtube div-container to your Website:

<div id="ytplayer">This will be replaced with the Youtube iFrame</div>

Add the Youtube Javascript Api (iFrame)

<script>
    // Ads Youtube JS API
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);


    // This function creates an <iframe> (and YouTube player) after the API code downloads.
    var player;
    function onYouTubeIframeAPIReady() {
    player = new YT.Player('ytplayer', {
      height: '390',
      width: '640',
      videoId: 'ncif63mSZl4',
        WMode: 'transparent',
        wmode: 'opaque',
        playerVars: {
            'autoplay': 0,
            'controls': 0,
            'autohide':1,
            'rel':0,
            'showinfo': 0,
            'modestbranding': 1,
        },
      });
    }

   function stopVideo() {
    player.stopVideo();
   }
    
   function pauseVideo() {
    player.pauseVideo();
   }
    
   function playVideo(){
    player.playVideo();
   }
</script>

Controll with jQuery (Bootstrap Modal)


  // Open Modal and start Playing Youtube Video
  $("#myModalTrigger").click(function(){
    $("#video-modal").modal(); // opens up the Modal
    playVideo(); // Starts playing Video
  });

  // Stop Player on Modal hide
  $('#video-modal').on('hide.bs.modal', function (e) {
    stopVideo(); // stop player
  });

onedrop
  • 41
  • 5
0
$('#myModal').on('hide', function () {
    $('#video_player')[0].stopVideo();
})
Ruslanas Balčiūnas
  • 7,310
  • 3
  • 24
  • 41
0

@guillesalazaar's answer was only the 1st half of my fix so I felt compelled to share my situation in case it helps someone in the future. I too have an embedded youtube video but I set mine to play automatically when the frame is loaded using autoplay=1. To get around the autoplay issue on page load I have my youtube url stored in a variable that sets the iframe source using a click handler. To solve this I simply removed the attribute source link:

My Url to trigger the modal window:

   <div id="movieClick" class="text-center winner"> 
<a href="#" data-toggle="modal" data-keyboard="true" data-target="#movie">
    </div>

My hidden modal window divs:

<div id="movie" class="modal fade" role="dialog" tabindex='-1'>
    <div class="modal-dialog">

<div class="modal-content">
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;</button>
        <h4 class="modal-title">They Live (1988)</h4>
    </div>
     <div class="modal-body">
        <iframe id="onscreen" width="100%" height="460px" src="" frameborder="0" allowfullscreen></iframe>

      </div>
</div>

</div>
</div>

My JS:

$("#movieClick").click(function(){
var theLink  = "https://www.youtube.com/embed/Wp_K8prLfso?autoplay=1&rel=0";
document.getElementById("onscreen").src = theLink;
});


// really annoying to play in the Background...this disables the link
$("#movie").on('hidden.bs.modal', function (e) {
    $("#movie iframe").attr("src", '');
});
Frankenmint
  • 1,570
  • 3
  • 18
  • 33
0
 //stop youtube video on modal close
$('.modal').on('hidden.bs.modal', function () {
    var iframVideo = $('.modal').find('iframe');
    $(iframVideo).attr("src", $(iframVideo).attr("src"));
});
0

My solution for 2 or more Youtube videos using the HTML data-* attribute. The video autoplays and stops when the modal is opened and closed.

<button data-url="https://www.youtube.com/embed/C0DPdy98e4c" data-toggle="modal" data-target="#mymodal">Video 1</button>
<button data-url="https://www.youtube.com/embed/ScMzIvxBSi4" data-toggle="modal" data-target="#mymodal">Video 2</button>

<!-- Modal -->
<div id="mymodal" class="modal fade">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">Close</button>
        </div>
        <div class="embed-responsive embed-responsive-16by9">
          <iframe class="embed-responsive-item" src="" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
        </div>
      </div>
    </div>
  </div>
</div>
$('.modal').on('show.bs.modal', function (event) {
  $(this).find('iframe').attr("src", $(event.relatedTarget).data('url') );
});

$('.modal').on('hidden.bs.modal', function (e) {
    $(this).find('iframe').attr("src", "");
});

Here is a Codepen demo: https://codepen.io/danielblazquez/pen/oOxRJq

DanielBlazquez
  • 1,045
  • 1
  • 13
  • 22
0

For angular or for dynamic html or if we have multiple iframes then use as below

$("#myModal").on('hidden.bs.modal', function (e) {
  $("#myModal iframe").each(function(){
    $(this).attr("src", $(this).attr("src"));
  });
});
Gopala Raja Naika
  • 2,321
  • 23
  • 18
0

if you have multiple modals with many videos, let's say you have a modal on each slide on a carousel for instance, you need something more dynamic to close/stop the video in the visible slide and not mess up all the other modals, use this:

$(".modal").on('hidden.bs.modal', function (e) {
      $(this).find("iframe").attr("src", $(this).find("iframe").attr("src"));
  });
Abdel Ourimchi
  • 196
  • 1
  • 5