0

So I'm trying to implement stellar.js but it must be initialized after an each loop is finished. The loop must add data attributes to the images that are going to be made parallax by the plugin.

The images are in a list:

<ul>
    <li class="item">
        <div class="item-image" data-stellar-background-ratio="0.7" data-image="http://picjumbo.picjumbocom.netdna-cdn.com/wp-content/uploads/IMG_7706-1300x866.jpg"></div>
    </li>
    ...
</ul>

I must add data-stellar-vertical-offset attribute to each of them that will offset the image by half of its height, so it can be vertically centered initially.

Here is the JS:

/* Inserting the background image */
$('.item-image').each(function () {
var $this = $(this);
$this.css('background-image', 'url(' + $this.data('image') + ')');
})

 /* Creating loop that will run as many times as items are in there */

var items = $('.item-image').length;
var currentItem = 0;

$('.item-image').each(function () {

var $this = $(this);

/* Taking the origin height, halving it and putting it as offset so the image can be vertically aligned */

var img = new Image();
img.src = $(this).data('image');
img.onload = function () {
    var H2 = this.height;
    $this.attr('data-stellar-vertical-offset', -(H2 / 2));
}

currentItem++;

/* Initializing the plugin after every item is looped */

if (currentItem >= items) {
        $.stellar();
}

})

However when the plugin is initialized it isn't using the data attribute. If it's put in a timeout like this:

 if (currentItem >= items) {
    setTimeout(function () {
        $.stellar();
    }, 10)
}

.. it works but it seems to me like an ugly hack. Is there a better way for this to be done?

Here is a jsfiddle: http://jsfiddle.net/9f2tc/1/

Ziik
  • 1,029
  • 1
  • 9
  • 17

1 Answers1

1

I believe what you want is to initialize stellar once after all the images have been downloaded. The simplest approach is to check each time in the onload handler:

img.onload = function () {
    var H2 = this.height;
    $this.attr('data-stellar-vertical-offset', -(H2 / 2))
    if (++currentItem === items) {
        $.stellar();   
    }
}

jsfiddle: http://jsfiddle.net/X6e9n/2/

However, there are issues with the onload event not firing for images in certain cases. See the caveats section on the jQuery page: http://api.jquery.com/load-event/ The problems listed apply to the load event itself not just jQuery's .load() See Javascript callback for knowing when an image is loaded for solutions. The first answer notes the handler should be attached before the src attribute is set, which you don't do here, but it doesn't seem to be a problem for me in this case.

Community
  • 1
  • 1
Alex Holt
  • 165
  • 8
  • Do I have to init stellar() for each image as `$this.stellar();` or only once after that ? – Ziik Jun 15 '14 at 09:20
  • Yes, you're right. Initializing stellar for each image is doing nothing since that repositions the image relative the scroll of that image which isn't scrolled and, therefore, the image will never be repositioned. I've updated the fiddle and the code snippet with that change. – Alex Holt Jun 17 '14 at 15:19
  • Thanks, you've been most useful! – Ziik Jun 17 '14 at 16:39