Safari caching my AJAX request - javascript

I want one of my pages to fire a javascript AJAX call every time the user loads the page, even if he is coming back to a page in the browser's history. So I've put this function in my jsp (I am using jQuery Mobile):
$(document).on(
"pageinit",
"#base-layout",
function() {
$.ajaxSetup({ cache: false });
myFunction(urlEndpoint);
});
With only this code, and the javascript function:
function myFunction(url) {
var currentTime = new Date();
var n = currentTime.getTime();
var epUrl = url + "?nocache" + n;
$.ajax({
url : epUrl,
dataType: "json",
method: "post",
headers : { "cache-control": "no-cache" },
cache:false,
}).done(function(data) {
//do something
});
}
I managed to get Chrome, Firefox and IE to actually fire the ajax call even when pressing the back button. But I can't manage to get Safari to show this behavior. No matter what I try, it's never going through my server side function.
As you can see, I tried disabling cache for the ajax call, and changing the endpoint url by appendind the current time, to no effect. I even tried to put
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
on my controller method, but it didn't work either. I can't get Safari to call this function when coming back to a page in history.

Related

Call AJAX state based on URL

I am loading content in an overlay with its own URL and it is running pretty good. But I have the problem that when I enter the URL in the browserbar, it links directly to the page of the url, but I want to stay (on the homepage) and the overlay with the project should fade in.
I've tried it with the window.location.href but it killed my function completely. (I am also pretty newbie when it comes to ajax stuff)
My Code
//AJAX Function to fetch project content
var url = $('.load').data('url');
function openUrlInModal(url, target){
$.ajax({
url: url,
type: "GET",
dataType: "html",
contentType: "text/html",
cache: false,
success: function(url) {
$(target).append(url).addClass('modal');
$('.modal').fadeIn('fast');
console.log("target:" + target);
console.log("url:" + url);
}
});
}
// Adds content to the modal on click
$('.load').bind('click', function(e) {
var target = $(this).data("target");
//History Pushstate
fetchedProjectUrl = $(this).attr("href");
history.pushState(null, null, fetchedProjectUrl);
//Call Ajax Function
openUrlInModal($(this).attr('href'), target);
e.preventDefault();
});
//Hitting Back Button
$(window).on("popstate", function(){
history.pushState(null, null, "");
$('.modal').fadeOut('fast');
function empty(){
$('.modal').empty();
}
setTimeout(empty, 300);
});
Thanks for any help in advance :)
I do not understand where the URL for modal come from. If you want to stop the browser to go to the URL which was tipped in the browserbar and then executed - this isn't possible due to security reasons and senseless programming in mind of a browser. In this meaning you must code an own browser, than it's ok - whatever your browser should want to do.
If the URL is a kind of dynamic, you must have a new window reference in your modal, like an iframe, than you can execute a separate location for it.
Otherwise only paste the response-html in your modal innerHTML

url for ajax is not working

my ajax code is
$.ajax({
url: "http://www.web-tutor99.com/ajax/template0.php",
beforeSend: function() {
$('div#divLoading').show();
},
complete: function() {
$('div#divLoading').hide();
},
success: function(data) {
var menuStyleSheets = $("head .menuStyleSheets");
var i;
for (i = 0; i < menuStyleSheets.length; i++) {
//code
$(menuStyleSheets[i]).remove();
}
$('<link rel="stylesheet" type="text/css" class="menuStyleSheets" href="styleSheets/styleSheet' + index + '.css" >').appendTo("head");
$("#menuThm").remove();
$(".showMenu").append(data);
temp = Tempo.prepare('list');
createMenu();
},
error: function() {
alert("try another theme");
},
type: "GET",
})
and in the tamplate.php file i'm just echoing the html code but the ajax call is not fetching it showing the error alert, please help me, Thank you.
Ensure your Syntax is Correct / No Cross Origin Issues
Try removing the trailing , at the end of your AJAX call (after your type parameter). It's likely that your code is expecting another parameter that isn't there :
type: "GET",
Additionally, you will want to ensure that you are making this request from the same domain, otherwise you may encounter a cross-site "Access-Control-Allow-Origin" scripting error.
Use Your Developer Tools To Examine The Request
You may want to try using the Developer Tools (F12) within your browser and try examining the Request / Response content within the Network tab (seen below using Chrome) :
This should give you any specific server-side errors within the response if they are present.

Is there another way to disable cache when fetching script?

