onload triggering too early for ajax content in IE - javascript

I have a page where the images are supplied dynamically and are scaled with javascript to fit within the appropriate dimensions. This was initially being done with an onload attribute in the img tag, but then I noticed that in IE, the height being returned for the image was much less in some cases than the actual height, which ended up distorting the image. I solved this by finding and resizing all the images after $(window).load() was done, which worked fine for the initial page load, but I also have the page set up to add more content with an ajax call. For the ajax content, I tried some code I found on here that improved the problem, but didn't completely solve it. Here is an example of one of my image tags
<img id="img<?php echo $prodModObj->rolloverID; ?>" class="mbImg unsized" src="<?php echo $prodModObj->img; ?>" alt="<?php echo $prodModObj->name; ?>" onerror="swapImage(<?php echo $prodModObj->rolloverID; ?>)" />
The swapImage function just swaps out the image with a placeholder if there is an error while loading. Here is my JS
function swapImage(thisImgID) {
var imgID = 'img#img' + thisImgID;
$(imgID).attr('src', '/images/NoImageAvail.jpg');
}
function checkImage(thisImgID, fitDimension, spaceDimension) {
var imgID = 'img#img' + thisImgID;
var imgHeight = $(imgID).height();
var imgWidth = $(imgID).width();
var displayHeight, displayWidth, newMargin;
if (imgHeight > imgWidth) {
displayHeight = fitDimension;
displayWidth = imgWidth*(displayHeight/imgHeight);
} else if (imgHeight < imgWidth) {
displayWidth = fitDimension;
displayHeight = imgHeight*(displayWidth/imgWidth);
} else {
displayWidth = fitDimension;
displayHeight = fitDimension;
}
$(imgID).css('height', displayHeight);
$(imgID).css('width', displayWidth);
newMargin = ((spaceDimension - displayHeight)/2);
$(imgID).css('margin-top', newMargin);
$(imgID).removeClass('mbImg unsized').addClass('mbImg sized');
}
And then on the page I have
$(window).load(function(){
// Resize product images
$('.mbImg.unsized').each( function() {
var rolloverID = $(this).attr('id').substr(3);
checkImage(rolloverID,250,270);
});
});
And then in the success portion of the ajax call, I have
$('.mbImg.unsized').each( function() {
var rolloverID = $(this).attr('id').substr(3);
if (this.complete) {
checkImage(rolloverID,250,270);
} else {
$(this).on('load', function(){
checkImage(rolloverID,250,270);
});
}
});
Images that have been cached by the browser work fine, and the images in the initial page load work fine, but about 1 in 5 of new ajax images come out distorted. Is there another method I can use to size all the ajax images correctly in IE?
Thanks for your help,

Maybe come at it another way?
I've tried to move away from html4 style tag syntax, to using simple html5 tags and a combination of JavaScript and CSS to control the "view".
Check out this fiddle:
http://jsfiddle.net/zacwolf/s1haq3mz/
A question becomes how you want your images to flow, as using this approach all of the images are technically the same size (as demonstrated by the border). Also note that the .src for the second image I tweeked the url a bit so that it was a 404 for the image file, which triggered the one error image instead.
<img id="one" class="myclass" />
<img id="two" class="myclass" />
<style>
.myclass{
height:270px;
width:250px;
background-position:center,center;
background-repeat:no-repeat;
background-size:contain;
}
</style>
<script>
var one = new Image();
one.onerror=
function(){
this.src='http://leomarketingep.com/wp-content/uploads/Sign-Error-icon.png'
}
one.onload=
function(){
$('#one').css('background-image','url('+one.src+')')
}
one.src='https://cjjulian.files.wordpress.com/2009/04/blah_blah_blah-703369.jpg';
var two = new Image();
two.onerror=
function(){
this.src='http://leomarketingep.com/wp-content/uploads/Sign-Error-icon.png';
}
two.onload=
function(){
$('#two').css('background-image','url('+two.src+')')
}
two.src='https://cjjulian.files.wordpress.com/2019/04/blah_blah_blah-703369.jpg';
</script>
If you have a lot of images, you can populate an array of Image objects, for better referencing, etc.

Related

Change CSS of element within elements and classes

