When I type a certain URL in FF, I get the XML returned displayed on the screen, so the web service is apparently working. However, when I try to access it from a local HTML document running JS, I get unexpected behavior. The returned code is "200 OK" but there's no text (or rather it's an empty string) nor xml (it's null) in the response sections according to FireBug.
This is how I make the call.
var httpObject = new XMLHttpRequest();
httpObject.open("GET", targetUrl, true);
httpObject.onreadystatechange = function () {
if (httpObject.readyState == 4) {
var responseText = httpObject.responseText;
var responseXml = httpObject.responseXML;
}
}
httpObject.send(null);
Why does it happen and how do I tackle it?
That may be an HTTP header problem (e.g. missing Accept header); observe the headers sent by FF (you can use Firebug for that) and try to replicate them in your script (setRequestHeader).
Otherwise, that may be a "same origin policy" problem.
Related
I'm trying to retrieve the online status of users from a chat client called IMVU(the regular little image holder by the profile pictures isn't enough, I'm making something bigger, so I need some signal), and the way to do that is use this line of the user ID 1111111 for example:
http://avatars.imvu.com/catalog/web_status_updater.php?ol=1&list=1111111
It returns a php file containing a line of JSON. I need that whole line of text put into a javascript variable so I can use it.
I need to use this in a script I'm making, but I can't seem to get it to work. I've tried lots of things, the closest seems to be this one:
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
alert(allText);
}
}
}
rawFile.send(null);
}
readTextFile("http://avatars.imvu.com/catalog/web_status_updater.php?ol=1&list=1111111");
(I'll change the alert(allText); to return allText; or return rawFile.responseText; when I get this experiment to work first and make sure that the text is actually stored and displayed.)
What happens is that the alert shows up blank. Just a white box, that's all. My prior attempts had the box show up and it said "undefined", but now it's doing something I guess? Why is it blank though? And how do I fix it?
EDIT:
It works in IE but not Firefox apparently.
I believe the problem here is the Same Origin Policy. You are attempting to make a request to a domain that is different than the one that originated the request.
Some websites specify headers which allow this, but the headers returned here are missing the Access-Control-Allow-Origin header.
One way around this is to use JSON-P on servers that support it.
Try this:
jQuery.ajax({
url:"http://avatars.imvu.com/catalog/web_status_updater.php?ol=1&list=1111111",
dataType:"jsonp"
})
.done(function(data) {
console.log(data)
});
I’m having a devil of a time between XHTML, PHP, and JavaScript. My intent is to have a user select an option from a form menu and have that update the innerHTML of a DIV with the content of a separate PHP page. For instance, choosing "Cat" would call "animaloptions.php?species=cat", and the result of that would be thrown into the DIV block. However, if I specify the Content-Type of the calling page through PHP’s Header function, then my code fails.
The following is my JavaScript code:
function showOptions(str) {
if (str == "") {
document.getElementById("mainArea").innerHTML = "";
return;
}
xmlhttp = new XMLHttpRequest();
if (xmlhttp) {
xmlhttp.open("GET", "animaloptions.php", true);
xmlhttp.setRequestHeader("Content-Type", "application/xhtml+xml; charset=utf-8");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("mainArea").innerHTML = xmlhttp.responseText;
}
else {
document.getElementById("mainArea").innerHTML = "Loading…";
}
}
xmlhttp.send("species=" + str);
}
}
This code works if I don’t include the following PHP code in the page that calls it:
header('Content-Type: application/xhtml+xml; charset=utf-8');
Doing so prevents the responseText from ever loading, presumably because readyState, status, or both don’t match the values I specified. If I don’t check for those conditions, then responseText is simply undefined.
My guess is asking PHP to send a raw HTTP header will prevent my XMLHttpRequest from functioning as expected. The problem is I need to send this raw header because the Web server is not identifying the page as UTF-8 on its own (thank you, unnamed Web host), and including the standard <?xml version=1.0 encoding=utf-8 ?> is impossible since my Web host turned on short tags in PHP. (Yes, I tried using echo to slap this into the page, but PHP automatically turns it into a commented line for some reason, which is a separate problem.)
Am I simply misusing XMLHttpRequest objects? Is there a practical way around this?
EDIT
I should have specified what I meant by “is not working”. In Safari's development tool, I see animaloptions.php added as a resource with code processed by PHP, but its contents are not added to the DIV block (or any block). If they were, then I would no longer see this page as a separate resource. If I use responseText in the JavaScript code, then the browser throws a DOM Error 12 (An invalid or illegal string was specified). If I use responseXML, then I get no error and no text, but animaloptions.php shows up under resources all the same.
Here is a demo In short brief:
If somebody clicks on change text next() function will be triggered.
next() function sends the relative data to ajax_next_track.php and retrieves a random data.
Then it replaces texts in artist_name and track_name spans with the random data.
These all works fine in Firefox and Chrome. However, it doesn't in Internet Explorer. If you click on change text more than two times with different browsers you can see the problem.
In other browsers, there will be an operation time with 'loading...' text in screen; but it happens immediately with no operation time in internet explorer.
Function next() can not send the data to ajax file.
So, how can i fix it?
Thanks is advance.
function next(tags)
{
var hr = new XMLHttpRequest();
var url = 'ajax_next_track.php?tags=' + tags;
hr.open("GET", url, true);
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
hr.onreadystatechange = function()
{
if(hr.readyState == 4 && hr.status == 200)
{
var return_data = hr.responseText;
jsonObj = JSON.parse(return_data);
document.getElementById("artist_name").innerHTML = jsonObj.artist_name;
document.getElementById("track_name").innerHTML = jsonObj.track_name;
document.getElementById("name").title = 'play '+jsonObj.artist_name+' - '+jsonObj.track_name+' radio';
else
{
}
}
document.getElementById("track_name").innerHTML = 'loading...';
document.getElementById("artist_name").innerHTML = '';
hr.send(null);
}
<div id="player">
<div id="playPauseOutDiv" onclick="pause();">
</div>
<div id="artist_track">
<span id="artist_name">gerry rafferty</span>
<span id="track_name">baker street</span>
</div>
</a>
<div id="ikinciSatir">
<a id="changeSong" title="Shuffle" href="javascript:void(0);" onclick="next('3871');">Change</a>
</div>
</div>
I ran into the same problem just 2 days ago. I was using IE8, and subsequent ajax call wasn't really made but IE8 try to use cache instead.
I found this on ajax documentation page
By default, requests are always issued, but the browser may serve results out of its cache. To disallow use of the cached results, set cache to false. To cause the request to report failure if the asset has not been modified since the last request, set ifModified to true.
Try if it helps. Here's the documentation http://api.jquery.com/jQuery.ajax/
For some reason, IE caches the JSON file and gets 304 Not Modified response instead of 200 OK each time after the 1st one.
The easiest workaround for this that doesn't need to change server side settings is to add some random parameter to the requested URL on each request, e.g.
var url = 'ajax_next_track.php?tags=' + tags + '&nocache=' + Math.random();
The error in IE's debugger says line 40 document.getElementById("name") is null or not an object. I see spans named "artist_name" and "track_name" in your html, but no "name".
I'm trying to implement sms functionality in Dynamics CRM 2011. I've created a custom activity for this and added a button to the form of an SMS. When hitting the button, a sms should be send.
I need to make an http request for this and pass a few parameters. Here's the code triggered:
function send() {
var mygetrequest = new ajaxRequest()
mygetrequest.onreadystatechange = function () {
if (mygetrequest.readyState == 4) {
if (mygetrequest.status == 200 || window.location.href.indexOf("http") == -1) {
//document.getElementById("result").innerHTML = mygetrequest.responseText
alert(mygetrequest.responseText);
}
else {
alert("An error has occured making the request")
}
}
}
var nichandle = "MT-1234";
var hash = "md5";
var passphrase = "[encryptedpassphrase]";
var number = "32497123456";
var content = "testing sms service";
mygetrequest.open("GET", "http://api.smsaction.be/push/?nichandle=" + nichandle + "&hash=" + hash + "&passphrase=" + passphrase + "&number=" + number + "&content=" + content, true)
mygetrequest.send(null)
}
function ajaxRequest() {
var activexmodes = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] //activeX versions to check for in IE
if (window.ActiveXObject) { //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
for (var i = 0; i < activexmodes.length; i++) {
try {
return new ActiveXObject(activexmodes[i])
}
catch (e) {
//suppress error
}
}
}
else if (window.XMLHttpRequest) // if Mozilla, Safari etc
return new XMLHttpRequest()
else
return false
}
I get the "access is denied error" on line:
mygetrequest.open("GET", "http://api.smsaction.be/push/?nichandle=" ......
Any help is appreciated.
The retrieving site has to approve cross domain AJAX requests. Usually, this is not the case.
You should contact smsaction.be or check their FAQ to see if they have any implementation in place.
Usually JSONP is used for cross domain requests, and this has to be implemented on both ends.
A good way to overcome this, is using your own site as a proxy. Do the AJAX requests to an script on your side, and let it do the call. In example PHP you can use cURL
I suppose the SMS-service is in different domain. If so, you cannot make AJAX-call to it, because it violates same origin policy. Basically you have two choices:
Do the SMS-sending on server-side
Use JSONP
Also, is it really so that the passphrase and other secrets are visible in HTML? What prevents people from stealing it and using it for their own purposes?
Your AJAX requests by default will fail because of Same Origin Policy.
http://en.wikipedia.org/wiki/Same_origin_policy
Modern techniques allow CORS ( see artilce by Nicholas ) http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
jQuery's Ajax allow CORS.
Another way to do it is to get the contents and dynamically generate a script element and do an insertBefore on head.firstchild ( refer jQuery 1.6.4 source line no : 7833 )
Google analytics code does some thing similar as well. you might want to take a look at that too.
Cheers..
Sree
For your example, when requesting from different domain error is:
XMLHttpRequest cannot load http://api.smsaction.be/push/?nichandle=??????&hash=?????&passphrase=[???????????]&number=????????????&content=???????????????. Origin http://server is not allowed by Access-Control-Allow-Origin.
For cross domains XMLHttp requests destination server must send Access-Control-Allow-Origin response header.
MDN: https://developer.mozilla.org/en/http_access_control
I do a bunch of json requests with dynamic script tags. Is it possible to detect if there's an error in the request (eg. 503 error, 404 error) and run something on detection of the error?
use ajax instead. AFAIK there is no way to detect if a script tag loads or not, and if not, why it didn't load. Using ajax you can load the json and it will tell you why it didn't load.
Using a library like jQuery this becomes very simple:
$.ajax({
type: "GET",
url: "test.js",
dataType: "script",
error: function(xhr, error, exception){
alert(xhr.status); //Will alert 404 if the script does not exist
}
});
AFAIK, there's no way to access status code of some external asset loaded from the document (such as script, style or image). Even detecting error (via, say, onerror event handler) is not that widely supported across browsers.
If whatever you're loading falls under SOP, use XHR which gives you access to response headers. Otherwise, you can try looking into recently introduced X-domain XHR.
I'm assuming you want this to work cross-domain, which is why you can't use XHR?
Try creating two script tags for each request, the first does your standard JSONP request, the second is basically an error handler.
If the first script tag executes, then clear the error handler in your callback. But if the first gets a 404, the error handler inside the second script tag will be run.
You probably also want to set a timeout, to cope with a slow JSONP response.
http://www.phpied.com/javascript-include-ready-onload/ ?
If you're using jQuery, check out jQuery-JSONP which is a jQuery plugin that does a fairly decent job of doing the <script> insertion for you as well as detecting fetch errors.
Quoting from the project page, jQuery-JSONP features:
error recovery in case of network failure or ill-formed JSON responses,
precise control over callback naming and how it is transmitted in the URL,
multiple requests with the same callback name running concurrently,
two caching mechanisms (browser-based and page based),
the possibility to manually abort the request just like any other AJAX request,
a timeout mechanism.
If you need to cross domains (and need the page to work portably), you have to use dynamic script tags.
If you have access to the remote server, you can pass back an error code from the server, and have the server page return 200.
Whether you have access or not, you can use setTimeout when you create the script tag, passing a function that will trigger an error if it expires before the jsonp handler is called. Make sure that the jsonp handler aborts if the error handler has been called.
You'll need to track each request through a global collection, but you'll gain the ability to cancel and count requests. This is similar to the way that XHR objects are managed by a library like jQuery.
If you want to detect errors, listen for an error event and compare the fileName property of the error with the file name of the script. If they match, you then handle the error. The thing is, I think that the fileName property is Firefox and Opera-only. Most browsers that have a stacktrace for errors can also simulate this behaviour.
Here's an example, as requested by Eric Bréchemier:
var getErrorScriptNode = (function () {
var getErrorSource = function (error) {
var loc, replacer = function (stack, matchedLoc) {
loc = matchedLoc;
};
if ("fileName" in error) {
loc = error.fileName;
} else if ("stacktrace" in error) { // Opera
error.stacktrace.replace(/Line \d+ of .+ script (.*)/gm, replacer);
} else if ("stack" in error) { // WebKit
error.stack.replace(/at (.*)/gm, replacer);
loc = loc.replace(/:\d+:\d+$/, "");
}
return loc;
},
anchor = document.createElement("a");
return function (error) {
anchor.href = getErrorSource(error);
var src = anchor.href,
scripts = document.getElementsByTagName("script");
anchor.removeAttribute("href");
for (var i = 0, l = scripts.length; i < l; i++) {
anchor.href = scripts.item(i).src;
if (anchor.href === src) {
anchor.removeAttribute("href");
return scripts.item(i);
}
}
};
}());