I use this to fetch script;
$.getScript("http://www.example.org/");
However, I dont want it to be cached. Means that if I use getScript again, the script should fetch it again.
This one works in theory;
$.getScript("http://www.example.org/?" + Math.random());
But in practically, it's not. Because the "?" is disabled on the remote site url, so my question is, is there any otherway to tell browser to not cache ?
Recreate the function for your needs:
(function () {
$.getScript = function(url, callback) {
$.ajax({
type: "GET",
url: url,
success: callback,
dataType: "script",
cache: false
});
};
})();
Now it won't cache anymore when you call the function like
$.getScript('script.js', function()
{
// non cached script.js
});
The remote site cannot disable the effectiveness of "http://www.example.org/?" + Math.random() to prevent caching.
The point of the "?" + Math.random() is to create a unique URL that will not be in the local browser cache. It is the local browser that makes this caching decision and, for local browser caching, it does not matter if the remote site is ignoring the "?" + Math.random() part of the URL or not.
FYI, another way to address caching is for your server to return proper cache headers when this script is retrieved that instruct the browser to never cache this file.

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.

window.onbeforeunload ajax request in Chrome

I have a web page that handles remote control of a machine through Ajax. When user navigate away from the page, I'd like to automatically disconnect from the machine. So here is the code:
window.onbeforeunload = function () {
bas_disconnect_only();
}
The disconnection function simply send a HTTP GET request to a PHP server side script, which does the actual work of disconnecting:
function bas_disconnect_only () {
var xhr = bas_send_request("req=10", function () {
});
}
This works fine in FireFox. But with Chrome, the ajax request is not sent at all. There is a unacceptable workaround: adding alert to the callback function:
function bas_disconnect_only () {
var xhr = bas_send_request("req=10", function () {
alert("You're been automatically disconnected.");
});
}
After adding the alert call, the request would be sent successfully. But as you can see, it's not really a work around at all.
Could somebody tell me if this is achievable with Chrome? What I'm doing looks completely legit to me.
Thanks,
This is relevant for newer versions of Chrome.
Like #Garry English said, sending an async request during page onunload will not work, as the browser will kill the thread before sending the request. Sending a sync request should work though.
This was right until version 29 of Chrome, but on Chrome V 30 it suddenly stopped working as stated here.
It appears that the only way of doing this today is by using the onbeforeunload event as suggested here.
BUT NOTE: other browsers will not let you send Ajax requests in the onbeforeunload event at all. so what you will have to do is perform the action in both unload and beforeunload, and check whether it had already taken place.
Something like this:
var _wasPageCleanedUp = false;
function pageCleanup()
{
if (!_wasPageCleanedUp)
{
$.ajax({
type: 'GET',
async: false,
url: 'SomeUrl.com/PageCleanup?id=123',
success: function ()
{
_wasPageCleanedUp = true;
}
});
}
}
$(window).on('beforeunload', function ()
{
//this will work only for Chrome
pageCleanup();
});
$(window).on("unload", function ()
{
//this will work for other browsers
pageCleanup();
});
I was having the same problem, where Chrome was not sending the AJAX request to the server in the window.unload event.
I was only able to get it to work if the request was synchronous. I was able to do this with Jquery and setting the async property to false:
$(window).unload(function () {
$.ajax({
type: 'GET',
async: false,
url: 'SomeUrl.com?id=123'
});
});
The above code is working for me in IE9, Chrome 19.0.1084.52 m, and Firefox 12.
Checkout the Navigator.sendBeacon() method that has been built for this purpose.
The MDN page says:
The navigator.sendBeacon() method can be used to asynchronously
transfer small HTTP data from the User Agent to a web server.
This method addresses the needs of analytics and diagnostics code that
typically attempt to send data to a web server prior to the unloading
of the document. Sending the data any sooner may result in a missed
opportunity to gather data. However, ensuring that the data has been
sent during the unloading of a document is something that has
traditionally been difficult for developers.
This is a relatively newer API and doesn't seems to be supported by IE yet.
Synchronous XMLHttpRequest has been deprecated (Synchronous and asynchronous requests). Therefore, jQuery.ajax()'s async: false option has also been deprecated.
It seems impossible (or very difficult) to use synchronous requests during beforeunload or unload
(Ajax Synchronous Request Failing in Chrome). So it is recommended to use sendBeacon and I definitely agree!
Simply:
window.addEventListener('beforeunload', function (event) { // or 'unload'
navigator.sendBeacon(URL, JSON.stringify({...}));
// more safely (optional...?)
var until = new Date().getTime() + 1000;
while (new Date().getTime() < until);
});
Try creating a variable (Boolean preferably) and making it change once you get a response from the Ajax call. And put the bas_disconnect_only() function inside a while loop.
I also had a problem like this once. I think this happens because Chrome doesn't wait for the Ajax call. I don't know how I fixed it and I haven't tried this code out so I don't know if it works. Here is an example of this:
var has_disconnected = false;
window.onbeforeunload = function () {
while (!has_disconnected) {
bas_disconnect_only();
// This doesn't have to be here but it doesn't hurt to add it:
return true;
}
}
And inside the bas_send_request() function (xmlhttp is the HTTP request):
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
has_disconnected = true;
}
Good luck and I hope this helps.
I had to track any cases when user leave page and send ajax request to backend.
var onLeavePage = function() {
$.ajax({
type: 'GET',
async: false,
data: {val1: 11, val2: 22},
url: backend_url
});
};
/**
* Track user action: click url on page; close browser tab; click back/forward buttons in browser
*/
var is_mobile_or_tablet_device = some_function_to_detect();
var event_name_leave_page = (is_mobile_or_tablet_device) ? 'pagehide' : 'beforeunload';
window.addEventListener(event_name_leave_page, onLeavePage);
/**
* Track user action when browser tab leave focus: click url on page with target="_blank"; user open new tab in browser; blur browser window etc.
*/
(/*#cc_on!#*/false) ? // check for Internet Explorer
document.onfocusout = onLeavePage :
window.onblur = onLeavePage;
Be aware that event "pagehide" fire in desktop browser, but it doesn't fire when user click back/forward buttons in browser (test in latest current version of Mozilla Firefox).
Try navigator.sendBeacon(...);
try {
// For Chrome, FF and Edge
navigator.sendBeacon(url, JSON.stringify(data));
}
catch (error)
{
console.log(error);
}
//For IE
var ua = window.navigator.userAgent;
var isIEBrowser = /MSIE|Trident/.test(ua);
if (isIEBrowser) {
$.ajax({
url: url,
type: 'Post',
.
.
.
});
}
I felt like there wasn't an answer yet that summarized all the important information, so I'm gonna give it a shot:
Using asynchronous AJAX requests is not an option because there is no guarantee that it will be sent successfully to the server. Browsers will typically ignore asynchronous requests to the server. It may, or may not, be sent. (Source)
As #ghchoi has pointed out, synchronous XMLHTTPRequests during page dismissal have been disallowed by Chrome (Deprecations and removals in Chrome 80). Chrome suggests using sendBeacon() instead.
According to Mozilla's documentation though, it is not reliable to use sendBeacon for unload or beforeunload events.
In the past, many websites have used the unload or beforeunload events to send analytics at the end of a session. However, this is extremely unreliable. In many situations, especially on mobile, the browser will not fire the unload, beforeunload, or pagehide events.
Check the documentation for further details: Avoid unload and beforeunload
Conclusion: Although Mozilla advises against using sendBeacon for this use case, I still consider this to be the best option currently available.
When I used sendBeacon for my requirements, I was struggling to access the data sent at the server side (PHP). I could solve this issue using FormData as recommended in this answer.
For the sake of completeness, here's my solution to the question:
window.addEventListener('beforeunload', function () {
bas_disconnect_only();
});
function bas_disconnect_only () {
const formData = new FormData();
formData.append(name, value);
navigator.sendBeacon('URL', formData);
}
I've been searching for a way in which leaving the page is detected with AJAX request. It worked like every time I use it, and check it with MySQL. This is the code (worked in Google Chrome):
$(window).on("beforeunload", function () {
$.ajax({
type: 'POST',
url: 'Cierre_unload.php',
success: function () {
}
})
})
To run code when a page is navigated away from, you should use the pagehide event over beforeunload. See the beforeunload usage notes on MDN.
On that event callback, you should use Navigator.sendBeacon(), as Sparky mentioned.
// use unload as backup polyfill for terminationEvent
const terminationEvent = "onpagehide" in self ? "pagehide" : "unload";
window.addEventListener(terminationEvent, (event) => {
navigator.sendBeacon("https://example.com/endpoint");
});

Categories

Resources