Showing pop up when internet connection is lost in php [duplicate] - javascript

How to detect the Internet connection is offline in JavaScript?

Almost all major browsers now support the window.navigator.onLine property, and the corresponding online and offline window events. Run the following code snippet to test it:
console.log('Initially ' + (window.navigator.onLine ? 'on' : 'off') + 'line');
window.addEventListener('online', () => console.log('Became online'));
window.addEventListener('offline', () => console.log('Became offline'));
document.getElementById('statusCheck').addEventListener('click', () => console.log('window.navigator.onLine is ' + window.navigator.onLine));
<button id="statusCheck">Click to check the <tt>window.navigator.onLine</tt> property</button><br /><br />
Check the console below for results:
Try setting your system or browser in offline/online mode and check the log or the window.navigator.onLine property for the value changes.
Note however this quote from Mozilla Documentation:
In Chrome and Safari, if the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true. So while you can assume that the browser is offline when it returns a false value, you cannot assume that a true value necessarily means that the browser can access the internet. You could be getting false positives, such as in cases where the computer is running a virtualization software that has virtual ethernet adapters that are always "connected." Therefore, if you really want to determine the online status of the browser, you should develop additional means for checking.
In Firefox and Internet Explorer, switching the browser to offline mode sends a false value. Until Firefox 41, all other conditions return a true value; since Firefox 41, on OS X and Windows, the value will follow the actual network connectivity.
(emphasis is my own)
This means that if window.navigator.onLine is false (or you get an offline event), you are guaranteed to have no Internet connection.
If it is true however (or you get an online event), it only means the system is connected to some network, at best. It does not mean that you have Internet access for example. To check that, you will still need to use one of the solutions described in the other answers.
I initially intended to post this as an update to Grant Wagner's answer, but it seemed too much of an edit, especially considering that the 2014 update was already not from him.

You can determine that the connection is lost by making failed XHR requests.
The standard approach is to retry the request a few times. If it doesn't go through, alert the user to check the connection, and fail gracefully.
Sidenote: To put the entire application in an "offline" state may lead to a lot of error-prone work of handling state.. wireless connections may come and go, etc. So your best bet may be to just fail gracefully, preserve the data, and alert the user.. allowing them to eventually fix the connection problem if there is one, and to continue using your app with a fair amount of forgiveness.
Sidenote: You could check a reliable site like google for connectivity, but this may not be entirely useful as just trying to make your own request, because while Google may be available, your own application may not be, and you're still going to have to handle your own connection problem. Trying to send a ping to google would be a good way to confirm that the internet connection itself is down, so if that information is useful to you, then it might be worth the trouble.
Sidenote: Sending a Ping could be achieved in the same way that you would make any kind of two-way ajax request, but sending a ping to google, in this case, would pose some challenges. First, we'd have the same cross-domain issues that are typically encountered in making Ajax communications. One option is to set up a server-side proxy, wherein we actually ping google (or whatever site), and return the results of the ping to the app. This is a catch-22 because if the internet connection is actually the problem, we won't be able to get to the server, and if the connection problem is only on our own domain, we won't be able to tell the difference. Other cross-domain techniques could be tried, for example, embedding an iframe in your page which points to google.com, and then polling the iframe for success/failure (examine the contents, etc). Embedding an image may not really tell us anything, because we need a useful response from the communication mechanism in order to draw a good conclusion about what's going on. So again, determining the state of the internet connection as a whole may be more trouble than it's worth. You'll have to weight these options out for your specific app.

IE 8 will support the window.navigator.onLine property.
But of course that doesn't help with other browsers or operating systems. I predict other browser vendors will decide to provide that property as well given the importance of knowing online/offline status in Ajax applications.
Until that happens, either XHR or an Image() or <img> request can provide something close to the functionality you want.
Update (2014/11/16)
Major browsers now support this property, but your results will vary.
Quote from Mozilla Documentation:
In Chrome and Safari, if the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true. So while you can assume that the browser is offline when it returns a false value, you cannot assume that a true value necessarily means that the browser can access the internet. You could be getting false positives, such as in cases where the computer is running a virtualization software that has virtual ethernet adapters that are always "connected." Therefore, if you really want to determine the online status of the browser, you should develop additional means for checking.
In Firefox and Internet Explorer, switching the browser to offline mode sends a false value. All other conditions return a true value.

if(navigator.onLine){
alert('online');
} else {
alert('offline');
}

There are a number of ways to do this:
AJAX request to your own website. If that request fails, there's a good chance it's the connection at fault. The JQuery documentation has a section on handling failed AJAX requests. Beware of the Same Origin Policy when doing this, which may stop you from accessing sites outside your domain.
You could put an onerror in an img, like <img src="http://www.example.com/singlepixel.gif" onerror="alert('Connection dead');" />.
This method could also fail if the source image is moved / renamed, and would generally be an inferior choice to the ajax option.
So there are several different ways to try and detect this, none perfect, but in the absence of the ability to jump out of the browser sandbox and access the user's net connection status directly, they seem to be the best options.

As olliej said, using the navigator.onLine browser property is preferable than sending network requests and, accordingly with developer.mozilla.org/En/Online_and_offline_events, it is even supported by old versions of Firefox and IE.
Recently, the WHATWG has specified the addition of the online and offline events, in case you need to react on navigator.onLine changes.
Please also pay attention to the link posted by Daniel Silveira which points out that relying on those signal/property for syncing with the server is not always a good idea.