I am trying to set the height of an image to be 50% of the width, but the image scales with the page. The current CSS I am targeting looks like this:
.img-quiz p span img { width: 100%; }
Here's what I've tried in js, but isn't working:
var imgQuiz = document.getElementByClassName('img-quiz').getElementsByTagName('img');
var elementStyle = window.getComputedStyle(imgQuiz);
var pixHeight = elementStyle.getPropertyValue('height');
imgQuiz.style.height = pixHeight * .5;
Also, I'm new to javascript, do I need to wrap this in a function (i.e. window.onload = function())?
Check out this JS Fiddle for help...
https://jsfiddle.net/Lm60v949/6/
var image = document.getElementsByClassName('img-quiz')[0].getElementsByTagName('img')[0];
// console.log( image ); // test to make sure the image was captured
/*
var image = document.getElementById('imgQuiz'); // much cleaner way to select
*/
image.height = image.width / 2;
// console.log( image.height, image.width ); // check the results
.img-quiz p span img { width: 100%; }
<div class="img-quiz">
<p>
<span>
<img id="imgQuiz" src="https://image.shutterstock.com/z/stock-photo--week-old-cocker-spaniel-puppy-630877553.jpg">
</span>
</p>
</div>
A couple of hiccups here:
.getElementsByClassName and .getElementsByTagName both return a HTMLCollection -- to use these, you will have to select the index of the collection that matches your image ([0], [1], [2], ... )
If you can, an ID on the targeted image would be ideal. Just easier to write and read code.
var image = document.getElementsByClassName('img-quiz')[0].getElementsByTagName('img')[0];
If you want brownie points, you can do something like:
image.onload = function(){
image.height = image.width / 2;
};
(assuming you have the image already captured and saved to the variable "image")
This is a nice sanity check to make sure the image exists (and has a height & a width) before trying to manipulate it.
You may be overthinking the problem a bit -- once an image is loaded, you can just look up the width and set the height property of the image.
There's a couple of extras that you can do here:
Check to make sure that the image width is not 0 (zero) ... this is a nice double-check that the image has loaded
if( image.width > 0 ){ ... }
Round the number down to a whole number (there's nothing wrong with .5 size increments, just nice to work with whole numbers)
image.height = Math.floor( image.width/2 );
Summary of your question:
My understanding of your situation is, your trying to make an image have the height of 50% of the webpage but its not doing so, you have looked into different methods including JavaScript but struggling, also you asked about onload methods.
If so this is my proposed solution
Solution
In this example we are using pure JavaScript (no library or framework)
The html has pre-set the src for the image, if you want to dynamically set the src then use the following imgEl.src = "path/to/file.jpg";
The method or trigger used is a DOMContentLoaded, which ensures all the HTML elements of the page have loaded before it begins trying to read and manipulate the DOM Elements.
The function we trigger is called funStart (Short for function Start), I always encourage people to use abreviations that define the object type so that it is easier to read such as fun for function, str for string, bl for boolean, obj for object, int for integer so on.
inside funStart we are assigning an DOM element as imgEl which is an image obj and we are saying set the width to be innerWidth which is the document width
We are then saying set the height to be 50% of the document height (innerHeight), by dividing the value into 2.
function funStart(){
var imgEl = document.getElementById("targetImg");
imgEl.height = innerHeight / 2;
imgEl.width = innerWidth;
}
document.addEventListener("DOMContentLoaded", funStart, false);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<img id="targetImg" src="https://static.pexels.com/photos/257360/pexels-photo-257360.jpeg" alt="background image" title="background">
</body>
</html>
Here's a simple example (you can learn more in here):
var image = document.getElementsByClassName('img-quiz')[0];
image.height = image.width / 2;
<img src="https://dummyimage.com/100x100">
<img class="img-quiz" src="https://dummyimage.com/100x100">
The HTML file would be like this:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<img src="https://dummyimage.com/100x100">
<img class="img-quiz" src="https://dummyimage.com/100x100">
<script>
// you could also move the script tag to the head and add an event handler to the event load (window.onload = function() {...};
var image = document.getElementsByClassName('img-quiz')[0];
image.height = image.width / 2;
</script>
</body>
</html>

How to do a process after completion of another one in JavaScript

I want to add an image by Javascript, then calculating the html element width as
window.onload=function(){
document.getElementById('x').addEventListener('click', function(e){
var el = document.getElementById('xx');
el.innerHTML = '<img src="img.jpg" />';
var width = el.offsetWidth;
.....
}, false);
}
but since JavaScript conduct all processes simultaneously, I will get the width of the element before loading the image. How can I make sure that the image has been loaded into the content; then calculating the element width?
UPDATE: Thanks for the answers, but I think there is a misunderstanding. img src="img.jpg" /> does not exist in the DOM document. It will be added later by Javascript. Then, when trying to catch the element by Id, it is not there probably.
You can give the img an ID and do the following :-
var heavyImage = document.getElementById("my-img");//assuming your img ID is my-img
heavyImage.onload = function(){
//your code after image is fully loaded
}
window.onload=function(){
document.getElementById('x').addEventListener('click', function(e){
var el = document.getElementById('xx');
var img = new Image();//dynamically create image
img.src = "img.jpg";//set the src
img.alt = "alt";
el.appendChild(img);//append the image to the el
img.onload = function(){
var width = el.offsetWidth;
}
}, false);
}
This is untested, but if you add the image to the DOM, set an onload/load event-handler and then assign the src of the image, the event-handling should fire (once it's loaded) and allow you to find the width.
This is imperfect, though, since if the image is loaded from the browser's cache the onload/load event may not fire at all (particularly in Chromium/Chrome, I believe, though this is from memory of a bug that may, or may not, have since been fixed).
For the chrome bug you can use the following:-
var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';//create a blank source
var tImg = document.getElementById("my-img");//get the image
var origSrc = tImg.src;//get the original src
tImg.src = BLANK;//change the img src to blank.
tImg.src = origSrc;//Change it back to original src. This will lead the chrome to load the image again.
tImg.onload= function(){
//your code after the image load
}
You can use a library called PreloadJS or you can try something like this:
//Somewhere in your document loading:
loadImage(yourImage, callbackOnComplete);
function loadImage(image, callbackOnComplete){
var self = this;
if(!image.complete)
window.content.setTimeout(
function() { self.loadImage(image, callbackOnComplete)}
,1000);
else callbackOnComplete();
}
I did this when I worked with images base64 which delay on loading.

Using javascript to derive height of image when only resized width is explicitly given in html

Forgive my ignorance of javascript, but I'm trying to create a simple image hover that enlarges the image when you hover your mouse over it. (And no, I don't want to use JQuery. I want to learn this directly in javascript!) My problem is that only the width is specified in the html. The height is omitted so that the image displays proportionally on the page. When I hover over the image with my mouse, the javascript works fine in IE, but in FF, Chrome, Safari, etc. img.offsetHeight gets assigned 0 rather than a proportion of img.offsetWidth.
<script type="text/javascript">
var img=document.getElementById('imageid');
var thiswidth=img.offsetWidth;
var thisheight=img.offsetHeight;
var ratio=thisheight/thiswidth;
var bigwidth=600;
var bigheight=bigwidth*ratio;
function bigImg(x) {
x.style.width=bigwidth;
x.style.height=bigheight;
}
function normalImg(x) {
x.style.width=thiswidth;
x.style.height=thisheight;
}
</script>
<img id="imageid" onmouseover="bigImg(this)" onmouseout="normalImg(this)" src="myimage.jpg" alt="image" width="200" >
As you can see from the img tag, height is inferred proportional to width by not being specified. Can someone tell me how I can use javascript to derive thisheight from thiswidth?
this will work for you in all ie FF, Chrome, Safari, etc
<html>
<body>
<img id="imageid" onmouseover="bigImg(this)" onmouseout="normalImg(this)" src="C810623C.gif" alt="image" width="200" >
<script type="text/javascript">
var img = document.getElementById('imageid');
var normsizeimg = img.style.width;
var bigwidth = 600;
function bigImg(x)
{ x.style.width = bigwidth; }
function normalImg(x) { x.style.width = normsizeimg; }
</script>
</body>
</html>
this is why it's easier to do such things with jquery, some browsers keep dimension values in offsetWidth others don't;
here's a tip of how you can get across this problem
var thiswidth=img.offsetWidth;
var thisheight=img.offsetHeight;
//it's non IE browser
if(XMLHttpRequest){
var thisheight=img.clientHeight;
var thiswidth=img.clientWidth;
}
This works fine for me on Firefox (I don't have access to other browsers right now, sorry):
<img id="imageid" src="myimage.jpg" alt="image" width="200" >
<script type="text/javascript">
var img = document.getElementById('imageid');
img.onload = function(){
var thiswidth = img.offsetWidth;
var thisheight = img.offsetHeight;
var ratio = thisheight/thiswidth;
var bigwidth = 600;
var bigheight = bigwidth*ratio;
img.onmouseover = function bigImg() {
img.style.width = bigwidth;
img.style.height = bigheight;
}
img.onmouseout = function normalImg(x) {
img.style.width = thiswidth;
img.style.height = thisheight;
}
};
</script>
The main differences between this code and yours is that:
I'm only accessing the element after it is declared
I'm only accessing its properties after the image loads
I'm also only adding the onmouseover and onmouseout attributes later because it makes the HTML look cleaner, but that's optional.
Update: actually, adding the event handlers later isn't optional, because they use the calculated bigwidth and bigheight, which are only available after the image loads.

Images not loaded when I display ajax content

I'm using jquery.load to pull in a fragment of html from another page. The fragment contains quite a large background image. Once the load function has finished and it calls it's callback I set the fragment to display block in the page - problem is that as the html loads I see the new content without the background image....the background image loads later.
Whats a good method of making sure the image is loaded before I show the ajax content?
You could do this...
$('button').click(function() {
$('#element').load('/echo/html/', function(responseText) {
// For testing
responseText = '<link href="http://sstatic.net/stackoverflow/all.css?v=ded66dc6482e" rel="stylesheet" type="text/css" /><div class="ac_loading" style="width: 200px; height: 200px;">ABC</div>';
var element = $(this),
responseTemp = $('<div />').hide().html(responseText).appendTo('body'),
styles = responseTemp.find('link[type="text/css"]'),
stylesHook = $('head link[type="text/css"]:last');
if (stylesHook.length === 0) {
stylesHook = $('head *:last-child');
}
styles.insertAfter(stylesHook);
preloadSrc = responseTemp.find('div').css('backgroundImage').replace(/^url\(["']?(.*?)["']?\)$/, '$1'), image = new Image();
image.onload = function() {
styles.add(responseTemp).remove();
element.html(responseText);
}
image.src = preloadSrc;
});
});
jsFiddle.

Changing source of image with an image of different size, won't resize in IE

I'm trying to create a very simple gallery using javascript. There are thumbnails, and when they're clicked the big image's source gets updated. Everything works fine, except when I try it in IE the images' size stays the same as the inital image's size was. Let's say initial image is 200x200 and I click on a thumbnail of a 100x100 image, the image is displayed but it is streched to 200x200. I don't set any width or height values, so I guess the browser should use image's normal size, and so does for example FF.
here's some code:
function showBigImage(link)
{
var source = link.getAttribute("href");
var bigImage = document.getElementById("bigImage");
bigImage.setAttribute("src", source);
return false; /* prevent normal behaviour of <a> element when clicked */
}
and html looks like this:
<ul id="gallery">
<li>
<a href="images/gallery/1.jpg">
<img src="images/gallery/1thumb.jpg">
</a>
</li>
(more <li> elements ...)
</ul>
the big image is created dynamically:
function createBigImage()
{
var bigImage = document.createElement("img");
bigImage.setAttribute("id", "bigImage");
bigImage.setAttribute("src", "images/gallery/1.jpg");
var gal = document.getElementById("gallery");
var gal_parent = gal.parentNode;
gal_parent.insertBefore(bigImage, gal);
}
There's also some code setting the onclick events on the links, but I don't think it's relevant in this situaltion. As I said the problem is only with IE. Thanks in advance!
Sounds like IE is computing the width and height attributes for #bigImage when it is created and then not updating them when the src is changed. The other browsers are probably noting that they had to compute the image dimensions themselves so they recompute them when the src is changed. Both approaches are reasonable enough.
Do you know the proper size of the image inside showBigImage()? If you do, then set the width and height attributes explicitly when you change the src:
function showBigImage(link) {
var source = link.getAttribute("href");
var bigImage = document.getElementById("bigImage");
bigImage.setAttribute("src", source);
bigImage.setAttribute("width", the_proper_width);
bigImage.setAttribute("height", the_proper_height);
return false;
}
If you don't know the new dimensions then change showBigImage() to delete #bigImage and create a new one:
function createBigImage(src) {
var bigImage = document.createElement("img");
bigImage.setAttribute("id", "bigImage");
bigImage.setAttribute("src", src || "images/gallery/1.jpg");
var gal = document.getElementById("gallery");
gal.parentNode.insertBefore(bigImage, gal);
}
function showBigImage(link) {
var bigImage = document.getElementById("bigImage");
if(bigImage)
bigImage.parentNode.removeChild(bigImage);
createBigImage(link.getAttribute("href"););
return false;
}

Categories

Resources