views:

22

answers:

2

Hi there fellow SOers,

I'm trying to do my own bookmarklet and I already tried to read some response in SO but nothing to answer the weird reaction I got from my script.

I'm doing an AJAX call from my bookmarklet, so I do the little trick :

var newScript = document.createElement("script");
newScript.type = "text/javascript";
newScript.src = "http://example.com/urlToMyJS.js";
document.body.appendChild(newScript);
void(0);

And the urlToMyJS.js is like this :

var u = 'http://example.com/scriptToCall.php';
var request = new XMLHttpRequest();
request.open("GET", u, true);
request.onreadystatechange = function() {
  var done = 4, ok = 200;
  if (request.readyState == done && request.status == ok) {
    if (request.responseText) {
      alert(request.responseText);
    }
  }
};
request.send(null);

The weird part is :

  • The javascript is always launched and scriptToCall.php is always called too (it logs every hit)
  • The alert shows the responseText when I click on the bookmarklet on example.com
  • Sometimes, on other sites, the alert shows nothing (but still appears)
  • Some other times, the alert doesn't even show... (but I still have the log hit...)

Do you have any idea why it does that? And if yes, do you have any idea how I could make it always show the responseText?

A: 

status won't be ok unless you are testing the bookmarklet on your own site (example.com).

When you run the bookmarklet on a different site to example.com (which is after all the whole point of having a bookmarklet), it will be doing a cross-origin XMLHttpRequest to example.com. Depending on what browser you're using, that might do the request, but you won't be able to read the response due to the Same Origin Policy. It's an essential security feature that you can't make user-impersonating XMLHttpRequests to other servers.

If you want to make an XMLHttpRequest back to your server, you must do it from a document on your server, typically by having the bookmarklet create an <iframe> pointing to example.com.

Alternatively, use JSONP (<script> inclusion) to call scriptToCall.php.

bobince
Chouchenos
Yeah, it's the location of the document that *includes* the script that is important; the source of the JS file is immaterial to the Same Origin Policy.
bobince
I get it. But I used this "hack" for a chrome extension and it works... Is it because the request comes from a localhost ?
Chouchenos
Code running in an extension is privileged and is allowed to do cross-origin requests (and can avoid the Some Origin Policy in general, amongst other features too dangerous to allow general web pages to do).
bobince
Thanks for the answer, very useful to me :)
Chouchenos
A: 

Well, finally, I used another trick :

var newScript = document.createElement("script");
newScript.type = "text/javascript";
newScript.src = "http://example.com/scriptToCall.php";
document.body.appendChild(newScript);
void(0);

This way (the PHP is sending a javascript header), no more AJAX. It was nonsense in my case since both file were in the same server/folder, 1 movement instead of 2!

Anyway, thanks bobince for all the details I might use in the future !

Chouchenos
Also look into CORS - useful...
mplungjan
hoooo, I didn't know about that. Interesting, but it doesn't work with IE7 apparently :-( (and FF < 3.5) Unless you know any hack ?
Chouchenos