Event propagation and ajax post - javascript

I have the following code:
<div id="parentDiv">
...
</div>
HTML inside the div comes from the external source and I don't know it's structure and can't control it.
I need to post some data when this link has been clicked. So I added an onclick event handler on the div element, hoping event will propagate, and posted data with jQuery ajax function.
This worked fine in all browsers but Safari - it doesn't return any errors, calls the callback function but doesn't reach the server for some reason. I write to database every time I get a request. Tried to manually load the post url in browser - works fine and record in db is created. Also tried FF and Chrome - works as expected.
When put an alert into callback function it's being called but in Safari data = null.
$('#parentDiv').delegate( 'a', 'click', function()
{
$.post('posturl',
{ param1: 'test'},
function(data)
{
alert('data = '+data);
},
"json"
);
});
Is it correct to expect AJAX working in this situation at all? And is there a better solution to this problem?
Thank you!

This sounds like you need to combine delegate with the asynchronous AJAX. Note that this is almost never a good thing -- the only real exception is when you want to do an AJAX request immediately before leaving a page.
Your code might look something like this:
$('#parentDiv').delegate( 'a', 'click', function()
$.ajax({
type: 'POST',
url: 'posturl',
{ param1: 'test'},
dataType: 'json',
async: false
});
});
This waits for the POST request to finish before continuing to follow the link. Note that this is superior to using location = url in a success callback as this solution allows normal browser action like middle-clicking to be followed as normal.

You want to look at jQuery's .delegate() method. It tells an element to listen for certain event bubbling up from a certain element and to execute behavior when it is observed. You also want to prevent the default action of the link, and send the browser to the link when the ajax operation is complete.
Docs: http://api.jquery.com/delegate/
Sample code:
$( '#parentDiv' ).delegate( 'a', 'click', function( e )
{
var url = this.href;
e.preventDefault();
$.post(
'posturl',
{
param1: 'test'
},
function(data)
{
alert('data = ' + data);
window.location = url;
},
'json'
);
} );
This:
delegates the event
prevents default
awaits ajax response
sends browser to link
Demo: http://jaaulde.com/test_bed/dasha_salo/

Related

Firing click event before ajax call

I have an ajax call on click of anchor tag in WordPress and I have not control over this. But before this ajax call I want to fire click event.
This click event is firing sometime but not every time. So I am not getting consistent results. Is there any way so that I can get correct results and get this click event fire before ajax call. I have tried putting my code in header and in footer as well.
Here is my code that i am using for click event.
jQuery(document).ready(function(){
jQuery("#addbtn").click(function(){
});
});
Any suggestion about this will be much appreciated.
you can use befor beforeSend
This event, which is triggered before an Ajax request is started, allows you to modify the XMLHttpRequest object (setting additional headers, if need be.)
source: https://api.jquery.com/Ajax_Events/
$.ajax({
type: 'POST',
url: url,
data: data,
beforeSend: function() {
/*using a loader while waiting or fire an event or execute a function */
},
success: function(data) {
//execute a function on request sucess
},
error: function(xhr) { // if error occured
alert("Error occured.please try again");
},
complete: function() {
//execute a function once the call completed
}
});
I hope this will help you slove the issue

jquery doesn't work after an ajax call (response in a pop up window)

