Image.onload event triggers apears to trigger before image is loaded - javascript

I have a function that displays a different image each time it is called.
function Trial() {
curTrial = increase(curTrial);
//generate the html code
$('#right_wrapper').append(`
<div id="image_holder">
<img id="image">
</div>`)
// present the image
var targetImage = document.getElementById('image')
targetImage.src = stimuli[curTrial];
console.log(targetImage.onload = targetImage.height)
The way i though onload works is that it will not trigger until the src is loaded, but it seems to trigger anyway, and thus result the 0 height for the unloaded image. I've found more threads with similar issues, but none of those I've seen work with template literals.
How can i be sure that targetImage.height always returns the height for the loaded image, instead of 0?

Related

Why is my div not updating when changing its class with JavaScript?

I currently have a div that's used to display and image via CSS.
For example:
HTML
<div id="myDiv" class="play"></div>
CSS
.play{background: url('../img/playIcon_black.png') no-repeat;}
This image appears as it should.
What I'm attempted to do is to change the image by changing the class (via JavaScript).
Example:
CSS
.pause{background: url('../img/pauseIcon_black.png') no-repeat;}
JavaScript
function myFunction() {
myDiv.className = "pause";
}
When I call myFunction() everything seems to work correctly with one exception. Occasionally the image does not update in the browser.
A few things to note:
I'm certain the function is being called correctly. If I put a console.log() statement within the function, it prints when it should. Additionally, if I inspect the element within the browser, the class is in fact changed to .pause
The image changes from the "play icon" to blank once the function is called, BUT upon hovering over the div the images then appears permanently.
This only seems to happen once the page is initially loaded. Meaning, I can only recreate the issue once upon refresh, then everything works correctly after that.
I have attempted to clear my cache but nothing seems to have changed.
(I'm not sure how relevant this is) I'm calling myFunction() via onended attribute of an audio tag.
For example:
<audio onended="myFunction()"></audio>
But I'm not certain if this would affect anything because the function appears to be called correctly.
Any ideas of why this might be happening?
So the issue is that when you change the class, the browser has to fetch the new image, which takes time. One way to fix the issue is by using sprites, where both images are actually in one image and you only show a piece of that image at a time.
Another solution is to preload the image and then apply the preloaded image source to your new element like this:
var image = newImage();
image.src = '../img/pauseIcon_black.png';
function myFunction() {
var cssBackground = 'url(' + image.src + ') no-repeat';
myDiv.style.background = cssBackground;
// Optionally with jQuery instead:
// $('#myElementID').css('background', cssBackground);
}
Note that if you call myFunction before the image loads you'll encounter the same error. The difference is that this will load the image when the page is loaded (or more properly, when this JS executes and myFunction is assigned) rather than when myFunction is called. To ensure the image is loaded you can use the onLoad event handler for the image object. For more details on preloading images check out this answer: preload image then change background javascript
You need to get the element id
function myfunction(){
var myDivElem = document.getElementById('myDiv');
myDivElem.className = 'pause';
}
You can use document.getElementById("myDiv").className="";in your function
OK if you don't want use first solution you can use second one:
You can add a class to element using
document.getElementById("myDiv").className +=" n";
Then add a class named .play.n to your css file after class named.play
Then add your image address.
If you want to manipulate the div with id "myDiv". Use it as
document.getElementById('myDiv').class
Sample codesnippet: example snippet

Changing src attribute of image element and getting size properties

I encounter a problem while performing changes on an img element via javascript:
I build a framework to cycle through different images via the arrow keys of the keyboard. I do this by loading all image urls into an array and then changing the src attribute of the img element accordingly.
So far everything works fine. But now I want to display the naturalHeight and naturalWidth of the current image. Unfortunately when I cycle through the images the sizes of the image preceeding the current image is displayed, although the element shows the correct image.
has this something to do with load order and rendering?
I would be very thankful if someone could help me on that issue.
best regards
Max
On the comments:
I simply load the images by:
imageLeft.setAttribute("src", imagesOld[rowCounter]);
imageRight.setAttribute("src", imagesNew[rowCounter]);
I have a function for updating the size information:
function updateSizeInformation() {
var imageLeftX = $find("<%= txtXImageLeft.ClientID %>");
var imageLeftY = $find("<%= txtYImageLeft.ClientID %>");
var imageRightX = $find("<%= txtXImageRight.ClientID %>");
var imageRightY = $find("<%= txtYImageRight.ClientID %>");
var imageLeft = document.getElementById("imageLeft");
var imageRight = document.getElementById("imageRight");
imageLeftX.set_value(imageLeft.naturalWidth);
imageLeftY.set_value(imageLeft.naturalHeight);
imageRightX.set_value(imageRight.naturalWidth);
imageRightY.set_value(imageRight.naturalHeight);
}
And a function to fit the image to the parent div:
function fitImagesToContainers() {
var divLeft = document.getElementById("imageContainerLeft");
var divRight = document.getElementById("imageContainerRight");
var imageLeft = document.getElementById("imageLeft");
var imageRight = document.getElementById("imageRight");
if (imageLeft.naturalWidth > imageLeft.naturalHeight) {
imageLeft.setAttribute("width", divLeft.clientWidth);
imageLeft.setAttribute("height", divLeft.clientWidth * (imageLeft.naturalHeight / imageLeft.naturalWidth));
} else if (imageLeft.naturalWidth < imageLeft.naturalHeight) {
imageLeft.setAttribute("height", divLeft.clientHeight);
imageLeft.setAttribute("width", divLeft.clientHeight * (imageLeft.naturalWidth / imageLeft.naturalHeight));
}
}
When you set the "src" attribute of an image element the page has not loaded, it normally instigates an asynchronous retrieval of the image file resource. After the image onload event fires the image element properties should represent that of the retrieved image, but be unpredictable before then.
If the code you provided executes synchronously it will run into the problem you report.
In Mozilla Firefox (at least) the image attributes can be that of the previous image if inspected immediately in the same script execution, because the new/next image has yet to be retrieved. Exactly what happens if the page has previously loaded the same image may be unpredictable - I found it giving correct dimension values immediately.
I tested this with standard javascript and do not wish to suggest how to program onload event handlers in jQuery . I did come across this other StackOerflow question on javascript, image onload() doesnt fire in webkit if loading same image which may be of interest.

I can't validate tag img

this is Augusto from Italy
when migrating from HTML to XHTML I am facing an unresolved problem
In html code I have an image (bigimg) that is at first charged via Js charged by the body onload, then other images, out of a preview series, are being charged, thus replacing my image,
In body:
<body onload="...........;viewimgac('images/accessories/img01cs.jpg');...............">
The function is:
// the waiting image view and the main image loading is managed
function elaboraimgac(urlimg) {
document.getElementById('dattesa').style.filter = "alpha(opacity:"+90+")";
document.getElementById('dattesa').style.MozOpacity = 90/100;
document.getElementById('dattesa').style.KHTMLOpacity = 90/100;
document.getElementById('dattesa').style.opacity = 90/100;
MM_changeProp('dattesa','','style.visibility','visible','LAYER'); // div is made visible through the waiting gift.
document.getElementById('bigimgid').src = urlimg; // I load the image
The code page shows:
<img src="#" id="bigimgid" style="position:absolute;left:0px;top:0px;" onload="finecaricimg()" alt="" />
the <img> tag, as it is, prevents XHTML validation. I have to eliminate onload="finecaricimg()", being the function allowing view of image duly placed in the page using the image size that is available after loading.
I acted this way:
1) change <img tag
<img src="#" id="bigimgid" style="position:absolute;left:0px;top:0px;" alt="" />
2) I added :
function elaboraimgac(urlimg) {
//to Js elaboraimgac function
//........
//........
document.getElementById('bigimgid').onload = finecaricimg(); // the specific function is called after loading
}
To intercept the image loading end and recall the loading end function
Unfortunately the procedure is unsuccessful. Via alert I realized that the image size – when the loading end is charged – is zero, as if finecaricimg() is charged right after the .src processing and not when the image loading is over.
I tried to add:
document.getElementById('bigimgid').src = urlimg;alert("AAAAA"); // load image
then, when the alert window appears, I wait for some seconds before clicking OK. This way the image size is correct and the image is properly placed in the page.
I am unable to understand, as the code seems the correct one.
I am therefore asking for your suggestion.
....onload = finecaricimg();
You just called your function immediately and assigned its result to onload (just like any other function call).
You want to assign the function itself, without calling it.
I have solved in this way:
var img = document.getElementById("bigimgid");
img.src = urlimg; // carico l'immagine
img.addEventListener("load", finecaricimg); // a fine caricamento richiamo la funzione specifica
thanks

Get new image to only appear when loaded if source changed

I've been having a problem caused by the previous image staying on the screen until the next is loaded.
My program uses a flowchart where various images are needed for certain questions. I've been using the following code to change the source from one to another.
HTML:
<img class= 'right' id= 'imageBox' style= 'width: 20%; height: auto;' src= www.1stimage.com/>
javascript:
document.getElementById("imageBox").src = 'www.2ndimagesite.com';
If the computer has a slow connection, the first image could stay on the screen for up to 10 seconds before the next one shows up. How do I get it to not display anything until it's finished?
Thanks.
Preload the image and update the src after it's loaded:
var img = new Image();
var newsrc = 'www.2ndimagesite.com';
img.onload = function () {
document.getElementById("imageBox").src = newsrc;
};
img.src = newsrc;
You can change aproach a bit to achieve what you want.
You can preload images and after that just select what image to show. You can read more about this here: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/
You can make start loading new image async and change current image to image like loading spinner or some image, which shows that something is loading at the moment (example: ) On onload handler you will rewrite this spinner to loaded image.
I wanted to write ~ same that #nedt wrote. Btw, I don't think that his code will help you. I think you will achieve same effect as you said in answer. Anyway, he was first and his answer was close, so I will just use his example.
document.getElementById("imageBox").src = "loading image link"; // load spinner
var img = new Image(); // load image asynchronously
var newsrc = 'www.2ndimagesite.com';
img.onload = function () { // onload handler
document.getElementById("imageBox").src = newsrc;
};
img.src = newsrc;
So, old image was loaded on page loaded. You did some action, for example pressed button. If you have low speed, loading spinner will be shown and after new image is loaded async, new image will be shown. If you have enought speed, new image will appear immediately.
Hope this will help you!
document.images[i].complete
will be true if picture[i] source is loaded.
you could preload all pictures an dont show it until the status change.

Image width traces zero with onload when cached

I'm building a Javascript lightbox and I'm trying to adjust the size once the image has loaded. I'm using the code below, which works fine - it outputs the correct width once loaded.
My problem:
When I refresh, it will load the image instantly from the cache, and it seems to bypass the load. I get an instant zero for the width. Why does this happen?
My code:
var oImage = new Image();
oImage.src = 'http://mydomain.com/image.png';
container.html(oImage);
oImage.onload = function(){
alert(this.width);
}
** Update **
#Alex: This is the code I've tried with your plugin, I assume I'm probably doing something wrong. I'd be eager to get this working because your plugin looks quite good.
container.waitForImages(function() {
var cWidth = $(this).width();
alert("width: "+cWidth); // returns 0 - works first time but not cached
});
// Adding the image to the container for preload
container.html('<img src="mygraphic.png" />');
You need to do a few things...
Check the complete property of the img element.
Attach the load event before setting the src property.
Also, I found creating a new Image and assigning the src there is the best way to determine if the image has loaded or not.
You may want to switch the .html() and the .onload() calls.
If the image is loading from cache, I'm imagining that the .html() call completes before the script has had a chance to attach a function handler to the image's onload event. Therefore, effectively bypassing the load event itself (as the image has already loaded).
If it's still downloading the image (i.e. not cached), there will be more than enough time to call the .onload attach before the image completely finishes rendering.
While you're at it, you may want to do this the jQuery way, just so you're attaching events more similarly to DOM2 than DOM0.
var image = $('<img/>', {
src : 'http://mydomain.com/image.png'
}).load(function () {
alert(this.width);
})
// maybe clear container before if you want
.appendTo(container);
If we're going to have to set the src after the onload, we might as well do this instead:
var image = $('<img/>')
.load(function () {
alert(this.width);
})
.attr('src','http://mydomain.com/image.png')
.appendTo(container)
;
Hopefully that works cleanly.
This answer JavaScript: Know when an image is fully loaded suggests that you should set onload before setting src

Categories

Resources