jquery .get download content fully before rendering - ajax

Is there a way to render content only after it's fully downloaded using AJAX/get/load with jQuery?
As it stands currently, the loader shows while the 'html' is being downloaded, but once that's done it starts rendering. There's lots of images in the html so they start loading independently after the render.
Is this good design practice? In my opinion once the loader disappears, everything should render 100%, but of course this will increase load time.
Can I achieve this without any 'hacks'?
$(document).ready(function() {
$('#clicks').click(function(){
$('#portfolio').append("<div id='loader'><img src='images/loader.gif'/></div>");
$.get("moreProjects.html", function(datas){
$('#portfolio').append(datas);
}, 'html').complete(function() {
$('#loader').hide();
});
return false;
});
});

You could always store the data returned in a variable and then append it in the complete function:
var returnedData;
$('#clicks').click(function(){
$('#portfolio').append("<div id='loader'><img src='images/loader.gif'/></div>");
$.get("moreProjects.html", function(datas){
returnedData = datas;
}, 'html').complete(function() {
$('#portfolio').append(returnedData);
$('#loader').hide();
});
return false;
});
Another option would be to use a hidden div container to load the content and then show on complete:
$('#clicks').click(function(){
$('#portfolio').append("<div id='loader'><img src='images/loader.gif'/></div>");
$('#portfolio').append("<div id='content' style='display:none'></div>");
$.get("moreProjects.html", function(datas){
$('#portfolio #content').append(datas);
}, 'html').complete(function() {
$('#portfolio #content').show();
$('#loader').hide();
});
return false;
});

Get the HTML, place it on your page or preload with JS, if placing it on your page the images can not be hidden if they are to be loaded, but they can be placed of screen.
When the images are loaded, move the HTML to your portfolio element.
The code below is just an example, not tested, and the load function will probably fire on the first image that is loaded, I think ?
If so you will have to count the images, place a load function on each image, and then show the HTML when all images have loaded, or you could try just attaching the load function to the last image in your HTML, but there is no guarantee that the last image in the markup is also the last to load, but it often is.
There could also be a problem with load if images are cached by the browser, if so you need to find another solution, or turn of caching in $.ajax!
$('#clicks').on('click', function(){
$('#portfolio').append("<div id='loader'><img src='images/loader.gif'/></div>");
var jqxhr = $.ajax({
type:'GET',
url: 'moreProjects.html',
datatype: 'html',
done: function(datas) {
$('<div id="somediv"></div>').append(datas)
.css({position: 'fixed', left: -5000})
.appendTo('body');
}
});
jqxhr.always(function() {
$('img', '#somediv').on('load', function() {
$('#loader').remove();
$('#portfolio').append($('#somediv').contents());
});
});
return false;
});

Check this link, the last post: Wait untill all images are loaded
In my opinion what you have to do is to save the html in a variable,
then filter out all the img tags and pass it to the _loadimages function
in the post i give you setting the complete callback.
Something like this:
var $retData = $(datas);
var $imgs = $retData.find('img');
_loadimages($imgs,function(){
$('#portfolio #content').append($retData);
});

Related

Ajax URL # isn't updating

