Method for disabling a jquery sortable while awaiting an ajax update? - ajax

I have a jquery sortable with an ajax callback tied to the update event. The ajax callback sends the updated sort order back to the server and then does a refresh of the sortable to guarantee that the client and server are both in sync.
The problem I am having is that the user can start a new sortable event before the ajax call has completed - I'd like to prevent that.
What I did try doing was disabling the sortable on the update event, and then re-enabling it when the ajax call returned. However unless I messed up the sequence, this didn't seem to work - I can still start a new sortable drag while the ajax call is still active.
Is there any other way to prevent this? I can certainly set a global javascript variable that says, "hey not right now, I'm ajaxing..." and reference it, but I'm not sure what sortable event would check for this, or how it would kill the sortable click request.
Thoughts?

For a better user experience...
Instead of disabling the interface, you should cancel the previous ajax request so that it doesn't overwrite any new requests.
This keeps the interface responsive, fluid and flexible.
It allows the user to 'change their mind' and reorder the list while waiting for it to save.
Any old requests are cancelled and therefore don't overwrite new requests...
//keep track of ajax request to allow cancellation of requests:
var ajaxRequest = null;
$('ul.sortable').sortable({
containment: 'parent',
update: function (event, ui) {
//display your loading anim gif
//get list of ids in correct order:
var ids = $(this).sortable('toArray').toString();
//cancel any previous ajax requests:
if (ajaxRequest) {
ajaxRequest.abort();
}
//post order to web service:
ajaxRequest = $.ajax({
type: 'POST',
url: 'somewebservice.blah',
data: ids,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (response) {
//saved ok:
ajaxRequest = null;
//hide your loading anim gif
}
});
}
});

You can simply overlay a transparent absolutely-positioned div over the whole list, which will prevent any clicks/drags on the list.
Set it in your CSS to display: none. Then, when you initiate an AJAX call, set it to display: block, and when your AJAX call completes, switch it back to display: none.

Did you try to set the disabled property ?
$('#sortable').sortable('option', 'disabled', true )
And then after the ajax request
$('#sortable').sortable('option', 'disabled', false )

Related

why browser request for image after ajax?

