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.
Related
I have a problem when I dynamically load content with the following code.
$(document).ready(function() {
$("#tags").keyup(function(){
var q = $(this).val();
$.ajax({
url: '/AnswerMedia/utilities/autoSearch/model/suggest.php?q='+q,
success: function (data) {
$("#ajaxDiv").html(data);
},
error: function (request, status, error) {
alert(request.responseText);
}
});
});
});
After the content loads, this code was intended to trigger an event when one of the loaded div tags is clicked, but did not.
$(".pdiv").click(function(){
var val = $(this).text();
$('#tags').val(val);
$('.mncontr').hide();
});
$("#closeSearch").click(function(){
$('.mncontr').hide();
});
Then I tried the following code:
$("body").delegate(".pdiv", "click", function(){
var val = $(this).text();
$('#tags').val(val);
$('.mncontr').hide();
});
$("body").delegate("#closeSearch", "click", function(){
$('.mncontr').hide();
});
It works well in Firefox, but in Chrome the problem persists. Please help me.
From this SO post:
If you want the click handler to work for an element that gets loaded
dynamically, then you set the event handler on a parent object (that
does not get loaded dynamically) and give it a selector that matches
your dynamic object like this:
$('#parent').on("click", "#child", function() {});
The event handler
will be attached to the #parent object and anytime a click event
bubbles up to it that originated on #child, it will fire your click
handler. This is called delegated event handling (the event handling
is delegated to a parent object).
It's done this way because you can attach the event to the #parent
object even when the #child object does not exist yet, but when it
later exists and gets clicked on, the click event will bubble up to
the #parent object, it will see that it originated on #child and there
is an event handler for a click on #child and fire your event.
I have a single page mark-up with popup divs that contain forms that the user can use to update his/her account information. After form submission the popup closes and the page refreshes showing the updated information that is located within a li (this seems to be working). The problem is, if the user goes back and tries to update again the button within the popup is not submitting.
Thanks in advance for any suggestions!!!
Javascript
$('#updateadmin').click(function() {
var admin = $('#adminform').serializeArray();
/*alert(admin);*/
$.ajax({
type: "POST",
url: 'adminupdate.php',
data: admin,
success: function(data) {
if(data=="success") {
$('#admindiv').popup('close');
$.mobile.changePage('companyinfo.php', {
allowSamePageTransition: true,
transition: 'none',
reloadPage: true,
changeHash: false
});
} else {
$('#adminupdatestatus').html(data).css({color: "red"}).fadeIn(1000);
}
}
});
return false;
});
It sounds like the #updateadmin link/button is located on the page that gets reloaded, if this is the case then you should delegate your event handler so it affects matching elements in the DOM for all time, not just when the code runs.
You would change this:
$('#updateadmin').click(function() {
to this:
$(document).on("click", "#updateadmin", function() {
This works because you're now attaching the event handler to the document element which always exists. When events reach the document element they are checked to see if the element on which they originally fired matches the selector we put as the second argument for .on().
Documentation for .on(): http://api.jquery.com/on
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
});
}
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 )
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.