I'm trying to load the source of a web page, as shown in "Javascript:The Definitive Guide" p.481, using firefox.
Here's my code:
var request = new XMLHttpRequest();
request.open("GET", "http://finance.yahoo.com/q?s=PG", false);
request.send(null);
if (request.status==200) { alert(request.responseText); }
else {alert("Error "+request.status + ": "+request.statusText);}
</script>
Firebug shows the GET statement, followed by 200 OK X 338ms.
Which looks like it was successful (code 200).
But the next Firebug line says: NS_ERROR_FAILURE, request.send(null);, with no further explanation.
and neither alert gets executed.
It doesn't help if I use help mode, and doesn't run in Chrome either. I don't have a popup or cookie or ad blocker running.
The page loads fine in perl with an LWP get().
If this is an inevitable cross-domain taboo, why doesn't the "definitive guide" say so?
I understand that JSONP returns JSON. I don't want that - I want just a string with the raw source, like with the perl LWP get().
Is this impossible with Javascript?
I suppose I could write a batch file which uses perl to get the source and put it into a JSON file whose name is hard-coded into the JS. But I'd like to avoid that sort of kludge.
In case it helps,
I have run into this problem a couple times before, and ran into it again. If the answer to this question doesn't help you, try adding the following lines which helped me:
request.overrideMimeType('text/xml; charset=UTF-8'); // needed to get utf8 req's to work
or this debug line (which you can monitor on the web console of your browser)
request.onreadystatechange = function() {console.log("statechanged. url= " + url);};
before your
request.open()
where url is a var that holds the url you are trying to request. Sometimes it will give you that cryptic error if there is a problem getting the url, in my (last) case, it was because the url was malformed. Hope that helps someone out there.
Related
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.
I've run into this funny issue I don't even know how to begin explaining but I'll do my best. So I have a website with a bunch of dynamic pages such as music, movies, etc., each in the form of an index.php inside a directory of its name. So, the music page calls the index.php in the /music folder and so on. I also have a WP blog that sits inside /blog.
When you open the music page, it queries a table and lists out the first 12 entries it retrieves. Along with the list, it also adds a "Load More" button to the page. Clicking this button triggers an XHR call to a back-end file (/assets/engines/more_music_engine.php). This engine file in turn queries the table for the next 12 entries and echoes the result to the /music/index.php page that initially called the engine.
This set up works perfectly fine. Until you visit any of the blog pages (it could be the main blog page or any of its sub-pages, e.g., posts, tags, authors, etc.). When you try revisiting the music page after having visited a blog page first, the XHR breaks down! Not only this, even the status code is not consistent across browsers. On Safari, I get a 0 whereas on Firefox, it's 500. This problem persists until you reload the page in a new tab or window.
Has anyone faced anything similar here and if so, what were the findings? I can share the codes but I need to know which parts to share. The entire dump would be impractically big for pasting here. For starters, here's the JS function making the XHR call:
function moretracks(){
var trackdivs = document.getElementsByTagName('trackitem');
var countoftracks = trackdivs.length;
var mus = $('#mus');
var totalcount = parseInt($('totalcount').text(), 10);
$('#loadmore-container').remove();
var waittext = '<div class="loading text-center"><i class="fa fa-4x fa-spinner fa-spin"></i></div>';
var hr = createXMLHTTPRequestObject();
var url = 'assets/engines/more_music_engine.php';
var vars = "count=" + countoftracks + "&totalcount=" + totalcount;
hr.open("POST", url, true);
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
hr.onreadystatechange = function(){
if(hr.readyState == 4 && hr.status == 200){
$('.loading').remove();
var return_data = hr.responseText;
mus.append(return_data);
}
else if(hr.status == 500){
mus.html("Something went wrong! Please try again later...");
}
}
hr.send(vars);
mus.append(waittext);
}
And here's the button that triggers this function:
<button id="loadmore" class="btn btn-lg btn-brown" onClick="moretracks();">See more</button>
The page in question is live at peppyburro.com/music.
Here's a portion of the server-side more_music_engine.php file:
<?php
require_once 'Admin/Connector.php';
include_once('simplehtmldom_1_5/simple_html_dom.php');
$clientcount = $_POST['count'];
$totalcount = $_POST['totalcount'];
// further processing...
?>
I repeat, the response code is 500 in FF and 0 in Safari. Upon debugging and tracing, I found that the server-side script isn't receiving an empty _POST which is hard to explain since the same script works like a charm when the page is reloaded in a different tab.
Here's a dump of my error.log file:
[20-Jul-2016 06:40:35 Etc/GMT] PHP Notice: Undefined index: count in /home/peppyoil/public_html/assets/engines/more_music_engine.php on line 5
[20-Jul-2016 06:40:35 Etc/GMT] PHP Notice: Undefined index: totalcount in /home/peppyoil/public_html/assets/engines/more_music_engine.php on line 6
[20-Jul-2016 06:40:35 Etc/GMT] PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' 12' at line 1' in /home/peppyoil/public_html/assets/engines/more_music_engine.php:12
Stack trace:
#0 /home/peppyoil/public_html/assets/engines/more_music_engine.php(12): PDOStatement->execute()
#1 {main}
thrown in /home/peppyoil/public_html/assets/engines/more_music_engine.php on line 12
Note that this log is only generated when running on FF (500). When running on Safari (response code 0), no log is generated.
Update: I replaced XHR with AJAX and the issue persisted. On Firefox, the error thrown is this:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://www.peppyburro.com/assets/engines/more_music_engine.php. (Reason: missing token 'x-requested-with' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel).
This doesn't make sense since the requesting script is a part of the file (peppyburro.com/music.php) that is also sitting on the same domain!
I tried to do a simple AJAX request on http://localhost:8080/ and I get an error right away when using IE 11. I don't think IE is even trying to send anything.
Did somebody meet this issue?
Here is a fiddle showing this behavior,
html:
<button id='btn1'>launch</button>
onLoad:
var xhr,btn=document.getElementById('btn1');
btn.onclick=onButton;
var onReadyState=function(){
console.log('ready state:'+_xhr.readyState);
if(xhr.readyState===4){
console.log('status:'+_xhr.status);
}
}
function onButton(){
xhr=new window.XMLHttpRequest();
xhr.onreadystatechange=onReadyState;
xhr.open('POST','http://localhost:8080/ScanAPI/v1/client');
xhr.send();
}
You will need to launch the IE F12 developer tool, before trying and you will see IE catching the exception.
Any help on this would be greatly appreciated.
Thanks!
It doesn't work because you are referencing an object named _xhr that does not exist within the scope of the onReadyState function.
You should be using this instead :
var onReadyState = function() {
if (this.readyState === 4) {
console.log('status :' + this.status);
}
};
That's because the XMLHttpRequest object will call back onReadyState with its own context, which is accessible through this in your function.
Also note that the onReadyState function misses a semi-colon at the end of its definition, didn't notice it at first sight.
EDIT : I also noticed that IE10 (and IE11) does interpret some HTTP response code as network errors (such as with a 401 response code), if it is your case, then it makes sense that IE fails at retrieving your resource.
I forked your fiddle and wrote a simple page that works well with IE11.
I was using fiddler core proxy to do some script injection. I noticed that gmail login just failed after its login progress bar moving forward and backward for some time. A sample is given below using c#, tested using google chrome as the browser. The below code goes inside the beforeresponse event of fiddler proxy where oS is the HTTP session.
oS.utilDecodeResponse();
oS.utilReplaceInResponse("</body>", "<script type='text/javascript'>var a = 10;</script></body>");
Updated
As Eric have suggested I made sure that the script is not making conflict with any other java script variables. Added the script only in the expected page when gmail logs in. However the problem is still there.
if (oS.oRequest.headers.HTTPMethod == "GET" || oS.oRequest.headers.HTTPMethod == "POST")
{ //exclude other HTTP Status codes
if (oS.oResponse.headers.HTTPResponseStatus == "200 OK")
{
if (!oS.oRequest.headers.Exists("X-Requested-With"))
{
var accept = oS.oRequest.headers.FindAll("Accept");
if (accept[0].Value.Contains("text/html"))
{
if (oS.oResponse.MIMEType == "text/html")
{
oS.utilDecodeResponse();
string script = "alert("Hello");"
//The main http request after gmail login has a response with a script closing tag before body closing, so I am replacing it with my script added.
oS.utilReplaceOnceInResponse("</script></body>", script + "</script></body>", false));
}
}
}
}
}
Works fine with chrome, however in safari and opera, alert is called infinitely so as the HTTP request to reload the page.
The problem you're having is that your replacement is insufficiently precise. You're replacing ALL instances of </body> on ALL pages with a string containing quotation marks. However, in some of the instances, the string you're replacing is appearing within JavaScript strings in the Google application, and as a consequence you're mangling the JavaScript string and causing a script error.
Use the following script sample to get a better understanding of all of the places you're replacing, then update your script to more specifically replace the expected string on only the expected page.
oSession.utilDecodeResponse();
if (oSession.utilReplaceInResponse("</body>", '<!-- INJECTED --></body>'))
{
oSession["ui-backcolor"] = "lime";
}
I'm trying to write a bookmarklet to help some QA testers submit useful debugging information when they come across issues. Currently I can set window.location to a URL that provides this debugging information, but this resource is an XML document with an xml-stylesheet processing directive.
It would actually be more convenient if the testers were able to see either the raw XML data as plain text, or the default XML rendering for IE and Firefox.
Does anyone know a way to disable or override xml-stylesheet directives provided inside an XML document, using Internet Explorer or Firefox?
Edit: I've opened a bounty on this question. Requirements:
Client-side code only, no user intervention allowed
Solutions for both IE and Firefox needed (they can be different solutions)
Disabling stylesheet processing and rendering it as text is acceptable
Overriding stylesheet processing with a custom XSL is acceptable
Rendering the XML with the browser default XML stylesheet is acceptable
EDIT: too bad, though all seemed fine in the preview, the clickable examples seem to mess up things... Maybe the layout is fine in the history.
I've heard, but cannot validate for IE, that both IE and Firefox support the "view-source:" pseudo-protocol. Firefox on Mac indeed understands it, but Safari does not.
The following bookmarklet will not trigger the XSLT transformation specified in the XML. And though Firefox will render this using some colours, it does not execute the default transformation it would normally use for XML without any XSLT (so, the result of view-source does NOT yield a collapsable document tree that Firefox would normally show):
javascript:(function(){
var u = 'http://www.w3schools.com/xsl/cdcatalog_with_ex1.xml';
var w = window.open();
w.document.location.href = 'view-source:' + u;
})()
When fetching the document using Ajax then one is not limited to the alert oneporter used, but can display it in a new window as well. Again: this will not invoke the XSLT transformation that is specified:
javascript:(function(){
var u = 'http://www.w3schools.com/xsl/cdcatalog_with_ex1.xml';
var w = window.open(); /* open right away for popup blockers */
var x = new XMLHttpRequest();
x.open('GET', u, true);
x.onreadystatechange = function(){
if(x.readyState == 4){
w.document.open('text/html');
/* hack to encode HTML entities */
var d = document.createElement('div');
var t = document.createTextNode(x.responseText);
d.appendChild(t);
w.document.write('<html><body><pre>'
+ d.innerHTML + '</pre></body></html>');
w.document.close();
w.focus();
}
};
x.send(null);
})()
Can't you just do "View Source" in both browsers?
You can avoid a processing instruction by using an intermediary step to pre-process the XML before the content is output in the browser.
Client-side suggestion
Retrieve the relevant XML document via an AJAX request
Parse the XML into a DOM (note: a DOM not the DOM)
Traverse the DOM and render in the browser the required data
Server-side suggestion
Instead of directly requesting the pertinent XML document, make a request instead to a proxy script that removed from the XML content all processing instructions, or indeed all that you don't want.
Instead of:
window.location = 'http://example.com/document.xml';
use:
window.location = 'http://example.com/proxy/';
The script at http://example.com/proxy/ would:
Load document.xml
Use whatever is necessary to remove the processing instruction from the XML content
Output the XML content
As long as you wouldn't have to deal with cross domain permissions, a simple ajax request / alert box with the XML source would do the trick. You'll have to add a little bit to the xmlHttp declaration to make it compatible with IE.
<html>
<body>
<script language="JavaScript">
function ajaxFunction()
{
var xmlHttp=new XMLHttpRequest();;
xmlHttp.onreadystatechange=function()
{
if(xmlHttp.readyState==4)
{
alert(xmlHttp.responseText);
}
}
xmlHttp.open("GET","YOURFILE.xml",true);
xmlHttp.send(null);
}
</script>
Errors
</body>
</html>
As far as I know, there is no way of doing what you are trying to do. The issue is, javascript cannot read the dom of the xml from a client side xml/xsl transform. As far as the javascript is concerned, it is executing on a normal html dom.
However, there may be some hope depending on the type of webapp. You could use ajax to get the xml of the current url. As long as there is no post data, or any other randomness, this method should work fine.