I'm using backbone and nodejs for a single page webapp.
I got a view, which has a model(a blog post) in it. when user click on 'like' button, the view will start ajax send the user'id to server to let the like number +1.
it looks like this:
this.model.save({
likedBy: userModel.get('_id')
}, {
url: '/posts/' + this.model.get('_id') + '/like',
success: function() {
// do something
},
patch: true
});
my problem is, when this code got run. browser start http request to retrieve all the images on the screen, and re-render them. so the screen got a "shake" after user clicked the like button.
this is not happening everywhere, but what caused this? how to stop the "shake"?
thanks for any advance.
When you call this.model.save() the model will update his data in the server and will call your view's render function. The render method will create a new DOM element and replace the old DOM element, that's what causing the flickering (it requests the images again).
I assume you have an API call for Like action (if not it's better to have one) so you can make a sperate AJAX call for like action on your model by adding a function like so:
addLike : function(data) {
Backbone.ajax({
url: '/api/like/'+ this.get('id'),
method: 'POST',
data: data,
success: options.success,
error: options.error
});
}

Ajax check if Url exists then redirect

Sorry to ask such a basic question. I would like to add an Ajax feature to my input page which does:
use the blockUI plugin to add a popup window which tells users to wait
in the meanwhile ajax detects the existence of output page
if calculations are finished, ajax redirects the browser to the output page (batchoutput.html)
If everything goes well, the popup message will appear for around 1-2 mins until the calculations are done, then the browser will be redirected to the batchoutput.html page.
However, the situation is: the popup message window appears only for a second, then after a min or two the browser goes to the batchoutput.html. My guess is something is wrong with my ajax function. It seems like the ajaxstart and ajaxstop are misfired. Can I have some suggestions?
Here is the code:
$('.input1_button').click(function () {
$(document).ajaxStart(function(){
$.blockUI({ css: {
border: 'none',
padding: '15px',
backgroundColor: '#000',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: .5,
color: '#fff'
} });
});
$(document).ajaxStop(function(){
$.unblockUI();
});
$.ajax({
type: "post",
url: "/batchoutput.html",
data: $(".articles").serialize(),
dataType: "html",
success: function() {
window.location = '/batchoutput.html';
}
});
});
ajaxStop is fired right after the ajax request is complete, and complete means error or success.
Therefore, what happens after you click a button is:
ajaxStart is fired, causing UI to block
ajax request to /batchoutput.html is performed
if request fails, ajaxStop is fired, causing UI to unblock
My suggestion is to:
block UI on button click (i.e. move $.blockUI directly into click function)
after that, send ajax request repeatedly until it finishes with success (you can use Javascript's native function setInterval or trigger next request on ajaxError)
when request succeds, unblock UI and redirect (this can be done either directly in success callback or in ajaxSuccess method)

Event Object is holding previous event properties in Full Calendar

I've got a problem with FullCalendar and I was looking for solution without any success.
I use eventClick to open overlay form with data of current event. Everything works great until I change my mind and don't want to edit this event but another one. And that causes ajax send request 2 times, once for opened event (which was ready to edit but form was not submitted) and once for event which was really edited and submitted.
$('#sc-calendar').fullCalendar({
eventClick: function(event) {
//opening overlay form window
$('#submit-event-update').bind('click',function() { //click submit
$.ajax({
type: "GET",
url: "event_update",
data: "id="+event.id+"&title="+event.title+"&start="+event.start+"&end="+event.end,
cache: false,
success: function() {
$('#submit-event-update').unbind();
$('#sc-calendar').fullCalendar('updateEvent',event);
}
});
});
}
});
This is starting to be my nightmare. Please help!
It seems to me like there is a problem with the onclick event listener for #submit-event-update.
You should modify your code in this way:
$('#sc-calendar').fullCalendar({
eventClick: function(event) {
//opening overlay form window
//Assign the event id of this event to the global variable event_id
event_id = event.id;
}
});
$('#submit-event-update').bind('click',function() { //click submit
$.ajax({
type: "GET",
url: "event_update",
data: "id=" + event_id + ..., //Note how event.id is not used anymore
cache: false,
success: function() {
$('#sc-calendar').fullCalendar('updateEvent',event);
}
});
});
I changed it so that you bind the onclick event handler to the button just once as opposed to every time an event is clicked. I also assign a variable event_id that holds the value of the current event's id.
Now, for an explanation. You said:
Everything works great until I change my mind and don't want to edit
this event but another one.
What happens when you click on an event?
You bind the onclick event to the #submit-event-update. Now if you do click the button, then you will go into the success() callback of your AJAX call and then unbind the button. But what if you change your mind and don't click the submit button? Now, you have one onclick listener with the old data already tied to the button. When you pick another event, you have two event listeners tied to the same button and hence, an AJAX request is sent two times.
It might be worth reading up on how JavaScript handles event binding here.

Jquery load in Dialog is repeated exponentially

I have a really annoying issue with jQuery and/or the jQuery UI Dialog Box.
After clicking on a special link a modal dialog will pop up with some loaded content (ajax) and inside this loaded content are new links/buttons that load their url inside the same div Box, so the dialog still is loaded, but with new content then. The Problem is, that if you link on that link (inside a fresh loaded dialog box and on a recently reloaded website) it works as it should, but with the second click it loads the url twice, with the third it loads 4 times ... It growing exponentially with every new link loaded inside the dialog. I testet this with a counter stored inside $_SESSION.
This is the Javascript Code:
var somedialog = $('<div></div>').dialog({
autoOpen: false,
resizable: false,
modal: true,
/*show: 'fade',
hide: 'puff',*/
closeOnEscape: true,
close: function(){
}
});
function openInDialog(url, title, width, height)
{
somedialog.empty();
somedialog.dialog("option", "width", width);
somedialog.dialog("option", "height", height);
somedialog.dialog("option", "title", title);
somedialog.load(url,{},function (responseText, textStatus, XMLHttpRequest)
{
somedialog.dialog('open');
}
);
//somedialog.load(url,{},function (responseText, textStatus, XMLHttpRequest){
// dialogdiv.somedialog('open');
//});
}
$('a.ajaxBuyItemDialog').on('click',function(){
openInDialog(this.href, this.title, 400, 300);
//prevent the browser to follow the link
return false;
});
There seemed to bee other people with this issue, but that was not a very effective discussion: https://stackoverflow.com/questions/6471360/jquery-load-after-load-repeated-results-problem
Thanks for your help!
EDIT:
This is part of the code which is located in the loaded script:
$("#_BUYITEM_FORM").live('submit', function(){
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('method'), // GET or POST
url: $(this).attr('action'), // the file to call
success: function(response){ // on success..
$("#_BUYITEM_CONTENT").html('<p class="AjaxLoaderImg"><span>Einen Moment bitte...</span></p>');
$("#_BUYITEM_CONTENT").html(response); // update the DIV
}
});
return false; // cancel original event to prevent form submitting
});
Without it I can't get it to refresh the dialog box with new content.
It seems that your javascript code is replicated in every $('a.ajaxBuyItemDialog') destination page clicked. Adding that script to the dialog again at every click causes event to be triggered more than once.
If you reload the script numerous times it will add a new submit handler to form each time since you are using live().
live() will delegate the handler to the document and thus should either only be called once or you need to call die() before script loads each time.
if you were to get rid of using live() you could move the submit handler to the success callback of load() and use submit() rather than live(). If the original form is replaced...the original submit() event handler will also be gone
"Dirty" solution
function watchBuyItemForm(){
$("#_BUYITEM_FORM").submit(function(){
$.ajax({ // create an AJAX call...
data: $(this).serialize(), // get the form data
type: $(this).attr('method'), // GET or POST
url: $(this).attr('action'), // the file to call
success: function(response){ // on success..
somedialog.html(ajaxLoader);
somedialog.html(response); // update the DIV
watchBuyItemForm();
}
});
return false; // cancel original event to prevent form submitting
});
}

