Show loader and post AJAX onbeforeunload - javascript

I have a settings page with a form. I noticed that people often forget to click the save button, so I decided to send a POST request with $.ajax() on window.onbeforeunload. I'd also like a loader (from Semantic UI) to show before sending the request and hide when it is completed.
This is what I have:
function save(e) {
var msg = 'Your settings were not saved. Please do not leave yet so we can try saving again';
$('form').dimmer('show');
var xhr = $.ajax('settings.php', {type: "POST",
data: $('form').serialize(), async: false});
$('form').dimmer('hide');
if (xhr.status !== 200){
$('form').submit(); //will trigger if the user stays
if (e)
return e.returnValue = msg;
}
}
if ('onbeforeunload' in window)
window.onbeforeunload = save;
else if ('onunload' in window)
window.onunload = save;
else {
var button = $('noscript.submitParent').text();
$('.ui.form.segment').append(button);
}
But now, the loader won't show up until the request is done. I suspect this happens because of async: false, which is necessary so that the page does not unload.
Any suggestions on how to show the loader before sending the request? Is it possible?
I tried $(window).trigger('resize') from here and $('form .dimmer').height() (idea from here), didn't work.
I'm aware of the localStorage alternative, but I'd like not to use it if possible.
I use jQuery 2.1.1

Related

Chrome window.open after ajax request acts like popup

I have a situation where, when a user pushes a button I perform an ajax request, and then use the result of the ajax request to generate a URL which I want to open in a new tab. However, in chrome when I call window.open in the success handler for the ajax request, it opens in a new window like a popup (and is blocked by popup-blockers). My guess is that since the the success code is asynchronous from the click handling code that chrome thinks it wasn't triggered by a click, even though it is causally related to a click. Is there any way to prevent this without making the ajax request synchronous?
EDIT
Here is some minimal code that demonstrates this behaviour:
$('#myButton').click(function() {
$.ajax({
type: 'POST',
url: '/echo/json/',
data: {'json': JSON.stringify({
url:'http://google.com'})},
success: function(data) {
window.open(data.url,'_blank');
}
});
});
http://jsfiddle.net/ESMUA/2/
One note of clarification: I am more conerned about it opening in a separate window rather than a tab, than I am about it being blocked by a popup blocker.
Try to add
window.open(url,'_blank');
Edit
Well, I don't think you can get around popup-blockers when opening a page that's not the immediate result of a user action (i.e. not async).
You could try something like this though, it should look like a user action to a popup-blocker:
var $a = $('<a>', {
href: url,
target: '_blank'
});
$(document.body).append($a);
$a.click();
Edit 2
Looks like you're better of keeping things sync.
As long as the new window is "same origin" you have some power to manipulate it with JS.
$('#a').on('click', function(e){
e.preventDefault();
var wi = window.open('about:blank', '_blank');
setTimeout(function(){ // async
wi.location.href = 'http://google.com';
}, 500);
});
Try adding async: false. It should be working
$('#myButton').click(function() {
$.ajax({
type: 'POST',
async: false,
url: '/echo/json/',
data: {'json': JSON.stringify({
url:'http://google.com'})},
success: function(data) {
window.open(data.url,'_blank');
}
});
});
What worked for me was:
var win = window.open('about:blank', '_blank');
myrepository.postmethod('myserviceurl', myArgs)
.then(function(result) {
win.location.href = 'http://yourtargetlocation.com/dir/page';
});
You open the new window tab before the sync call while you're still in scope, grab the window handle, and then re-navigate once you receive the ajax results in the promise.
The answer posted by #pstenstrm above (Edit 2) mostly works, but I added just one line to it to make the solution more elegant. The ajax call in my case was taking more than a second and the user facing a blank page posed a problem. The good thing is that there is a way to put HTML content in the new window that we've just created.
e.g:
$('#a').on('click', function(e){
e.preventDefault();
var wi = window.open('about:blank', '_blank');
$(wi.document.body).html("<p>Please wait while you are being redirected...</p>");
setTimeout(function(){ // async
wi.location.href = 'http://google.com';
}, 500);
});
This fills the new tab with the text "Please wait while you are being redirected..." which seems more elegant than the user looking at a blank page for a second. I wanted to post this as the comment but don't have enough reputation.
There is no reliable way. If your tab/window has been blocked by a pop-blocker in FF and IE6 SP2 then window.open will return the value null.
https://developer.mozilla.org/en-US/docs/Web/API/Window/open#FAQ
How can I tell when my window was blocked by a popup blocker? With the
built-in popup blockers of Mozilla/Firefox and Internet Explorer 6
SP2, you have to check the return value of window.open(): it will be
null if the window wasn't allowed to open. However, for most other
popup blockers, there is no reliable way.

Two functions in onclick - Ajax call in second (cross browser)

I have
Click me
What I want to do is take the confirmation box result (true/false), pass it to the submit button, and then kill the href call if its false.
I have it working in my development environment, but when I load this into a cross browser scenario, the second call isn't working:
function submit(msg, evt) {
if(msg == true) {
$.ajax({
type:"POST",
data:{answer:'Correct'},
url:'https://myurl/p'
});
}
else { evt.preventDefault(); return false; }
}
The URL passed is just the URL and has no data to it (in production). This exact code works perfectly fine in my environment, but in the cross browser scenario it fails. If I remove the confirmation box, everything works perfectly.
I have a feeling it's tied to the preventDefault call on the cancel of the confirmation box. Would that preventDefault disable the next call out with that same link?
First of all, please don't use inline event handlers, you can remove this from the markup and deal with it in your js where it belongs:
HTML:
Click me
JS:
anchor = $('#myanchor')[0];
anchor.on('click',function(){
var msg = confirm('Confirm?');
submit(msg, event);
});
Secondly, if msg is true the ajax call is immediately interrupted by a page redirect, which doesn't make much sense. I believe you want the redirect to take place once the ajax call has completed, in which case you should use:
function submit(msg, evt) {
if(msg == true) {
$.ajax({
type:"POST",
data:{answer:'Correct'},
url:'https://myurl/p',
complete: function(){window.location="url";}
});
}
evt.preventDefault();
return false;
}
Click me
$(function(){
$("#myUrlID").click(function(event){
event.preventDefault();
var msg = confirm('Confirm?');
if(msg == true) {
$.ajax({
type:"POST",
data:{answer:'Correct'},
url:'https://myurl/p'
});
}
});
});

