简体   繁体   中英

Triggering a function after ajax call has finished loading images in Laravel

I've got an image gallery on my page, which works a lot like pinterest.

$images = Images::paginate(5);

On my image page, I start off with 5 images.

Controller:

if($request->ajax()) {
    return [
        'images' => view('browse.partials.imagePartials')->with(compact('images'))->render(), 'next_page' => $images->nextPageUrl()
    ];
}           

return view('browse.combined_results')->with('images', $images);

Markup:

<div id="freewall" class="freewall endless-pagination" data-next-page={{ $images->nextPageUrl() }}>
@foreach ($images as $image)
<a href="{{ route('image.get', ['username' => $image->created_by_username, 'URLtitle' => $image->url_title]) }}">
    <div class='brick featuredTextContainer' style="width:150px">
        <img src='{{ url($image->medium_path) }}' width='100%' class="profileImg">
        <span class="featuredArtistName">{{ $image->title }}</span>             
    </div>
</a>
@endforeach
</div>

These images are arranged using freewall:

var wall = new Freewall("#freewall");
wall.reset({
    selector: '.brick',
    animate: true,
    cellW: 150,
    cellH: 'auto',
    onResize: function() {
        wall.fitWidth();
    }
});

var images = wall.container.find('.brick');
images.find('img').on('load', function() {
    wall.fitWidth();
});

wall.fitWidth();    

wall.fitWidth() is the method that arranges the images all neatly, like so:

在此处输入图片说明

However, if you scroll down, you get an ajax request

$(window).scroll(fetchImages);

function fetchImages() {
    var page = $('.endless-pagination').data('next-page');

    if(page !== null) {

        clearTimeout( $.data( this, "scrollCheck" ) );

        $.data( this, "scrollCheck", setTimeout(function() {
            var scroll_position_for_images_load = $(window).height() + $(window).scrollTop() + 100;

            if(scroll_position_for_images_load >= $(document).height()) {
                $.get(page, function(data){
                    $('.endless-pagination').append(data.images);
                    $('.endless-pagination').data('next-page', data.next_page);
                });

            }
        }, 350))

    }
}

The ajax request loads a partial, which is essentially just the next page of the pagination.

imagePartial.blade.php

@foreach ($images as $image)
        <a href="{{ route('image.get', ['username' => $image->created_by_username, 'URLtitle' => $image->url_title]) }}">
            <div class='brick featuredTextContainer' style="width:150px">
                <img src='{{ url($image->medium_path) }}' width='100%' class="profileImg">
                <span class="featuredArtistName">{{ $image->title }}</span>             
            </div>
        </a>
@endforeach

In other words, it loads in more images from the $images pagination into the images container.

Which is great. It works. However, the images aren't arranged right away. You have to execute wall.fitWidth() once more for the images to fit into place. The problem is, I can't simply put this at the end of the fetchImages function, because the images take a moment to load in. Therefore, all the images are loaded behind the other images, unarranged.

A solution to this would be to, say, have the new images loaded in with opacity set to 0, have the wall.fitWidth() function executed after a check to make sure all the images have been loaded into the DOM, THEN set the images back to opacity: 1. But I'm not sure how to do this.

Help?

You can do it like this - prepare one variable

var loading = 0;

and a function

function imageLoaded(){
 loading -= 1;
 if(loadingImages == 0){
  wall.fitWidth();
  var imgs = document.getElementsByTagName('img');
  for(var i=0;i<imgs.length;i++)
   if(imgs[i].style.opacity == '0')
    imgs[i].style.opacity = '1';
 }
}

then add this to all the image elements / to the image template

onload="imageLoaded();" style="opacity:0;"

and finally whenever you load new images, increase the loading variable by the amount of new images.

Edit:

In reply to your comment :

onload="loading-=1;if(loadingImages==0){wall.fitWidth();var imgs=document.getElementsByTagName('img');for(var i=0;i<imgs.length;i++)if(imgs[i].style.opacity=='0')imgs[i].style.opacity='1';}}" style="opacity:0;"  

It's ugly, but makes sure there won't be any context errors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM