How to show processing animation / spinner during ajax request? - javascript

I want a basic spinner or processing animation while my AJAX POST is processing. I'm using JQuery and Python. I looked at the documentation but can't figure out exactly where to put the ajaxStart and ajaxStop functions.
Here is my js:
<script type="text/javascript">
$(function() {
$('.error').hide();
$("#checkin-button").click(function() {
var mid = $("input#mid").val();
var message = $("textarea#message").val();
var facebook = $('input#facebook').is(':checked');
var name = $("input#name").val();
var bgg_id = $("input#bgg-id").val();
var thumbnail = $("input#thumbnail").val();
var dataString = 'mid='+mid+'&message='+message+'&facebook='+facebook+'&name='+name+'&bgg_id='+bgg_id+'&thumbnail='+thumbnail;
$.ajax({
type: "POST",
url: "/game-checkin",
data: dataString,
success: function(badges) {
$('#checkin-form').html("<div id='message'></div><div id='badges'></div>");
$('#message').html("<h2><img class=\"check-mark\" src=\"/static/images/check-mark.png\"/>You are checked in!</h2>");
$.each(badges, function(i,badge) {
$('#badges').append("<h2>New Badge!</h2><p><img class='badge' src='"+badge.image_url+"'><span class='badge-title'>"+badge.name+"</span></p>");
});
}
});
return false;
});
});
</script>

$.ajax({
type: "POST",
url: "/game-checkin",
data: dataString,
beforeSend: function () {
// ... your initialization code here (so show loader) ...
},
complete: function () {
// ... your finalization code here (hide loader) ...
},
success: function (badges) {
$('#checkin-form').html("<div id='message'></div><div id='badges'></div>");
$('#message').html("<h2><img class=\"check-mark\" src=\"/static/images/check-mark.png\"/>You are checked in!</h2>");
$.each(badges, function (i, badge) {
$('#badges').append("<h2>New Badge!</h2><p><img class='badge' src='" + badge.image_url + "'><span class='badge-title'>" + badge.name + "</span></p>");
})
}
});
http://api.jquery.com/jQuery.ajax/:
Here are the callback hooks provided by $.ajax():
beforeSend callback is invoked; it receives the jqXHR object and the settings map as parameters.
error callbacks are invoked, in the order they are registered, if the request fails. They receive the jqXHR, a string indicating the error type, and an exception object if applicable. Some built-in errors will provide a string as the exception object: "abort", "timeout", "No Transport".
dataFilter callback is invoked immediately upon successful receipt of response data. It receives the returned data and the value of dataType, and must return the (possibly altered) data to pass on to success.
success callbacks are then invoked, in the order they are registered, if the request succeeds. They receive the returned data, a string containing the success code, and the jqXHR object.
complete callbacks fire, in the order they are registered, when the request finishes, whether in failure or success. They receive the jqXHR object, as well as a string containing the success or error code.
Note the beforeSend and complete method additions to the code.
Hope that helps.

If you're using jQuery 1.5 you could do that nicely, unobtrusively and generically with a prefilter. Let's make a very simple plugin for this:
(function($) {
var animations = {};
$.ajaxPrefilter(function( options, _, jqXHR ) {
var animation = options.animation && animations[ options.animation ];
if ( animation ) {
animation.start();
jqXHR.then( animation.stop, animation.stop );
}
});
$.ajaxAnimation = function( name, object ) {
if ( object ) {
animations[ name ] = object;
}
return animations[ name ];
};
})( jQuery );
You install an animation as follows:
jQuery.ajaxAnimation( "spinner" , {
start: function() {
// code that starts the animation
}
stop: function() {
// code that stops the animation
}
} );
then, you specify the animation in your ajax options:
jQuery.ajax({
type: "POST",
url: "/game-checkin",
data: dataString,
animation: "spinner",
success: function() {
// your success code here
}
});
and the prefilter will ensure the "spinner" animation is started and stopped when needed.
Of course, that way, you can have alternative animations installed and select the one you need per request. You can even set a default animation for all requests using ajaxSetup:
jQuery.ajaxSetup({
animation: "spinner"
});

The best method I have found, assuming you are populating a present but empty field is to have a .loading class defined with background-image: url('images/loading.gif') in your CSS. You can then add and remove the loading class as necessary with jQuery.

you can set global ajax loading icon handler using here #ajxLoader takes your loading icon
$( document ).ajaxStart(function() {
$("#ajxLoader").fadeIn();
});
$( document ).ajaxComplete(function() {
$("#ajxLoader").fadeOut();
});

$(function() {
$('.error').hide();
$("#checkin-button").click(function() {
var mid = $("input#mid").val();
var message = $("textarea#message").val();
var facebook = $('input#facebook').is(':checked');
var name = $("input#name").val();
var bgg_id = $("input#bgg-id").val();
var thumbnail = $("input#thumbnail").val();
var dataString = 'mid=' + mid + '&message=' + message + '&facebook=' + facebook + '&name=' + name + '&bgg_id=' + bgg_id + '&thumbnail=' + thumbnail;
$.ajax({
type : "POST",
url : "/game-checkin",
data : dataString,
beforeSend : function() {
$('#preloader').addClass('active');
},
success : function(badges) {
$('#preloader').removeClass('active');
$('#checkin-form').html("<div id='message'></div><div id='badges'></div>");
$('#message').html("<h2><img class=\"check-mark\" src=\"/static/images/check-mark.png\"/>You are checked in!</h2>");
$.each(badges, function(i, badge) {
$('#badges').append("<h2>New Badge!</h2><p><img class='badge' src='" + badge.image_url + "'><span class='badge-title'>" + badge.name + "</span></p>");
});
},
complete : function() {
$('#preloader').removeClass('active');
}
});
return false;
});
});
#preloader{
background: url(staticpreloader.gif);
}
.active {
background: url(activepreloader.gif);
}

I wrote a blog post about how to do this on a generic document level.
// prepare the form when the DOM is ready
$(document).ready(function() {
// Setup the ajax indicator
$('body').append('<div id="ajaxBusy"><p><img src="images/loading.gif"></p></div>');
$('#ajaxBusy').css({
display:"none",
margin:"0px",
paddingLeft:"0px",
paddingRight:"0px",
paddingTop:"0px",
paddingBottom:"0px",
position:"absolute",
right:"3px",
top:"3px",
width:"auto"
});
});
// Ajax activity indicator bound to ajax start/stop document events
$(document).ajaxStart(function(){
$('#ajaxBusy').show();
}).ajaxStop(function(){
$('#ajaxBusy').hide();
});

The AJAX process starts when you run the $.ajax() method, and it stops when the 'complete' callback is run. So, start your processing imagery/notification right before the $.ajax() line, and end it in the 'complete' callback.
ajaxStart and ajaxStop handlers can be added to any elements, and will be called whenever ajax requests start or stop (if there are concurrent instances, start only gets called on the first one, stop on the last to go). So, it's just a different way of doing global notification if you had, for example, a status spinner somewhere on the page that represents any and all activity.

Related

Search on keyup and document ready using Ajax