I've a jsp page with a form and some jquery code. Jquery code works perfectly, but if I return that page in a popup window by using an ajax call, the jquery code doesn't work any more.
I tried also to use delegation, that is:
$('select[name=myElementName]').on("change", function() {
// some code
});
or
$(document).on("change", 'select[name=myElementName]', function() {
// some code
});
instead of
$('select[name=myElementName]').change(function() {
// some code
});
Ajax call:
var preview = function () {
$.ajax({
type: "POST",
url: myAction.do,
data: "id=" + myid,
success: function (response) {
// some code
var x=window.open('', '_blank', 'titlebar=no,scrollbars=yes,menubar=no,height='+height+',width='+width+',resizable=yes,toolbar=no,location=no,location=0,status=no,left='+left+',top='+top+'');
x.document.open();
x.focus();
x.document.write(response);
return false;
},
error: function () {
return false;
},
});
};
EDIT
On Firefox 26.0 and Chrome 32.0.x, I resolved by using
x.document.close();
after
x.document.write(replace);
Instead, on IE, all the .js included scripts are ignored (for example the jquery-ui-1.9.1.js).
EDIT 2
I resolved with
<body onload="myload()">
and in my jsp I've myload() definition in which I call the scripts.
It is because you are creating new DOM structure but it doesn't have the event handlers attached. The easiest way is to run the event handler in the ajax callback:
$.ajax({
...
success: function (response) {
// some code
var x=window.open('', '_blank', 'titlebar=no,scrollbars=yes,menubar=no,height='+height+',width='+width+',resizable=yes,toolbar=no,location=no,location=0,status=no,left='+left+',top='+top+'');
x.document.open();
x.focus();
x.document.write(response);
// now, place the event handler here
$('select[name=myElementName]', x.document.body).change(function() {
// some code
});
}
});
Don't use document.write it completely overwrites whatever is on the page at the time of writing and leads to race conditions (e.g. the external scripts might have already been loaded, but they also might not, leading to unknown order of the write and script loads). Also, I believe documnt.write is putting serialized text into the document, not DOM objects so it may not trigger events.
Instead, you can open the new window and then manipulate the DOM objects there directly (assuming it's on the same server as your main page):
//Open a new window for the success info
var newWindow = window.open(newUrl);
//Now grab some element
var someItem = newWindow.document.getElementById( "someId");
//Manipulate dom either by "someItem.innerHTML" or "someItem.appendChild(...)"
If you are calling an AJAX server routine and putting the entire response w/o processing it on the client in to a new window, why not opening the window directly with the URL of that AJAX routine and skipping all stuff:
....
var x=window.open(myAction.do + "?id=" + myid,
'_blank',
'titlebar=no,scrollbars=yes,menubar=no,height='+height+',width='+width+',resizable=yes,toolbar=no,location=no,location=0,status=no,left='+left+',top='+top+'');
....
The only diff here is, that the request is a GET and not a POST request, but the data is just one id, which is acceptable, probably?
I had a similar problem in on of my projects. I solved it by writing a success method after the ajax call.
{
$.ajax({
type: "POST",
url: "/abc/",
data:{<data>},
async:false,
dataType:'json',
success: function(response)
{
success=1;
Id=response;
return;
}
});
if (success)
{
#your code here
var a='/xyz/?Id='+Id
window.open(a,'_blank');
window.location.href='/registration/'
}
return false;}
instead of using document.write, try fetching your success data(records arrived in success function) in a hidden DIV and clone it into your popup that should work

Ajax working on pageload but not on button click

I have an ajax query that's working if I call it from onpageload but not if I call it from a button click. Any reason why?
Edit: I've added the events as requested, please be aware I have debugged this and it is getting to the AJAX but just silently skipping it. It will call a failure function if I add one.
function detailsQuery(crn, semester, year, questionId, clickedButton)
{
$.ajax({
url: somebigurlwithnocallback (same domain),
type: "GET",
dataType: "json",
success: function (data) {alert(data)}});
}
-
$(function() {
$(document).delegate(".button", "click", function(){detailsQuery(CRN,Semester,Year,QuestionID, this);});
});
window.onload=(function() {detailsQuery(CRN,Semester,Year,QuestionID, this);});
Did you attempt to check if the click event was even working ? Try this code:
$(".button").live("click", function(){
function detailsQuery(crn, semester, year, questionId, clickedButton)
{
$.ajax({
url: somebigurlwithnocallback (same domain),
type: "GET",
dataType: "json",
success: function (data) {alert(data)}
});
});
});
This appears to be an issue with Google Chrome. If an HTML file is modified and only refreshed (even with ctrl+f5) Chrome does not always process the modified AJAX call properly. I don't have access to server side code so I can't see what's going on there, being a 'GET' not much can be going on. I can only see that it returns 'error'. Closing chrome and re-opening resolves the issue. Why it only happens when the AJAX occurs on a button click is beyond me.
Do this:
Change
$(function() {
$(document).delegate(".button", "click", function(){detailsQuery(CRN,Semester,Year,QuestionID, this);});
});
to
$(document).ready(function(){
$(".button").bind({"click": function(){
function(){detailsQuery(CRN,Semester,Year,QuestionID, this);}
}
});
});
That should resolve the issue.
Hope the explanation is clear and this helps.