You can use $.ajax()'s error callback, which fires if the request fails. If textStatus equals the string "timeout" it probably means connection is broken:
function (XMLHttpRequest, textStatus, errorThrown) {
// typically only one of textStatus or errorThrown
// will have info
this; // the options for this ajax request
}
From the doc:
Error: A function to be called if the request
fails. The function is passed three
arguments: The XMLHttpRequest object,
a string describing the type of error
that occurred and an optional
exception object, if one occurred.
Possible values for the second
argument (besides null) are "timeout",
"error", "notmodified" and
"parsererror". This is an Ajax Event
So for example:
$.ajax({
type: "GET",
url: "keepalive.php",
success: function(msg){
alert("Connection active!")
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
if(textStatus == 'timeout') {
alert('Connection seems dead!');
}
}
});

window.navigator.onLine
is what you looking for, but few things here to add, first, if it's something on your app which you want to keep checking (like to see if the user suddenly go offline, which correct in this case most of the time, then you need to listen to change also), for that you add event listener to window to detect any change, for checking if the user goes offline, you can do:
window.addEventListener("offline",
()=> console.log("No Internet")
);
and for checking if online:
window.addEventListener("online",
()=> console.log("Connected Internet")
);

The HTML5 Application Cache API specifies navigator.onLine, which is currently available in the IE8 betas, WebKit (eg. Safari) nightlies, and is already supported in Firefox 3

I had to make a web app (ajax based) for a customer who works a lot with schools, these schools have often a bad internet connection I use this simple function to detect if there is a connection, works very well!
I use CodeIgniter and Jquery:
function checkOnline() {
setTimeout("doOnlineCheck()", 20000);
}
function doOnlineCheck() {
//if the server can be reached it returns 1, other wise it times out
var submitURL = $("#base_path").val() + "index.php/menu/online";
$.ajax({
url : submitURL,
type : "post",
dataType : "msg",
timeout : 5000,
success : function(msg) {
if(msg==1) {
$("#online").addClass("online");
$("#online").removeClass("offline");
} else {
$("#online").addClass("offline");
$("#online").removeClass("online");
}
checkOnline();
},
error : function() {
$("#online").addClass("offline");
$("#online").removeClass("online");
checkOnline();
}
});
}

an ajax call to your domain is the easiest way to detect if you are offline
$.ajax({
type: "HEAD",
url: document.location.pathname + "?param=" + new Date(),
error: function() { return false; },
success: function() { return true; }
});
this is just to give you the concept, it should be improved.
E.g. error=404 should still mean that you online