Can I make an Ajax request inside an ongoing Ajax request (e.g. on the success callback function)?

I have a jQuery application, a shopping cart, that posts back info to the server, if the text inputfield is changed. This is done in an Ajax request. Now, if the Ajaxrequest is a success, I want to reload the shoppingcart asynchronously. The code is as follows:
$(document).ready(function() {
var jInput = $(":input");
jInput.change(function() {
var vareAntal = $(this).val();
var vareID = $(this).siblings("input#vareID").val();
$.ajax({
type: 'POST',
url: 'checkout.aspx',
data: { 'ID': vareID, 'Antal': vareAntal },
success: function() {
$("#newbasket").load(location.href + " #newbasket>*", "");
}
});
});
});
This works, but only once! If I change the text inputfield, after the page is loaded for the first time, the div with the ID of newbasket reloads asynchronously. But if I try to change it again, nothing happens.
I've tried to do some debugging with Firebug, and the first time I change the text inputfield, it fires a POST-event, and afterwards a GET-event, when the POST-event is succesful. But after that, nothing happens when I change the text inputfield again.
So, how do I achieve triggering the .load() method after each text input change?
I've also tried experimenting with the .ajaxComplete() function, but that, of course, resulted in an infinite loop, since the .load() is an ajax-object.
Instead of .change(func), use .live('change', func) here, like this:
jInput.live('change', function() {
This will make the selector work on any new inputs added as well. When you're replacing the elements like you are currently, their event handlers are lost (or rather, not re-created, because you have new elements). .live() is just for this purpose, it listens for events from old and new elements, regardless of when they were added.

Resources