Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading all images before triggering JQuery Slideshow

I've modified Visual Idiot's Unslider (http://unslider.com/) to accommodate multiple-width slides based on image proportions, but in the process, I've encountered a bug which causes slides to load as tiny thumbnails (I think in the case where the images haven't loaded all the way). That's problem #1. So I'm trying to wait until all images are loaded. But I haven't found a way to do that successfully. That's problem #2.

Here is my added code inside the Unslider init() function:

_.init = function(el, o) {
  //  Check whether we're passing any options in to Unslider
  _.o = $.extend(_.o, o);

  _.el = el;
  _.ul = el.find(_.o.items);
  _.max = [el.outerWidth() | 0, el.outerHeight() | 0];
  _.max = [100, 100];
  _.li = _.ul.find(_.o.item).each(function(index) {
    var me = $(this);
    var an_image = me.find('img');
    an_image.load(function() {
      width = an_image[0].naturalWidth,
      height = an_image[0].naturalHeight;

      setSlideHeight(an_image, width, height, 300, 20);
      if ( an_image.parent().parent().is(":last-child") ) {

        _.el.css("width", 900);
      }
    })  

    //  Set the max values
    //if (width > _.max[0]) _.max[0] = width;
    //if (height > _.max[1]) _.max[1] = height;
  });

And here is my Ruby partial with a script inline for triggering Unslider when all the images are loaded.

<% if @page.cap_gallery_images.any? %>
  <script>
    $(document).ready(function() {
      var numLoaded = 0;
      var numToLoad = $('#gallery img').length;
      alert("To Load: " + numToLoad);
      $('#gallery img').load(function(){
        numLoaded += 1;
        alert("Loaded: " + numLoaded);
        if (numLoaded == numToLoad) {
          var gallery = $('#gallery').unslider(),
          data = gallery.data('unslider');
          data.to(0);
        }
      });
      $("#slidecontainer .slide a").click(function(e) {
        destination = $(this).parent().index();
        data.to(destination);
        e.preventDefault;
      });
      $(window).scroll(function() {
        checkGalleryAgainstLogo();
      });
      $(window).resize(function() {
        checkGalleryAgainstLogo();
      });
      checkGalleryAgainstLogo();
      $('#logo.small').addClass('white');
    });
  </script>
<% end %>

The issue is that it looks like the image loading handlers aren't all triggering. Look at it in context on the page I'm using it on: http://penumbra-2.herokuapp.com/education

like image 751
Duncan Malashock Avatar asked May 11 '14 15:05

Duncan Malashock


4 Answers

Regarding #2: I think youve made this too complex. You don't have to check on the individual img assets like you're doing; you really just want to know when the entire gallery has loaded, so make your life simple:

  $('#gallerycontainer').load(function(){
      $('#gallery').unslider();
    }
  });

Your might want to add the HTML into your question so people know how to target the jQuery:

<div id="gallerycontainer">
  <div id="gallery">
    <div id="slidecontainer">
      <div class="slide">
        <a href="#"><img /></a>
      </div>
    </div>
  </div>
</div>
like image 77
serraosays Avatar answered Oct 11 '22 19:10

serraosays


The load event is sent to an element when it and all sub-elements have been completely loaded. .load is what you need. An advantage of using this is that you can attach this to a subset of DOM. If you have a images in a division like this

<div class="slider">
  <img src="image1.jpg"/>
  <img src="image2.jpg"/>
  <img src="image3.jpg"/>
</div>

Now you can use .load just on the slideshow container if all the images have loaded.

$('.slider img').load(function(){
  //Your code goes here
});

CAUTION : If you are using jQuery 1.8, this has been deprecated. You can use .on with appropriate arguments e.g .on('load', handler)

like image 21
Pankaj Avatar answered Oct 11 '22 18:10

Pankaj


I can see two different solutions on this, and depends on what's your objective.

On the code you're using $(document).ready(); which triggers when the DOM is ready, and not when the assets are totally downloaded, so makes sense to to detect when the image are loaded, but in this case I'd go for use the native Image() object and avoid using .load() as I found it extremely unreliable in several occasions, and as far as I know also sometimes it does not trigger perfectly if the images are loaded from the browser cache.

$('#gallery img').each(function() {
    var currentimage = new Image();
    currentimage.src = this.src;
    currentimage.onload = function(){
        numLoaded += 1;
        alert("Loaded: " + numLoaded);
        if (numLoaded == numToLoad) {
            var gallery = $('#gallery').unslider(),
            data = gallery.data('unslider');
            data.to(0);
        }
    };
});

Another solution (which I'll prefer to use here) is to use window.onload which triggers when your document and assets are fully downloaded, and you should use it in that way:

window.onload = function(){
    // Initialise your slider here
}
like image 36
MacK Avatar answered Oct 11 '22 18:10

MacK


Try this (pattern)

html

<!-- load images container, images with document, `display:none` -->
        <div id="slidecontainer" style="display:none;">
            <div class="slide"> <a href="#">
              <img alt="Chemistry-1" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/chemistry-1.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Hamilton" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/Hamilton.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Platinum6" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/platinum6.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Lectures-1-2" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/lectures-1-2.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Lenses-1-2" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/lenses-1-2.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Bromoil-1" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/bromoil-1.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Platinum2-1" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/platinum2-1.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Schaefer2" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/Schaefer2.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Classroom-1-2" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/classroom-1-2.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Dagbeq_web" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/dagbeq_web.jpg" />
            </a>

            </div>
            <div class="slide"> <a href="#">
              <img alt="Carbon_schaefer" class="center-slide" src="https://test-penumbra-images-cap.s3.amazonaws.com/uploads/Carbon_Schaefer.jpg" />
            </a>

            </div>
        </div>

    <div id="gallerycontainer">
        <div id="gallery" style="margin-top: 67px;"></div>
    </div>

js

// hold jquery `ready` `event`
$.holdReady(true);
// load images container, images into `slider` container
$("#gallery").load(document.location.href + " #slidecontainer", 
  function(data, textStatus, jqxhr) {
    // if all images loaded (11), document.ready, release `holdReady`
    return ($("#gallery img").length === 11 
              && $.isReady 
              && jqxhr.state() === "resolved"
            ? $.when($.holdReady(false)).done(function() {                    
                alert($.isReady);  
                $("#slidecontainer").css("display", "block");
                // images appended to document,                  
                // do (`slider`) stuff                   
              }) 
            : alert(!$.isReady) )
});

jsfiddle http://jsfiddle.net/guest271314/tLca3/

like image 24
guest271314 Avatar answered Oct 11 '22 19:10

guest271314