desandro / imagesloaded

:camera: JavaScript is all like "You images done yet or what?"
https://imagesloaded.desandro.com
MIT License
8.88k stars 1.15k forks source link

Performance problem with imagesLoaded and AJAX #286

Closed plusPlus91 closed 5 years ago

plusPlus91 commented 5 years ago

Hello,

I have a performance problem with imagesloaded. I've created a sandbox with this code:

var $grid = $('.home-posts-container').masonry({
  itemSelector: 'none', // select none at first
  columnWidth: '.grid-sizer',
  gutter: '.gutter-sizer',
  percentPosition: true,
  stagger: 30,
  visibleStyle: { transform: 'translateY(0)', opacity: 1 },
  hiddenStyle: { transform: 'translateY(100px)', opacity: 0 },
});

$grid.imagesLoaded( function() {
  $grid.removeClass('are-images-unloaded');
  $grid.masonry( 'option', { itemSelector: '.timeline-posts' });
  var $items = $grid.find('.timeline-posts');
  $grid.masonry( 'appended', $items );
});

Everything is working fine and with a lot of speed. Then I tried to insert this code into an existing script. The script code was BEFORE I added Masonry:

jQuery(document).ready(function($) {
            var scrolled = 0;
            var last_id  = 0;
            var posts_cn = $('.home-posts-container');

            $(window).scroll(function() {
                if($(window).scrollTop() + $(window).height() > $(document).height() - 1000) {
                    if (scrolled == 0 && $('.home-posts-container').length > 0 && $('.home-posts-container').attr('data-there-posts') != 'no_posts') {
                        scrolled = 1;
                        posts_cn.siblings('.posts__loader').removeClass('hidden');
                        if ($('[data-post-id]').length > 0) {
                            last_id  = $('[data-post-id]').last().data('post-id');
                        }

                        $.ajax({
                            url: link('posts/load-tl-posts'),
                            type: 'GET',
                            dataType: 'json',
                            data: {offset:last_id},
                        }).done(function(data) {
                            if (data.status == 200) {
                                posts_cn.append($(data.html));
                                scrolled = 0;

                                if (data.html == '') {
                                    $('.home-posts-container').attr('data-there-posts','no_posts');
                                }
                            } [...]

And changed it to:

var $grid = $('.home-posts-container').masonry({
  itemSelector: 'none', // select none at first
  columnWidth: '.grid-sizer',
  gutter: '.gutter-sizer',
  percentPosition: true,
  stagger: 30,
  visibleStyle: { transform: 'translateY(0)', opacity: 1 },
  hiddenStyle: { transform: 'translateY(100px)', opacity: 0 },
});

$grid.imagesLoaded( function() {
  $grid.removeClass('are-images-unloaded');
  $grid.masonry( 'option', { itemSelector: '.timeline-posts' });
  var $items = $grid.find('.timeline-posts');
  $grid.masonry( 'appended', $items );
});

        jQuery(document).ready(function($) {
            var scrolled = 0;
            var last_id  = 0;
            var posts_cn = $('.home-posts-container');

            $(window).scroll(function() {
                if($(window).scrollTop() + $(window).height() > $(document).height() - 1000) {
                    if (scrolled == 0 && $('.home-posts-container').length > 0 && $('.home-posts-container').attr('data-there-posts') != 'no_posts') {
                        scrolled = 1;
                        posts_cn.siblings('.posts__loader').removeClass('hidden');
                        if ($('[data-post-id]').length > 0) {
                            last_id  = $('[data-post-id]').last().data('post-id');
                        }

                        $.ajax({
                            url: link('posts/load-tl-posts'),
                            type: 'GET',
                            dataType: 'json',
                            data: {offset:last_id},
                        }).done(function(data) {
                            if (data.status == 200) {
//                              posts_cn.append($(data.html));

                                var $content = $(data.html);
                                $grid.imagesLoaded( function() {
                                  posts_cn.append( $content ).masonry( 'appended', $content );
                                  scrolled = 0;
                                });

                                if (data.html == '') {
                                    $('.home-posts-container').attr('data-there-posts','no_posts');
                                }
                            } [...]

Everything is working but the loading time is not good, 2-5 seconds. If I delete the $grid.imagesLoaded and only use the "posts_cn.append( $content ).masonry( 'appended', $content );" than the speed is great but the masonry overlaps the divs.

Do you have any idea?

desandro commented 5 years ago

Currently, in the done method, you are triggering imagesLoaded on $grid, but you could trigger it just on the $content

$content.imagesLoaded( function() {
  posts_cn.append( $content ).masonry( 'appended', $content );
  scrolled = 0;
});

Otherwise, this looks okay. If it takes longer than you would prefer, that's just how long it takes for images to be loaded.