Detect if and when any jQuery AJAX calls are made

I have a toolbar that exists on all my webpages that makes requests to a server side XML file regularly.
Some of the web pages also make requests to the same XML file, but more frequently. Ideally I would like to, where possible, combine this easily into a single request. Where the toolbar uses the same request that the page made (as the page refresh rate is greater than that of the toolbar)
Is there any way to tell if any jQuery AJAX calls have been made to a certain resources and, if so, be notified on success?
Update:
Based on Darin Dimitrov's answer I have tried the following:
$.ajaxSetup({
success: function(){ console.log("woop"); }
});
This never fires, I presume because the success handler is being overwritten when I make my other AJAX calls.
You could use the $.ajaxSetup() to subscribe for the common events.
Subscribe to all ajax events at the document level;
$(document).bind("ajaxSend", function(){
alert('ajax fired');
});
In your AJAX add response callback, something like this:
$.ajax({
type: "POST",
url: "mypage.php",
data: "name=John&location=Boston",
success: function(data){
alert(data);
}
});
and on your php page where you process AJAX request add some echo statement:
echo "POSTed OK!";
If you post is a success you'll get an alert confirmation.
You can also get a confirmation if it failes but modifying the code slightly:
success: function(result) {
if (result==1) {
alert('Success');
} else {
alert('Failed');
}
}
Good luck!

process a page on UnLoad?

I need for a php file to process when the user click a link/go back/exits a page. Its part of a saving user info process. if i do a jquery unload how would I fire the php file to load and process.
jQuery(window).bind("unload", function() {
// what should i add?
});
$(document).ready(function() {
$(':input',document.myForm).bind("change", function() {
setConfirmUnload(true);
}); // Prevent accidental navigation away
});
function setConfirmUnload(on) {
// To avoid IE7 and prior jQuery version issues
// we are directly using window.onbeforeunload event
window.onbeforeunload = (on) ? unloadMessage : null;
}
function unloadMessage() {
if(Confirm('You have entered new data on this page. If you navigate away from this page without first saving your data, the changes will be lost.')) {
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
}
}
Make sure you have upgraded version of jQuery. jQuery version 1.3.2 had a bug:
Ticket #4418: beforeunload doenst work correctly
Or use native function:
window.onbeforeunload = function() {....}
I'm guessing a synchronous AJAX call might work.
$.ajax({
async: true,
url: '/foo/',
success: function(data) {
// Finished.
}
});
Of course, keep in mind there's no guarantee any of this will ever happen. My browser may crash. My computer may even power down. And of course I may disable JavaScript. So you'll definitely need a server-side way of handling this in case the convenient JavaScript technique doesn't actually work.
You should use the beforeunload event. You can fire a synchronised ajax request in there.
$(window).bind('beforeunload', function() {
$.ajax({
url: 'foo',
async: false,
// ...
});
});
Be aware that onbeforeunload is not supported by some older browsers. Even if this technique works, I'm not sure how long you can (should?) block this event. Would be a pretty bad user experience if that request would block a few seconds.
A good trade-off is probably to tell the user that something has changed what was not saved yet. Do this with a few boolean checks and finally return a string value in the onbeforeunload request. The browser will then gracefully ask the user if he really wants to leave your site, also showing the string you provided.

Categories