I'm trying to load an element only after the img element has been loaded, but I've tried everything I can think of and nothing is working. Right now I'm trying to see where the code stops working and I found that the alert I set up isn't running after the line I need the code to execute from.
$img = $('#picture');
function bubbleOnLoad() {
$(document).ready(function() {
$img.load(function(){
alert('document loaded')
$('#left-bubble').show();
})
})
The $img is defined within a function. The alert works at the document.ready line but not after the $img.load. I have tried to add eventlisteners, jquery .on, .load, and a bunch of others. I'm also calling the function to run within my init function. Can someone explain to me why nothing is working?
function choosePic()
$('.speechbubble').hide();
$('#picture').remove();
var randomNum = Math.floor(Math.random() * samplePics.length);
var img = new Image();
img.onload = function() {
$('.playing-field').prepend(img);
handleImageLoad();
}
img.src = samplePics[randomNum];
img.id = "picture";
}
var samplePics =
"assets/images/barack-obama.jpg",
"assets/images/donald-trump_3.jpg",
"assets/images/dt-2.jpg",
"assets/images/bill-clinton.jpg",
"assets/images/Rose-Byrne.jpg",
"assets/images/pic.jpeg",
"assets/images/priest.jpg",
"assets/images/tb.jpg",
"assets/images/test.jpg",
"assets/images/amy-poehler.jpg",
"assets/images/stephen-colbert.jpg",
"assets/images/aziz-ansari.jpg"
];
You had some syntax errors in your code which I corrected and came up with this:
function bubbleOnLoad() {
$img = $('#picture');
$img.load(function () {
alert('document loaded');
$('#left-bubble').show();
});
}
$(document).ready(function () {
bubbleOnLoad();
});
Here is the JSFiddle demo
In you code you are not even telling the browser it's supposed to run a code after image load. you should do something like this:
$(function(){
// DOM Content is ready, let's interact with it.
$('#picture').attr('src', 'image.jpg').load(function() {
// run code
alert('Image Loaded');
});
});
Also according to docs a common challenge developers attempt to solve using the .load() shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
Try this jQuery plugin waitForImages
https://github.com/alexanderdickson/waitForImages
//Javascript/jQuery
$(document).ready(function(){
var counter = 0,totalImages= $('#preloader').find('img').length;
$('#preloader').find('img').waitForImages(function() {
//fires for all images waiting for the last one.
if (++counter == totalImages) {
$('#preloader').hide();
yourCallBack();
}
});
});
/*css*/
#preloader{
position:absolute;
top:-100px;/*dont put in DOM*/
}
#preloader > img{
width:1px;
height:1px;
}
<!--HTML [add the plugin after jQuery] -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.waitforimages/1.5.0/jquery.waitforimages.min.js" ></script>
<!--HTML [after body start] -->
<div id=preloader>
<img src="1.jpg" />
<img src="2.jpg" />
<img src="3.png" />
<img src="4.gif" />
<img src="5.jpg" />
</div>
You can only access the HTML element after it was created in DOM.
Also you need to check if the image was loaded before showing.
Thus your code need to look something as below:
$(document).ready(function() {
bubbleOnLoad();
});
function bubbleOnLoad() {
var newSrc = "https://lh5.googleusercontent.com/-lFNPp0DRjgY/AAAAAAAAAAI/AAAAAAAAAD8/Fi3WUhXGOY0/photo.jpg?sz=328";
$img = $('#picture');
$img.attr('src', newSrc) //Set the source so it begins fetching
.each(function() {
if(this.complete) {
alert('image loaded')
$('#left-bubble').show();
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="left-bubble" style="display:none">
<img id="picture"/>
</div>
Related
The page begins to load.
<img id="logo" src="/logo.png">
Then we run a bunch of JavaScript and by the time we get to the error handling for the <img> above, it has experienced an error... /logo.png returns 404 or 500 or something.
Now, this JavaScript:
document.getElementById('logo').onerror = () => {
console.log('logo img did not load');
}
is useless because the onload and onerror callbacks would have already been called.
A solution to see if it loaded successfully would be to check:
document.getElementById('logo').complete
but this shows true even if there was an error, and looking in the JavaScript console and Googling has shown me nothing similar to this for error checking.
Does anyone know of any way to see if there was an error when the <img> tried to load.
I don't want to use the following:
let img = new Image();
img.onerror = () => {
console.log('logo img did not load');
}
img.src = '/logo.png';
Edit: I am unable to add any JavaScript attributes to the html. That would be handy, and a solution in some situations, but it is not a solution for my situation. So this:
<img id="logo" src="/logo.png" onerror="errorHandler()">
won't work for me.
Firstly, you might find some good answers in this thread here: Check if an image is loaded (no errors) with jQuery (Not all answers are strictly jQuery, but even the ones that are still offer good insight).
Here's a quick answer though. Whenever an image is not loaded properly its naturalWidth and naturalHeight properties will be 0. Based on that knowledge you can create a function that will register an error listener if the image is not yet loaded, or immediately call your listener if it is, i.e. the images complete property is set to true but the naturalHeight or naturalWidth is set to 0.
You should be able to use this function anywhere you intend to add an onerror listener.
const [img1, img2] = document.querySelectorAll("img")
function onImgError(img, fn){
if (img.complete){
if(!img.naturalWidth || !img.naturalHeight){
fn(new Error("Image not loaded"))
}
}
img.addEventListener('error', fn)
}
setTimeout(()=>{
// these won't fire when image is already loaded
img1.addEventListener('error', (e) => {
console.log("img1 error")
})
img2.addEventListener('error', (e) => {
console.log("img2 error")
})
// but this one will
onImgError(img1, (e)=>{
console.error(e)
})
// this image loads, so no error
onImgError(img2, (e)=>{
console.error(e)
})
}, 1000)
<img src="fdsf"/>
<img src="https://upload.wikimedia.org/wikipedia/commons/8/84/Example.svg" width="100"/>
Use onerror="" event.
Documentation:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
myFunction = (image) => {
// If this calls, it's gone wrong.
console.log('Error');
// Access this
image.src = 'https://example.jpg';
}
<img src="image.gif" onerror="myFunction(this)">
You can also have a placeholder image for any errors, if detected change image without a function.
<img src="image.png" onError="this.onerror=null;this.src='/error.gif';" />
If you aren't using attribute javascript as you said, get all images on pageload. Use .error to grab all errors with JQuery.
$('img')
.error(function() {
alert( "Handler for .error() called." )
})
.attr( "src", "missing.png" );
Non JQuery
var img = document.querySelector('img')
function loaded() {
alert('loaded')
}
if (img.complete) {
loaded()
} else {
img.addEventListener('load', loaded)
img.addEventListener('error', function() {
alert('error')
})
}
<img src="#">
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!
$img.on('load', triggerAction);
function triggerAction() {
//identify the div and put
.style.display = "none";
}
You hide the cover on the window load event, which fires after all images are loaded.
$(window).on('load', function(e){
$('.cover').hide();
});
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>
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>
I have a slideshow that I need to initialize with jQuery. The initialization requires all slideshow images to be fully loaded, so that I can get their actual width and height. I can not change this part.
Consider the following layout:
<div class="slideshow">
<img />
<img />
<img />
</div>
<img />
<img />
<img />
I need to initialize the slideshow as soon as the three images inside the slideshow container have been loaded. I can NOT wait until the rest of the images on the page have been loaded, as there might be thousands of images.
Any ideas how I could solve this?
As per my comment, you can wrap the checking/load behavior in a jQuery plugin and return a single promise like this:
$.fn.imagesLoaded = function () {
var def = $.Deferred();
var count = this.length;
this.each(function () {
if (this.complete) {
if (!--count) {
def.resolve();
}
} else {
$(this).load(function () {
if (!--count) {
def.resolve();
}
});
}
});
return def.promise();
}
and then simply use like this:
$('.slideshow img').imagesLoaded().done(function () {
alert("loaded");
});
Here's what I ended up using, quite a bit more complicated than I'd hoped:
// Prepare the slideshow as soon as all of its images have been loaded
var slideshowImages = $('.slideshow img');
var slideshowImagesLoadedCount = 0;
// Check how many images have already been loaded
slideshowImages.each(function() {
if(this.complete) {
slideshowImagesLoadedCount++;
}
});
// If all the images have loaded already, prepare the slideshow
if(slideshowImagesLoadedCount === slideshowImages.length) {
prepareSlideshow();
} elseĀ {
// Otherwise wait until all images have been loaded
slideshowImages.load(function() {
slideshowImagesLoadedCount++;
if(slideshowImagesLoadedCount === slideshowImages.length) {
prepareSlideshow();
}
});
}
I wanted to load the default image if the user's one didn't exist. I tried this but it didn't work.
$('#avatar').load(function(){
// ... loaded
}).error(function(){
// ... not loaded
$(this).attr('src','/images2/no-avatar2.png');
});
Anyone know how I could do this?
Someone uses this:
function loadDefault(f, ff) {
img = document.getElementById(f);
if(!img.complete) {
img.src = ff;
}
if(typeof(img.naturalWidth) != "undefined" && img.naturalWidth == 0) {
img.src = ff;
}
}
function init() {
setTimeout("loadDefault('side_avatar', '/images/default/avatar_player_profile.gif')", 100);
setTimeout("imageResize(740)", 100);
tooltip = new ToolTip();
tooltip.init('hoverBox', 'loading...');
}
How could I use something like this?
It looks like you are missing your load url as the first parameter of the load() function. Also, without seeing your HTML, I'll assume #avatar is an img tag the way you are using it in the error function. I don't think you can load HTML into an img so you may be better off structuring your html and js like so:
HTML Example:
<div id="avatarDiv">
<img id="avatar" src="" alt="" />
</div>
JS Example:
$('#avatarDiv').load('avatar.php', function() {
// ... loaded
}).error(function() {
// ... not loaded
$('img#avatar').attr('src','/images2/no-avatar2.png');
});
Then just make sure your avatar.php file returns the full html of the image object:
<img id="avatar" src="successful-avatar.jpg" alt="" />
Docs: http://api.jquery.com/load/
I'd try something like this:
$.get("get-avatar.php", function(response) {
$("#avatar").attr('src', response);
}).error(function(response) {
$(this).attr('src', '/images2/no-avatar2.png');
})
as long as avatar.php returns a http error message if the image doesn't exist.
This routine uses ajax to see if the image file exists:
HTML:
<img id='avatar' src='/images2/avatar2find.png' alt='No Image Available'></img>
Script:
$(window).load(function() {
var $img = $('#avatar');
$.ajax({
url: $img.attr('src'),
type: 'get',
statusCode: {
404: function() {
$img.attr('src', '/images2/no-avatar2.png');
}
},
error:
function() {
// do something?
}
});
});
I have the following markup with inline javascript and would like to change it to Jquery. Any help would be appreciated.
<a title="823557" href="/PhotoGallery.asp?ProductCode=471823557" id="product_photo_zoom_url">
<img border="0" onload="vZoom.add(this, '/v/vspfiles/photos/471823557-2.jpg');"
alt="823557"
src="/v/vspfiles/photos/471823557-2T.jpg" id="product_photo"></a>
I guess I would need to use this?
$(function(){
<---- somecode---->
});
$(function () {
$("#product_photo").load(function (e) {
vZoom.add(this, this.src.replace('T.', '.'));
})
})();
If $ doesn't work for some reason, this should also work. I incorporated Kranu's advice since that library most likely only needs the DOM loaded as a prerequisite, rather than the load event:
jQuery(function ($) {
$("#product_photo").each(function () { // in case there is more than one
vZoom.add(this, this.src.replace('T.', '.'));
});
});
Note that there is no need to put a separate bind event on the img because the $(function() { }) waits until the body loads.
$(function(){
vZoom.add(document.getElementById('product_photo'),'/v/vspfiles/photos/471823557-2.jpg');
});
Not exactly sure what you are trying to do, but essentially you would remove the image from the HTML and dynamically load it using JS. Once loaded, you would inject it in the DOM and set the onload event.
var jsImg = new Image();
jsImg.onload = function(){
vZoom.add(this,'/v/vspfiles/photos/471823557-2.jpg');
var img = document.createElement('IMG');
img.setAttribute('id','product_photo');
img.setAttribute('alt','823557');
img.setAttribute('src','/v/vspfiles/photos/471823557-2T.jpg');
img.style.border = 'none';
//inject image now in the DOM whereever you want.
};
jsImg.src = '/v/vspfiles/photos/471823557-2T.jpg';