I am trying to make search function based on Ajax/Jquery.
My web app shows the data of service requests from the database. I want to make searchbar for my app as follows:
show all service request on the table initially.
If something is typed on the searchbar, it searches data and load those data to the table.
Finally if user deletes anyword from searchbar it will show all data as stated on No.1
I managed doing second and third function but I am having issues with the first one.
$(document).ready(function(){
$('#search_text').keyup(function(){
var txt = $(this).val();
if(txt != '') {
$.ajax({
url:"ajax/fetchRequests.php",
method:"post",
data:{search:txt},
dataType:"text",
success:function(data) {
$('#result').html(data);
}
});
}
else if(txt == '') {
$.get("ajax/readRequests.php", {}, function (data, status) {
$("#result").html(data);
});
}
});
});
Here is another script that i have worked on trying:
$(document).ready(function(){
var txt = $('#search_text').val();
if(txt != ''){
$.ajax({
url:"ajax/fetchRequests.php",
method:"post",
data:{search:txt},
dataType:"text",
success:function(data) {
$('#result').html(data);
}
});
}
else if(txt == '') {
$.get("ajax/readRequests.php", {}, function (data, status) {
$("#result").html(data);
});
}
});
All my features are working except for the search functions. Any tips or critics are welcome, thank you very much in advance.
I suggest you do two things, 1) use the suggested .on() and 2) use only one ajax function to simplify things. The idea is to funnel your calls through one function so that you know if something fails, it's not because you messed up the ajax part of the script:
// Create a generic ajax function so you can easily re-use it
function fetchResults($,path,method,data,func)
{
$.ajax({
url: path,
type: method,
data: data,
success:function(response) {
func(response);
}
});
}
// Create a simple function to return your proper path
function getDefaultPath(type)
{
return 'ajax/'+type+'Requests.php';
}
$(document).ready(function(){
// When the document is ready, run the read ajax
fetchResults($, getDefaultPath('read'), 'post', false, function(response) {
$('#result').html(response);
});
// On keyup
$(this).on('keyup','#search_text',function(){
// Get the value either way
var getText = $(this).val();
// If empty, use "read" else use "fetch"
var setPath = (!getText)? 'read' : 'fetch';
// Choose method, though I think post would be better to use in both instances...
var type = (!getText)? 'post' : 'get';
// Run the keyup function, this time with dynamic arguments
fetchResults($, getDefaultPath(setPath), type, { search: getText },function(response) {
$('#result').html(response);
});
});
});
To get initial results hook onto jQuery's document ready event.
var xhr;
var searchTypingTimer;
$(document).ready(function(){
// initial load of results
fetchResults([put your own params here]);
// apply on change event
$('#search_text').on('input', function() {
clearTimeout(typingTimer);
searchTypingTimer = setTimeout(fetchResults, 300);
});
});
function fetchResults($,path,method,data,func)
{
if (xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: path,
type: method,
data: data,
success:function(response) {
func(response);
}
});
}
As Rasclatt mentions you should use jQuery's on method to catch any changes.
Secondly I'd recommend disposing of previous requests when you make new ones, since if you are sending a new one on each character change then for one word many requests will be made. They won't necessarily arrive back in the order you send them. So for example as you type 'search term', the result for 'search ter' may arrive after and replace 'search term'. (welcome to async).
Thirdly since you will send many requests in quick succession I'd only call your fetchResults function after a short time out, so for example if a user types a five character word it doesn't fire until 300ms after the last character is typed. This will prevent 4 unnecessary requests that would just be ignored but put strain on your backend.

Ajax wont call when output from another ajax

I have comment system using live ajax php, and also include for vote system on that comment
Logic: when i post new comment, system will call ajax function with method post, and display response in above of textarea for comment, that response is include vote system (a class="with_unique_id"), but when i click that vote, it wont calling ajax function (nothing happend in browser console), whereas in current comment that displaying in above of new comment, it working fine.
This is my ajax code for vote
jQuery(document).ready(function($){
$(".voteMe").click(function() {
var voteId = this.id;
var upOrDown = voteId.split('_');
$.ajax({
type: "post",
url: "<?php echo base_url('blog/likepost');?>/"+upOrDown[0],
cache: false,
data:'voteId='+upOrDown[0] + '&upOrDown=' +upOrDown[1],
success: function(response){
try{
if(response=='true'){
var newValue = parseInt($("#"+voteId+'_result').text()) + 1;
$("#"+voteId+'_result').html(newValue);
document.getElementById('likeStatus_'+upOrDown[0]).innerHTML = 'Success';
$("#likeStatus_"+upOrDown[0]).show();
setTimeout(function() { $("#likeStatus_"+upOrDown[0]).hide(); }, 5000);
}else{
$("#likeStatus_"+upOrDown[0]).show();
document.getElementById('likeStatus_'+upOrDown[0]).innerHTML = 'Liked';
setTimeout(function() { $("#likeStatus_"+upOrDown[0]).hide(); }, 5000);
}
}catch(err) {
alert(err.message);
}
},
error: function(){
alert('Error while request..');
}
});
});
});
It took me a while to read your code, but I guess this is the root cause:
if(response=='true'){
var newValue = parseInt($("#"+voteId+'_result').text()) + 1;
$("#"+voteId+'_result').html(newValue);
document.getElementById('likeStatus_'+upOrDown[0]).innerHTML = 'Success';
$("#likeStatus_"+upOrDown[0]).show();
setTimeout(function() { $("#likeStatus_"+upOrDown[0]).hide(); }, 5000);
}
This line here:
$("#"+voteId+'_result').html(newValue);
That become the link you want to click again. Right?
If that is so, then you need to re-assign the event handler.
By replacing the DOM element, you have also removed the assigned event handler
PS: You code is very hard to read. It will be nightmare for you to maintain it.
i have fixed my code with adding same ajax code function in response of current ajax with different id.
thankyou

