Wait for image to load plugin not functioning - javascript

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

Related

How to open largest version of image in lightbox upon click

I have embedded images in text blocks on my Divi website. I'd like that when the user clicks on the image, the largest/original size of the image opens up in a lightbox (instead of the thumbnail size as stated in the src). I have hundreds of images and therefore would be too time consuming to change the src link on each to the original size url. Could anyone help me on how I can change the src link to point to the largest/original image size and then for it to open in a lightbox upon click? I'm not sure of the JQuery to go about this. I've included below the HTML structure I'm using for each embedded image in the text blocks. I've also included the JQuery snippet I'm currently using. The snippet opens the image in a lightbox but only the thumbnail version (not the largest size possible).
Here are a few examples of the URLs of the images on my site:
https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg
https://mydomain/wp-content/uploads/2023/01/myimage.jpg
https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg
HTML:
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
JQuery:
<script>
if ( jQuery('.dmpro_timeline_item_description').length > 0 ) {
jQuery(".dmpro_timeline_item_description p img").each(function(i, e){
var img_src = jQuery(this).attr("src");
var img = jQuery(this).parent().html();
var new_elem = jQuery('<a style="color: inherit;" href="'+img_src+'">'+img+'</a>');
jQuery(this).parent().html(new_elem);
});
}
jQuery(document).ready(function($){
$(".dmpro_timeline_item_description p").magnificPopup({
delegate: 'a',
type: 'image',
closeOnContentClick: true,
closeBtnInside: false,
mainClass: 'mfp-no-margins mfp-with-zoom',
gallery:{
enabled:false,
},
zoom: {
enabled: true,
duration: 200
}
});
});
</script>
In the snippet below you can see that the width and the height attributes can be toggled.
function toggleLarge(context) {
if (!context.large) {
context.large = true;
context.formerWidth = context.width;
context.formerHeight = context.height;
context.removeAttribute("width");
context.removeAttribute("height");
} else {
context.large = false;
context.width = context.formerWidth;
context.height = context.formerHeight;
}
}
for (let img of document.querySelectorAll("img.size-medium")) {
img.addEventListener('click', function(event) {
toggleLarge(this);
});
}
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://www.yourtango.com/sites/default/files/styles/header_slider/public/image_blog/lion-meaning.png?itok=-eB2XSyC" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
If you also need to change the URLs, then you will need to proceed similarly. Since you have not given a sample of large URLs, it's impossible to tell you how to convert the URL to something you did not specify. However, if the "-235x300" part is the problematic, then you can do something like this:
function toggleSrc(context) {
if (context.large) {
context.src = context.src.replace(".", "-235x300.");
} else {
context.src = context.src.replace("-235x300", "");
}
}
and call this function in toggleLarge just before the if, passing context. If this is inappropriate to your problem, then you need to provide further information.
EDIT
Initially, for the sake of simplicity, the event listener was defined with the onclick attribute, but I have changed it to be an addEventListener as per Roko C. Buljan's suggestion.
EDIT2
As Roko C. Buljan explained, it's also possible to use forEach instead of a for loop. For those who prefer that syntax, there is another snippet below:
function toggleLarge(context) {
if (!context.large) {
context.large = true;
context.formerWidth = context.width;
context.formerHeight = context.height;
context.removeAttribute("width");
context.removeAttribute("height");
} else {
context.large = false;
context.width = context.formerWidth;
context.height = context.formerHeight;
}
}
document.querySelectorAll("img.size-medium").forEach(function(img) {
img.addEventListener('click', function(event) {
toggleLarge(this);
});
});
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://www.yourtango.com/sites/default/files/styles/header_slider/public/image_blog/lion-meaning.png?itok=-eB2XSyC" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
EDIT3
In the snippet below I have implemented the two functions you need based on the comment section's content:
/*
https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg
https://mydomain/wp-content/uploads/2023/01/myimage.jpg
https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg
*/
function thumbnailToLarge(input) {
return input.substring(0, input.lastIndexOf(".")).split("-").filter((item) => (
!/[0-9]+x.*[0-9]+/g.test(item)
)).join("-") + input.substring(input.lastIndexOf("."));
}
console.log("Thumbnail to large: " + thumbnailToLarge("https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg"));
function largeToThumbnail(input) {
return input.substring(0, input.lastIndexOf(".")) + "-235x300" + input.substring(input.lastIndexOf("."))
}
console.log("Large to thumbnail " + largeToThumbnail("https://mydomain/wp-content/uploads/2023/01/myimage.jpg"));
console.log("Large to thumbnail " + largeToThumbnail("https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg"));

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);
}
});
});

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

jQuery fade to new image - then continue to cycle through a list of images?

So I've got a header image that upon being clicked animates with transit, fades out, and fades back in with a new image. I'm then able to click on the new image and it will also animate and fade out to blank space. How can I continuously animate/fade through a series of ordered images - one new image per click ad infinitum?
Here's what I've got so far...
$(document).ready(function(){
$("#headuh").click(function(){
$("#headimg").transition({ skewY: '30deg' },1000);
$("#headimg").fadeOut(function() {
$(this).transition({ skewY: '00deg' }) .load(function() { $(this).fadeIn(); });
$(this).attr("src", "/imgurl.jpg");
You can use the javascript function called setInterval(); like this:
setInterval(function(){
//this code will keep on executing on every 2 seconds.
},2000)
The following snippet doesn't solve your problem exactly, but it might put you on the right track, as it randomly cycles through a set of 28 images with fading in and out. You can see it live at http://moodle.hsbkob.de:
<script src="jquery-1.4.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var g_first_call = true;
var g_pic_old;
$(document).ready(function() {
pickPic();
setInterval("pickPic()", 7500);
});
function randomPic() {
do {
var pic = parseInt(28*Math.random()+1);
} while (pic == g_pic_old); // Don't want same pic twice
g_pic_old = pic;
document.getElementById("_image_").src = "./picfolder/picno" + pic + ".jpg";
}
function pickPic() {
if (g_first_call) {
randomPic();
g_first_call = false;
}
$("#_fadee_").fadeIn(750, function() {
$("#_fadee_").delay(6000).fadeOut(750, randomPic);
});
}
//]]>
</script>
<div id="_fadee_"><img id="_image_" alt="Image" /></div>

Use Javascript to load some images last

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.

Categories

Resources