What I want is to show loading animation while image is loading.
Basically I have large system and all code bits are injected using ngInclude.
So if I have to construct the bit I'm interested in it would look like:
<div ng-controller="MyTabCtrl">
<div id="preview-panel" waiting-animation="img/loading.gif" waiting-property="isLoadingPreview">
<ng-include src="htmlInclude" />
</div>
</div>
And htmlInclude html for example would just be a div with img.
The htmlInclude changes when I click different posts I have.
So far I loaded low quality images so loading wasn't an issue - it was quick. Now I want to load high-quality images and their loading takes a while.
So all my included html (text, buttons etc) is loaded, and the image gets replaced after a few moments.
I tried to fiddle with different events I found in other questions, but they don't seem to be working for me. Either the loading doesn't appear at all, or it appears and stays there even after loading is complete.
Some stuff I tried is:
$scope.$on('$includeContentLoaded', function () {
$scope.isLoadingPreview = false ;
});
or
$scope.$on('$viewContentLoaded', function() {
$scope.isLoadingPreview = false ;
});
How can I make this happen?
Thanks!
Related
I have a Bootstrap carousel and an invisible div with a loading gif that I want to show while a big image is loading. I'd like to show this div only when I change the active image on the carousel and this image is still loading.
I've already got the HTML and CSS working, I just need an help with jQuery.
I fetch the images links from Imgur and then build the carousel-items that I need with jQuery and append them on the carousel container.
I then attached to the carousel event slide.bs.carousel a function that shows me the loader. and this works
BUT BUT BUT
I'm worried that the loader will show for few milliseconds even if the image is already loaded/cached. How can I prevent this? How can I know if the image that is becoming active is already loaded? Do I really need to worry about this or I just leave it like this?).
I then want to hide the loader when the active image is ready, and I've done this:
$('.carousel-item img').each(function(){
$(this).on('load', function(){
$("#loader_container").css("visibility","hidden");
});
});
But it doesn't work. Seems like this load even keeps firing until
all the images of the whole carousel are loaded, and also somehow
the loader doesn't hide in the end, and this is the issue n.2.
Probably I'm approaching this wrong.
Is issue n.1 really a problem? And how can I solve issue n.2?
Thank you!
EDIT 1:
I tried to do this but still doesn't work. When I slide to the next slide I see that the image is already loaded, then the loader appears and doesn't go away anymore.
$(".carousel-item img").each(function(index){
$(this).on('slid.bs.carousel', function(){
$("#loader_container").css("visibility","visible");
});
$(this).on('load', function(){
$("#loader_container").css("visibility","hidden");
});
$(this).attr("src",links[index]);
});
EDIT 2:
Also, it seems like the browser try to load all the images as soon as possible, even the ones that are not displayed/are not active items.
I'd like to load the images only if the user goes to that slide and makes the item active.
EDIT 3:
I've found a library name jquery.unveil.js that seems like it does exactly what I need and is super easy to use... but somehow it doesn't work.
Maybe AngularJS can help me? Anyone know how can I modify my code to do this with angular? Like using ngui-in-view?
$('.carousel-item img').each(function(){
$(this).on('slid.bs.carousel', function(){
$("#loader_container").css("display","none");
});
});
You can use the slide.bs.carousel and slid.bs.carousel instead
Solved with lazy loader, here the code:
$(".carousel.lazy").on("slide.bs.carousel", function(ev) {
var lazy;
lazy = $(ev.relatedTarget).find("img[data-src]");
if(lazy.length > 0){
$("#loader_container").css("visibility","visible");
$(".carousel-item img").on("load",function(){
$("#loader_container").css("visibility","hidden");
});
lazy.attr("src", lazy.data('src'));
lazy.removeAttr("data-src");
}});
I needed that if(lazy.length > 0) because once I did a full round of the carousel and all the images where loaded, somehow the loader would show up and never go away. I tried with if(img.complete) but it didn't work so I used that technique.
I have a lot of images on my site. To load them and avoid the ugly top to bottom image loading effect I am currently setting the body to display none and then
$(window).load(function(){
$("body").fadeIn(2000);
});
This seems to work for the homepage. But when I fetch pages, inside ng-view using angular, which also have images in them, the images don't seem to be loaded already and I seem to be getting the ugly top to bottom image loading effect. How do I avoid this?
Try something like this:
$.ajax("url/to/page", {
success: function(data) {
$temp = $("<div/>").html(data);
$temp.on("load", function() {
// Assume body is already faded out for loading
// Add HTML to the body
$("body").html($temp.html());
// Show content
$("body").fadeIn(2000);
});
}
});
This will load the returned HTML into a temporary div and wait for the assets linked within it to load before adding it to the <body>.
I have a script that draws a QR code with an Image on canvas .
It is using a plugin, and normally - everything works great - but not in chrome .
HTML
<img id="#o99-qrs-img-buffer" src="http://localhost/www.beta.com/logo1.png"
style="display:none">
<div id="o99_qrcode" class="code"></div>
JS script is as follows ( ignore the PHP part - it is working great ):
jQuery(document).ready(function() {
var options = {
render: "'.$qr_render.'", // Canvas, Div ,Image
size: '.$qr_size.',
radius: '. ($qr_corner_r * 0.1) .',
.... tons of other options....
// Image Label -> the problem is here
image: jQuery("#o99-qrs-img-buffer")[0], // taken as example
};
jQuery("#o99_qrcode").empty().qrcode(options);
});
Like said , it is working great on all tested browsers - except in chrome - where it works sporadically . more fail than work. ( 90% - 10% )
Observing a bit , I have noticed two things :
1 - The jQuery(document).ready(function() is not really working as form my understaning of what it should be doing ( and my understanding might be wrong of course ) because the script is firing and displaying the image BEFORE the document is finished to load.
2 - I assume by observing that the script fails becuase ( related to 1 ) - the image is actually nowhere to be found when the script fires - so it has nowhere to take the source from ..
At the beginning I blamed the "display:none" and changed the div to style="width:100px;height:100px;" with jQuery("#o99-qrs-img-buffer").hide(); after the script firing .
No good .
then I tried to change the jQuery(document).ready to load and onLoad.
Still no go .
Reading a LOT of related question here on SE - I found 3 with the hint of my problem : HERE, HERE and HERE.
So I tried to implement the first one , which looked like a solid solution :
var imagetest = new Image();
imagetest.onload = function() {
// wrap the firing in a function only when the image loads
jQuery("#o99_qrcode").empty().qrcode(options);
};
imagetest.src: jQuery("#o99-qrs-img-buffer")[0]; // taken as example
But chrome seems a lot more persistent than me ...
Either I am implementing the solution totally wrong ( very possible ) or I am so unfamiliar with JS that I do not understand the problem at the first place .
The fact that the script working with a plugin seems irrelevant because the plugin works great on all browsers (and sometimes chrome too ..)
At any rate , I need help In finding a way to load the Image and be sure it is loaded before the script fires ...
$(document).ready() is fired, when DOM is fully loaded. In practice this happens at the time when parser have just met </body>. This doesn't mean that the page would be ready/fully loaded, content of external resources like iframes or img might still be loading. $(document).ready() only guarantees you can refer all elements within the HTML.
If you want to wait untill the whole page and all its resources have been completely loaded, you need to use $(window).load().
Also looks like document never triggers load event, $(document).onLoad() doesn't exist.
I'm a creating a loading screen for website I am making. The website loads many images, scripts, etc. The HTML and CSS part is great, but I need a way to guarantee that the "loading..." image will be loaded before anything else.
I'm using jQuery, and everything is initiated within $(function () { ... });. I imagine that the code for this would need to be called before/outside that block, and the code to remove the loading screen will be called at the very end of that block. Currently, the loading image is set as a DIV background, which is the way I prefer it. However, if it's completely necessary, I will settle for an IMG tag.
Update: (solution)
I was able to answer my own question by using a combination of Robin and Vlad's responses. Both were very good, and excellent answers, however the problem is that they were aimed to load an image before another image, rather than load an image before anything else. (CSS, JS, etc...)
Here's the dirty version of what I came up with:
var files = [new Image(), document.createElement('link'), document.createElement('script')];
files[0].setAttribute('src', 'images/loading.gif');
files[1].setAttribute('rel', 'stylesheet');
files[1].setAttribute('type', 'text/css');
files[1].setAttribute('href', 'test.css');
files[2].setAttribute('type', 'text/javascript');
files[2].setAttribute('src', 'js/jquery-1.5.1.min.js');
window.onload = function (e) {
document.getElementsByTagName('head')[0].appendChild(files[1]);
document.getElementsByTagName('head')[0].appendChild(files[2]);
}
Taking a look at the load sequence on the network tab of Chrome's developer console shows that 'loading.gif' is loaded first, then 4 dummy images, then 'test.css', and then 'jquery.1.5.1.min.js'. The CSS and JS files don't begin to load, until they've been inserted into the head tag. This is exactly what I want.
I'm predicting that I may begin to have some problems, however, when I begin to load a list of files. Chrome reports that sometimes the JS file is loaded first, but the majority of the time the CSS file is loaded first. This isn't a problem, except when I begin to add files to load, I will need to ensure that jQuery is loaded before a script file that uses jQuery.
If anyone has a solution for this, or a way to detect when the CSS/JS files are finished loading, using this method, then please comment. Though, I'm not sure that it's going to be a problem yet. I may need to ask a new question in the future about this, if I start to run into problems.
Thank you to every who has helped with this issue.
Update: (glitch fix)
I ended up running into a lot of problem with this method, because the script files were being loaded asynchronously. If I would clear the browser cache, and then load the page, it would finish loading my jquery dependent files first. Then if I refreshed the page, it would work, because jquery was loaded from cache. I solved this by setting up an array of files to load, then putting the load script into a function. Then I would step through each array item using this code:
element.onload = function() {
++i; _step();
}
element.onreadystatechange = function() {
if (("loaded" === element.readyState || "complete" === element.readyState)) { ++i; _step(); }
}
You can reuse resource prealoding browser support.
I'm not sure it works across all browsers but in my case this approach helps me to load images first. Also it allows to define concrete images so UI specific could be skipped
First define in header what resource you want to preload and define resource priority
<link rel="preload" href="link-to-image" as="image">
or
<link rel="preload" href="link-to-image">
Second line allow to increase loading priority across all object types (scripts / images / styles). First line - only through images.
Then define in body link to image as usual:
<img src="link-to-image" alt="">
Here is my working example
https://jsfiddle.net/vadimb/05scfL58/
As long as the "loading..." image is positioned before any other html elements, it should load first. This of course depends on the size of the image. You could put the loading div right after the tag and position it using 'position:absolute'.
Regarding the code to remove the loading screen, one method is to do the following.
Put all the images, scripts that need to be loaded in a hidden div (display: none)
Set up a variable that will hold the total of the images / scripts to be loaded
Set up a counter variable
Attach to each image / script the "onload" event
Everytime the "onload" event is triggered it will call a function that will increment the counter variable and check if the value of the counter equals the value of the total variable
If all resources have been loaded, fire a custom event that will show the div with the images, and hide the div with the loading screen.
The code below isn't tested so it might not work. Hope it helps
var totalImages = 0;
var loadCounter = 0;
function incrementLoadCounter() {
loadCounter++;
if(loadCounter === totalImages) {
$(document).trigger('everythingLoaded');
}
}
function hideLoadingScreen() {
$('#loadingScreen').hide();
$('#divWithImages').show();
}
$(document).ready(function(e) {
$('#loadingScreen').bind('everythingLoaded', function(e) {
hideLoadingScreen();
});
var imagesToLoad = $('img.toLoad');
totalImages = imagesToLoad.length;
$.each(imagesToLoad, function(i, item) {
$(item).load(function(e) {
incrementLoadCounter();
})
});
})
I'm not sure if it's possible to enforce.
If it is, try adding this in the head-tag:
<script type="text/javascript">
if(document.images)
(new Image()).src="http://www.image.com/example.png";
</script>
In theory that may load and cache that image before anything else.
I think if you place the IMG tag at the top of your html body it will be loaded first. If you do not want to move your div just use a copy of the image tag. Once the images is loaded it will be shown in every image tag which shows the same picture.
Or you could use spin.js as loading image. It display this "loading cycle image" via javascript.
Check it out under:
http://fgnass.github.com/spin.js/
Hello everyone I got trapped when Im using jquery loading some content into my page.
The code is like this:
$("#holder").fadeout();
$("#holder").load("test.html", callbackfn);
function callbackfn(){
$("#holder").fadein();
}
test.html
<div style="background-image:url(1.jpg);">test</div>
That's the main idea, and actually it works quiet fine except that #holder is faded in before pictures are fully loaded.
How can I make sure everything in test.html is fully loaded before #holder is displayed?
This would be a bit tricky, if you have many images. My best guess, since you didn't provide test.html, is this.
$("#holder").load("test.html", cbLoaded);
function cbLoaded(){
var onLoadCount = $("img","#holder").length;
var count = 0;
$("img","#holder").bind("load",function(){
count++;
if( count === onLoadCount ){
//Everything loaded!
}
});
};
This will work with >=1 images, if you have one image just use the bind("load") and forget the counting business.
Images are loaded in their own request. So even though you are loading the image via ajax, once they are placed in the DOM, they perform their own request to fetch the image. There is an onload event you have access to on the IMG. So you'll need to know how many images you are expecting and then somehow track which ones are complete, then perform your fadein.