Use Javascript to load some images last - javascript

Hi I just wondered if this is possible. I have quite a few images on my website and I have made them as small file size as possible. Some of the images are used as a slideshow but there are all loaded in one go. Is there a way using javascript to make the slideshow images load last so that the background images etc load up first and the slideshow loads at the end.
The images are in the main body of the page and are "slideshowified" using javascript.
The code for this images is simple:
<div id="pics">
<img src="images/cs9.png" width="270px" height="270px" alt="teaching"/>
<img src="images/cs1.png" width="200px" height="200px" alt="teaching"/>
<img src="images/cs3.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs5.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs6.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs7.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs4.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs12.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs8.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs10.png" width="200" height="200px" alt="teaching"/>
<img src="images/cs14.png" width="200" height="200px" alt="teaching"/>
</div>
Any idea would be great
Thanks

Edit - See the bottom of this answer, a much better idea came to me
Original Answer
Yes, totally possible. Others have noted plug-ins for doing this, which are great in that they come pre-tested and such, but if you want to do it yourself it's surprisingly easy. You add img elements to the DOM (document object model):
function addAnImage(targetId, src, width, height) {
var img;
img = document.createElement('img');
img.src = src;
img.style.width = width + "px";
img.style.height = height + "px";
target = document.getElementById(targetId);
target.appendChild(img);
}
(I couldn't immediately recall how to set the alt attribute; it may well be img.alt = "...";)
Naturally you'll want to add some error checking to that. :-) So for one of your images, you want to add them to the pics div, so for example:
addAnImage('pics', 'images/cs12.png', 200, 200);
Set up a function to add your images and call it when the page is loaded (either using window.onload or whatever support your JavaScript library, if any, has for doing things a bit earlier than that). For instance, your load script might look like this (I don't typically use window.onload, but it's convenient for an example):
function pageLoad() {
var images = [
{src: "images/cs9.png", width: 270, height: 270, alt: "teaching"},
{src: "images/cs1.png", width: 200, height: 200, alt: "teaching"},
{src: "images/cs3.png", width: 200, height: 200, alt: "teaching"},
// ..., make sure the last one *doesn't* have a comma at the end
];
var index;
// Kick start the load process
index = 0;
nextImageHandler();
// Load an image and schedule the next
function nextImageHandler() {
var imgdata;
imgdata = images[index];
addOneImage('pics', imgdata.src, imgdata.width, imgdata.height);
++index;
if (index < images.length) {
window.setTimeout(nextImagePlease, 200);
}
}
}
window.onload = pageLoad;
On window load, that will load the first image and then schedule the next one to be loaded 200ms (a fifth of a second) later. When that happens, it'll schedule the next, etc., etc., until it's loaded all of the images.
JavaScript libraries like jQuery, Prototype, Closure, etc. typically have various helper functions for this sort of thing.
Updated answer
The above is fine, but it means that you have to completely change how you layout your pages, and you have to intermix content stuff (the image sources and sizes) with your JavaScript, etc. Blech.
How 'bout this: Make all of your image tags that are the same size refer to the same image:
<div id="pics">
<img src="images/w270h270.png" width="270" height="270" alt="teaching"/>
<img src="images/w200h200.png" width="200" height="200" alt="teaching"/>
<img src="images/w200h200.png" width="200" height="200" alt="teaching"/>
...
These would be placeholders. Then, add data attributes to them with the real image source:
<div id="pics">
<img src="images/w270h270.png" data-src="cs9.png" width="270" height="270" alt="teaching"/>
<img src="images/w200h200.png" data-src="cs1.png" width="200" height="200" alt="teaching"/>
<img src="images/w200h200.png" data-src="cs3.png" width="200" height="200" alt="teaching"/>
...
Attributes in the form data-xyz will be valid as of HTML5 (and they work today, they just don't validate).
Now the magic: Once the main load is completed, you walk through the img tags in the DOM, updating their src to make their data-src attribute:
function pageLoad() {
var nodeList, index;
// Get a NodeList of all of the images on the page; will include
// both the images we want to update and those we don't
nodeList = document.body.getElementsByTagName('img');
// Kick-start the process
index = 0;
backgroundLoader();
// Our background loader
function backgroundLoader() {
var img, src;
// Note we check at the beginning of the function rather than
// the end when we're scheduling. That's because NodeLists are
// *live*, so they can change between invocations of our function.
// So avoid going past what is _now_ the end of the list.
// And yes, this means that if you remove images from
// the middle of the document while the load process is running,
// we may end up missing some. Don't do that, or account for it.
if (index >= nodeList.length) {
// we're done
return;
}
// Get this image
img = nodeList[index];
// Process it
src = img.getAttribute("data-src");
if (src) {
// It's one of our special ones
img.src = src;
img.removeAttribute("data-src");
}
// Schedule the next one
++index;
window.setTimeout(backgroundLoader, 200);
}
}
window.onload = pageLoad;
Again, you'll want to add error handling and that's completely untested, but fundamentally it should work.

You can use a jquery Lazy Load plugin

you can use a lazy loading script. A good example is (jquery):
http://www.appelsiini.net/projects/lazyload

In the window onload event, use document.createElement to create images, and element.appendChild to insert them where desired.

I think you could write a javascript that will insert some tags after the page is loaded. In this manner the slideshow won't interfer with main content load.

I think this is quite late (10 years later) 😂😂, but I wrote an adaptation of the first answer.
Assuming you have some images you want to be affected but the rest to load first like:
<!-- Load Earlier -->
<img src="linktoimg">
<!-- Load After DOM loaded -->
<img data-src="linktoimg">
If you noticed, the ones to load later, I used a data-src attribute to specify the src it should use.
Javascript
function pageLoad() {
var $imgList = document.body.getElementsByClassName('img-speed');
// Kick-start the process
var $i = 0;
imgLoader();
function imgLoader() {
var $img, $src;
if ($i >= $imgList.length) {
//Done
return;
}
// Get this image
$img = $imgList[$i];
$src = $img.getAttribute('data-src');
if ($src) {
// It's one of our special ones
$img.src = $src;
$img.removeAttribute('data-src');
}
// Schedule the next one
++$i;
window.setTimeout(imgLoader, 200);
}
}
window.onload = pageLoad;
Uses a bit of jquery though.

Related

Wait for image to load plugin not functioning

I'm using the plugin from https://github.com/alexanderdickson/waitForImages to detect when is the image loaded.
Below is my code:
$('.marquee').waitForImages(function() {
console.log('All images have loaded.');
setTimeout(startMarquee);
}, function(loaded, count, success) {
console.log(loaded + ' of ' + count +
' images has ' + (success ? 'loaded' : 'failed to load') + '.');
$(this).addClass('loaded');
});
I will start a marquee scrolling of images when the images is loaded complete.
My problem is, some images had not yet load but just show a small empty square box like this:
,
the plugin also consider it already load. Any idea how to fix it?
Does showing a small empty square box only is consider image loaded?
Just write your own.
<marquee id="marquee" style="visiblity:hidden">
<img src="image1.jpg" onload="countMe(this,1)" onerror="countMe(this,0)"/>
<img src="image1.jpg" onload="countMe(this,1)" onerror="countMe(this,0)"/>
<img src="image1.jpg" onload="countMe(this,1)" onerror="countMe(this,0)"/>
</marquee>
<script>
var imageCount = 0, nofImages=$("#marquee img");
function countMe(img,success) {
if (!success) $(img).hide();
imageCount++;
if (imageCount == nofImages) $("#marquee").show();
}
</script>
If you want to give the image a chance and not load the marquee if permanent error you can try
<marquee id="marquee" style="visiblity:hidden">
<img src="image1.jpg" onload="countMe(this)" onerror="reloadMe(this)"/>
<img src="image2.jpg" onload="countMe(this)" onerror="reloadMe(this)"/>
<img src="image3.jpg" onload="countMe(this)" onerror="reloadMe(this)"/>
</marquee>
<script>
var imageCount = 0, nofImages=$("#marquee img");
function countMe(img) {
imageCount++;
if (imageCount == nofImages) $("#marquee").show();
}
function reloadMe(img) {
var tries = img.getAttribute("tries")?parseInt(img.getAttribute("tries"),10):1;
if (tries) == 3) return; // stop it
tries++;
img.setAttribute("tries",tries);
img.src=img.src;
}
</script>
If you want to wait till all page images loaded before running your marquee code you can use:
$(window).on("load", function() {
// all page html and images loaded
});
More details can be found in this questions:
Official way to ask jQuery wait for all images to load before executing something

Is it possible to clone an image after load in other parts of the page without loading?

I'm faced with a simple problem. Let says my user load around 150 images through a simple <img data-image='1' src="myimg1.jpg"> <img data-image=2' src="myimg2.jpg"> .. etc
When the user hovers over one of he images.I wish to display this myimg-thisimage.jpg in a small menu at the bottom of the screen. As of now, I'm changing the src attribute in my menu as:
$('#info-poster').attr("src","myimage-thisimage.jpg");
Note: myimage-thisimage.jpg is the current hovered over image.
But, when I do this. The browser is reloading the image (because, there is a small delay). Is there any way to bypass this loading since the user has already loaded the image using a clever way of cloning a DOM element maybe?
PS: The browser image cache is enabled. Therefore, the cache isnt the problem.
Edit: I know one way is to create 300 image elements and hide the other 150 of them. But in a scenario (definitely possible) where there are close to 500 images I would have to create around 1000 DOM elements which would be a big performance issue.
You can use a canvas element to show the thumbnail, this way the image is copied and scaled locally. In the following snippet I added two canvas, in the first one the image is scaled while keeping the aspect ratio (I use the Letterboxing and Pillarboxing techniques when required); in the second one the image is stretched. I also added another image at the bottom which is ignored, as it doesn't have the data-image attribute.
Is important not to use the scaling algorithm of drawImage as it produces unsmooth results when you reduce the image a lot. To achieve this, set the logical size of the canvas to match the natural size of the image. Then copy the image to the canvas by calling the drawImage method. Finally set the display size of the canvas to the desired one. This way the browser uses a better algorithm to scale the image.
Here are some outstanding quotes from the specification of the drawImage() method:
You can be sure the image will not be reloaded, and that you have to use the natural size of the image to avoid scaling with drawImage:
If the original image data is a bitmap image, the value painted at a point in the destination rectangle is computed by filtering the original image data.
The browser decides which scaling algorithm to use. At the moment of writing this: Edge, Chrome and Firefox don't use nothing better than the bilinear or nearest-neighbor algorithms. This may change in the future:
The user agent may use any filtering algorithm (for example bilinear interpolation or nearest-neighbor).
function initCanvas(id,image,naturalWidth,naturalHeight){
var canvas = document.getElementById(id);
var ctx = canvas.getContext("2d");
// Set the logical size of the canvas to match the
// natural size of the image, this way we don't use
// the scaling algorithm of drawImage (It isn't good
// for reducing big images as it produces unsmooth results).
$(canvas).attr("width",naturalWidth) ;
$(canvas).attr("height",naturalHeight) ;
// Copy the image:
ctx.drawImage(image,0,0,naturalWidth,naturalHeight);
return canvas ;
}
function clearCanvas(id){
var canvas = document.getElementById(id);
var ctx = canvas.getContext("2d");
ctx.clearRect(0,0,canvas.width,canvas.height);
}
$(window).on("load", function( ){
var images = $("img").filter(function(){
var dataImage = $(this).data("image") ;
if( typeof dataImage != "number" ) return false ;
var number = parseInt(dataImage,10) ;
return number > 0 && dataImage === number ;
}) ;
images.on("mouseenter", function( ){
var naturalWidth = $(this).prop("naturalWidth") ;
var naturalHeight = $(this).prop("naturalHeight") ;
// Scaled thumbnail:
// Copy the image to canvas-scaled and get a reference to it:
var scaledCanvas = initCanvas("canvas-scaled",this,naturalWidth,naturalHeight);
// Calculate the display size of the canvas:
var hwfactor = naturalHeight/naturalWidth ;
var whfactor = naturalWidth/naturalHeight ;
var scaledWidth, scaledHeight ;
if( hwfactor >= 1 ){ // Pillarboxing
scaledHeight = "100px" ;
scaledWidth = (100*whfactor)+"px" ;
}
else{ // Letterboxing
scaledWidth = "100px" ;
scaledHeight = (100*hwfactor)+"px" ;
}
// Now we change the display size of the canvas.
// A better scaling algorithm will be used.
$(scaledCanvas).css("width",scaledWidth);
$(scaledCanvas).css("height",scaledHeight);
// Stretched thumbnail:
// Copy the image to canvas-stretched. The display size
// of canvas-stretched is already set in the style section.
initCanvas("canvas-stretched",this,naturalWidth,naturalHeight);
});
images.on("mouseleave", function( ){
clearCanvas("canvas-scaled");
clearCanvas("canvas-stretched");
});
});
body{
background: #000;
}
.wrapper img{
width: 100px ;
height: auto ;
}
#banner{
display: block ;
width: 100% ;
height: 40px ;
padding-top: 1pt ;
}
#canvas-stretched{
width: 100px ;
height: 100px ;
}
.canvas-wrapper{
display: -webkit-inline-flex ;
display: inline-flex ;
-webkit-justify-content: space-around ;
justify-content: space-around ;
-webkit-align-items: center ;
align-items: center ;
vertical-align: bottom ;
border: 1px solid #888 ;
width: 100px ;
height: 100px ;
overflow: hidden ;
}
.viewer{
display: inline-block ;
}
.viewer span{
color: #ddd ;
font-family: sans-serif ;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<span class="wrapper">
<img data-image="1" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/550px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg"/>
<img data-image="2" src="https://upload.wikimedia.org/wikipedia/en/8/81/Megadrive_another_world.png"/>
<img data-image="3" src="https://upload.wikimedia.org/wikipedia/en/e/ee/TheKlingonHamlet.jpg"/>
</span>
<span class="viewer">
<span>scaled</span><br>
<div class="canvas-wrapper">
<canvas id="canvas-scaled"></canvas>
</div>
</span>
<span class="viewer">
<span>stretched</span><br>
<div class="canvas-wrapper">
<canvas id="canvas-stretched"></canvas>
</div>
</span>
<img id="banner" src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/The_southern_plane_of_the_Milky_Way_from_the_ATLASGAL_survey.jpg/320px-The_southern_plane_of_the_Milky_Way_from_the_ATLASGAL_survey.jpg"/>
This line is the problem:
$('#info-poster').attr("src","myimage-thisimage.jpg");
The browser is reloading the image because you reasign(bad practice) the "src" attribute.
Instead, you can use CSS options to display/hide "myimage-thisimage.jpg".
Since you use jQuery, we can make use of the methods: hide/show.
You mentioned "clone", I don't think you mean HTML elements clonning.
Example: (live on JS Bin)
<img id="dummy" width="200" height="150" data-image='1' src="http://europunkt.ro/wp-content/uploads/2016/06/romania.jpg">
<!-- Hidden by default -->
<img style="display:none" id="info-poster" width="200" height="150">
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<script>
var $dummy = $("#dummy");
var $infoPoster = $("#info-poster");
var infoPosterHasLoaded = false;
$dummy.on("mouseenter", function() {
// add the src attribute ONLY once
if(infoPosterHasLoaded === false){
$infoPoster.attr("src", "http://www.ilovemaramures.com/wp-content/uploads/2012/05/Pasul-Prislop.jpg")
infoPosterHasLoaded = true;
}
$infoPoster.show();
});
$dummy.on("mouseleave", function() {
$infoPoster.hide();
});
</script>
For a more fancy "hide/show" you can check jQuery Effects.
Edit - after I read your comment
In case you want to use the "data-image" attribute from the hovered element, check these objects: event.target, event.currentTarget, this
New JS Bin version.
I believe that what you are wanting is possible with the jQuery .clone() and .append() function. See the example below.
jQuery.clone()
jQuery.append()
$(function() {
$('img#ToClone').click(function(){
var imageClone = $('#ToClone').clone();
var cloneDestination = $('#CloneTo');
cloneDestination.append(imageClone);
});
});
div
{
padding:2px;
background:blue;
}
div#CloneTo
{
background:green;
}
img{
height:50px;
width:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<p>Click on the red square to clone it below.</p>
<img id="ToClone" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGlSURBVHhe7dCxTQQAEMRACiGk/86o4UmMxEpY/KW8R5ddtH575GnFOijWQbEOinVQrINiHRTroFgHxTr4Pdbbq2K/KNZgvyjWYL8o1mC/KNZgv3gq1uf7x389Fn5jvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgv3gq1utgvyjWYL8o1mC/KNZgvyjWYL/4452finVQrINiHRTroFgHxToo1kGxDor1tMfjC8KHtIEDA9XCAAAAAElFTkSuQmCC" />
</div>
<div id="CloneTo">
<p>Clone should appear here.</p>
<!-- The cloned image should appear here. -->
</div>
You may convert the image requests at server to respond with base64 string which you can store in your own cache.
Sample code below:
HTML
<img id="image1Id" src="" />
<input type="button" onclick='javascript:loadSomeThing("image1", "", "image1Id");' value="Load Image1" />
Script
var imageArray = [];
function loadSomeThing(key, someUrl, elementId) {
var imageData = imageArray[key];
if (!imageData) {
imageData = ajaxGetImageData(someUrl);
imageArray[key] = imageData;
}
document.getElementById(elementId).src = imageData;
}
function ajaxGetImageData(url) {
//Code to get base64 image string
return "data:image/jpeg;base64,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";
}
Demo
jsFiddle
You should let the browser to do the cache handling.
I suggest you could have a <img id="info-poster" src="myimage-thisimage.jpg" class="hide-on-load"/>, so then if your browser want to load a new copy of the image, it would do it before the user mouse over your other images. (if it is a small/acceptable image that user may have to download it every page load)
Then you could simply bind $("img.bind-event").on("mouseenter", function() { $("#info-poster").show(); }); and $("img.bind-event").on("mouseleave", function() { $("#info-poster").hide(); });
IDEA
initial markup
<img data-src='myimg1.jpg' data-image='1' src='placeholder.jpg'>
after myimg1.jpg has loaded dynamically (*)
<img data-image='1' src='blob:asdfasdfasdfasdfadfa'>
Then on 'mouseenter'
infoPosterEl.src = thisImageEl.src
// update image src to an object url(e.g. "blob:") will not bother http comm.
(*)
// Fetch acutal image as blob
// Create object url for the blob
// Update this <img> src to the object url
You can store the path to each image in an array, iterate array using Array.prototype.forEach(), set the background of each <img> element using url("/path/to/image"); at mouseover of each <img> set background-size of menu element to 100% 100% at index of hovered <img> element within collection using Array.prototype.slice(), Array.prototype.splice(). The approach should request each image from server at most once, toggling the image displayed at menu element to correspond to hovered image.
var urls = ["http://placehold.it/100x100?text=1"
, "http://placehold.it/100x100?text=2"
, "http://placehold.it/100x100?text=3"
, "http://placehold.it/100x100?text=4"
, "http://placehold.it/100x100?text=5"]
, sources = []
, sizes = []
, imgs = document.querySelectorAll(".img")
, menu = document.querySelector(".menu");
function toggleImage(index) {
this.onmouseover = function() {
var curr = sizes.slice(0);
curr.splice(index, 1, "100% 100%");
menu.style.backgroundSize = curr.join(",");
}
}
urls.forEach(function(path, index) {
sources.push("url(" + path + ")");
sizes.push("0% 0%");
imgs[index].style.background = sources[index];
toggleImage.call(imgs[index], index);
});
menu.style.background = sources.join(",");
menu.style.backgroundSize = sizes.join(",");
.menu {
left: calc(100vw / 2 - 50px);
position: relative;
width: 75px;
height: 75px;
display: block;
}
<img class="img" width="100" height="100" src="" /><img class="img" width="100" height="100" /><img class="img" width="100" height="100" /><img class="img" width="100" height="100" /><img class="img" width="100" height="100" />
<div class="menu">
</div>

Know offset of a div placed after lazy load images

I have a div wrapper in which lazy load images are present. Then I have a div below those images and I want to make it Sticky.
<div id="someWrapper">
<img class="lazy" data-original="someImageURL"></img>
<img class="lazy" data-original="someImageURL"></img>
<img class="lazy" data-original="someImageURL"></img>
<img class="lazy" data-original="someImageURL"></img>
<div class="sticky">SomeContents</div> <!-- want to make this sticky on scrool -->
</div>
In order to make them sticky I need offset of the div. Problem is offset is not fixed on the page because of lazy load images that keep pushing the div downward. Image heights are unknown. No of images are 4. Tried using appear event on the last load element but its not giving me accurate results. Please help me how to solve this problem. I want to get offset of the sticky div so I can make a check on the scroll event.
After playing around and some research achieved the desired like this:
function activateStickyScrollEvent(offSetValue){
//code to activate scroll event
}
var lazyLength=$('#someWrapper lazy').length;
var lazyCount=0;
$('#someWrapper lazy').one('appear',function(){
++lazyCount;
if(lazyCount===lazyLength){
var getWrapperOffset=$('#someWrapper').offSet().top;
activateStickyScrollEvent(getWrapperOffset);
})
So, as I said, you may have to check if the last image in the set has been loaded, and then check for the element's offset. Here is a demo of how it could be done. Feel free to adapt the code to suit your needs.
//Ref to the wrapper
var $wrapper = $("#someWrapper");
//Ref to the last image in the set
var lastImgSrc = $wrapper.find(" > img:last").attr("data-original");
var image = new Image();
image.onload = function () {
//do something on load...
var offset = $wrapper.find(".sticky").offset();
alert (offset.top);
}
image.onerror = function () {
//do something on error...
}
image.src = lastImgSrc;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="someWrapper">
<img class="lazy" data-original="someImageURL" />
<img class="lazy" data-original="someImageURL" />
<img class="lazy" data-original="http://dreamatico.com/data_images/sea/sea-4.jpg" src="http://dreamatico.com/data_images/sea/sea-4.jpg" width="100%" />
<img class="lazy" data-original="http://dreamatico.com/data_images/sea/sea-3.jpg" src="http://dreamatico.com/data_images/sea/sea-3.jpg" width="100%" />
<div class="sticky">SomeContents</div> <!-- want to make this sticky on scrool -->
</div>
Hope that helps.
You can count images to load, and the get the offset (OFFSET in my example) :
$(function() {
function imageLoaded() {
counter--;
if( counter === 0 ) {
// Here All your "lazy" images are loaded
var OFFSET = $('#someWrapper').offset().top; <---- you can get offset
}
}
var images = $('.lazy'),
counter = images.length; // initialize the counter
images.each(function() {
if( this.complete ) {
imageLoaded.call( this );
} else {
$(this).one('load', imageLoaded);
}
});
});

onload triggering too early for ajax content in IE

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.

Why won't image auto refresh

Trying to get images to refresh themselves with javascript a set number of times, then stop (to avoid large cache generation). This code won't function though, so not sure what's missing?
<script>
var c = 0;
function fnSetTimer()
{
document.getElementById('refreshimage1').src='http://68.116.42.142:8080/cam_4.jpg?\'+new Date().getMilliseconds();
var t = setTimeout(fnSetTimer,5000);
c=c+1;
if(c>5)
clearTimeout(t);
}
</script>
<img src="http://68.116.42.142:8080/cam_4.jpg"; id="refreshimage1" onload="fnSetTimer()" width="400" />
However, this code does work:
<img src="http://68.116.42.142:8080/cam_4.jpg"; id="refreshimage2" onload="setTimeout('document.getElementById(\'refreshimage2\').src=\'http://68.116.42.142:8080/cam_4.jpg?\'+new Date().getMilliseconds()', 5000)" width="400" />
So if you place both side by side, the bottom image will refresh (indefinitely), but the top image just loads once and never refreshes. Any thoughts what I missed in the top code?
The problem is that the function re-loads the image, which calls the function, which re-loads the image...
You also had a problem with the image url - '\' is used to escape special characters, if you want a slash you need two - '\\'
PUT THIS IN YOUR HEADER
<script language="javascript">
function fnSetTimer(image, src, counter, limit)
{
image.onload = null;
if(counter < limit)
{
counter++;
setTimeout(function(){ fnSetTimer(image, src, counter, limit); },5000);
image.src= src+ '?\\'+new Date().getMilliseconds();
alert(counter); // show frame number
}
}
</script>
PUT THIS IN THE BODY
<img src="http://68.116.42.142:8080/cam_4.jpg"; id="refreshimage1" onload="fnSetTimer(this, this.src, 0, 5);" width="400" />
This should fix it for you - it only fires onLoad once and then loops through 5 times, and you should be able to edit the image tag in Wordpress, etc.
MAKE SURE YOU GIVE EACH IMAGE A DIFFERENT ID

Categories

Resources