Preloaded images are not beeing used - javascript

I am trying to preload images for use in a image gallery. The images are taken threw a php script from a folder outside of the htdocs folder. And when they are loaded the images should be used in a masonry layout.
As far as my knowledge goes the javascript that I am using should be working. However when I am using the page on a gallery for several 100 images it does not work. Some images are loaded others are not.
I also have very little knowledge of javascript in general. So any advice would be helpful.
I tried a lot of things. The imagesloaded from desandro. Several iterations of the script I will share on the bottom. I am at a loss.
Javascript code
<script type="text/javascript">
var images = <?php echo json_encode($images); ?>;
var folder = <?php echo json_encode($folderName); ?>;
var imageArray = [];
function preloadImages() {
for (var i = 0; i < images.length; i++) {
var img[i] = new Image();
img[i].src = "img/jpg/" + folder + "/" + images[i].image_name;;
imageArray.push(img);
}
}
</script>
JSON example (for the images)
{"image_id":"8","image_name":"DSC00058.JPG","image_selected":"1","image_locked":"0"},
{"image_id":"9","image_name":"DSC00053.JPG","image_selected":"1","image_locked":"1"},
HTML
<body class="h-100 bg-light" onload="preloadImages();">
The expected result would be that the masonry only starts building and using the images that are preloaded. Is there a way to use the preloaded images or do I need to doe a specific thing in HTML?

Your preload function is loading the images, but it's not preloading them. The trick is to wait for them all to load before initializing the masonry plugin..
Here's an example using promises.
function preloadImages() {
var promises = [];
for (var i = 0; i < images.length; i++) {
promises.push(new Promise(done => {
var img[i] = new Image();
img.onload = ()=>done();
img[i].src = "img/jpg/" + folder + "/" + images[i].image_name;;
imageArray.push(img);
}));
}
Promise.all(promises).then(()=>{
// initialize masonry here...
});
}

Related

lazysizes unveil Method does not load all images - lazySizes.loader.unveil(imgElem)

On this example page on Github: https://afarkas.github.io/lazysizes/index.html
When I inject following JS the lazy images outside the viewport load fine:
var lazyObj = window.lazySizes;
var images = document.getElementsByClassName('lazyload');
for (var i = 0; i < images.length; i++) {
lazyObj.loader.unveil(images[i]);
}
If I do the same on the following >>> example page <<< which uses the EWWW Image Optimizer the images outside the viewport are NOT loaded.
The lazysizes object is present
var lazyObj = window.lazySizes;
console.log('window.lazySizes Object:' + JSON.stringify(lazyObj));
but FAILS invoking the Method lazySizes.loader.unveil(DOMNode) https://github.com/aFarkas/lazysizes#js-api---methods

How to get remote image using jQuery asynchronously?

I want to show a remote image on my page. I use Bootstrap 2.3.2 Carousel. All the information comes from another web site's RSS feed. I get data into a div like the following:
...
<div id="newsItem-<?php echo $i;?>" class="item" data-src="<?php echo $feed[$i]->image; ?>" data-alt="<?php echo $feed[$i]->title; ?>">
</div>
...
The images takes too long to load. Page is loaded about 15 seconds. So I have decided to load images after the page loading finished.
There could be various dimensions of the pictures to be displayed.
I want to show the largest existing one.
For each news item, all the images may have different but similar dimensions such as 1024x768, 620x350, 528x350, 527x350.
I have written a jQuery script to achieve this but something is wrong.
jQuery(function () {
jQuery("div[id^='newsItem-']").each(function () {
var r = jQuery(this).attr("data-src");
var r620 = r.replace(".jpg", "-620x350.jpg");
var r527 = r.replace(".jpg", "-527x350.jpg");
var r1024 = r.replace(".jpg", "-1024x678.jpg");
var r528 = r.replace(".jpg", "-528x350.jpg");
var altImg = jQuery(this).attr("data-alt");
if (pictureExists(r1024)){
r = r1024;
}
else if (pictureExists(r620)){
r = r620;
}
else if (pictureExists(r528)){
r = r528;
}
else if (pictureExists(r527)){
r = r527;
}
jQuery(this).prepend("<img src='" + r + "' alt='" + altImg + "' />");
jQuery(this).removeAttr("data-alt");
jQuery(this).removeAttr("data-src");
});
});
function pictureExists(url) {
var img = new Image();
img.src = url;
if (img.height !== 0) {
return false;
} else {
return true;
}
}
I want to display the largest existing picture in the carousel.
You cannot know the height/width of the image until its loaded. So its an async process.
In pictureExists function try to do it in this way:
/ Create new image
var img = new Image();
// Create var for image source
var imageSrc = "http://example.com/blah.jpg";
// define what happens once the image is loaded.
img.onload = function() {
// Stuff to do after image load ( jQuery and all that )
// Within here you can make use of src=imageSrc,
// knowing that it's been loaded.
};
// Attach the source last.
// The onload function will now trigger once it's loaded.
img.src = imageSrc;
If you want to use the above way then you will have to implement promise structure to tackle the async nature of the image load to fetch the height/width
Or you can use this small plugin.
https://github.com/desandro/imagesloaded

Preloading images in an array (and waiting until they have downloaded)

