This question already has answers here:
Detect the Internet connection is offline?
(22 answers)
Closed 8 years ago.
How do you check if there is an internet connection using jQuery? That way I could have some conditionals saying "use the google cached version of JQuery during production, use either that or a local version during development, depending on the internet connection".
The best option for your specific case might be:
Right before your close </body> tag:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"><\/script>')</script>
This is probably the easiest way given that your issue is centered around jQuery.
If you wanted a more robust solution you could try:
var online = navigator.onLine;
Read more about the W3C's spec on offline web apps, however be aware that this will work best in modern web browsers, doing so with older web browsers may not work as expected, or at all.
Alternatively, an XHR request to your own server isn't that bad of a method for testing your connectivity. Considering one of the other answers state that there are too many points of failure for an XHR, if your XHR is flawed when establishing it's connection then it'll also be flawed during routine use anyhow. If your site is unreachable for any reason, then your other services running on the same servers will likely be unreachable also. That decision is up to you.
I wouldn't recommend making an XHR request to someone else's service, even google.com for that matter. Make the request to your server, or not at all.
What does it mean to be "online"?
There seems to be some confusion around what being "online" means. Consider that the internet is a bunch of networks, however sometimes you're on a VPN, without access to the internet "at-large" or the world wide web. Often companies have their own networks which have limited connectivity to other external networks, therefore you could be considered "online". Being online only entails that you are connected to a network, not the availability nor reachability of the services you are trying to connect to.
To determine if a host is reachable from your network, you could do this:
function hostReachable() {
// Handle IE and more capable browsers
var xhr = new ( window.ActiveXObject || XMLHttpRequest )( "Microsoft.XMLHTTP" );
// Open new request as a HEAD to the root hostname with a random param to bust the cache
xhr.open( "HEAD", "//" + window.location.hostname + "/?rand=" + Math.floor((1 + Math.random()) * 0x10000), false );
// Issue request and handle response
try {
xhr.send();
return ( xhr.status >= 200 && (xhr.status < 300 || xhr.status === 304) );
} catch (error) {
return false;
}
}
You can also find the Gist for that here: https://gist.github.com/jpsilvashy/5725579
Details on local implementation
Some people have commented, "I'm always being returned false". That's because you're probably testing it out on your local server. Whatever server you're making the request to, you'll need to be able to respond to the HEAD request, that of course can be changed to a GET if you want.
Ok, maybe a bit late in the game but what about checking with an online image?
I mean, the OP needs to know if he needs to grab the Google CMD or the local JQ copy, but that doesn't mean the browser can't read Javascript no matter what, right?
<script>
function doConnectFunction() {
// Grab the GOOGLE CMD
}
function doNotConnectFunction() {
// Grab the LOCAL JQ
}
var i = new Image();
i.onload = doConnectFunction;
i.onerror = doNotConnectFunction;
// CHANGE IMAGE URL TO ANY IMAGE YOU KNOW IS LIVE
i.src = 'http://gfx2.hotmail.com/mail/uxp/w4/m4/pr014/h/s7.png?d=' + escape(Date());
// escape(Date()) is necessary to override possibility of image coming from cache
</script>
Just my 2 cents
5 years later-version:
Today, there are JS libraries for you, if you don't want to get into the nitty gritty of the different methods described on this page.
On of these is https://github.com/hubspot/offline. It checks for the connectivity of a pre-defined URI, by default your favicon. It automatically detects when the user's connectivity has been reestablished and provides neat events like up and down, which you can bind to in order to update your UI.
You can mimic the Ping command.
Use Ajax to request a timestamp to your own server, define a timer using setTimeout to 5 seconds, if theres no response it try again.
If there's no response in 4 attempts, you can suppose that internet is down.
So you can check using this routine in regular intervals like 1 or 3 minutes.
That seems a good and clean solution for me.
You can try by sending XHR Requests a few times, and then if you get errors it means there's a problem with the internet connection.
I wrote a jQuery plugin for doing this. By default it checks the current URL (because that's already loaded once from the Web) or you can specify a URL to use as an argument. Always doing a request to Google isn't the best idea because it's blocked in different countries at different times. Also you might be at the mercy of what the connection across a particular ocean/weather front/political climate might be like that day.
http://tomriley.net/blog/archives/111
i have a solution who work here to check if internet connection exist :
$.ajax({
url: "http://www.google.com",
context: document.body,
error: function(jqXHR, exception) {
alert('Offline')
},
success: function() {
alert('Online')
}
})
Sending XHR requests is bad because it could fail if that particular server is down. Instead, use googles API library to load their cached version(s) of jQuery.
You can use googles API to perform a callback after loading jQuery, and this will check if jQuery was loaded successfully. Something like the code below should work:
<script type="text/javascript">
google.load("jquery");
// Call this function when the page has been loaded
function test_connection() {
if($){
//jQuery WAS loaded.
} else {
//jQuery failed to load. Grab the local copy.
}
}
google.setOnLoadCallback(test_connection);
</script>
The google API documentation can be found here.
A much simpler solution:
<script language="javascript" src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script>
and later in the code:
var online;
// check whether this function works (online only)
try {
var x = google.maps.MapTypeId.TERRAIN;
online = true;
} catch (e) {
online = false;
}
console.log(online);
When not online the google script will not be loaded thus resulting in an error where an exception will be thrown.
This is the error message that I get:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided
('https://www.youtube.com') does not match the recipient window's origin
('http://localhost:9000').
I've seen other similar problems where the target origin is http://www.youtube.com and the recipient origin is https://www.youtube.com, but none like mine where the target is https://www.youtube.com and the origin is http://localhost:9000.
I don't get the problem. What is the problem?
How can I fix it?
I believe this is an issue with the target origin being https. I suspect it is because your iFrame url is using http instead of https. Try changing the url of the file you are trying to embed to be https.
For instance:
'//www.youtube.com/embed/' + id + '?showinfo=0&enablejsapi=1&origin=http://localhost:9000';
to be:
'https://www.youtube.com/embed/' + id + '?showinfo=0&enablejsapi=1&origin=http://localhost:9000';
Just add the parameter "origin" with the URL of your site in the paramVars attribute of the player, like this:
this.player = new window['YT'].Player('player', {
videoId: this.mediaid,
width: '100%',
playerVars: {
'autoplay': 1,
'controls': 0,
'autohide': 1,
'wmode': 'opaque',
'origin': 'http://localhost:8100'
},
}
Setting this seems to fix it:
this$1.player = new YouTube.Player(this$1.elementId, {
videoId: videoId,
host: 'https://www.youtube.com',
You can save the JavaScript into local files:
https://www.youtube.com/player_api
https://s.ytimg.com/yts/jsbin/www-widgetapi-vfluxKqfs/www-widgetapi.js
Into the first file, player_api put this code:
if(!window.YT)var YT={loading:0,loaded:0};if(!window.YTConfig)var YTConfig={host:"https://www.youtube.com"};YT.loading||(YT.loading=1,function(){var o=[];YT.ready=function(n){YT.loaded?n():o.push(n)},window.onYTReady=function(){YT.loaded=1;for(var n=0;n<o.length;n++)try{o[n]()}catch(i){}},YT.setConfig=function(o){for(var n in o)o.hasOwnProperty(n)&&(YTConfig[n]=o[n])}}());
Into the second file, find the code: this.a.contentWindow.postMessage(a,b[c]);
and replace it with:
if(this._skiped){
this.a.contentWindow.postMessage(a,b[c]);
}
this._skiped = true;
Of course, you can concatenate into one file - will be more efficient.
This is not a perfect solution, but it's works!
My Source : yt_api-concat
Make sure you are loading from a URL such as:
https://www.youtube.com/embed/HIbAz29L-FA?modestbranding=1&playsinline=0&showinfo=0&enablejsapi=1&origin=https%3A%2F%2Fintercoin.org&widgetid=1
Note the "origin" component, as well as "enablejsapi=1". The origin must match what your domain is, and then it will be whitelisted and work.
In my case this had to do with lazy loading the iframe. Removing the iframe HTML attribute loading="lazy" solved the problem for me.
I got the same error. My mistake was that the enablejsapi=1 parameter was not present in the iframe src.
You also get this message when you do not specify a targetOrigin in calls to window.postMessage().
In this example we post a message to the first iFrame and use * as target, which should allow communication to any targetOrigin.
window.frames[0].postMessage({
message : "Hi there",
command :"hi-there-command",
data : "Some Data"
}, '*')
Try using window.location.href for the url to match the window's origin.
Remove DNS Prefetch will solve this issue.
If you're using WordPress, add this line in your theme's functions.php
remove_action( 'wp_head', 'wp_resource_hints', 2 );
There could be any of the following, but all of them lead into DOM not loaded before its accessed by the javascript.
So here is what you have to ensure before actually calling JS code:
* Make sure the container has loaded before any javascript is called
* Make sure the target URL is loaded in whatever container it has to
I came across the similar issue but on my local when I am trying to have my Javascript run well before onLoad of the main page which causes the error message. I have fixed it by simply waiting for whole page to load and then call the required function.
You could simply do this by adding a timeout function when page has loaded and call your onload event like:
window.onload = new function() {
setTimeout(function() {
// some onload event
}, 10);
}
that will ensure what you are trying will execute well after onLoad is trigger.
In my instance at least this seems to be a harmless "not ready" condition that the API retries until it succeeds.
I get anywhere from two to nine of these (on my worst-case-tester, a 2009 FossilBook with 20 tabs open via cellular hotspot).... but then the video functions properly. Once it's running my postMessage-based calls to seekTo definitely work, haven't tested others.
It looks it's only a Chrome security system to block repeated requests, using CORB.
https://www.chromestatus.com/feature/5629709824032768
In my case, YouTube was blocking Access after the first load of the same webpage which has many video API data request, high payload.
For pages with low payload, the issue does not occur.
In Safari and other non Chronuim based browsers, the issue does not occur.
If I load the webpage in a new browser, the issue does not occur, when I reload the same page, the issue appears.
In some cases (as one commenter mentioned) this might be caused if you are moving the player within DOM, like append or etc..
This helped me (with Vue.js)
Found here vue-youtube
mounted() {
window.YTConfig = {
host: 'https://www.youtube.com/iframe_api'
}
const host = this.nocookie ? 'https://www.youtube-nocookie.com' : 'https://www.youtube.com'
this.player = player(this.$el, {
host,
width: this.width,
height: this.height,
videoId: this.videoId,
playerVars: this.playerVars
})
...
}
UPDATE:
Working like a charm like this:
...
youtube(
video-id="your_video_code_here"
nocookie
)
...
data() {
return {
playerVars: {
origin: window.location.href,
},
};
},
I think the description of the error is misleading and has originally to do with wrong usage of the player object.
I had the same issue when switching to new Videos in a Slider.
When simply using the player.destroy() function described here the problem is gone.
I had this same problem and it turns out it was because I had the Chrome extension "HTTPS Everywhere" running. Disabling the extension solved my problem.
This exact error was related to a content block by Youtube when "playbacked on certain sites or applications". More specifically by WMG (Warner Music Group).
The error message did however suggest that a https iframe import to a http site was the issue, which it wasn't in this case.
You could change your iframe to be like this and add origin to be your current website. It resolves error on my browser.
<iframe class="test-testimonials-youtube-group" type="text/html" width="100%" height="100%"
src="http://www.youtube.com/embed/HiIsKeXN7qg?enablejsapi=1&origin=http://localhost:8000"
frameborder="0">
</div>
ref: https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
Just wishing to avoid the console error, I solved this using a similar approach to Artur's earlier answer, following these steps:
Downloaded the YouTube Iframe API (from https://www.youtube.com/iframe_api) to a local yt-api.js file.
Removed the code which inserted the www-widgetapi.js script.
Downloaded the www-widgetapi.js script (from https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl7VfO1r/www-widgetapi.js) to a local www-widgetapi.js file.
Replaced the targetOrigin argument in the postMessage call which was causing the error in the console, with a "*" (indicating no preference - see https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage).
Appended the modified www-widgetapi.js script to the end of the yt-api.js script.
This is not the greatest solution (patched local script to maintain, losing control of where messages are sent) but it solved my issue.
Please see the security warning about removing the targetOrigin URI stated here before using this solution - https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Patched yt-api.js example
Adding origin=${window.location.host} or "*" is not enough.
Add https:// before it and it will work.
Also, make sure that you are using an URL that can be embedded: take the video ID out and concatenate a string that has the YouTube video prefix and the video ID + embed definition.
I think we could customize the sendMessage of the YT.Player
playerOptions.playerVars.origin = window.location.origin or your domain.
this.youtubePlayer = new YT.Player(element,playerOptions);
this.youtubePlayer.sendMessage = function (a) {
a.id = this.id, a.channel = "widget", a = JSON.stringify(a);
var url = new URL(this.h.src), origin = url.searchParams.get("origin");
if (origin && this.h.contentWindow) {
this.h.contentWindow.postMessage(a, origin)
}
}
I used this function to resolve in my project.
Extending #Hokascha's answer above it was also lazy loading for me being automatically added by WordPress. This code will remove all lazy loading on the site's iframes (add to functions.php):
function disable_post_content_iframe_lazy_loading( $default, $tag_name, $context ) {
if ( 'iframe' === $tag_name ) {
return false;
}
return $default;
}
add_filter('wp_lazy_loading_enabled', 'disable_post_content_iframe_lazy_loading', 10, 3);
I got a similar error message in my attempt to embed a Stripe pricing table when:
Adding the embed code via PHP through a custom WordPress short code
Or by appending the code to the page dynamically with JavaScript (Even a using a setTimeout() delay to ensure the DOM was loaded didn't work).
I was able to solve this on my WordPress site by adding the code to the WordPress page itself using plain html code in the block editor.
mine was:
<youtube-player
[videoId]="'paxSz8UblDs'"
[playerVars]="playerVars"
[width]="291"
[height]="194">
</youtube-player>
I just removed the line with playerVars, and it worked without errors on console.
You can try :
document.getElementById('your_id_iframe').contentWindow.postMessage('your_message', 'your_domain_iframe')
I was also facing the same issue then I visit official Youtube Iframe Api where i found this:
The user's browser must support the HTML5 postMessage feature. Most modern browsers support postMessage
and wander to see that official page was also facing this issue. Just Visit official Youtube Iframe Api and see console logs. My Chrome version is 79.0.3945.88.
I have some problems with page navigation using Windows Phone 8 with Apache Cordova 3.0.
I tried different ways to solve this problems but it still does not work.
At first i tried to use forms to navigate to another page.
<form action="CreateUser.html" method="get">
<input class="buttons" name="btnCreateUser" type="submit" value="Create User" />
</form>
When i click on the button the page can not be found. The CreateUser.html page is in the same directory. If i use a Browser (Chrome/IE) it works.
When i change the action to http://www.google.com both options (Browser and Phone) work.
I also tried to navigate to another page by using JavaScript. Here is my code:
function get(httpUrl) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", httpUrl, true);
xmlHttp.send(null);
return xmlHttp.responseText;
}
Now i use onclick="get("CreateUser")" event of the button but there is no reaction.
Both in the browser and on the mobile device.
The only thing that worked for me is the window.location feature. But it seems that i can't transform informations on the next page with that way.
Is there any opportuinity to navigate between those two pages and transfer some information?
Or did i just something wrong in my code?
"The CreateUser.html page" if i'm correct you are using AJAX to read file (page) contents and paste them in HTML?
If yes, then read this:
2.1. Cross-domain problem
Before making AJAX request you must allow cross-domain requests and core support, by setting:
jQuery.support.cors = true;
$.mobile.allowCrossDomainPages = true;
Those must be set in a specific-phonegap function “DeviceReady”, example:
document.addEventListener('deviceready', function () {
jQuery.support.cors = true;
$.mobile.allowCrossDomainPages = true;
$.ajax({
url: "www/about.txt",
dataType: 'text'
}).done(function (result) {
alert(result);
});
});
2.2. url
Making Windows Phone 8 oriented application, in AJAX request you MUST specify full path to resource, example:
url: "www/about.txt",
Making Windows Phone 8 oriented application, in AJAX request you MUST NOT specify full path to resource, example:
url: "about.txt",
2.3. Source File extensions
Be careful using unknown extension files, like template extension *.tpl or similar. Sometimes AJAX doesn’t like them, I suggest using simple *.txt and *.html extensions.
This is what I am trying to accomplish:
Get the static content of an 'external' url and check it for certain keywords for example, "User Guide" or "page not found".
I tried to use Ajax, dojo.xhr etc., but they don't support cross domain. In my case it is an external url. Also, I cannot use jQuery.
I also looked at dojo.io.iframe but I couldn't find useful example to accomplish this.
A dojo.io.iframe example would be really helpful.
Please help.
Thanks!
Modern browsers restrict the use of cross-domain scripting. If you're the maintainer of the server, read Access-Control-Allow-Origin to get knowledge on how to enable cross-site scripting on your website.
EDIT: To check whether an external site is down or not, you could use this method. That external site is required to have an image file. Most sites have a file called favicon.ico at their root directory.
Example, testing whether http://www.google.com/ is online or not.
var test = new Image();
//If you're sure that the element is not a JavaScript file
//var test = document.createElement("script");
//If you're sure that the external website is reliable, you can use:
//var test = document.createElement("iframe");
function rmtmp(){if(tmp.parentNode)tmp.parentNode.removeChild(tmp);}
function online(){
//The website is likely to be up and running.
rmtmp();
}
function offline(){
//The file is not a valid image file, or the website is down.
rmtmp();
alert("Something bad happened.");
}
if (window.addEventListener){
test.addEventListener("load", online, true);
test.addEventListener("error", offline, true);
} else if(window.attachEvent){
test.attachEvent("onload", online);
test.attachEvent("onerror", offline);
} else {
test.onload = online;
test.onerror = offline;
}
test.src = "http://www.google.com/favicon.ico?"+(new Date).getTime();
/* "+ (new Date).getTime()" is needed to ensure that every new attempt
doesn't get a cached version of the image */
if(/^iframe|script$/i.test(test.tagName)){
test.style.display = "none";
document.body.appendChild(test);
}
This will only work with image resources. Read the comments to see how to use other sources.
Try this:
<script src="https://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/dojo.xd.js.uncompressed.js" type="text/javascript" djConfig="parseOnLoad:true"></script>
<script>
dojo.require("dojo.io.script");
</script>
<script>
dojo.addOnLoad(function(){
dojo.io.script.get({
url: "http://badlink.google.com/",
//url: "http://www.google.com/",
load: function(response, ioArgs) {
//if no (http) error, it means the link works
alert("yes, the url works!")
}
});
});
</script>
I find this excellent code, posted by aemkei as answers to this questions:
How do you dynamically load a javascript file? (Think C’s #include)
Use javascript to inject script references as needed?
You may write dynamic script tags
(using Prototype):
new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});
The problem here is that we do not
know when the external script file is
fully loaded.
We often want our dependant code on
the very next line and like to write
something like:
if (iNeedSomeMore){
Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
myFancyMethod(); // cool, no need for callbacks!
}
There is a smart way to inject script
dependencies without the need of
callbacks. You simply have to pull the
script via a synchronous AJAX request
and eval the script on global level.
If you use Prototype the Script.load
method looks like this:
var Script = {
_loadedScripts: [],
include: function(script){
// include script only once
if (this._loadedScripts.include(script)){
return false;
}
// request file synchronous
var code = new Ajax.Request(script, {
asynchronous: false, method: "GET",
evalJS: false, evalJSON: false
}).transport.responseText;
// eval code on global level
if (Prototype.Browser.IE) {
window.execScript(code);
} else if (Prototype.Browser.WebKit){
$$("head").first().insert(Object.extend(
new Element("script", {type: "text/javascript"}), {text: code}
));
} else {
window.eval(code);
}
// remember included script
this._loadedScripts.push(script);
}
};
I found that, the code does not work on IE if the all of them is executed in 'file://' protocol, however, it is not the problem since its use case involved real web application.
I tried it once to include http://www.google-analytics.com/urchin.js by google, but from one of web page, but it looks like it cannot request javascript file from different domain.
How we could dynamically add javascript, just like what above scripts does, but from another domain?
You can use the onload and onreadystatechange event to understand when the <script> tag is loaded.
var script = new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});
script.onload = script.onreadystatechange = function(){
if (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") {
//script is loaded
}
};
The security model in modern browsers prevents JavaScript from making cross-domain requests. That has holes (see every website exploit since the beginning of the internet), but using them is more than a little shady and it's only a matter of time before they're patched.
What Rex said is correct, although HTML5 has added cross domain messaging and xhr, which require a little bit of work on your part but should be usable to achieve this. Alas they're not yet present in all released browsers (i think the latest betas of safari, firefox, and IE have support for some of these features, but i'm not sure which browsers support which apis)