jquery mobile autocomplete , to show message while searching

I am using jquery mobile auto complete , Please see the demo at http://jsfiddle.net/Q8dBH/11/.
So whenever user press any letter,i need to show some message like "please wait."
So i added some code like below.But its showing only 1st time or 2nd time or not showing at all some times..How to show message whenever user types something until server responds back with data.
$ul.html('<center>Searching Please Wait<br><img src="http://freegifts.in/diet/themes/images/ajax-loader.gif"></center>');
my full js is below.
$(document).on("pagecreate", ".ui-responsive-panel", function () {
$(document).on("click", "li", function () {
var text = $(this).text();
$(this).closest("ul").prev("form").find("input").val(text); });
$("#autocomplete").on("filterablebeforefilter", function (e, data) {
var $ul = $(this),
$input = $(data.input),
value = $input.val(),
html = "";
$ul.html("");
if (value && value.length >0) {
$ul.html('<center>Searching Please Wait<br><img src="http://freegifts.in/diet/themes/images/ajax-loader.gif"></center>');
//$ul.listview("refresh");
$('.ui-responsive-panel').enhanceWithin();
$.ajax({
url: "http://freegifts.in/diet/calorie.php",
dataType: "jsonp",
crossDomain: true,
data: {
q: $input.val()
}
})
.then(function (response) {
$.each(response, function (i, val) {
html += "<li data-role='collapsible' data-iconpos='right' data-shadow='false' data-corners='false'><h2>Birds</h2>" + val + "</li>";
});
$ul.html(html);
//$ul.listview("refresh");
//$ul.trigger("updatelayout");
$('.ui-responsive-panel').enhanceWithin();
});
}
});
});
Working example: http://jsfiddle.net/Gajotres/Q8dBH/12/
Now this is a complex question. If you want to show jQuery Mobile AJAX loader there's one prerequisite, AJAX call must take longer then 50 ms (jQuery Mobile dynamic content enhancement process time will not get into account). It works in jsFiddle example but it may not work in some faster environment.
You can use this code:
$.ajax({
url: "http://freegifts.in/diet/calorie.php",
dataType: "jsonp",
crossDomain: true,
beforeSend: function() {
// This callback function will trigger before data is sent
setTimeout(function(){
$.mobile.loading('show'); // This will show ajax spinner
}, 1);
},
complete: function() {
// This callback function will trigger on data sent/received complete
setTimeout(function(){
$.mobile.loading('hide'); // This will hide ajax spinner
}, 1);
$.mobile.loading('hide'); // This will hide ajax spinner
},
data: {
q: $input.val()
}
})
beforeSend callback will trigger AJAX loader and complete callback will hide it. Of course this will work only if AJAX call lasts more then 50ms. Plus setTimeout is here because jQuery Mobile AJAX loader don't work correctly when used with web-kit browsers, it is a triggering workaround.

Ajax callback appending desired url to existing url