So I came across another problem.
When I started redoing the webpage I am working on , I came across an idea - Why not have the page preload the materials, and while it's doing just that, show a loading screen?
Well, I made a function for that, but the thing is, it starts doing what it's supposed to, until it comes to the open() part of the image preloading. It simply does not work. It is because I am giving it the arguments[i] part that is causing it to stop there? Is there a better way to do it?
function mainPageLoad() {
var loadScreen = document.getElementById('pageload');
loadScreen.innerHTML = "<p>Loading<span id='loadingWhat'>...</span></p><img src='images/loading.gif?v2'>";
var loadspan = document.getElementById('loadingWhat');
loadspan.innerHTML = " images";
preloadImages(["images/logo.jpg"])
//loadspan.innerHTML = " content";
//preloadContent([""]);
}
function preloadImages() {
var images = new Array();
var imagesToLoad = arguments.length;
document.writeln(imagesToLoad);
var imagesLoaded = 0;
document.writeln(imagesLoaded);
for (i = 0; i < arguments.length; i++) {
document.writeln("Loading images.");
images[i] = new XMLHttpRequest();
document.writeln("Made object");
images[i].open("GET", arguments[i], true);
document.writeln("Well, that worked.");
images[i].send(null);
document.writeln("Sent.");
images[i].onreadystatechange = function() {
document.writeln("Ready state change!");
if (images[i].readystate == 4 && images[i].status == 200){
imagesLoaded = imagesLoaded + 1;
window.alertln("We have loaded another image.");
window.alertln("Image" + String(imagesLoaded) + "out of" + String(imagesToLoad));
}
}
}
}
window.onload = init;
Here's a much, much simpler way to preload images and have it call a callback when the images are done loading in a related prior question/answer: Image preloader javascript that supports events.

jQuery Image Load Loop - Wrap HTML & Check Size?

I have a folder with images in it and I'm loading those images using jQuery. This code:
$(function () {
var i=1;
for (i=1;i<=50;i++){
var curImg = "blog/wp-content/uploads/" + i + ".jpg";
var img = new Image();
$(img).load(function () {
$(this).hide();
$('#loader').removeClass('loading')
.append(this);
$(this).fadeIn();
}).error(function () {})
.attr('src', ''+curImg+'');
}
});
works fine for smoothly loading 50 images from this folder. I am trying to do 2 things:
I want to add a link like this: <a href='blog/wp-content/uploads/" + i + ".jpg' class='picLink'> to each individual image. I have tried using .wrap in my .load function here, but that isn't working for me. This just creates a nest of links (e.g. <a><a></a></a>).
Currently this finds the first 50 photo's, starting at number 1, and loads them. But if more photo's are added they won't be found, and the oldest will always be first. I would like it to find all photo's in the folder and print the newest (highest number) first. It can be presumed that there won't be more than, say, 4000 photo's. So would it be possible to do this loop in reverse, start at 4000, check if that photo exists and work down and just load photo's that exist in the folder?
Thanks in advance for any help, I hope the question is clear enough!
For 1. you can do something like this fiddle
$(function () {
var i=1;
for (i=1;i<=50;i++){
var curImg = "blog/wp-content/uploads/" + i + ".jpg";
var img = new Image();
$(img).load(function () {
$(this).hide();
$('#loader').removeClass('loading')
.append($('').append(this));
$(this).fadeIn();
}).error(function () {})
.attr('src', ''+curImg+'');
}
});
Also they may not be in order as some images may take longer to load than others.
For 2. I think you should get the image count server-side and inject it into the for loop something like,
for (i=<?php echo $count; ?>; i > <?php echo ($count>50?$count-50:0); ?>; i--){
assuming you're using php, where $count represents the amount of images in the folder.

Precache a varying number of images in jQuery and call back if all are loaded

I would like to do an animation with the images, but only when they are all loaded.
When I start the animation with images still loading, it looks bad.
The images are dynamically added to the dom by parsing a json requested by javascript on $(document).ready.
After the images are loaded I would like to get a callback.
my core code is like this:
$('.gallery-block').each(function () {
$.ajax({
url: $(this).data("url"),
dataType: 'json',
outerthis: this,
success: function (json) {
$(this.outerthis).data("json", json);
var i = json.length;
while (i--) {
var preload = new Image();
preload.src = json[i];
}
$(this.outerthis).data("loaded", "true");
}
});
});
As you can see I'm trying to preload the images, but I don't know how fickle they are this way. They are not attached to the dom or anything.
The other problem is that I wnat the line
$(this.outerthis).data("loaded", "true");
only to be executed when the images are really preloaded.
Should I iterate a variable on every image's callback?
And probably this.outerthis is a bad design pattern, but I'm new to javascript.
The images don't need to be connected to the DOM to be loaded. What you can do is hook up an onload event to each image (before you set the URL), which will acts as your callback. Just count up the number of responses to onload and you can figure out when they're all loaded.
Something like this (untested):
var i, image,
preload = [], loaded = 0,
images = ["a", "b"], count = images.length;
for(i = 0; i < count; i++) {
image = new Image();
image.onload = onImageLoaded;
image.src = images[i] + ".jpg";
preload[i] = image;
}
function onImageLoaded() {
loaded++;
if(loaded === count) {
alert("done");
}
}

Categories