Well I am unable to lazy load images for some reason. Here is the waterfall view of the tested site
Apparently I am using two lazy load scripts with lazy load script 1 which works but kills the lightbox plugin and also requires lots of tweaking using data-src and src and class="lazy-load" attributes. which I am using for non post related images.
But the main problem lies in the second script which requires Jquery but doesn't require any tweaking with the images. The script is called stalactite (via Github) which I am using like this
<script charset='utf-8' src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js' type='text/javascript' />
<script href='http://googledrive.com/host/0B2xMFcMT-eLiV1owdlBMeklGc2M' type='text/javascript' />
<script type='text/javascript'>
$( 'body').stalactite({
loader: '<img/>' // The contents of the loader. Defaults to a dataURL animated gif.
});
</script>
You can find the link of the stalactite script in the above code and here is the documentation.
I don't know why it doesn't work ! Or am I executing it wrongly.
A solution to the problem will be very helpful. Many thanks in advance.
If you are tired of trying to use lazy load libraries and haven't managed to make all of it work, I can suggest you to create lazy load script on your own, or you can take a look at this code below.
By only using jQuery and without needing any other library, you can use this script to achieve the lazy load (I modified the codes from the original one that I used at work):
var doLazyLoad = true;
var lazyLoadCounter = 0;
var lazyLoadMax = 2; // Maximum number of lazy load done
// Button to indicate lazy load is loading,
// or when lazy load has reached its maximum number,
// this button load data manually.
// You can replace this with something like gif loading animation.
var $btnLoadMore = $("#btn-lazy-load-more");
// I use AJAX function to get the data on lazy load
var ajaxFn = function (enableScrollAnim = true) {
var loadingStr = 'Loading...',
idleStr = 'Load more',
ajaxUrl = 'http://www.example.com/posts',
ajaxHeaders = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'},
ajaxData = {
start: $('.posts-wrapper .post').length
};
$btnLoadMore.text(loadingStr); // You can disable the button to prevent manual loading
return $.ajax({
url: ajaxUrl,
type: 'GET',
dataType: 'json',
data: ajaxData,
headers: ajaxHeaders,
// On success AJAX, append newly loaded data to lazy load container.
// Here in my example, the GET request returns data.view i.e. the content, and data.total i.e. total number of posts
success: function (data) {
var $newLoadedPosts = $(data.view),
nlsMarginBottom;
$('.posts-wrapper').append($newLoadedPosts);
$newLoadedPosts.css('display', 'none').fadeIn();
// Animate auto scroll to newly loaded content
if (enableScrollAnim) {
$('html, body').animate({
scrollTop: $newLoadedPosts.first().offset().top
});
}
if ($('.posts-wrapper .post').length < data.total) {
$btnLoadMore.text(idleStr); // If you disable the button, enable the button again here
} else {
// Remove the button when there's no more content to load.
// Determined by data.total
$btnLoadMore.remove();
}
},
error: function () {
$btnLoadMore.text(idleStr); // If you disable the button, enable the button again here
}
});
};
// Do the lazy load here
if ($btnLoadMore.length) {
$(window).scroll(function () {
var scrollOffset = (($btnLoadMore.offset().top - $(window).height()) + $btnLoadMore.height()) + 100;
var hasReachedOffset = $(window).scrollTop() >= scrollOffset;
var isLmsBtnExist = $btnLoadMore.length;
if (hasReachedOffset && lazyLoadCounter < lazyLoadMax && doLazyLoad && isLmsBtnExist) {
doLazyLoad = false;
ajaxFn(false).always(function () {
doLazyLoad = true;
lazyLoadCounter++;
});
}
});
}
$btnLoadMore.click(ajaxFn);
And here is the GIF demo image of my working code.
If you need any further explanation, just comment this answer and I will try to help you.
Related
I´m having several problems with a progress bar in one of my developments.
I have a JavaScript function which launch serveral Ajax calls which call a PHP process, all at the same time. Those Ajax calls represent a percentage of a bigger proccess, so, for example, if I launch 100 ajax calls each one represent a 1% of the process.
The problem is that I can't force re-draw the HTTP DOM via JavaScript when an Ajax call ends.
So, the imports are these:
<link rel="stylesheet" href="(...)/javascript/themes/base/ui.core.css">
<link rel="stylesheet" href="(...)/javascript/themes/base/ui.theme.css">
<script src="(...)/js/jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>
And the important code is the next one:
Creation of progressbar (before launch Ajax calls):
$("#progressbar").progressbar({max:100, value:0});
$("#progressbar").progressbar("enable");
Every Ajax call will modify a variable when they finish. When I launch all Ajax calls I create an Observer function with JavaScript setTimeout, which looks at that variable and get the percentage:
setTimeout (function(){
(...)
var percentage = Math.round(((proccessedLines)/totalLines)*100);
$("#progressbar").progressbar("value", percentage);
(...)
}, 500);
And, finally, that $("#progressbar") is just a div HTML tag with that name.
So, the problem is that timeout. It supposed to update that progressbar value and update the DOM, it should to be redrawn but It doesn´t work as It should.
Any ideas?
I have to point one more thing: this process was working perfectly 'till 2 days ago; could be some new changes in the browsers?
The setTimeout function is just executed one time after 500ms. Maybe use the setInterval function to execute your function every 500ms or consider this snippet: https://jsfiddle.net/nicolastorre/o35teyq3/32/
// Parameters
var queryList = new Array('code', 'js', 'php');
var lenQueryList = queryList.length;
var percentage = 0;
var proceed = 0;
var totalPercentage = 100;
// Init progress bar
$("#progressbar").progressbar({max:totalPercentage, value:percentage});
$("#progressbar").progressbar("enable");
for(var i = 0; i < lenQueryList; i++) {
/*### setTimeout to make a pause (just for the demo) ###*/
setTimeout(function() {
console.log('just a pause to see slowly!');
console.log(queryList[i]);
// Wikipedia api search
$.ajax({
url: 'https://en.wikipedia.org/w/api.php?callback=?',
data: {
srsearch: queryList[i],
action: "query",
list: "search",
format: "json"
},
error: function() {
console.log('An error occured');
},
dataType: 'json',
success: function(data) {
// Get results
console.log(data);
// Update progress bar
proceed++;
percentage = Math.round((proceed/lenQueryList)*totalPercentage);
$("#progressbar").progressbar("value", percentage);
},
type: 'POST'
});
}, 500 * i); // setTimeout to make a pause (just for the demo)
/*########################################*/
}
(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')
});
Ok I will try to make it simple.
1) I have 3 links that execute an Ajax Request and update a div with some content.
The DIV
<div id="content-to-update"></div>
The 3 links that update #content-to-update
example 1
example 2
example 3
Each link update the div #content-to-update with the content just below with one parameter named CODE
The the div #content-to-update is updated with the code below.
var loading = false;
$(window).scroll(function () {
var winTop = $(window).scrollTop();
var docHeight = $(document).height();
var winHeight = $(window).height();
//if user reach bottom of the page
if (!loading && (winTop / (docHeight - winHeight)) > 0.95) {
loading = true;
//the CODE parameter is different on each call from the links that I
//talked earlier.
$.get("/items/next/?list_name=" + CODE, function(data){
//executing some javascript to display next items
}).done(function() {
loading = false;
})
}
});
});
The problem is that it seams the browser keep all different version of the updated div.
Its like the old content is not erased before the new content is added.
If I click on the first link and scroll I get the right items OK!.
Then if I click on the second link, when I scroll I get the Item twice (duplicated- it calls the code from the previous ajax call)
Then if I click on the third link, when I scroll I get the Item 3 times. (it calls the code from the 2 previous ajax call )
When I use the Chrome debugger I see that it goes first in the code that have received the parameter EXAMPLE_1 then it goes in the code that has received the parameter EXAMPLE_2 etc
But this code should has been overridden by the call of the EXAMPLE_2 link.
It is difficult to explain I don't know if someone understand what Im trying to explain but I give it a try :) and again sorry for my english.
Thanks
I'm a bit picky about POST and GET, so even though Wayne is technically correct, the fact that you are retrieving data makes your use of GET the right way of doing it.
The way around caching is either by using jQuery's ajax method and setting cache to false, like so:
$.ajax({
url: "/items/next/?list_name=" + CODE,
type: 'GET',
success: function(data) {
$('#content-to-update').html(data);
},
cache:false,
error: function(e) {
alert("Server failure! Is the server turned off?");
}
});
You can also trick the browser by adding a random string to the end of the URL, which is what I usually do. Something like this:
$.get("/items/next/?list_name=" + CODE + '&cache_buster=' + (new Date()).getTime().toString(), function(data){
//executing some javascript to display next items
}).done(function() {
loading = false;
})
If you are using .html() to set the content, the error is definitely somewhere else. Ensure that you are not appending the new content to the div, which seems like what you are doing.
Also, your functions should act independently of one another. Your current process seems to support that, but your problem seem to suggest otherwise.
Try the suggestions first and if they don't work, post more code.
Update
Try this:
var loading = false;
function executeSomeAjax(CODE){
$(window).scroll(function () {
var winTop = $(window).scrollTop();
var docHeight = $(document).height();
var winHeight = $(window).height();
//if user reach bottom of the page
if (!loading && (winTop / (docHeight - winHeight)) > 0.95) {
loading = true;
//the CODE parameter is different on each call from the links that I
//talked earlier.
$.get("/items/next/?list_name=" + CODE, function(data){
//executing some javascript to display next items
}).done(function() {
loading = false;
})
}
});
});
}
As you can see, the variable loading is now a global variable. I suspect that it was a local variable in your original function and as a result was set to false anytime the function ran.
Making it a global variable should resolve your issue.
Hope this helps.
UPDATE
Ok this is the final working code thanks to everybody for helping me out !
I think the problem was coming from low memory on my computer. The code you see below was used yesterday and was not working.
Since I rebooted the computer this morning everything works like a charm. I have 4GO of memory and working with Grails 2.2.2 and Intellij IDEA Im often with 100Mo of memory left I guess this should have a side effect. I cant see other explanations.
If That can help anyone to read this post
var loading = false;
function nextProject(){
$('.logo').html('<img src="/images/ajax-loader-transparent.gif">');
$.ajax({
type:'GET',
url: "/project/next/",
data:"list_name=" + CODE,
beforeSend:function(){
console.log("loading : " + loading)
}
}).done(function(data) {
if(data != ""){
var arrayOfObjects = eval(data);
for(var i=0; i < arrayOfObjects.length; i++){
TrackManager.newTrack(btoa(arrayOfObjects[i].base64Params));
var projectMgr = new ProjectManager(arrayOfObjects[i].id);
projectMgr.socialShare();
<sec:ifNotLoggedIn >
projectMgr.runDeny();
</sec:ifNotLoggedIn>
<sec:ifLoggedIn >
projectMgr.runGranted(arrayOfObjects[i].likeUp, arrayOfObjects[i].inPlayList );
</sec:ifLoggedIn>
INC++;
}
loading = false;
$('.logo').html('<img src="/images/soundshare_logo_32.png">');
console.log(INC + "/" + PROJECT_COUNT );
}
}).fail(function(){
console.error("Ajax error!")
});
}
$(window).scroll(function(){
var winTop = $(window).scrollTop();
var docHeight = $(document).height();
var winHeight = $(window).height();
if ((winTop / (docHeight - winHeight)) > 0.95) {
if(INC < PROJECT_COUNT){
if(!loading){
loading = true;
nextProject()
}
}
}
});
I have this script which should show the text "Loading..." while images are loading, then change the text to "loaded" when all images are loaded. I added a button to load new images to make sure that it works for dynamically loaded images as well.
This works perfectly in Chrome but in Firefox the "Loading..." text never appears. I have no idea why this would be. The page begins loading and not all images are loaded so it should create the text "Loading.." but it doesn't. Then when all images are done loading the text "Loading" appears.
I just don't get why one message would appear and the other wouldn't. Especially because there are no qualifications that have to be met before creating the "Loading..." text, it should just fire automatically.
jsfiddle Example | Full Page Example
$(document).ready(function() {
var checkComplete = function() {
if($('img').filter(function() {return $('img').prop('complete');}).length == $('img').length) {
$('.status').text('Loaded');
} else {
$('.status').text('Loading...');
}
};
$('img').on('load',function() {
checkComplete();
});
$('#button').click(function() {
$('img.a').attr('src' , 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg');
$('img.b').attr( 'src' , 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg');
checkComplete();
});
checkComplete();
});
You have several issues in the code.
First off, the checkComplete() function is not written correctly. It should be this:
var checkComplete = function() {
var imgs = $('img');
if(imgs.filter(function() {return this.complete;}).length == imgs.length) {
$('.status').text('Loaded');
} else {
$('.status').text('Loading...');
}
};
The main fix here is that the filter callback needs to refer to this.complete, not to $('img').prop('complete') because you are trying to filter a single item at a time.
Second off, you are relying on both .complete and .load working correctly AFTER you've changed the .src value. This is explicitly one of the cases where they do not work properly in all browsers.
The bulletproof way to work around this is to create a new image object for the new images, set the onload handler before you set the .src value and when both onload handlers have fired, you will know that both new images are loaded and you can replace the once you have in the DOM with the new ones.
Here is a version that works in FF:
$(document).ready(function() {
$('#button').click(function() {
var imgA = new Image();
var imgB = new Image();
imgA.className = "a";
imgB.className = "b";
var loaded = 0;
imgA.onload = imgB.onload = function() {
++loaded;
if (loaded == 2) {
$("img.a").replaceWith(imgA);
$("img.b").replaceWith(imgB);
$('.status').text('Loaded');
}
}
// the part with adding now to the end of the URL here is just for testing purposes to break the cache
// remove that part for deployment
var now = new Date().getTime();
imgA.src = 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg?' + now;
imgB.src = 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg?' + now;
$('.status').text('Loading...');
});
});
Working demo: http://jsfiddle.net/jfriend00/yy7GX/
If you want to preserve the original objects, you can use the newly created objects only for preloading the new images and then change .src after they've been preloaded like this:
$(document).ready(function() {
$('#button').click(function() {
var imgA = new Image();
var imgB = new Image();
var loaded = 0;
imgA.onload = imgB.onload = function() {
++loaded;
if (loaded == 2) {
$("img.a")[0].src = imgA.src;
$("img.b")[0].src = imgB.src;
$('.status').text('Loaded');
}
}
// the part with adding now to the end of the URL here is just for testing purposes to break the cache
// remove that part for deployment
var now = new Date().getTime();
imgA.src = 'http://farm9.staticflickr.com/8545/8675107979_ee12611e6e_o.jpg?' + now;
imgB.src = 'http://farm9.staticflickr.com/8382/8677371836_651f586c99_o.jpg?' + now;
$('.status').text('Loading...');
});
});
Working demo of this version: http://jsfiddle.net/jfriend00/ChSQ5/
From the jQuery API .load method
Caveats of the load event when used with images
A common challenge developers attempt to solve using the `.load()` shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
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>