I am trying to make a ajax call back to a Drupal 7. The problem I am encountering is that the url I want to use to make the callback is appended to the current page the user is viewing. I am not sure why this is happening and am wondering if some can point out my error for me. Here is the javascript code I am using to make the call:
(function($) {
function todaysHours(context) {
var callbackFunction = window.location.host +'/' + Drupal.settings.library_hours.callbackFunction,
content = $("#todays-hours").find(".block");
nIntervId = setInterval(checkTime, 300000);
function checkTime() {
request = $.ajax({
url: callbackFunction,
dataType: "json",
type: "GET"
});
request.done(function( result ) {
content.text(result[0].data);
})
}
}
Drupal.behaviors.library_hours = {
attach: function(context) {
todaysHours(context);
}
}
})(jQuery);
The url I expect to use is http://mydomain.com/ajax/get-time but what is actually being used in the ajax call is http://mydomain.com/current-page/mydomain.com/ajax/get-time even though the callbackfunction variable is set to mydomain.com/ajax/get-time.
Why is this happening and how do I fix it? Thanks.
Problem:
Protocol is not defined in the url
Solution:
update the following part in the code
(function($) {
function todaysHours(context) {
var callbackFunction = '//'+window.location.host +'/' + Drupal.settings.library_hours.callbackFunction,
// rest code
})(jQuery);

jQuery: How to apply a function to all elements including some which are loaded later via Ajax?

I have a simple jQuery function that resizes text areas, and I want it to apply to all text areas.
For the most part, this works great:
$(document.ready(function(){$("text_area").resizer('250px')});
However, because it is only called once when the document is ready, it fails to catch text areas that are later added onto the page using Ajax. I looked at the .live() function, which seems very close to what I'm looking. However, .live() must be bound to a specific event, whereas I just need this to fire once when they're done loading (the onLoad event doesn't work for individual elements).
The only thing I can get working is a really obtrusive inclusion of the JavaScript call directly into the Ajax. Is that the recommended way to be doing this?
Edit: Here is the rails source code for what it does for Ajax requests:
$('a[data-confirm], a[data-method], a[data-remote]').live('click.rails', function(e) {
var link = $(this);
if (!allowAction(link)) return false;
if (link.attr('data-remote') != undefined) {
handleRemote(link);
return false;
} else if (link.attr('data-method')) {
handleMethod(link);
return false;
}
});
// Submits "remote" forms and links with ajax
function handleRemote(element) {
var method, url, data,
dataType = element.attr('data-type') || ($.ajaxSettings && $.ajaxSettings.dataType);
if (element.is('form')) {
method = element.attr('method');
url = element.attr('action');
data = element.serializeArray();
// memoized value from clicked submit button
var button = element.data('ujs:submit-button');
if (button) {
data.push(button);
element.data('ujs:submit-button', null);
}
} else {
method = element.attr('data-method');
url = element.attr('href');
data = null;
}
$.ajax({
url: url, type: method || 'GET', data: data, dataType: dataType,
// stopping the "ajax:beforeSend" event will cancel the ajax request
beforeSend: function(xhr, settings) {
if (settings.dataType === undefined) {
xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
}
return fire(element, 'ajax:beforeSend', [xhr, settings]);
},
success: function(data, status, xhr) {
element.trigger('ajax:success', [data, status, xhr]);
},
complete: function(xhr, status) {
element.trigger('ajax:complete', [xhr, status]);
},
error: function(xhr, status, error) {
element.trigger('ajax:error', [xhr, status, error]);
}
});
}
So in my particular case, I've got a link, that has data-remote set to true, which points to a location that will return JavaScript instructing a form containing a text area to be appended to my document.
A simple way to do this would be to use ajaxComplete, which is fired after every AJAX request:
$(document).ajaxComplete(function() {
$('textarea:not(.processed)').resizer('250px');
});
That says "every time an AJAX request completes, find all textarea elements that don't have the processed class (which seems to be added by the resizer plugin -- terrible name for its purpose!) and call the resizer plugin on them.
You may be able to optimise this further if we could see your AJAX call.
Generally speaking, I would do it this way..
$.ajax({
type : "GET",
url : "/loadstuff",
success: function(responseHtml) {
var div = $("#containerDiv").append(responseHtml);
$("textarea", div).resizer("250px");
}
});
Wondering if you could use .load for this. For example:
$('text_area').load(function() {
$("text_area").resizer('250px');
});

Categories

Resources