Start javascript after lazy load images - javascript

I have a problem with a javascript. The script causes three elements on my website to be the same size. I would like to load my pictures by lazy load. This makes the rendering incorrect because the size of the elements is calculated by the script without the images. Is it possible to give the javascript a function that it will start only after the images have been loaded successfully by lazy load?
<script type="text/javascript">
jQuery(document).ready(function($){
function kb_equal_height() {
var highest_element = 0;
// Delete the height
$('.navigation-left,.site-content,.widget-area').each(function() {
$(this).removeAttr('style');
});
// Check which element is highest
$('.navigation-left,.site-content,.widget-area').each(function() {
if ($(this).height() > highest_element) {
highest_element = $(this).height();
}
});
// Assign this height to all elements
$('.navigation-left,.site-content,.widget-area').each(function() {
$(this).height(highest_element);
});
};
window.onload = kb_equal_height;
var resizeTimer;
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(kb_equal_height, 100);
});
});
</script>

You can use image.onload to call the function when the image finished to load
You might not really see it in action here as the images probably won't take long enough to load for you to see intermediate state but it works
you'll need to clean your cache if you want to see it in action a second time as your browser will load the images from cache the second, third... times
let nbCat = 0
let div = document.getElementById("nbImg")
Array.from(document.getElementsByClassName("doAction")).forEach(img => {
img.onload = imgLoaded // your function here
})
function imgLoaded(e) {
nbCat++
div.textContent = nbCat + " cat" + (nbCat > 1? "s":"") + " loaded"
}
img {
max-height: 50vh
}
<img class="doAction" src="https://r.hswstatic.com/w_907/gif/tesla-cat.jpg">
<img class="doAction" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg">
<img class="doAction" src="https://pre00.deviantart.net/5d96/th/pre/f/2012/103/d/d/dd0d35acf8ea1817dffe7677f018b5a4-d4vzsbg.jpg">
<img class="doAction" src="https://pre00.deviantart.net/758d/th/pre/f/2018/006/2/7/tigerfieldadjusted_by_mssylviarose-dbz65qt.jpg">
<div id="nbImg">no cat loaded</div>

Related

Execute js after all image loaded not working

(not duplicate, because not find exactly/easy solution)
I'm trying to execute JS after all images completely loaded. My goal is, when all images finish load completely, then removeClass my-loader and addClass visible to main-slider div.
HTML:
<div class='main-slider my-loader'>
<img src="https://unsplash.it/200/300/">
<img src="https://unsplash.it/200/300/">
<img src="https://unsplash.it/200/300/">
</div>
Execute below js when all images completely loaded
$(".main-slider").removeClass("my-loader").addClass("visible");
Tried this js :
But not works properly on my site, problem is when i clear browser cache, then it works/execute! when i reload page then next time it's not works/execute! It only works when i clear browser cache.
var img = $('.main-slider img')
var count = 0
img.each(function(){
$(this).load(function(){
count = count + 1
if(count === img.length) {
$('.main-slider').removeClass('my-loader').addClass('visible')
}
});
});
Any simple solution? Thanks in advance.
jQuery provides a way to register a callback for the window load event which will fire when the entire page, including images and iframes, are loaded.
Reference: https://learn.jquery.com/using-jquery-core/document-ready/
Your code should look something like:
$( window ).load(function () {
var img = $('.main-slider img')
var count = 0
img.each(function(){
$(this).load(function(){
count = count + 1
if(count === img.length) {
$('.main-slider').removeClass('my-loader').addClass('visible')
}
});
});
});
Here's how to do this, using Deferreds and native handlers, and calling the onload handler if the image is cached in older browsers etc.
var img = $('.main-slider img');
var defs = img.map(function(){
var def = new Deferred();
this.onload = def.resolve;
this.onerror = def.reject;
if (this.complete) this.onload();
return def.promise();
});
$.when.apply($, defs).then(function() {
$('.main-slider').removeClass('my-loader').addClass('visible')
});

Initializing a plugin AFTER a foreach loop

