We have image and links in separate blocks.
When link is clicked, its href attribute puts to src of the image.
What I'm trying to do:
If image is not already loaded (not cached) {
fadeOut previous image {
fadeIn loader {
load image (when animation of loader ends) {
fadeOut loader {
fadeIn image
}
}
}
}
} else (if image is cached, do not show loader) {
fadeOut previous image {
fadeIn new image
}
}
Here is what I have: http://jsfiddle.net/EvXJr/13/
First part works, don't know how to code the second (else) part.
Please help.
The dirty way would be to assign ids to loaded images, if there is no element with such id on a page - show loader, else just animate image.
Example:
html:
<div id="container">
</div>
js:
$('#container').delegate('a', 'click', function () {
var sel_id = this.id;
if (!document.getElementById('img_' + this.id)) {
//create image with id like: sel_id = 'img_' + this.id
} else {
//just show image
}
});
Why don't you just keep track of what HREFs you have loaded with a javascript array that you have loaded and if your HREF can be found in the loaded array just take out the loader related functions.
Couldn't get the jsfiddle to load but if I understand correctly I would just set the background image of the element that holds the images to a loading gif then you don't have to worry about fading in and out a loader. If an image is already cached it will load so quickly you will never see the loading gif. And if it isn't and takes a while to load the user will see the loading gif and using the function below the image will fade in nicely once loaded.
And if you want to perform a function once an image has loaded use
$("img").load(function(){
//do stuff once image has loaded.
//for example
$(this).fadeIn("slow");
});
Related
TL;DR: Is there a way to swap the images reliably while showing whichever image is being loaded at the time without causing page flicker?
I have 2 images and 2 buttons and when I hover over one button it shows the one image. Hovering over the other button swaps to the second image. I was doing it like this:
$('#button1').mouseover(function() {
$('#image').attr('src', 'image1.png');
});
$('#button2').mouseover(function() {
$('#image').attr('src', 'image2.png');
});
This works fine but when the first image has loaded and the second hasn't, it doesn't show the second image until it has completed loading. To try to give the user some indication of when the new image is loading (which they're expecting to appear immediately), I forced it to add a null image before these swaps, like this:
$('#button1').mouseover(function() {
$('#image').attr('src', '#');
$('#image').attr('src', 'image1.png');
});
$('#button2').mouseover(function() {
$('#image').attr('src', '#');
$('#image').attr('src', 'image2.png');
});
This works great when one image is loading by showing the image as it's loading but now once both are loaded, the null image in between them causes a flicker when switching images. I thought I could fix this by turning the null image off once both images are loaded but that has turned out to be unreliable. Both $('#image').prop('complete') and imagesloaded as suggested in other locations on stackoverflow are inconsistent at noticing whether the image has been loaded or not. Detecting loaded images just seems to be a dead end.
I also considered trying to force the images to show and hide before and after they were created but this doesn't seem to work at all though I'm not sure why. The new one doesn't show while loading and I'm not sure if they're swapping properly:
$('#button1').mouseover(function() {
$('#image').hide();
$('#image').attr('src', 'image1.png');
$('#image').show();
});
$('#button2').mouseover(function() {
$('#image').hide();
$('#image').attr('src', 'image2.png');
$('#image').show();
});
Is there a way to swap the images reliably while showing whichever image is being loaded at the time without causing page flicker that I haven't tried?
What you're wanting to do is preload the images so that they are cached in the browser. then there's no delay on your mouse over. Here's a jquery plugin to cache the images and a call for them.
$.fn.preload = function() {
this.each(function(){
$('<img/>')[0].src = this;
});
}
// Usage:
$(['image1.png','image2.png']).preload();
This is not my code: credit to James # Preloading images with jQuery
Try storing the sources of the image into JavaScript variables, and use those variables to swap the image sources.
This might avoid the loading, not sure, but it might.
Try this:
var preloadImages = ['image1.png', 'image2.png'];
$('#button1').mouseover(function() {
$('#image').attr('src', preloadImages[0]);
});
$('#button2').mouseover(function() {
$('#image').attr('src', preloadImages[1]);
});
The problem is having this HTML content updated by changing the src location makes the browser wait until the image is loaded before displaying the image. This doesn't seem to be modifiable.
The HTML:
<img id="image" src="">
and javascript with this behavior:
$('#button1').mouseover(function() {
$('#image').attr('src', 'image1.png');
});
$('#button2').mouseover(function() {
$('#image').attr('src', 'image2.png');
});
Changing the HTML:
<div id='image_container'> </div>
and javascript to:
$('#button1').mouseover(function() {
// Remove the old image and replace it with the new one
$('#image_container').empty()
.append("<img id='image' src='image1.png'>");
});
$('#button2').mouseover(function() {
$('#image_container').empty()
.append("<img id='image' src='image2.png'>");
});
makes the browser show the image while it is downloaded. I'm not exactly sure why but it seems to just be that new <img>s are handled differently than <img>s with src modifications.
In reference to this post: How to display loading image while actual image is downloading
I have the following code, but for some reason I cannot get the #loader_img to hide. I would also like to add a preloader because the large image is really heavy, but I want to keep it simple if possible since I am new to javascript...
<img id="loader_img" src="img/ajax-loader.gif" alt="Loading..." />
<div class="magnifier" style="height: 584px; width: 467px; margin: 20px;">
<div class="maglens">
<img id="imgload" src="img/largeimage.jpg" />
</div>
</div>
JS:
// show loading image
$("#loader_img").show();
$("#imgload").hide();
// main image loaded ?
$("#imgload").on('load', function(){
// hide/remove the loading image
$("#loader_img").hide();
});
Any help will be much appreciated! Thank you!
The image's load event is almost certainly firing before you hook the event. Since it's already fired when you hook the event, you never see it occur.
Also, you start out hiding the image (#imgload), but you never then show it.
To ensure that you get the event, you have to hook load before setting the image's src.
Alternately, you can use the image's complete property to know if it's already been loaded:
// show loading image
$("#loader_img").show();
$("#imgload").hide();
// main image loaded ?
var img = $("#imgload");
if (img[0].complete) {
imageDone();
} else {
img.on('load', imageDone);
}
function imageDone() {
// hide/remove the loading image
$("#loader_img").hide();
// And show the image!
img.show();
}
You also have to ensure that the code above runs after the elements have been created. The best way to do that is to put your script tag containing the code after the elements it refers to in the HTML (usually putting it just before the closing </body> tag works well). As a second-best solution, you can use jQuery's ready function. Either way, you'll still need to handle the possibility the load event has already fired.
Here's an example:
<div id="loader_img">Loading</div>
<div class="content">
<img id="imgload" src="http://i.stack.imgur.com/rTQCa.jpg?s=512&g=1" />
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
(function() { // Avoid creating globals
// show loading image
$("#loader_img").show();
$("#imgload").hide();
// main image loaded ?
var img = $("#imgload");
if (img[0].complete) {
console.log("Complete");
imageDone();
} else {
console.log("Wait for load");
img.on('load', imageDone);
}
function imageDone() {
console.log("Loaded");
// hide/remove the loading image
$("#loader_img").fadeOut();
// And show the image!
img.show();
}
})();
</script>
Hi you may use this method. jQuery.ready()I have tried on my computer and it's okay this way.
BTW, you forgot to let the "imgload" show again.
// show loading image
$("#loader_img").show();
$("#imgload").hide();
// main image loaded ?
$("#imgload").ready(function(){
// hide/remove the loading image
$("#loader_img").hide();
$("#imgload").show(); // show the loaded img again
});
I think that the script is executed before the DOM is loaded.
Take your script and put it between:
$(function () {
//Your code here
});
This will insure that the code will run after the DOM is loaded.
I'm building an JQM app and I'm having a few JS problems which im sure are quite easy to fix but I dont know much JS.
1) I'm placing divs on top of an image which links to over images. So when the app loads the divs are visible and then they fadeout. The problem is I want them to still be clickable and link to the other images when they are invisible.
CODE
setTimeout(function () {
$(".link").fadeIn(3000);
$(".link").fadeOut('slow');
}, 2000 /* Time to wait in milliseconds */);
setTimeout();
Simple but I want to just make them not viewable and keep the link.
2) my second problem is I have a sound file that plays onload and two images that turn the sound file on and off. The code I made will only change the image on the home page and will not work on any other page (turning the sound on and off works but the image wont change)
CODE
function playSound() {
sound.play();
}
sound.play();
newsrc = "soundOff.png";
function changeImage() {
if ( newsrc == "soundOff.png" ) {
document.getElementById("sound").src = "img/soundOff.png";
document.getElementById("sound").alt = "Sound Off";
newsrc = "soundOn.png";
sound.pause();
}
else {
document.getElementById("sound").src = "img/soundOn.png";
document.getElementById("sound").alt = "Sound On";
newsrc = "soundOff.png";
sound.play();
}
};
From the jQuery manual:
The .fadeOut() method animates the opacity of the matched elements. Once the opacity reaches 0, the display style property is set to none, so the element no longer affects the layout of the page.
If you set the display property back to inline or block after the fadeOut() is finished, the elements will remain clickable. You can do this using the complete paramater of fadeOut(). Something like this should work:
$(".link").fadeOut('slow', function(){
$(".link").css({"display":"inline"});
});
When .fadeOut is complet element display is none and not clickable. You should change element display property and hide it by visibility property. I would do that this way:
$(".link").fadeOut('slow', function(){
//animation complete callback
$(this).show().css('visibility', 'hidden');
});
I am using jQuery load() to check if an image that I'm replacing the src on is loaded. Sometimes it appears to get stuck or hang though. I have a jsFiddle link below to check out. To make the loading graphic get stuck on the page click one of the buttons twice.
http://jsfiddle.net/dmcgrew/LLMs8/3/
This "almost" replicates a problem on a site I'm currently building, but I think the issues are related. On the site I'm building this "hanging" only happens when I do the following steps:
Click Image 3 button
Click Hide button
Click Image 3 button again
The loading graphic is now stuck on the page.
Here is my JS...
$("button").not("off").bind("click", function(){
var imgPath = $(this).attr("data-image"); //grab image path from data attr
console.log(imgPath);
$(".loading").show(); //show loading gif
$("img.the_image").hide(); //hide the img
$("img.the_image").attr("src","http://farm7.staticflickr.com/"+imgPath).load(function() {
$(".loading").hide(); //hide loading gif
$("img.the_image").show(); //show the newly loaded img
});
});
$("button.off").bind("click", function(){
$("img").hide();
});
Is load() the best way to check if an image has been loaded? Is there a better way that I should replace the image and check if its loaded (maybe AJAX?).
You have two issues: First, your code attaches the load handler multiple times, which is causing funky behavior. Second, your code doesn't handle multiple clicks on the same element in a row. Try this:
http://jsfiddle.net/E3Avx/
$("button").not("off").bind("click", function () {
var imgPath = $(this).attr("data-image"); //grab image path from data attr
var newImgPath = 'http://farm7.staticflickr.com/' + imgPath;
if ($('img.the_image').attr('src') != newImgPath) {
$(".loading").show(); //show loading gif
$("img.the_image").hide(); //hide the img
$("img.the_image").attr("src", newImgPath);
}
});
$("img.the_image").load(function () {
console.log('load handler');
$(".loading").hide(); //hide loading gif
$("img.the_image").show(); //show the newly loaded img
});
$("button.off").bind("click", function () {
$("img").hide();
});
This problem seems to be related to you trying to load() the same image twice, as the src doesn't actually change I think it's causing problems.
The easiest way to deal with it is just to check if the current src matches the src that has been selected, eg:
if($('img.the_image').attr('src') != 'http://farm7.staticflickr.com/' + imgPath) { }
http://jsfiddle.net/LLMs8/7/
I have an image being edited and reloaded with a new query string appened to make sure it doenst use cached copy . As Image already has an image source and when I change image user still sees old image and if image is big he might think that it didnt do processing . Is there any way to show user that image is being loaded ?
Replace the initial image with a loading message:
function SomeImageChangeFunction()
{
$('ProcessingImage').parent().text('loading...');
$('ProcessingImage').attr('href', 'newURL');
}
The loading could be an animated gif or whatever you wanted.
Do you have jquery?
On change of the new image, hide it and show a div containing a loading image/text in the same position. Then, in the image onload, re-show the image and hide the div.
<img id="loadingimg" src="loading.gif"><img id="theimage" src="whatever-1.jpg" onload="imgloaded();" onchange="imgchanged();">
function imgchanged() {
$('#theimage').css('display', 'none');
$('#loadingimg').css('display', 'inline');
}
function imgloaded() {
$('#loadingimg').css('display', 'none');
$('#theimage').css('display', 'inline');
}