Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image slider doesn't show my images properly before they're cached

EDIT: MeteorPad demo here. (The slider should work but it shouldn't show the first image, only a sliver of it. But the bug only shows sometimes (and primarily on Safari or everything that isn't Chrome), so beware).

EDIT: The bug is that the first image in the slider is not displayed properly, only the very top of it, until you swipe or click the next/prev button. This bug only turns up if you load the images from a database source, not when you use the slider "normally".

I'm using Ken Wheeler's Slick slider, and while it's the best I've found it comes with a pretty nasty bug when I want to load images in an each loop in that it only shows the top of them until I press either the next/prev buttons or drag to the next image.

My collection has the following field:

"galleryImages": [
    {
      "name": "picture1",
      "position": "first"
    },
    {
      "name": "picture2",
      "position": "second",
    },
    {
      "name": "picture3",
      "position": "last"
    }
]

I use gallery as the slick container:

<div class="gallery">
  {{#each galleryImages}}
    <div>{{> Images}}</div>
  {{/each}}
</div>

<template name="Images">
  <img src="{{imageUrlMaker name}}" alt="{{name}}">
</template>

The imageUrlMaker just creates the correct url to fetch them at, not an issue.

And when Images is rendered I initialize the slider:

Template.Images.onRendered(function() {
    setTimeout(function() {
        $('.gallery').slick({
            arrows: true,
            dots: true,
            infinite: true,
            mobileFirst: true,
            adaptiveHeight: true
        })
    }, 100)
})

The reason for the setTimeout is that I find it erases some of the times the slider initializes before the images are loaded (for some reason).

As I said, the first time I visit a page that has images, they won't show (only the top) until they are dragged or the prev/next buttons are clicked. Or I could reload the page and everything will work.

Can anyone think of a workaround or fix, maybe using position: "last" in some clever way? Can anyone figure out why this bug shows?

like image 676
Yeats Avatar asked Oct 31 '22 23:10

Yeats


1 Answers

First of all: you're initializing your entire slick slider on every image render, if I'm not mistaken. Therefore it would be better to run $('.gallery').slick within Template.Gallery.onRendered() rather than Template.Images.onRendered().

The issue is that you'll have to wait for (1) the Gallery Collection to be ready and (2) the images to be loaded.

The only thing I could come up with to address both of those issues is to access the collection within a Meteor.autorun() and make sure the first image is loaded by the browser using an Image.onload:

Template.Gallery.onRendered(function() {

  Meteor.autorun(function() {
    var firstImage = Gallery.findOne();
    if (firstImage) {
      var img = new Image();
      img.onload = function() {
            $('.gallery').slick({
                infinite: true,
                mobileFirst: true,
                adaptiveHeight: true
            });
      }
      img.src = firstImage.url;
    }
  });
})

I see two possible issues with this approach, though:

  • Since the slick initializer is within a Meteor.autorun() it will run every time there's a change on the Gallery datasource. This may or may not be a problem.
  • It's not actually guaranteed that the images are rendered by the time the slick initializer runs. You may want to encapsulate some of the code within a Meteor.timeout() with a timeout of 0 just to make sure it runs within the next cycle. By then the renderer should have reacted to the datasource and created all the image DOM nodes.

Hope this helps in any way.

like image 111
user3252261 Avatar answered Nov 08 '22 09:11

user3252261