So I'm trying to implement stellar.js but it must be initialized after an each loop is finished. The loop must add data attributes to the images that are going to be made parallax by the plugin.
The images are in a list:
<ul>
<li class="item">
<div class="item-image" data-stellar-background-ratio="0.7" data-image="http://picjumbo.picjumbocom.netdna-cdn.com/wp-content/uploads/IMG_7706-1300x866.jpg"></div>
</li>
...
</ul>
I must add data-stellar-vertical-offset attribute to each of them that will offset the image by half of its height, so it can be vertically centered initially.
Here is the JS:
/* Inserting the background image */
$('.item-image').each(function () {
var $this = $(this);
$this.css('background-image', 'url(' + $this.data('image') + ')');
})
/* Creating loop that will run as many times as items are in there */
var items = $('.item-image').length;
var currentItem = 0;
$('.item-image').each(function () {
var $this = $(this);
/* Taking the origin height, halving it and putting it as offset so the image can be vertically aligned */
var img = new Image();
img.src = $(this).data('image');
img.onload = function () {
var H2 = this.height;
$this.attr('data-stellar-vertical-offset', -(H2 / 2));
}
currentItem++;
/* Initializing the plugin after every item is looped */
if (currentItem >= items) {
$.stellar();
}
})
However when the plugin is initialized it isn't using the data attribute. If it's put in a timeout like this:
if (currentItem >= items) {
setTimeout(function () {
$.stellar();
}, 10)
}
.. it works but it seems to me like an ugly hack. Is there a better way for this to be done?
Here is a jsfiddle: http://jsfiddle.net/9f2tc/1/
I believe what you want is to initialize stellar once after all the images have been downloaded. The simplest approach is to check each time in the onload handler:
img.onload = function () {
var H2 = this.height;
$this.attr('data-stellar-vertical-offset', -(H2 / 2))
if (++currentItem === items) {
$.stellar();
}
}
jsfiddle: http://jsfiddle.net/X6e9n/2/
However, there are issues with the onload event not firing for images in certain cases. See the caveats section on the jQuery page: http://api.jquery.com/load-event/ The problems listed apply to the load event itself not just jQuery's .load() See Javascript callback for knowing when an image is loaded for solutions. The first answer notes the handler should be attached before the src attribute is set, which you don't do here, but it doesn't seem to be a problem for me in this case.

javascript preloader/progress/percentage

I'm having trouble finding any good information on how to make a javascript(or jquery) progress bar WITH text that tells you the percentage.
I don't want a plug in, I just want to know how it works so that I can adapt it to what I need. How do you preload images and get a variable for the number of images that are preloaded. Also, how do you change html/css and-or call a function, based on the number of images that are loaded already?
<img> elements have an onload event that fires once the image has fully loaded. Therefore, in js you can keep track of the number of images that have loaded vs the number remaining using this event.
Images also have corresponding onerror and onabort events that fire when the image fails to load or the download have been aborted (by the user pressing the 'x' button). You also need to keep track of them along with the onload event to keep track of image loading properly.
Additional answer:
A simple example in pure js:
var img_to_load = [ '/img/1.jpg', '/img/2.jpg' ];
var loaded_images = 0;
for (var i=0; i<img_to_load.length; i++) {
var img = document.createElement('img');
img.src = img_to_load[i];
img.style.display = 'hidden'; // don't display preloaded images
img.onload = function () {
loaded_images ++;
if (loaded_images == img_to_load.length) {
alert('done loading images');
}
else {
alert((100*loaded_images/img_to_load.length) + '% loaded');
}
}
document.body.appendChild(img);
}
The example above doesn't handle onerror or onabort for clarity but real world code should take care of them as well.
What about using something below:
$('#btnUpload').click(function() {
var bar = document.getElementById('progBar'),
fallback = document.getElementById('downloadProgress'),
loaded = 0;
var load = function() {
loaded += 1;
bar.value = loaded;
/* The below will be visible if the progress tag is not supported */
$(fallback).empty().append("HTML5 progress tag not supported: ");
$('#progUpdate').empty().append(loaded + "% loaded");
if (loaded == 100) {
clearInterval(beginLoad);
$('#progUpdate').empty().append("Upload Complete");
console.log('Load was performed.');
}
};
var beginLoad = setInterval(function() {
load();
}, 50);
});
JSFIDDLE
You might also want to try HTML5 progress element:
<section>
<p>Progress: <progress id="p" max=100><span>0</span>%</progress></p>
<script>
var progressBar = document.getElementById('p');
function updateProgress(newValue) {
progressBar.value = newValue;
progressBar.getElementsByTagName('span')[0].textContent = newValue;
} </script>
</section>
http://www.html5tutorial.info/html5-progress.php

Javascript taking too long to load