I know this question has already been answered but i will like to add my 10 cents explaining what's better and what's not.
Window.navigator.onLine
I noticed some answers spoke about this option but they never mentioned anything concerning the caveat.
This option involves the use of "window.navigator.onLine" which is a property under Browser Navigator Interface available on most modern browsers. It is really not a viable option for checking internet availability because firstly it is browser centric and secondly most browsers implement this property differently.
In Firefox: The property returns a boolean value, with true meaning online and false meaning offline but the caveat here is that
"the value is only updated when the user follows links or when a script requests a remote page." Hence if the user goes offline and
you query the property from a js function or script, the property will
always return true until the user follows a link.
In Chrome and Safari: If the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other
conditions return true. So while you can assume that the browser is
offline when it returns a false value, you cannot assume that a true
value necessarily means that the browser can access the internet. You
could be getting false positives, such as in cases where the computer
is running a virtualization software that has virtual ethernet
adapters that are always "connected".
The statements above is simply trying to let you know that browsers alone cannot tell. So basically this option is unreliable.
Sending Request to Own Server Resource
This involves making HTTP request to your own server resource and if reachable assume internet availability else the user is offline. There are some few caveats to this option.
No server availability is 100% reliant, hence if for some reason your server is not reachable it would be falsely assumed that the user is offline whereas they're connected to the internet.
Multiple request to same resource can return cached response making the http response result unreliable.
If you agree your server is always online then you can go with this option.
Here is a simple snippet to fetch own resource:
// This fetches your website's favicon, so replace path with favicon url
// Notice the appended date param which helps prevent browser caching.
fetch('/favicon.ico?d='+Date.now())
.then(response => {
if (!response.ok)
throw new Error('Network response was not ok');
// At this point we can safely assume the user has connection to the internet
console.log("Internet connection available");
})
.catch(error => {
// The resource could not be reached
console.log("No Internet connection", error);
});
Sending Request to Third-Party Server Resource
We all know CORS is a thing.
This option involves making HTTP request to an external server resource and if reachable assume internet availability else the user is offline. The major caveat to this is the Cross-origin resource sharing which act as a limitation. Most reputable websites blocks CORS requests but for some you can have your way.
Below a simple snippet to fetch external resource, same as above but with external resource url:
// Firstly you trigger a resource available from a reputable site
// For demo purpose you can use the favicon from MSN website
// Also notice the appended date param which helps skip browser caching.
fetch('https://static-global-s-msn-com.akamaized.net/hp-neu/sc/2b/a5ea21.ico?d='+Date.now())
.then(response => {
// Check if the response is successful
if (!response.ok)
throw new Error('Network response was not ok');
// At this point we can safely say the user has connection to the internet
console.log("Internet available");
})
.catch(error => {
// The resource could not be reached
console.log("No Internet connection", error);
});
So, Finally for my personal project i went with the 2nd option which involves requesting own server resource because basically there are many factors to tell if there is "Internet Connection" on a user's device, not just from your website container alone nor from a limited browser api.
Remember your users can also be in an environment where some websites or resources are blocked, prohibited and not accessible which in turn affects the logic of connectivity check. The best bet will be:
Try to access a resource on your own server because this is your users environment (Typically i use website's favicon because the response is very light and it is not frequently updated).
If there is no connection to the resource, simply say "Error in connection" or "Connection lost" when you need to notify the user rather than assume a broad "No internet connection" which depends on many factors.

I think it is a very simple way.
var x = confirm("Are you sure you want to submit?");
if (x) {
if (navigator.onLine == true) {
return true;
}
alert('Internet connection is lost');
return false;
}
return false;

The problem of some methods like navigator.onLine is that they are not compatible with some browsers and mobile versions, an option that helped me a lot was to use the classic XMLHttpRequest method and also foresee the possible case that the file was stored in cache with response XMLHttpRequest.status is greater than 200 and less than 304.
Here is my code:
var xhr = new XMLHttpRequest();
//index.php is in my web
xhr.open('HEAD', 'index.php', true);
xhr.send();
xhr.addEventListener("readystatechange", processRequest, false);
function processRequest(e) {
if (xhr.readyState == 4) {
//If you use a cache storage manager (service worker), it is likely that the
//index.php file will be available even without internet, so do the following validation
if (xhr.status >= 200 && xhr.status < 304) {
console.log('On line!');
} else {
console.log('Offline :(');
}
}
}

I was looking for a client-side solution to detect if the internet was down or my server was down. The other solutions I found always seemed to be dependent on a 3rd party script file or image, which to me didn't seem like it would stand the test of time. An external hosted script or image could change in the future and cause the detection code to fail.
I've found a way to detect it by looking for an xhrStatus with a 404 code. In addition, I use JSONP to bypass the CORS restriction. A status code other than 404 shows the internet connection isn't working.
$.ajax({
url: 'https://www.bing.com/aJyfYidjSlA' + new Date().getTime() + '.html',
dataType: 'jsonp',
timeout: 5000,
error: function(xhr) {
if (xhr.status == 404) {
//internet connection working
}
else {
//internet is down (xhr.status == 0)
}
}
});

How about sending an opaque http request to google.com with no-cors?
fetch('https://google.com', {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
mode: 'no-cors',
}).then((result) => {
console.log(result)
}).catch(e => {
console.error(e)
})
The reason for setting no-cors is that I was receiving cors errors even when disbaling the network connection on my pc. So I was getting cors blocked with or without an internet connection. Adding the no-cors makes the request opaque which apperantly seems to bypass cors and allows me to just simply check if I can connect to Google.
FYI: Im using fetch here for making the http request.
https://www.npmjs.com/package/fetch

My way.
<!-- the file named "tt.jpg" should exist in the same directory -->
<script>
function testConnection(callBack)
{
document.getElementsByTagName('body')[0].innerHTML +=
'<img id="testImage" style="display: none;" ' +
'src="tt.jpg?' + Math.random() + '" ' +
'onerror="testConnectionCallback(false);" ' +
'onload="testConnectionCallback(true);">';
testConnectionCallback = function(result){
callBack(result);
var element = document.getElementById('testImage');
element.parentNode.removeChild(element);
}
}
</script>
<!-- usage example -->
<script>
function myCallBack(result)
{
alert(result);
}
</script>
<a href=# onclick=testConnection(myCallBack);>Am I online?</a>

Just use navigator.onLine if this is true then you're online else offline

request head in request error
$.ajax({
url: /your_url,
type: "POST or GET",
data: your_data,
success: function(result){
//do stuff
},
error: function(xhr, status, error) {
//detect if user is online and avoid the use of async
$.ajax({
type: "HEAD",
url: document.location.pathname,
error: function() {
//user is offline, do stuff
console.log("you are offline");
}
});
}
});

You can try this will return true if network connected
function isInternetConnected(){return navigator.onLine;}

Here is a snippet of a helper utility I have. This is namespaced javascript:
network: function() {
var state = navigator.onLine ? "online" : "offline";
return state;
}
You should use this with method detection else fire off an 'alternative' way of doing this. The time is fast approaching when this will be all that is needed. The other methods are hacks.

There are 2 answers forthis for two different senarios:-
If you are using JavaScript on a website(i.e; or any front-end part)
The simplest way to do it is:
<h2>The Navigator Object</h2>
<p>The onLine property returns true if the browser is online:</p>
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = "navigator.onLine is " + navigator.onLine;
</script>
But if you're using js on server side(i.e; node etc.), You can determine that the connection is lost by making failed XHR requests.
The standard approach is to retry the request a few times. If it doesn't go through, alert the user to check the connection, and fail gracefully.

Related

Ajax GET Request is Sent Twice

I have encountered baffling behavior when running an Ajax request as part of my Flask application. I have written a handler receive a div click and then send an Ajax request with certain data to a specific route specified in my app.py. The data is then inserted into a database. While this approach worked fine when running my Flask app on my own machine, upon moving my app to another hosting service (Pythonanywhere), every time I click the div, the request is being sent twice, as evidenced by the data being inserted twice into the database.
Similar variants of this question have been asked before (here and here, for instance), but those questions all deal with POST requests, while mine is using a GET. Additionally, those questions generally involved an HTML form that was being submitted alongside the POST request, hence the additional request. However, my code does not have any forms.
My code sample (simplified, but the same in essence to my current efforts):
In frontend.html:
<div class='wrapper'>
<div class='submit_stamp' data-timestamp='2019-8-2'>Submit</div>
</div>
In frontend.js:
$('.wrapper').on('click', '.submit_stamp', function(){
$.ajax({
url: "/submit_time",
type: "get",
data: {time: $(this).data('timestamp')},
success: function(response) {
$('.wrapper').append(response.html);
},
});
});
In app.py:
#app.route('/submit_time')
def submit_time():
db_manager.submit_stamp(flask.request.args.get('time'))
return flask.jsonify({'html':'<p>Added timestamp</p>'})
As such, whenever I click the submit_stamp element, the Ajax request fires twice, the timestamp is inserted twice into my database, and "Added timestamp" is appended twice to .wrapper. Some things I have done to fix this include:
Adding an event.stopPropagation() in the handler
Using a boolean flag system where a variable is set to true just after the click, and reset to false in the success handler of the .ajax. I wrapped the $.ajax with this boolean in a conditional statement.
None of these patches worked. What confuses me, however, is why $.ajax is called once when running on my machine, but is called twice when running on the hosting service. Does it have to do with the cache? How can I resolve this issue? Thank you very much!
Edit:
Strangely, the duplicate requests occur infrequently. Sometimes, only one request is made, other times, the requests are duplicated. However, I have checked Network XHR output in Chrome and it is only displaying the single request header.
The access log output (with IPs removed):
<IP1> - - [05/Aug/2019:16:35:03 +0000] "GET /submit_time?payload=.... HTTP/1.1" 200 76 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1" "<IP>" response-time=0.217
<IP2> - - [05/Aug/2019:16:35:05 +0000] "GET /submit_time?payload=.... HTTP/1.1" 200 71 "http://www.katchup.work/create" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "<IP2>" response-time=0.198
With your latest update, I'd have to say this isn't a duplicate request. With your log saying one request was from Mozilla on a Windows based machine, and the other request coming from Chrome on a Mac, it's simply 2 different requests coming from two different locations that happen to be close to each other in time. Even if it was a test from a virtual machine, it shouldn't record the multiple OSs or browsers, as VM will take care of all translations, preventing confusion like this.
You don't include IP addresses, but if they are public addresses (as in something other than 127.x.x.x, 10.x.x.x, or 192.x.x.x) then they are definitely two different users that happen to be using your software at the same time.
If you are tracking that it's the same user, it might simply be them using your software on 2 different devices (such as a desktop vs mobile phone). If that's not allowed, then make sure their access reflects this. If it can be tracked through DNS to different geographical locations, you might have a compromised account to lock down until the real user can confirm their identity.
However you slice it, with the new data, I don't think it's actually your software, unless you can reproduce it through testing even somewhat reliably. Take time to consider that it might just Not be a bug, but something else. Software devs are conditioned to think everything is a bug and their fault, when it could be something benign or a malicious attack that might not have been previously considered.
Good luck and hopefully I gave you something to think about!
Thank you to everyone who responded. Ultimately, I was able to resolve this issue with two different solutions:
1) First, I was able to block the offending request by checking the IP in the backend:
#app.route('/submit_time')
def submit_time():
_ip = flask.request.environ.get('HTTP_X_REAL_IP', flask.request.remote_addr)
if _ip == '128.177.108.218':
return flask.jsonify({'route':'UNDEFINED-RESULT'.lower()})
return flask.jsonify({"html":'<p>Added timestamp</p>'})
The above is really more of a temporary hack, as there is no guarantee the target IP will stay the same.
2) However, I discovered that running on HTTPS also removed the duplicate request. Originally, I was loading my app from the Pythonanywhere dashboard, resulting in http://www.testsite.com. However, once I installed a proper SSL certificate, refreshed the page, and ran the request again, I found that the desired result was produced.
I am awarding the bounty to #computercarguy as his post prompted me to think about the external/network related reasons why my original attempt was failing.
Very unusual solution, but it should work (If not, I think the problem can't be solved with js.)
EDITED: Check the sent ID in the ajax request! (So check on server side!) This is sure will be a unique id, so, you can test with this #computercarguy has right or not.
let ids = []
function generateId(elem) {
let r = Math.random().toString(36).substring(7)
while ($.inArray(r, ids) !== -1) {
r = Math.random().toString(36).substring(7)
}
ids.push(r)
elem.attr("id", r)
}
$(document).ready(function() {
$(".wrapper").find(".submit_stamp").each(function() {
generateId($(this))
})
console.log(ids)
});
function ajaxHandler(stampElem, usedId) {
let testData = new FormData()
testData.append("time", stampElem.data('timestamp'))
testData.append("ID", usedId)
$.ajax({
url: "/submit_time",
type: "get",
data: testData,
success: function(response) {
$('.wrapper').append(response.html);
generateId(stampElem);
if (stampElem.attr("id").length) {
console.log("new id:"+stampElem.attr("id"));
}
},
});
}
$(".wrapper").on("click", ".submit_stamp", function(ev) {
ev.preventDefault()
ev.stopImmediatePropagation()
if ($(this).attr("id").length) {
let id = $(this).attr("id")
$("#"+id).one("click", $.proxy(ajaxHandler, null, $(this), id))
$(this).attr("id", "")
}
});
So first of all I would use below syntax as a personal preference
$('.wrapper').click(function (event) {
event.stopImmediatePropagation();
$.ajax({
url: "/submit_time",
type: "get",
data: {
time: $(this).data('timestamp')
},
success: function (response) {
$('.wrapper').append(response.html);
},
});
});
Also as I said, you need to make sure when you refer to two concurrent request, they are indeed from same IP+client, else you may be confusing between parallel request from different places to be repeated as such
Little change in your js file.
$('.wrapper').on('click', '.submit_stamp', function(event){
event.preventDefault();
event.stopImmediatePropagation();
$.ajax({
url: "/submit_time",
type: "get",
data: {time: $(this).data('timestamp')},
success: function(response) {
$('.wrapper').append(response.html);
},
});
});

Checking for an Internet connection before executing a page refresh [duplicate]

How to detect the Internet connection is offline in JavaScript?
Almost all major browsers now support the window.navigator.onLine property, and the corresponding online and offline window events. Run the following code snippet to test it:
console.log('Initially ' + (window.navigator.onLine ? 'on' : 'off') + 'line');
window.addEventListener('online', () => console.log('Became online'));
window.addEventListener('offline', () => console.log('Became offline'));
document.getElementById('statusCheck').addEventListener('click', () => console.log('window.navigator.onLine is ' + window.navigator.onLine));
<button id="statusCheck">Click to check the <tt>window.navigator.onLine</tt> property</button><br /><br />
Check the console below for results:
Try setting your system or browser in offline/online mode and check the log or the window.navigator.onLine property for the value changes.
Note however this quote from Mozilla Documentation:
In Chrome and Safari, if the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true. So while you can assume that the browser is offline when it returns a false value, you cannot assume that a true value necessarily means that the browser can access the internet. You could be getting false positives, such as in cases where the computer is running a virtualization software that has virtual ethernet adapters that are always "connected." Therefore, if you really want to determine the online status of the browser, you should develop additional means for checking.
In Firefox and Internet Explorer, switching the browser to offline mode sends a false value. Until Firefox 41, all other conditions return a true value; since Firefox 41, on OS X and Windows, the value will follow the actual network connectivity.
(emphasis is my own)
This means that if window.navigator.onLine is false (or you get an offline event), you are guaranteed to have no Internet connection.
If it is true however (or you get an online event), it only means the system is connected to some network, at best. It does not mean that you have Internet access for example. To check that, you will still need to use one of the solutions described in the other answers.
I initially intended to post this as an update to Grant Wagner's answer, but it seemed too much of an edit, especially considering that the 2014 update was already not from him.
You can determine that the connection is lost by making failed XHR requests.
The standard approach is to retry the request a few times. If it doesn't go through, alert the user to check the connection, and fail gracefully.
Sidenote: To put the entire application in an "offline" state may lead to a lot of error-prone work of handling state.. wireless connections may come and go, etc. So your best bet may be to just fail gracefully, preserve the data, and alert the user.. allowing them to eventually fix the connection problem if there is one, and to continue using your app with a fair amount of forgiveness.
Sidenote: You could check a reliable site like google for connectivity, but this may not be entirely useful as just trying to make your own request, because while Google may be available, your own application may not be, and you're still going to have to handle your own connection problem. Trying to send a ping to google would be a good way to confirm that the internet connection itself is down, so if that information is useful to you, then it might be worth the trouble.
Sidenote: Sending a Ping could be achieved in the same way that you would make any kind of two-way ajax request, but sending a ping to google, in this case, would pose some challenges. First, we'd have the same cross-domain issues that are typically encountered in making Ajax communications. One option is to set up a server-side proxy, wherein we actually ping google (or whatever site), and return the results of the ping to the app. This is a catch-22 because if the internet connection is actually the problem, we won't be able to get to the server, and if the connection problem is only on our own domain, we won't be able to tell the difference. Other cross-domain techniques could be tried, for example, embedding an iframe in your page which points to google.com, and then polling the iframe for success/failure (examine the contents, etc). Embedding an image may not really tell us anything, because we need a useful response from the communication mechanism in order to draw a good conclusion about what's going on. So again, determining the state of the internet connection as a whole may be more trouble than it's worth. You'll have to weight these options out for your specific app.
IE 8 will support the window.navigator.onLine property.
But of course that doesn't help with other browsers or operating systems. I predict other browser vendors will decide to provide that property as well given the importance of knowing online/offline status in Ajax applications.
Until that happens, either XHR or an Image() or <img> request can provide something close to the functionality you want.
Update (2014/11/16)
Major browsers now support this property, but your results will vary.
Quote from Mozilla Documentation:
In Chrome and Safari, if the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other conditions return true. So while you can assume that the browser is offline when it returns a false value, you cannot assume that a true value necessarily means that the browser can access the internet. You could be getting false positives, such as in cases where the computer is running a virtualization software that has virtual ethernet adapters that are always "connected." Therefore, if you really want to determine the online status of the browser, you should develop additional means for checking.
In Firefox and Internet Explorer, switching the browser to offline mode sends a false value. All other conditions return a true value.
if(navigator.onLine){
alert('online');
} else {
alert('offline');
}
There are a number of ways to do this:
AJAX request to your own website. If that request fails, there's a good chance it's the connection at fault. The JQuery documentation has a section on handling failed AJAX requests. Beware of the Same Origin Policy when doing this, which may stop you from accessing sites outside your domain.
You could put an onerror in an img, like <img src="http://www.example.com/singlepixel.gif" onerror="alert('Connection dead');" />.
This method could also fail if the source image is moved / renamed, and would generally be an inferior choice to the ajax option.
So there are several different ways to try and detect this, none perfect, but in the absence of the ability to jump out of the browser sandbox and access the user's net connection status directly, they seem to be the best options.
As olliej said, using the navigator.onLine browser property is preferable than sending network requests and, accordingly with developer.mozilla.org/En/Online_and_offline_events, it is even supported by old versions of Firefox and IE.
Recently, the WHATWG has specified the addition of the online and offline events, in case you need to react on navigator.onLine changes.
Please also pay attention to the link posted by Daniel Silveira which points out that relying on those signal/property for syncing with the server is not always a good idea.
You can use $.ajax()'s error callback, which fires if the request fails. If textStatus equals the string "timeout" it probably means connection is broken:
function (XMLHttpRequest, textStatus, errorThrown) {
// typically only one of textStatus or errorThrown
// will have info
this; // the options for this ajax request
}
From the doc:
Error: A function to be called if the request
fails. The function is passed three
arguments: The XMLHttpRequest object,
a string describing the type of error
that occurred and an optional
exception object, if one occurred.
Possible values for the second
argument (besides null) are "timeout",
"error", "notmodified" and
"parsererror". This is an Ajax Event
So for example:
$.ajax({
type: "GET",
url: "keepalive.php",
success: function(msg){
alert("Connection active!")
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
if(textStatus == 'timeout') {
alert('Connection seems dead!');
}
}
});
window.navigator.onLine
is what you looking for, but few things here to add, first, if it's something on your app which you want to keep checking (like to see if the user suddenly go offline, which correct in this case most of the time, then you need to listen to change also), for that you add event listener to window to detect any change, for checking if the user goes offline, you can do:
window.addEventListener("offline",
()=> console.log("No Internet")
);
and for checking if online:
window.addEventListener("online",
()=> console.log("Connected Internet")
);
The HTML5 Application Cache API specifies navigator.onLine, which is currently available in the IE8 betas, WebKit (eg. Safari) nightlies, and is already supported in Firefox 3
I had to make a web app (ajax based) for a customer who works a lot with schools, these schools have often a bad internet connection I use this simple function to detect if there is a connection, works very well!
I use CodeIgniter and Jquery:
function checkOnline() {
setTimeout("doOnlineCheck()", 20000);
}
function doOnlineCheck() {
//if the server can be reached it returns 1, other wise it times out
var submitURL = $("#base_path").val() + "index.php/menu/online";
$.ajax({
url : submitURL,
type : "post",
dataType : "msg",
timeout : 5000,
success : function(msg) {
if(msg==1) {
$("#online").addClass("online");
$("#online").removeClass("offline");
} else {
$("#online").addClass("offline");
$("#online").removeClass("online");
}
checkOnline();
},
error : function() {
$("#online").addClass("offline");
$("#online").removeClass("online");
checkOnline();
}
});
}
an ajax call to your domain is the easiest way to detect if you are offline
$.ajax({
type: "HEAD",
url: document.location.pathname + "?param=" + new Date(),
error: function() { return false; },
success: function() { return true; }
});
this is just to give you the concept, it should be improved.
E.g. error=404 should still mean that you online
I know this question has already been answered but i will like to add my 10 cents explaining what's better and what's not.
Window.navigator.onLine
I noticed some answers spoke about this option but they never mentioned anything concerning the caveat.
This option involves the use of "window.navigator.onLine" which is a property under Browser Navigator Interface available on most modern browsers. It is really not a viable option for checking internet availability because firstly it is browser centric and secondly most browsers implement this property differently.
In Firefox: The property returns a boolean value, with true meaning online and false meaning offline but the caveat here is that
"the value is only updated when the user follows links or when a script requests a remote page." Hence if the user goes offline and
you query the property from a js function or script, the property will
always return true until the user follows a link.
In Chrome and Safari: If the browser is not able to connect to a local area network (LAN) or a router, it is offline; all other
conditions return true. So while you can assume that the browser is
offline when it returns a false value, you cannot assume that a true
value necessarily means that the browser can access the internet. You
could be getting false positives, such as in cases where the computer
is running a virtualization software that has virtual ethernet
adapters that are always "connected".
The statements above is simply trying to let you know that browsers alone cannot tell. So basically this option is unreliable.
Sending Request to Own Server Resource
This involves making HTTP request to your own server resource and if reachable assume internet availability else the user is offline. There are some few caveats to this option.
No server availability is 100% reliant, hence if for some reason your server is not reachable it would be falsely assumed that the user is offline whereas they're connected to the internet.
Multiple request to same resource can return cached response making the http response result unreliable.
If you agree your server is always online then you can go with this option.
Here is a simple snippet to fetch own resource:
// This fetches your website's favicon, so replace path with favicon url
// Notice the appended date param which helps prevent browser caching.
fetch('/favicon.ico?d='+Date.now())
.then(response => {
if (!response.ok)
throw new Error('Network response was not ok');
// At this point we can safely assume the user has connection to the internet
console.log("Internet connection available");
})
.catch(error => {
// The resource could not be reached
console.log("No Internet connection", error);
});
Sending Request to Third-Party Server Resource
We all know CORS is a thing.
This option involves making HTTP request to an external server resource and if reachable assume internet availability else the user is offline. The major caveat to this is the Cross-origin resource sharing which act as a limitation. Most reputable websites blocks CORS requests but for some you can have your way.
Below a simple snippet to fetch external resource, same as above but with external resource url:
// Firstly you trigger a resource available from a reputable site
// For demo purpose you can use the favicon from MSN website
// Also notice the appended date param which helps skip browser caching.
fetch('https://static-global-s-msn-com.akamaized.net/hp-neu/sc/2b/a5ea21.ico?d='+Date.now())
.then(response => {
// Check if the response is successful
if (!response.ok)
throw new Error('Network response was not ok');
// At this point we can safely say the user has connection to the internet
console.log("Internet available");
})
.catch(error => {
// The resource could not be reached
console.log("No Internet connection", error);
});
So, Finally for my personal project i went with the 2nd option which involves requesting own server resource because basically there are many factors to tell if there is "Internet Connection" on a user's device, not just from your website container alone nor from a limited browser api.
Remember your users can also be in an environment where some websites or resources are blocked, prohibited and not accessible which in turn affects the logic of connectivity check. The best bet will be:
Try to access a resource on your own server because this is your users environment (Typically i use website's favicon because the response is very light and it is not frequently updated).
If there is no connection to the resource, simply say "Error in connection" or "Connection lost" when you need to notify the user rather than assume a broad "No internet connection" which depends on many factors.
I think it is a very simple way.
var x = confirm("Are you sure you want to submit?");
if (x) {
if (navigator.onLine == true) {
return true;
}
alert('Internet connection is lost');
return false;
}
return false;
The problem of some methods like navigator.onLine is that they are not compatible with some browsers and mobile versions, an option that helped me a lot was to use the classic XMLHttpRequest method and also foresee the possible case that the file was stored in cache with response XMLHttpRequest.status is greater than 200 and less than 304.
Here is my code:
var xhr = new XMLHttpRequest();
//index.php is in my web
xhr.open('HEAD', 'index.php', true);
xhr.send();
xhr.addEventListener("readystatechange", processRequest, false);
function processRequest(e) {
if (xhr.readyState == 4) {
//If you use a cache storage manager (service worker), it is likely that the
//index.php file will be available even without internet, so do the following validation
if (xhr.status >= 200 && xhr.status < 304) {
console.log('On line!');
} else {
console.log('Offline :(');
}
}
}
I was looking for a client-side solution to detect if the internet was down or my server was down. The other solutions I found always seemed to be dependent on a 3rd party script file or image, which to me didn't seem like it would stand the test of time. An external hosted script or image could change in the future and cause the detection code to fail.
I've found a way to detect it by looking for an xhrStatus with a 404 code. In addition, I use JSONP to bypass the CORS restriction. A status code other than 404 shows the internet connection isn't working.
$.ajax({
url: 'https://www.bing.com/aJyfYidjSlA' + new Date().getTime() + '.html',
dataType: 'jsonp',
timeout: 5000,
error: function(xhr) {
if (xhr.status == 404) {
//internet connection working
}
else {
//internet is down (xhr.status == 0)
}
}
});
How about sending an opaque http request to google.com with no-cors?
fetch('https://google.com', {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
mode: 'no-cors',
}).then((result) => {
console.log(result)
}).catch(e => {
console.error(e)
})
The reason for setting no-cors is that I was receiving cors errors even when disbaling the network connection on my pc. So I was getting cors blocked with or without an internet connection. Adding the no-cors makes the request opaque which apperantly seems to bypass cors and allows me to just simply check if I can connect to Google.
FYI: Im using fetch here for making the http request.
https://www.npmjs.com/package/fetch
My way.
<!-- the file named "tt.jpg" should exist in the same directory -->
<script>
function testConnection(callBack)
{
document.getElementsByTagName('body')[0].innerHTML +=
'<img id="testImage" style="display: none;" ' +
'src="tt.jpg?' + Math.random() + '" ' +
'onerror="testConnectionCallback(false);" ' +
'onload="testConnectionCallback(true);">';
testConnectionCallback = function(result){
callBack(result);
var element = document.getElementById('testImage');
element.parentNode.removeChild(element);
}
}
</script>
<!-- usage example -->
<script>
function myCallBack(result)
{
alert(result);
}
</script>
<a href=# onclick=testConnection(myCallBack);>Am I online?</a>
request head in request error
$.ajax({
url: /your_url,
type: "POST or GET",
data: your_data,
success: function(result){
//do stuff
},
error: function(xhr, status, error) {
//detect if user is online and avoid the use of async
$.ajax({
type: "HEAD",
url: document.location.pathname,
error: function() {
//user is offline, do stuff
console.log("you are offline");
}
});
}
});
Just use navigator.onLine if this is true then you're online else offline
You can try this will return true if network connected
function isInternetConnected(){return navigator.onLine;}
Here is a snippet of a helper utility I have. This is namespaced javascript:
network: function() {
var state = navigator.onLine ? "online" : "offline";
return state;
}
You should use this with method detection else fire off an 'alternative' way of doing this. The time is fast approaching when this will be all that is needed. The other methods are hacks.
There are 2 answers forthis for two different senarios:-
If you are using JavaScript on a website(i.e; or any front-end part)
The simplest way to do it is:
<h2>The Navigator Object</h2>
<p>The onLine property returns true if the browser is online:</p>
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = "navigator.onLine is " + navigator.onLine;
</script>
But if you're using js on server side(i.e; node etc.), You can determine that the connection is lost by making failed XHR requests.
The standard approach is to retry the request a few times. If it doesn't go through, alert the user to check the connection, and fail gracefully.

is there a way to detect what type of image is being loaded from an img src that is redirected?

I'm using the this facebook service to return profile pictures.
<img src="http://graph.facebook.com/username/picture">
If the fb user did not set a profile picture, the service redirects to this facebook anonymous person image: http://static.ak.fbcdn.net/rsrc.php/v2/yo/r/UlIqmHJn-SK.gif. I would like to avoid presenting those.
Is there a way, using javascript, to detect if the image returned is http://static.ak.fbcdn.net/rsrc.php/v2/yo/r/UlIqmHJn-SK.gif. That address is from a CDN, so I wonder if we can just check the file size is <= 390B and mime-type is image/gif?
EDIT: Unfortunately the solutions involving only modern browsers (HTML5 and canvas) might not work for me since the requirement is that we still need to support back to ie7.
Yes there is, you can simply make your request with AJAX and parse the MIME-type yourself. Indeed, Facebook includes this header:
Access-Control-Allow-Origin: *
This authorizes CORS (Cross Origin Resource Sharing), which is now supported by most browsers.
If you absolutely must support old browsers, have a look at the Open Graph documentation:
https://developers.facebook.com/docs/reference/api/using-pictures/
Instead of directly fetching the picture, you can just fetch its metadata with JSONP. This should work in IE7:
function checkPictureUrl(userName, cb) {
$.ajax({
url: 'http://graph.facebook.com/' + userName + '/picture?redirect=false',
dataType: 'jsonp',
success: function (json) {
// user only has a default profile picture
if(json.data.is_silhouette)
return cb(null);
else
return cb(null, json.data.url);
},
error: function (err) {
cb(err);
}
});
}

MooTools Request Failing

So I have a bit of a problem. When I ask MooTools to send a request it comes back as failed every time. I can't seem to diagnose the problem either because if I try to get the returned header info the console just gives me "Refused to get unsafe header 'Status'" Message. The only thing I can think of is that the server isn't letting me access outside resources but maybe I just coded it wrong.
Here's the request code:
var finfo = current.textFontData();
var url = 'http://antiradiant.com/clients/TMW/rbwizard/mailer.php?s='+current.size+'&b='+current.box+'&l='+current.lidWood+'&c='+current.cartID+'&f='+finfo.font+'&l1='+finfo.line1+'&l2='+finfo.line2;
console.log(url);
var req = new Request({
url: url,
onSuccess: function() {
console.log('success');
//atc2.send();
},
onFailure: function() {
console.log('failure');
console.log(this.getHeader('Status'));
//atc2.send();
},
onException: function(headerName, value) {
console.log('exception');
console.log(headerName+': '+value);
}
});
req.send();
This code is derived from the resource rb_wizard.js (lines 81-103) on http://tylermorriswoodworking.myshopify.com/pages/recipe-box-wizard?b=maple&l=cherry&s=3x5&c=42042892
Mootools has a class called Request.JSONP that will help with your cross domain problem. Its sub class of the Request class, so your methods should work the same. I believe you need to call .post() or .get() at the end instead of send, but thats about all that should chnge. I'm not sure what version you're running on but here is the link tot he docs Mootools Request.JSONP
The error message "Refused to get unsafe header 'Status'" is spat out by WebKit based browsers (Safari, Chrome, etc) when you violate the cross-domain security model.
Therefore, it seems likely that the code you pasted is located on a domain other than antiradiant.com, and therefore is not allowed (by the browser) to request sites on antiradiant.com.
What I ended up doing was just using an iframe. All I really had to do was send data to another site and not receive any so it worked out.

Firefox XMLHttpRequest sets error flag on a 302 response

I have a web app driven by a servlet that times out users' sessions after a period of inactivity by redirecting to a login page. I had code in place on the web client that checked for this, essentially similar to the following:
function error(request, errtype) {
if (request.status == 302) {
// Display a "timed out" dialog, then:
window.location = request.getResponseHeader("Location");
}
}
However, recently this scheme stopped working; on timeout, the request.status was 0. Using Firebug I could see that the same HTTP 302 response was being returned.
I read the spec for XMLHttpRequest carefully, and found this section:
If the redirect does not violate security (it is same origin for instance), infinite loop precautions, and the scheme is supported, transparently follow the redirect while observing the same-origin request event rules.
Otherwise, this is a network error.
I hadn't even known that clients were supposed to automatically follow redirects that they get in response to Ajax requests; the browsers I care about didn't do that before, since my code above used to work. I recently upgraded my version of Firefox, which now perhaps is following the spec more closely. The network error prescribed by the spec would explain the zero response code I'm seeing. However, the redirect I'm getting is to the same host (albeit on a different port), there shouldn't be an infinite loop, and the scheme remains HTTP, so I don't understand why I'm getting a network error.
Any ideas?
how you are you getting to this function? if you're only sending it to "error" on a 200 status obviously this wouldn't work...
request.onreadystatechange = function( )
{
if( this.readyState == 4 )
{
// if we got a 200
if( this.status == 200 ){ /* cool */ }
// if we got anything else
else { error( this, this.status ); }
}
};
But I'm assuming you know this. Also, you should probably include .href at the end of window.location and possibly a default location just in case
// Display a "timed out" dialog, then:
window.location.href = request.getResponseHeader("Location") || defaultPage;
If this doesn't work, you might wanna try a different status in the onreadystatechange method, as some browsers may interpret a non 200 status as an error. These could be (from that same spec you're reading from):
0 (if it's considered aborted after unset, though unlikely)
2 (headers-sent) as that 302 code is actually a HTTP header
good luck!

Categories