How to run masonry only after all html5 videos are loaded with infinitescroll?
Asked Answered
T

1

12

masonry infinite scroll append html5 videos overlapping

i am currently using imagesLoaded library which checks whether images are loaded then calls masonry.

But it was not working with html5 video tag, because of this videos gets overlapped on one another.

so i changed calling masonry from document.ready to window.load and removed call to imagesLoaded on initial loading i.e. from this

$(document).ready(function(){

    var $container = $('#media');
    // layout Masonry again after all images have loaded
    $container.imagesLoaded( function() {

      $container.masonry({
          "columnWidth": "." + "col-sm-2",
          itemSelector: '.item',
          gutter: 0,
        });
      $('.item').css('opacity', '1.0');
    });

});

to this

$(window).load(function(){
        var $container = $('#media');

          $container.masonry({
              "columnWidth": "." + "col-sm-2",
              itemSelector: '.item',
              gutter: 0,
            });
          $('.item').css('opacity', '1.0');
});

now html5 videos in masonry are not overlapping, and are rendering perfectly on page's first load i.e. initial load, but as i am also using infinite-scroll which adds more images/videos on scrolling page down, so when new videos are being added to container they are being overlapped , this behavior is caused by early running of masonry before all the video elements are being loaded as imagesloaded cant check the videos loaded.

this is the code.

$(document).ready(function(){
    var $container = $('#media');
    var no_more_media = "<?= Lang::get('lang.no_more_to_load') ?>";
    var loading_more_media = "<?= Lang::get('lang.loading_more_media') ?>";

    $container.imagesLoaded(function(){
            $container.masonry();
        });

$container.infinitescroll({
        loading: {
            finished: undefined,
            finishedMsg: "<p>" + no_more_media + "</p>",
            img: "data:image/gif;base64,R0lGODlhAQABAHAAACH5BAUAAAAALAAAAAABAAEAAAICRAEAOw==",
            msg: null,
            msgText: "<div class='loading'><i></i><i></i><i></i></div><p>" + loading_more_media + "</p>",
            selector: null,
            speed: 'fast',
            start: undefined,
        },
        navSelector  : "ul.pagination",            
                       // selector for the paged navigation (it will be hidden)
        nextSelector : "ul.pagination a:first",    
                       // selector for the NEXT link (to page 2)
        itemSelector : ".container #media .item",
        animate: false,
        bufferPx: 160,
      },

      function( newElements ) {
         // hide new items while they are loading
        //var $newElems = 
        $.each($(newElements), function(index, value){
            item_click_events($(value));
        });

            $( newElements ).css({ opacity: 0 });

            $(newElements).imagesLoaded(function(){
               var $newElems = $( newElements );
               $newElems.animate({ opacity: 1 });
               $container.masonry( 'appended', $newElems, true);
            }
            );

      });
});

i have tried changing document.ready to window.load in above code too, and removing running imagesloaded altogether, but its not working with infinitescroll.,

e.g. modified code

$(window).load(function(){
    var $container = $('#media');
    var no_more_media = "<?= Lang::get('lang.no_more_to_load') ?>";
    var loading_more_media = "<?= Lang::get('lang.loading_more_media') ?>";

            $container.masonry();

    $container.infinitescroll({
        loading: {
            finished: undefined,
            finishedMsg: "<p>" + no_more_media + "</p>",
            img: "data:image/gif;base64,R0lGODlhAQABAHAAACH5BAUAAAAALAAAAAABAAEAAAICRAEAOw==",
            msg: null,
            msgText: "<div class='loading'><i></i><i></i><i></i></div><p>" + loading_more_media + "</p>",
            selector: null,
            speed: 'fast',
            start: undefined,
        },
        navSelector  : "ul.pagination",            
                       // selector for the paged navigation (it will be hidden)
        nextSelector : "ul.pagination a:first",    
                       // selector for the NEXT link (to page 2)
        itemSelector : ".container #media .item",
        animate: false,
        bufferPx: 160,
      },

      function( newElements ) {
         // hide new items while they are loading
        //var $newElems = 
        $.each($(newElements), function(index, value){
            item_click_events($(value));
        });

            $( newElements ).css({ opacity: 0 });

               var $newElems = $( newElements );
               $newElems.animate({ opacity: 1 });
               $container.masonry( 'appended', $newElems, true);

      });
});

there is another way i can solve this overlapping issue, by specifying video width and height, but as its responsive design, specifying video width and height breaks the responsiveness.

so my question is , is there any js library simmilar to imagesloaded which makes sure all videos are loaded and then i can call to masonry ? or how can i make sure the videos wont get overlapped on infinitescroll ?


update 1 :

