Reputation: 557
EDIT : Added jsfiddle
open in IE, output values of 30 are wrong (IE placeholder height)
I tried to return DOM naturalHeight and clientHeight, and while naturalHeight works properly in IE, clientHeight (the one I need) does not.
Here's an obvious workaround, but it kinda sucks https://jsfiddle.net/0rhjt0wn/1/
Seems like the problem is that IE renders image after it is loaded, while other browsers render it while it is being loaded, but Im just guessing here.
I've some images, that I want to load by assigning their "data-src" attribute value to theirs "src" attribute and vertically center them after.
It works without a problem in all browsers except IE (tested from 8 to edge).
In IE some images get centered without a problem, but some wont and it is because code in the .on("load") event gets executed (probably) after the image is loaded, but before it gets its size set.
Is there any way to always execute the code after the image is loaded and its size is set (in IE)?
for (i = 0; i < 100; i++)
{
targetSrc = $divElement.eq(i).children(imgClass).attr(dataSrc) + "?v=" + datetime;
$divElement.eq(i).find(imgClass).attr("src", targetSrc).on("load", function()
{
$holder.append($(this).attr("src") + " || height = " + $(this).height() + "<br>");
});
}
Upvotes: 1
Views: 193
Reputation: 5205
Initially thought requestAnimationFrame
and a timeout fallback could easily solve this but it turned out to be a lot more complicated. Apparently the exact frame at which an image is rendered after onload is not very predictable in IE. But I eventually came up with this solution that checks the naturalHeight
against the current height to see if an image has been rendered, looping through to the next display frame when it is not the case yet :
https://jsfiddle.net/r8m81ajk/
$(function() {
if (window.requestAnimationFrame) var modern = true;
var element = $('.divElement'),
reference = '.imgElement',
holder = $('.holder'),
datetime = Date.now(),
path, image;
for (var i = 0; i < 100; i++) {
var target = element.eq(i).children(reference),
path = target.data('src') + '?v=' + datetime;
target.one('load', function() {
image = this;
if (modern) requestAnimationFrame(function() {
nextFrame(image);
});
else setTimeout(renderImage, 50);
}).attr('src', path);
}
function nextFrame(picture) {
var dimension = $(picture).height();
if (dimension == picture.naturalHeight) {
holder.append('height = ' + dimension + '<br>');
}
else nextFrame(picture);
}
function renderImage() {
holder.append('height = ' + $(image).height() + '<br>');
}
});
The fallback will always check on the third frame (when there's no bottleneck). Don't mind I adapted the code a bit to my usual conventions, the external references should have remained the same.
From the question I realise the loop might not even be needed and getting naturalHeight
when the image loads would be enough. Interesting exercise to detect the exact point of rendering in any case.
Upvotes: 1