1

I am using this method to create custom thumbnails for embedded YouTube/Vimeo videos.

It is simple - image as placeholder, replace with embed when clicked.

My content is being generated through JSON $.getJSON and the click-binding appears not to catch. If I go through the console after the page has loaded and run my binding function, it works fine. So I think my problem is timing - I think that the click-binding is running before the content is generated.

I've tried $( document ).ready() and I've tried using a callback (as seen below)

    function binding()
    {
    $('.portfolioVideoPlaceholder').click(function(){
                                var video = '<iframe src="'+ $(this).attr('data-video') +'"></iframe>';
                                $(this).replaceWith(video);
                                }
                        );      
    }
    function fillSection(callback)
    {

        $.getJSON('js/Mammola-portfilio-list.json', function (data){.......}
    callback(); 
    }

    fillSection(binding);

And my HTML for the placeholders looks like this: <img class="portfolioVideoPlaceholder" src="images/thumb-gpwit.png" data-video="//www.youtube.com/embed/WiOZdLFrbDE">

Any help would be appreciated.

Community
  • 1
  • 1

2 Answers2

2

Are you calling binding inside your response function from getJSON? If not, you should.

Alternatively, switch to using "on".

http://api.jquery.com/on/

$('body').on('.portfolioVideoPlaceholder', 'click', function(){} );      

You can call this on your document load, and if it notices a new element, it will bind that function to it and never have to call it again.

Andrew Spode
  • 637
  • 1
  • 7
  • 12
  • 1
    Thanks for the advice! I switched the order to $('body').on('click', '.portfolioVideoPlaceholder', function(){} ); It now is functioning as expected, thanks so much! – Matthew J Mammola Apr 22 '15 at 12:32
1

It is easier to register a delegated event handler, once, at DOM ready, than to try and reconnect element-based handlers when items are added to the DOM. The handler should be attached to the nearest non-changing ancestor of the dynamic elements. document is your default if nothing else is closer/convenient.

e.g. use:

$(document).on('click', '.portfolioVideoPlaceholder', function(){} );   

or preferably

$('#someAncestor').on('click', '.portfolioVideoPlaceholder', function(){} );   

This works by listening for the event to bubble up the DOM to the connected element, then it applies the jQuery selector (against the elements in the bubble-chain only), then it calls the function for any matching elements that caused the event. This is very efficient and means the matching elements only need to exist at event time and not event registration time.

Note: If you are going to use delegated events with a root element, do not use body. Instead use document as the default. Not many people seem to know this, but if your page styling results in a calculated body height of 0, e.g. thanks to absolute elements, then mouse events will not bubble to body. They will however always bubble to document. Also $(document) is faster to parse than $('body') (trivial difference mind you).

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • Thanks for the full explanation and the additional tidbit! – Matthew J Mammola Apr 22 '15 at 16:27
  • What exactly is the difference between _delegated event handler_ and _element-based handler_? I suppose _element-based_ is the way that i was trying to do it initially (a one-time application) vs _delegated event_ which listens for changes in the DOM? – Matthew J Mammola Apr 22 '15 at 16:36
  • @Matthew J Mammola: Yes. A delegated handler "delegates" the responsibility for event handling to an ancestor (hence the name). A element-based handler is connected directly to the elements (multiple handlers pointing at the same function). – iCollect.it Ltd Apr 22 '15 at 16:38
  • Good advice on the "body". – Andrew Spode Apr 22 '15 at 16:41