i have tried many techniques, for infinitescroll

$(newElements).load(function(){
   var $newElems = $( newElements );
   $newElems.animate({ opacity: 1 });
   $container.masonry( 'appended', $newElems, true);
});

doesnt loads new content after pagescroll.

$(window).load(function(){
   var $newElems = $( newElements );
   $newElems.animate({ opacity: 1 });
   $container.masonry( 'appended', $newElems, true);
});

doesnt loads new content after pagescroll.

   var $newElems = $( newElements );
   $newElems.animate({ opacity: 1 });
   $container.masonry( 'appended', $newElems, true);

overlaps video content

so i have came up with calling infinite-scroll early and slowing down the container.masonry by 3 seconds which is working perfectly for now., but still waiting for proper solution.

e.g.

bufferPx: 700,

setTimeout(function(){
       var $newElems = $( newElements );
       $newElems.animate({ opacity: 1 });
       $container.masonry( 'appended', $newElems, true);
}, 3000);

above is delaying running masonry by 3 seconds.

i tried looking for something like window.load for div, but there is none, so my best option is check whether all the videos and images are loaded and then call masonry after calling infinite-scroll


added working demo http://plnkr.co/edit/46YzHBJ7eFAXfsPqZB1q you can see the issue, by clicking run and scrolling down.

Testaceous answered 7/8, 2016 at 5:1 Comment(3)
Add a fiddle or a code snippet and I ( or someone else ), will fix it.Talcahuano
A fiddle would definitely be the best result and most valuable to the question. Adding external links is generally discouraged because of "link rot". But if you really can't add a fiddle a link might be ok. I don't think there is a policy against NSFW links.Talcahuano
added working demo plnkr.co/edit/46YzHBJ7eFAXfsPqZB1qTestaceous
N
7

Looks like you can fix it by waiting for the loadeddata event of the video's

Here is the basic idea:

function waitForvidLoad(vids, callback) {
     /* if no videos i.e. mobile mode only gifs and jpgs then call callback else masonry breaks.*/
        if(vids.length === 0){
            callback();
        }
    var vidsLoaded = 0;
    vids.on('loadeddata', function() {
      vidsLoaded++;
      if (vids.length === vidsLoaded) {
        callback();
      }
    });
  }

.

  var $container = $('#container');
  var vids = $('#container').find('video');
  waitForvidLoad(vids, function() {
    $container.imagesLoaded(function() {
      $container.masonry({
        itemSelector: '.box',
        columnWidth: 100
      });
  });

Working plunker here: http://plnkr.co/edit/jXJ7oFxF3sFWBAJuBqdQ?p=preview

Nonplus answered 11/8, 2016 at 3:35 Comment(14)
how is this working for second page load too ? i dont get it. i mean i dont see anything for $container.infinitescrollTestaceous
Hmm, probably because the assets are cached, I couldn't test with cache disabled because the video's load really really slow. You can probably apply the same solution to the infinitescroll loading code.Talcahuano
@AMB Where you able to use this to fix the issue on your website ?Talcahuano
Hi, not yet, i am still trying various code combinations , but none are working, yet. for initial load its working fine bcoz i used window.load but the issue is for seconds load.Testaceous
i tried exact same code from plunkr , now there are vertical gaps in masonry, but no more video overlapping.Testaceous
okie., update, if i use your code even for initial loading, then its breaking masonry, vertical gaps are there. i double checked, if i dont use your solution then masonry works fine, for initial load, any specific reason ? ill add diferrent diamension images in the demo, so it will be clear as to whats breaking the masonry.Testaceous
okie., here is new plunkr which shows masonry breaks using the same old code. + solution , embed.plnkr.co/7Ibw9eCFu0N49HEDWtmvTestaceous
looks like masonry is not being called at all.,Testaceous
@AMB I updated the code with a working plunker, give it a try now. Sorry for the mess up there.Talcahuano
Hi, np, but the masonry is still not being called, you can see the empty vertical gaps.Testaceous
@AMB Sorry messed up again, check the plunker again please. It does take some time for masonry to start because the video's load so slow. You could solve that with some sort of overlay and preloading the video's, that's a different issue tough I think.Talcahuano
Thanks, its working perfect as expected and indeed its kind of slow , but i guess thats problem with server serving videos. ill look into it more., thanks.Testaceous
update, masonry wan't being called when theres no video element, so i updated waitForvidLoad function , plnkr.co/edit/ABvyweIOSET3VWvWV1lm?p=previewTestaceous
Ah good catch, I updated the answer to include that as well. Hope everything works now ! Please feel free to accept the answer if you have no other issues with the solution :DTalcahuano

© 2022 - 2024 — McMap. All rights reserved.