The javascript of the div "intro" is loading at last. It's taking too long to load as the web page loads the bg image first and then loads the java script. Is there a way i can display "loading please wait" message in that "intro" div until it completely loads. I just want that the intro should load first.
Javascript code:
var tl = new Array(
"=======================",
" Welcome user, ",
" ###########################################"
);
var speed = 50;
var index = 0;
text_pos = 0;
var str_length = tl[0].length;
var contents, row;
function type_text() {
contents = '';
row = Math.max(0, index - 20);
while (row < index)
contents += tl[row++] + '\r\n';
document.forms[0].elements[0].value = contents + tl[index].substring(0, text_pos) + "_";
if (text_pos++ == str_length) {
text_pos = 0;
index++;
if (index != tl.length) {
str_length = tl[index].length;
setTimeout("type_text()", 500);
}
}
else setTimeout("type_text()", speed);
}
This is the script and its basically typing letter by letter in a text area in the div "intro". The problem is that it loads at last when the whole page has loaded. It starts printing the text after like 15 seconds or so.
There are "domready" events you can listen to on the document but seems that's not cross-browser.
Eg: Mozilla
document.addEventListener("DOMContentLoaded", methodName, false)
A better option is to use jQuery's .ready() event. They handle all cross-browser implementations.
Eg:
$(document).ready(function(){
//execute code here
});
//Shorthand
$(function(){
//...
});
See this related question for more on domready.
Load a page with the empty intro div, run the script with "loading please wait" then trigger an ajax request to load the rest of the page and update the page on onComplete event from the ajax request
Using jQuery
$(document).ready(function() {
// update div here
});
http://api.jquery.com/ready/
Or you could do that with
window.onload= (function() {
// update div here
};
You can use jquery for this by wrapping the content in a div tag and then another div that holds a loading image, something to this effect:
$(document).ready(function () {
$('#loading').show();
$('#divShowMeLater').load(function () {
$('#loading').hide();
$('#divShowMeLater').show();
});
})
Assume divShowMeLater is the div that contains all the content being loaded. The markup would look similiar to this:
<div id="divShowMeLater" style="margin-left:auto;margin-right:auto;text-align:center;" >
<div id="loading">Page loading...
<img src="images/ajax-loader.gif" alt="loading page..." />
</div>
</div>

JavaScript Photo Slider

I'm working on making a JS script that will go in the header div and display a few pictures. I looked into JQuery Cycle, but it was out of my league. The code I wrote below freezes the browser, should I be using the for loop with the timer var?
<script type="text/JavaScript" language="JavaScript">
var timer;
for (timer = 0; timer < 11; timer++) {
if (timer = 0) {
document.write('<img src="images/one.png">');
}
if (timer = 5) {
document.write('<img src="images/two.png">');
}
if (timer = 10) {
document.write('<img src="images/three.png">');
}
}
</script>
Thanks!
Assuming you want a script to rotate images and not just write them to the page as your code will do, you can use something like this:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="target"></div>
<script>
var ary = ["images/one.png","images/two.png","images/three.png"];
var target = document.getElementById("target");
setInterval(function(){
target.innerHTML = "<img src=\""+ary[0]+"\" />";
ary.push(ary.shift());
},2000);
</script>
</body>
</html>
Of course the above code has no effects (like fading) which jQuery will give yous, but it also doesn't require loading the entire jQuery library for something so basic.
How about just running the script after the page loads?
<script>
// in <head> //
function load() {
var headDiv = document.getElementById("head");
var images = ["images/one.png", "images/two.png"];
for(var i = 0; i<images.length; i++) {
image = document.createElement("img");
image.src = images[i];
headDiv.appendChild(image);
}
}
</script>
Then use <body onload="load();"> to run the script.
Edit
To add in a delay loading images, I rewrote the code:
<script>
// in <head> //
var displayOnLoad = true; // Set to true to load the first image when the script runs, otherwise set to false to delay before loading the first image
var delay = 2.5; // seconds to delay between loading images
function loadImage(url) {
image = document.createElement("img");
image.src = images[i];
headDiv.appendChild(image);
}
function load() {
var headDiv = document.getElementById("head");
var images = ["images/one.png", "images/two.png"];
for(var i = 0; i<images.length; i++) {
setTimeout(loadImage(images[i]), (i+displayOnLoad)*(delay*1000));
}
}
</script>
Set displayOnLoad = false; if you want to wait the specified delay before loading the first image. The delay is set in seconds. I recommend waiting over a single second between images, as they may take some time to download (depending on the user's internet speed).
As with the first snippet, I haven't tested the code, so please tell me if an error occurs, and I will take a look.
Since you used the jquery tag on your question, I assume you are OK with using jQuery. In which case, you can do something like this:
In your static HTML, include the img tag and set its id to something (in my example, it's set to myImg) and set its src attribute to the first image, e.g.:
<img id="myImg" src="images/one.png">
Next, use jQuery to delay execution of your script until the page has finished loading, then use setTimeout to create a further delay so that the user can actually spend a few seconds looking at the image before it changes:
<script>
var imgTimeoutMsecs = 5000; // Five seconds between image cycles
$(function() {
// Document is ready
setTimeout(function() {
// We will get here after the first timer expires.
// Change the image src property of the existing img element.
$("#myImg").prop("src", "images/two.png");
setTimeout(function() {
// We will get here after the second, nested, timer expires.
// Again, change the image src property of the existing img element.
$("#myImg").prop("src", "images/three.png");
}, imgTimeoutMsecs);
}, imgTimeoutMsecs);
});
</script>
Of course, that approach doesn't scale very well, so if you are using more than three images total, you want to modify the approach to something like this:
var imgTimeoutMsecs = 5000; // Five seconds between image cycles
// Array of img src attributes.
var images = [
"images/one.png",
"images/two.png",
"images/three.png",
"images/four.png",
"images/five.png",
];
// Index into images array.
var iCurrentImage = 0;
function cycleImage() {
// Increment to the next image, or wrap around.
if (iCurrentImage >= images.length) {
iCurrentImage = 0;
}
else {
iCurrentImage += 1;
}
$("#myImg").prop("src", images[iCurrentImage]);
// Reset the timer.
setTimeout(cycleImages, imgTimeoutMsecs);
}
$(function() {
// Document is ready.
// Cycle images for as long as the page is loaded.
setTimeout(cycleImages, imgTimeoutMsecs);
});
There are many improvements that can be made to that example. For instance, you could slightly simplify this code by using setInterval instead of setTimer.
The code you've provided simply iterates through the for loop, writing the images to the browser as it does so. I suggest you take a look at JavaScript setTimeout function.
JS Timing

Categories