0

I'm using Semantic Ui and jQuery to make an album. I want to write a function that gets called when all images in div class="images" are loaded.

There is a loading cover div class="dimmer" which covers all images. When all images are loaded, the cover should be removed.

How can I determine when all images have been loaded so I can remove the cover?

Here is the code I have so far:

<div id="loader1" class="ui active dimmer">
    <div class="ui text loader">Loading...</div>
</div>
<div id="image1" class="ui small images">
    <img src="pics/pic_suzhou/sz1.jpg">
    <img src="pics/pic_suzhou/sz2.jpg">
    <img src="pics/pic_suzhou/sz3.jpg">
    <img src="pics/pic_suzhou/sz4.jpg">
    <img src="pics/pic_suzhou/sz5.jpg">
    <img src="pics/pic_suzhou/sz6.JPG">
    <img src="pics/pic_suzhou/sz7.JPG">
    <img src="pics/pic_suzhou/sz8.JPG">
</div>

Thanks!

lucascaro
  • 16,550
  • 4
  • 37
  • 47
Li Shen
  • 47
  • 2
  • 7
  • 1
    This post is a great resource https://stackoverflow.com/questions/20613984/jquery-or-javascript-check-if-image-loaded also for reference: https://www.w3schools.com/jsref/prop_img_complete.asp – ian Nov 10 '18 at 20:34
  • window load event is all you need. It fires after all images have loaded. Remove the dimmer in event handler – charlietfl Nov 10 '18 at 20:39
  • Check my edited answer using Promises - thta's the best way I can see. – Reflective Nov 10 '18 at 23:19

4 Answers4

0
$img.on('load', triggerAction);

function triggerAction() {
   //identify the div and put 
   .style.display = "none";
}
KevinO
  • 4,303
  • 4
  • 27
  • 36
  • 1
    Welcome to [so]! Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. – lucascaro Nov 11 '18 at 06:20
0

You hide the cover on the window load event, which fires after all images are loaded.

$(window).on('load', function(e){
   $('.cover').hide();
});
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
  • Thank you for your help! But I don't know how to determine when all the pics are loaded. My plan is when all the pics in the div are loaded, then the cover will be removed. Could you please give me some suggestions? – Li Shen Nov 10 '18 at 20:51
  • `.load()` shortcut is deprecated. Use `.on('load', func...` – charlietfl Nov 10 '18 at 21:12
  • 1
    @LiShen all the images are loaded when this event handler gets triggered – charlietfl Nov 10 '18 at 21:12
0

EDITED! I found that it won't work the way I offered, so I've made a complete edit, proposing the way it will work. The best way I see is using Promises. This will guarantee that even the even is missed because the handler is attached after the event is fired, we will be able to get its result as success of failure. The other ways may fail because of the cached images and/or async handling. That's why Promises are made for.

Check it out running the snippet below:

$(function(){

  function load(img) {
    return new Promise(function(resolve, reject) {
      img.onload = function() {
          console.log(img);
          resolve('OK');
      };
      img.onerror = function() {
        reject(Error("Loading error"));
      };
    });
  }

  var all = $.map($('#image1 img').get(), function(item) { return load(item); });
  Promise.all(all).then(function() {
    console.log('All loaded');
  }, function() {
    console.log('One or more failed');
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="image1">
  <img src="https://shop.r10s.jp/book/cabinet/5963/4988064935963.jpg?v=30">
  <img src="https://images-na.ssl-images-amazon.com/images/I/816L51ge55L._SL1202_.jpg?v=30">
  <img src="https://img-shop.mu-mo.net/img/pc_sp/aaa2018_m2th4i/header01.jpg?v=30">
  <img src="https://img-shop.mu-mo.net/img/pc_sp/aaa2018_m2th4i/header01.jpg?v=30">
</div>
Reflective
  • 3,854
  • 1
  • 13
  • 25
  • You are a bit confused about how promises work, try adding a `setTimeout` to force calling your code after the images have loaded and you will see that the code doesn't work -- example: http://jsfiddle.net/sLxn8g9b/2/ – lucascaro Nov 11 '18 at 09:29
0

You don't need jQuery. Modern Javascript provides idiomatic ways to deal with this functionality that are better alternatives to common jQuery functionality.

Important: at the moment there is no 100% reliable way of detecting when images in the HTML have finished loading.

Because of this, the most reliable way would be to dynamically create the image elements, and use the 'load' event. You can also fall-back to the 'load' event on the 'document' which will fire when all resources on the page are loaded.

For example, the following code removes your dimmer div when all images have been loaded, and also has a fallback on window.onload to remove the dimmer which gets triggered even if there are any errors:

const loader = document.getElementById('loader1');
const container = document.getElementById('image1');
const imageURLs = [
  "https://lorempixel.com/48/48/abstract/1/",
  "https://lorempixel.com/48/48/abstract/2/",
  "https://lorempixel.com/48/48/abstract/3/",
  "https://lorempixel.com/48/48/abstract/4/",
  "https://lorempixel.com/48/48/abstract/5/",
  "https://lorempixel.com/48/48/abstract/6/",
  "https://lorempixel.com/48/48/abstract/7/",
  "https://lorempixel.com/48/48/abstract/8/",
];

// Fallback handler that will run when everything has loaded.
window.addEventListener('load', onDocumentLoaded);

// Create images from list of sources
const images = imageURLs.map(src => {
  const image = new Image();

  // Return a promise for the loaded image.
  return new Promise((resolve, reject) => {
    // resolve when loaded
    image.addEventListener('load', () => {
      console.log(`image loaded ${src}`);
      resolve();
    });
    // reject on error
    image.addEventListener('error', (err) => {
      console.log(`error loading ${src}`);
      reject(err);
    });
    
    // Once the handlers are set, set the src and add the images to the DOM.
    image.src = src;
    container.appendChild(image);
  });
});

// Act once all promises are resolved:
Promise.all(images)
  .then(onAllImagesLoaded)
  .catch(e => {
    console.log('something went wrong.');
  });

// All images have been loaded -- success case.
function onAllImagesLoaded() {
  console.log('all images loaded');
  loader.remove();
}

// Everything finished loading -- fallback and error cases.
function onDocumentLoaded() {
  console.log('all content loaded');
  loader.remove();
}
<html>

<head></head>

<body>
  <div id="loader1" class="ui active dimmer">
    <div class="ui text loader">Loading...</div>
  </div>
  <div id="image1" class="ui small images">
  </div>
</body>

</html>
lucascaro
  • 16,550
  • 4
  • 37
  • 47
  • I showed using promises in my answer yesterday and I used jQuery just to collect images and more clear code. Of course jQuery is not a requirement, it's pretty clear from the code. The thing which is very inconvenient in your code is inherited by the old techniques where you have to set `image.src = src` later than the DOM model is ready. Using Promises in modern browsers eliminates this requirement as promise will be always executed no matter if the event 'loaded' may happen earlier than you assign a handler for it. That's the idea of the Promise. So all images may be added in initial HTML. – Reflective Nov 11 '18 at 09:01
  • Hi and thanks for the feedback! @Reflective did you have a chance to read the link I posted? as far as I understand, the problem is unrelated to promises, it's the unreliability of the `onload` event on `` tags, thus the only reliable way to detect images were loaded is to create them as Image elements dynamically, does that make sense?. Also, as it may be clear to you, the fact that you don't need jquery is not necessarily clear to everyone else reading this post :) – lucascaro Nov 11 '18 at 09:06
  • The main thing I'm saying that using Promises makes `onload` catching reliable as the promise will be handled no matted if the event happened before or after adding the handler, so you don't have to set `src` later than assigning the handler. Check it how it works in the snippet provided and re-read the docs for Promises. Actually your answer is a kind of feedback to my answer as it uses and I thank you for showing another variation of it, but mainly you may eliminate the `src` setting on later stage. – Reflective Nov 11 '18 at 09:22
  • You are a bit confused about how promises work, try adding a `setTimeout` to force calling your code after the images have loaded and you will see that the code doesn't work -- example: http://jsfiddle.net/sLxn8g9b/2/ – lucascaro Nov 11 '18 at 09:29
  • You might be right, I will check it later today, and if you are right you'll have my excuses. – Reflective Nov 11 '18 at 09:41
  • no need, just let me know if I'm wrong so I can learn :) cheers. – lucascaro Nov 11 '18 at 09:44