WebDevDanno WebDevDanno - 1 month ago 9
Ajax Question

Bootstrap modal won't load youtube embed source

I am having trouble loading a modal with a youtube embed. My "videos" are loaded from an AJAX call to the youtube data API and use mustache templates to govern content display:

{{#statuses}}
<div class="videoBox col-xs-12 col-md-4 col-lg-4 {{source}}" data-date="{{timestamp}}" data-source="{{source}}">
<div class="videoBox__thumbnail">
<a class="modal__button videoBox__button" data-toggle="modal" data-src="https://www.youtube.com/embed/{{embed}}" data-video-fullscreen="1" data-width="640" data-height="480" data-target="#myModal">
<div class="videoBox__overlay"> </div>

<div class="videoBox__thumb">
<img src="{{thumbnail}}" alt="{{{text}}}" />
</div>

<div class="videoBox__play">
<object data="{{tempURL}}/assets/img/video_player_icon.svg"> </object>
</div>

<div class="videoBox__text">
<p><span class="title">{{{text}}}</span> <span class="date">{{{posted}}}</span></p>
</div>
</a>
</div>
</div>
{{/statuses}}


I have this function which I'm using in a file called
tv.js
and then I'm calling the function within my page like the below:

function loadIframeModal() {
$('.modal__button').bind('click', function(e) {
var src = $(this).attr('data-src');
var width = $(this).attr('data-width');
var height = $(this).attr('data-height');
var allowfullscreen = $(this).attr('data-video-fullscreen');

$("#myModal iframe").attr({
'src': src,
'height': height,
'width': width,
'allowfullscreen': allowfullscreen
});
});

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


And the function call

$(document).ready(function(){
loadIframeModal();
});


The modal loads but the embed does not display at all. I think I need a second pair of eyes on this. If I
console.log
within the
click
event - it is not displayed in the console but I've bound the click event to the button class so I'm a bit confused.

Answer

Bind event handlers after AJAX content is loaded

I'm turning my comment into an answer as I'm nearly sure this is your problem. jQuery's event binding methods require existing DOM elements to run successfully. From the docs for .on():

Event handlers are bound only to the currently selected elements; they must exist at the time your code makes the call to .on().

This means that to use event binding with content loaded via AJAX, you have three options:

1) Ugly inline HTML handlers

Inject the content with the event handler calls already present in them, as in <a href="#" onclick="openInModal('whateverID');">. This is a quick and dirty way that mixes presentation and logic, but I'll list it here for the sake of completeness.

2) Re-bind the handlers after loading content

To ensure your new arrivals have event handlers attached, you need to call the binding code again after the DOM finished loading. This means your call inside $(document).ready() will only work on content present at the time of initial DOM parsing, and you need to call it again every time new DOM elements are loaded - for example in the callback function of the $.ajax() call.

3) Use delegated events

To keep a single call to .on() that will work on AJAX content as well, read up on event delegation in the jQuery docs for .on(). Basically, the trick is to not attach the handler to the element directly but to a parent element (for example document) and include a selector to limit the handler's context. This will work on all present and future elements with your supplied selector as long as the parent element remains the same.

Here is a quick example of your code with event delegation:

function loadIframeModal() {

    $(document).on('click', '.modal__button', function(e) {

        var src             = $(this).attr('data-src'),
            width           = $(this).attr('data-width'),
            height          = $(this).attr('data-height'),
            allowfullscreen = $(this).attr('data-video-fullscreen');

        $("#myModal iframe").attr({
            'src'               : src,
            'height'            : height,
            'width'             : width,
            'allowfullscreen'   : allowfullscreen
        });

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