I have a little problem with my script here. For some reason, it doesn't enable the #-tags and I don't know why. I created this javascript using the help of this tutorial. (The loading of the pages works well with no problems at all.)
Could someone please look it over and tell me why it doesn't work?
var default_content="";
$(document).ready(function(){ //executed after the page has loaded
checkURL(); //check if the URL has a reference to a page and load it
$('ul li a').click(function (e){ //traverse through all our navigation links..
checkURL(this.hash); //.. and assign them a new onclick event, using their own hash as a parameter (#page1 for example)
});
setInterval("checkURL()",250); //check for a change in the URL every 250 ms to detect if the history buttons have been used
});
var lasturl=""; //here we store the current URL hash
function checkURL(hash)
{
if(!hash) hash=window.location.hash; //if no parameter is provided, use the hash value from the current address
if(hash != lasturl) // if the hash value has changed
{
lasturl=hash; //update the current hash
loadPage(hash); // and load the new page
}
}
function loadPage(url) //the function that loads pages via AJAX
{
// Instead of stripping off #page, only
// strip off the # to use the rest of the URL
url=url.replace('#','');
$('#loading').css('visibility','visible'); //show the rotating gif animation
$.ajax({
type: "POST",
url: "load_page.php",
data: 'page='+url,
dataType: "html",
success: function(msg){
if(parseInt(msg)!=0) //if no errors
{
$('#content').html(msg); //load the returned html into pageContet
} $('#loading').css('visibility','hidden');//and hide the rotating gif
}
});
}
You can simplify this immensely by adding a function to listen to the hashchange event, like this:
$(window).on("hashchange", function() {
loadPage(window.location.hash);
});
This way you don't need to deal with timers or overriding click events on anchors.
You also don't need to keep track of lasthash since the hashchange even will only fire when the hash changes.

Loading images with ajax (in rails) [duplicate]