Javascript window.open not working

Ok. I'm trying to login to twitter. The window is not opening in this code. The response that gets alerted is not null and is a link to a login screen. Any ideas?
var url = "./twitter_login.php";
var con = createPHPRequest();
con.open("POST",url,true);
con.setRequestHeader("Content-type","application/x-www-form-urlencoded");
con.send("");
var response = "";
con.onreadystatechange = function() {
if(con.readyState==4 && con.status==200) {
response = con.responseText;
alert(response);
window.open(response,"twitter","menubar=1,resizable=1,width=350,height=500");
}
}
The standard popup-blocker logic contained in most browsers these days will block any calls to window.open() that are not the direct result of a user action. Code that is triggered by timers or by any asynchronous callback (like your ajax ready function) will be treated as NOT caused directly by user actions and the new popup window will generally be blocked.
You can verify this is what is happening by temporarily changing your browser's popup blocking (turning it off) and see that it then starts working.
Probably what you need to do as a work-around is to create the window upon the user action that started this thread of code and then put the content into the window when you get your ajax response. The browser will probably allow that. I know that's less desirable from a visual perspective, but you can put some temporary content in the window until the ajax response comes in (something like "loading...").
Just had this exact same issue. Just in case you wanted the code that fixed it. I used this:
newWindow = window.open("", "_blank");
request = $.ajax({ ... my request which returns a url to load ... })
request.done((function(_this) {
return function(data, textStatus, jqXHR) {
return newWindow.location = data.Url;
};
})(this));

jquery get redirected url

Edit -
Wasn't getting a response so let me ask this. Can I do this?
facebook button
Let the page load on top of the current page and listen for the window.location.hostname before the page actually redirects with jquery?
Facebook site url = http://www.mysite.com
In a mobile app, you can use fb(YOUR_APP_ID)://authorize/ to request for auth_token.
Using jquery, how can I catch the redirected url before the page goes to it?
i.e.
CALLBACK_URL = fb(YOUR_APP_ID)://authorize/
url = "https://m.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=CALLBACK_URL"
WebView.navigate(url)
WebView.execture_js('$(document).ready(function() {
$("body").ajaxComplete(function(e, xhr, settings) {
if (xhr.getResponseHeader("Location").hostname == "fb(YOUR_APP_ID)://authorize/"){
alert(xhr.getResponseHeader("Location"));
// and redirect back to action in my app...
}
});
});')
If you are using jQuery Mobile, take a look at the pagebeforeshow event.
http://jquerymobile.com/demos/1.0b1/#/demos/1.0b1/docs/api/events.html
$('div').live('beforepageshow', function(event, ui) {
var page = $(this).attr("id");
if (page == 'mypage') {
// your logic here
}
});
You might also try adding registering an ajaxComplete handler within a handler for the mobileinit event.
http://jquerymobile.com/demos/1.0b1/#/demos/1.0b1/docs/api/globalconfig.html
$(document).bind("mobileinit", function() {
$("body").ajaxComplete(function(e, xhr, settings) {
if (xhr.getResponseHeader("Location").hostname == "fb(YOUR_APP_ID)://authorize/"){
alert(xhr.getResponseHeader("Location"));
// and redirect back to action in my app...
}
});
});

window.open popup getting blocked during click event

What I ultimately need to do is run an $.ajax() call and then after that is run, open a new window.
A use clicks on a "Preview" button that saves their current form then opens a new window that shows a preview of the item with the data that was just saved.
But as-is, the window.open function gets blocked by popup blockers.
Here's the basic parts of my code:
HTML:
Preview
JavaScript:
$('.preview').live('click', function(event){
save_survey($(this).attr('href'));
event.preventDefault();
});
function save_survey(url) {
$.ajax({
type: "POST",
url: form_url,
dataType: 'json',
data: form_data,
success: function(data) {
window.open(url, '_blank');
}
});
}
I ran into this problem recently and found this work-around:
1) call window.open just before calling $.ajax and save window reference:
var newWindow = window.open(...);
2) on callback set location property of the saved window reference:
newWindow.location = url;
Maybe it will help you too.
Popup blockers usually works blocking every popup shown not triggered by a direct user action, like clicking on a button or a link.
If you use a ajax request on your click event, the request is fired asyncronous from the click event, that's why by the time the ajax request has done its job and you get your event with the response from the request you have lost your chance to trigger a window.open withouth the popup blocker getting in the way, the original click event it's long dead by that time.
According this this post, it looks like you would have to open your window in direct response to the click (to avoid getting hit by the popup blockers) rather than waiting until the AJAX call completes to open the new window.
I solved my case by making the Ajax call synchronous. E.g. (with jQuery):
$("form").submit(function(e){
e.preventDefault();
$.ajax({
async: false,
url: ...,
data: ...,
success: function(results){
if(results.valid){
window.open(...);
}
}
});
return false;
});
const newWin = window.open(`${BASE_URL}`, 'expampleName')
if (newWin) {
newWin.onload = () => {
const currentOpenWindow = newWin
const href = newWin.location.href
}
}

Categories

Resources