I want to load external images on my page asynchronously using jQuery and I have tried the following:
$.ajax({
url: "http://somedomain.com/image.jpg",
timeout:5000,
success: function() {
},
error: function(r,x) {
}
});
But it always returns error, is it even possible to load image like this?
I tried to use .load method and it works but I have no idea how I can set timeout if the image is not available (404). How can I do this?
No need for ajax. You can create a new image element, set its source attribute and place it somewhere in the document once it has finished loading:
var img = $("<img />").attr('src', 'http://somedomain.com/image.jpg')
.on('load', function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
alert('broken image!');
} else {
$("#something").append(img);
}
});
IF YOU REALLY NEED TO USE AJAX...
I came accross usecases where the onload handlers were not the right choice. In my case when printing via javascript. So there are actually two options to use AJAX style for this:
Solution 1
Use Base64 image data and a REST image service. If you have your own webservice, you can add a JSP/PHP REST script that offers images in Base64 encoding. Now how is that useful? I came across a cool new syntax for image encoding:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE..."/>
So you can load the Image Base64 data using Ajax and then on completion you build the Base64 data string to the image! Great fun :). I recommend to use this site http://www.freeformatter.com/base64-encoder.html for image encoding.
$.ajax({
url : 'BASE64_IMAGE_REST_URL',
processData : false,
}).always(function(b64data){
$("#IMAGE_ID").attr("src", "data:image/png;base64,"+b64data);
});
Solution2:
Trick the browser to use its cache. This gives you a nice fadeIn() when the resource is in the browsers cache:
var url = 'IMAGE_URL';
$.ajax({
url : url,
cache: true,
processData : false,
}).always(function(){
$("#IMAGE_ID").attr("src", url).fadeIn();
});
However, both methods have its drawbacks: The first one only works on modern browsers. The second one has performance glitches and relies on assumption how the cache will be used.
cheers,
will
Using jQuery you may simply change the "src" attribute to "data-src". The image won't be loaded. But the location is stored with the tag. Which I like.
<img class="loadlater" data-src="path/to/image.ext"/>
A Simple piece of jQuery copies data-src to src, which will start loading the image when you need it. In my case when the page has finished loading.
$(document).ready(function(){
$(".loadlater").each(function(index, element){
$(element).attr("src", $(element).attr("data-src"));
});
});
I bet the jQuery code could be abbreviated, but it is understandable this way.
$(<img />).attr('src','http://somedomain.com/image.jpg');
Should be better than ajax because if its a gallery and you are looping through a list of pics, if the image is already in cache, it wont send another request to server. It will request in the case of jQuery/ajax and return a HTTP 304 (Not modified) and then use original image from cache if its already there. The above method reduces an empty request to server after the first loop of images in the gallery.
You can use a Deferred objects for ASYNC loading.
function load_img_async(source) {
return $.Deferred (function (task) {
var image = new Image();
image.onload = function () {task.resolve(image);}
image.onerror = function () {task.reject();}
image.src=source;
}).promise();
}
$.when(load_img_async(IMAGE_URL)).done(function (image) {
$(#id).empty().append(image);
});
Please pay attention: image.onload must be before image.src to prevent problems with cache.
If you just want to set the source of the image you can use this.
$("img").attr('src','http://somedomain.com/image.jpg');
This works too ..
var image = new Image();
image.src = 'image url';
image.onload = function(e){
// functionalities on load
}
$("#img-container").append(image);
AFAIK you would have to do a .load() function here as apposed to the .ajax(), but you could use jQuery setTimeout to keep it live (ish)
<script>
$(document).ready(function() {
$.ajaxSetup({
cache: false
});
$("#placeholder").load("PATH TO IMAGE");
var refreshId = setInterval(function() {
$("#placeholder").load("PATH TO IMAGE");
}, 500);
});
</script>
use .load to load your image. to test if you get an error ( let's say 404 ) you can do the following:
$("#img_id").error(function(){
//$(this).hide();
//alert("img not loaded");
//some action you whant here
});
careful - .error() event will not trigger when the src attribute is empty for an image.
//Puedes optar por esta soluciĆ³n:
var img = document.createElement('img');
img.setAttribute('src', element.source)
img.addEventListener('load', function(){
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
alert('broken image!');
} else {
$("#imagenesHub").append(img);
}
});
$(function () {
if ($('#hdnFromGLMS')[0].value == 'MB9262') {
$('.clr').append('<img src="~/Images/CDAB_london.jpg">');
}
else
{
$('.clr').css("display", "none");
$('#imgIreland').css("display", "block");
$('.clrIrland').append('<img src="~/Images/Ireland-v1.jpg">');
}
});

jQuery Masonry and Ajax-fetching to Append Items Causing Image Overlap

Another image overlap issue here using Masonry and Ajax to append items in Wordpress. The first time more items are appended, the images overlap. However, when the page is reloaded, the images no longer overlap. I realize after doing some research this has to do with calculating the height of the images.
From the help page on the Masonry website, it is suggested to use the getimagesize function in order to specify the width and height of the images.
However, this is where I am stuck. Because of my limited knowledge of PHP, I have no idea how to utilize this function or where to place it in my code, so I'm looking for a little direction here. Can anyone help me figure out how to integrate the getimagesize function into my code?
Here is the masonry code:
$(document).ready(function(){
var $container = $('#loops_wrapper');
$container.imagesLoaded( function(){
$container.masonry({
itemSelector : '.post_box',
columnWidth: 302
});
});
});
This is the ajax fetching code:
$('.load_more_cont a').live('click', function(e) {
e.preventDefault();
$(this).addClass('loading').text('Loading...');
$.ajax({
type: "GET",
url: $(this).attr('href') + '#loops_wrapper',
dataType: "html",
success: function(out) {
result = $(out).find('.post_box');
nextlink = $(out).find('.load_more_cont a').attr('href');
$('#loops_wrapper').append(result).masonry('appended', result);
$('.load_more_cont a').removeClass('loading').text('Load more posts');
if (nextlink != undefined) {
$('.load_more_cont a').attr('href', nextlink);
} else {
$('.load_more_cont').remove();
}
}
});
});
You could try to implement David DeSandro's timer approach here for appending images...
"As recommended in the primer, the best solution to handle images is to have the size attributes defined in the img tag, especially when using Infinite Scroll. This is the solution employed in the example below.
Of course, this is not a viable option in some CMSs, most notably Tumblr. In this situation, Masonry needs to be called after the newly-appended images are fully loaded. This is done by delaying the Masonry callback."
function( newElements ) {
setTimeout(function() {
$wall.masonry({ appendedContent: $(newElements) });
}, 1000);
}
EDIT: If you can't implement the common delay idea for appending items with infinite scroll, you could try reloading after appending new items so instead of
$('#loops_wrapper').append(result).masonry('appended', result);
do it like that
$("#loops_wrapper").append(result).masonry('reload');

How to use AJAX as an alternative to iframe

I'm trying to put together a snappy webapp, utilizing JS, Prototype and AJAX for all my requests once the GUI has loaded. The app is simple: A set of links and a container element to display whatever the links point to, just like an iframe. Here's an approximate HTML snippet:
<a class="ajax" href="/somearticle.html">An article</a>
<a class="ajax" href="/anotherarticle.html">Another article</a>
<a class="ajax" href="/someform.html">Some form</a>
<div id="ajax-container"></div>
The JS that accompanies the above (sorry it's a bit lengthy) looks like this:
document.observe('dom:loaded', function(event) {
ajaxifyLinks(document.documentElement);
ajaxifyForms(document.documentElement);
});
function ajaxifyLinks(container) {
container.select('a.ajax').each(function(link) {
link.observe('click', function(event) {
event.stop();
new Ajax.Updater($('ajax-container'), link.href, {
method: 'get',
onSuccess: function(transport) {
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
function ajaxifyForms(container) {
console.debug('Notice me');
container.select('form.ajax').each(function(form) {
form.observe('submit', function(event) {
event.stop();
form.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
When clicking a link, the response is displayed in the container. I'm not using an iframe for the container here, because I want whatever elements are on the page to be able to communicate with each other through JS at some point. Now, there is one big problem and one curious phenomenon:
Problem: If a form is returned and displayed in the container, the JS above tries to apply the same behavior to the form, so that whatever response is received after submitting is displayed in the container. This fails, as the submit event is never caught. Why? Note that all returned form elements have the class="ajax" attribute.
Phenomenon: Notice the console.debug() statement in ajaxifyForms(). I expect it to output to the console once after page load and then every time the container is updated with a form. The truth is that the number of outputs to the console seems to double for each time you click a link pointing to a form. Why?
I found another way to achieve what I wanted. In fact, the code for doing so is smaller and is less error prone. Instead of trying to make sure each link and form element on the page is observed at any given time, I utilize event bubbling and listen only to the document itself. Examining each event that bubbles up to it, I can determine whether it is subject for an AJAX request or not. Here's the new JS:
document.observe('submit', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
event.target.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
}
});
}
});
document.observe('click', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
new Ajax.Updater($('ajax-container'), event.target.href, {
method: 'get'
});
}
});
Works like a charm :)

Ajaxed div hide and show hides only after div load

I have this issue. I'm working on a jquery ajaxed site. I have the main content div in the middle and on top the navigation. I need to AJAX the content, because I have flash backgound so that the flash video won't start from beginning after every page load. The only way I was able to do this was with this sort of code:
$(document).ready(function(){
$.ajaxSetup ({
cache: false
});
//For loading
var ajax_load = "<img src='img/load.gif' alt='loading...' /><p>";
// Var
var loadPage1 = "page1.html";
// Load page
$("#page1").click(function(){
$("#content").hide(2000);
$("#content").html(ajax_load).load(loadPage1);
$("#content").show(2000);
});
All other ways to get the div didn't work because there was issues on getting plugins etc. working in the ajaxed div (content).
So... everythig is working fine - but, the div loads it's content from page1.html and shows it and only after this does it hide it and show it. So it loads the page and then does the effects I want to.
Do I need to queue this some how or what's the proper jquery way? I tried delay, stop etc.. but can't seem to solve this out. It's propably very simple.
Thanks.
Show the element in the load callback handler.
i.e:
$("#page1").click(function(){
$("#content").hide();
$("#content").html(ajax_load).load(loadPage1, function(){
$("#content").show(2000)
});
});
.load() takes 2 arguments, the URI and a callback to fire after load.
API is found here: http://api.jquery.com/load/
function() {
$("#content").hide(2000);
$("#content").html(ajax_load).load(loadPage1, function() {
$("#content").show(2000);
});
}

Resources