jQuery.getJSON inside a greasemonkey user script - javascript

I am attempting to write a user script that makes a cross domain AJAX request.
I have included jQuery inside my script using #require and everything seems to be working fine up until the point where I try to run jQuery.getJSON.
The API I am accessing supports jsonp, however I keep getting an error stating jsonp123456789 is not defined.
From what I have been able to gather this is due to jQuery writing the jsonp response directly into the head of the page, which then becomes sandboxed. Once that has occured jQuery can no longer access the callback resulting in it being undefined. (I'm not 100% on this being the case, but it seems likely to me).
Is there any way to work around this? It has been suggested I declare the callback function inside unsafeWindow but I'm unsure how to do this and haven't managed to get it to work.

Wouldn't it be nice if jQuery used GM_xmlhttpRequest internally so that you could have all the convenience of the jQuery methods and the cross-site functionality of Greasemonkey? As mahemoff points out, Greasemonkey could let you make the request without relying on JSONP and running into the callback problem you're facing, but you'll have to deal with the JSON contents yourself.
We've written a library that will do just that: the Greasemonkey/jQuery XHR bridge. If you #require that script in your userscript, then all $.get and $.getJSON and $.post, etc. jQuery calls will work cross-site without relying on techniques like JSONP.
So if you use this bridge and simply remove the ?callback=? from your URL, your jQuery code should work without modification. This blog post provides a step-by-step walkthrough. If anyone has any questions, comments, bug reports or suggestions about the bridge plugin, please let me know.

The workaround is to use GM_HttpRequest. You can get away with it, instead of JSONP for cross-domain requests, because unlike the usual XHR, GM_HttpRequest does allow cross-domain calls. You want something like:
GM_xmlhttpRequest({
method: "GET",
url: "http://example.com/path/to/json",
onload: function(xhr) {
var data = eval("(" + xhr.responseText + ")");
// use data ...
}
});
Note that this eval's JSON the simplest way. If you want a more secure solution for untrusted JSON, you'll need to include a small JSON-parsing library.
Unfortunately, you also have to wrap a seemingly useless zero-duration setTimeout around the whole thing. I find it easiest to stick the GM_xmlhttpRequest in its own method, then run setTimeout(makeCall, 0);.
You can see a real example here.

As many of you will know, Google Chrome doesn't support any of the handy GM_ functions at the moment.
As such, it is impossible to do cross site AJAX requests due to various sandbox restrictions (even using great tools like James Padolsey's Cross Domain Request Script)
I needed a way for users to know when my Greasemonkey script had been updated in Chrome (since Chrome doesn't do that either...). I came up with a solution which is documented here (and in use in my Lighthouse++ script) and worth a read for those of you wanting to version check your scripts:
http://blog.bandit.co.nz/post/1048347342/version-check-chrome-greasemonkey-script

Related

Getting access to a XML from javascript without Node-Without JQuery

I am trying to developp modifications to a game. The thing is the game is already compiled and the developpers prefer not to decompile the game (for the time beeing). Because of the compilation probably, everytime I try to load JQuery or Node.js whatever version I get the error "that a key already exists in the dictionary". The thing is everything is fine without Node.js or JQuery.js.
What I am trying to achieve is add some features to the game that unfortunately aren't available through the Game's API function call itself. I want to be able to get access to data Inside .xml files used for items/weapons/devices/engines spécifications of items Inside the game. I've tried pretty much all I could find on Stackexchange with what I searched for which was Node and JQuery. Im sorry if you guys think this is a duplicate question. Because it isn't. I can't use Node.js neither can i use JQuery. What else could I try? can someone help me please.
I am a bit new to programing with only 1 year experience in c# and Javascript. Sorry if this feels really noObish to you guys.
What you need is ajax. Modern browsers provide a pretty functional XMLHttpRequest, so you don’t even need a framework anymore.
One important thing to know: you most likely won’t be able to download the xml file using ajax if it’s on a distant server, due to the same-origin policy. You need a reliable access to it. The most convenient solution is to have a copy of the file on a local server such as WAMP, XAMPP, and the like.
I’m not going to write yet another ajax tutorial. Insteal I’ll just provide you with a working minimal HTML page, and point you towards XMLHttpRequest documentation.
<button>Request</button>
<script>
'use strict';
document.querySelector('button').addEventListener('click',
function () {
let req = new XMLHttpRequest();
req.onload = function () {
if (this.responseXML) {
console.log(this.responseXML);
}
else {
console.log(this.responseText);
}
};
req.open('GET', xmlURL); // xmlURL should be the location of the .xml file
req.send();
});
</script>
When you click on the button, the script will request, and then display the server’s response, if any, in your browser console. To open the console, press F12 and select the console tab.
Be aware that the responseXML property will only be populated if the xml sent by the server is strictly well-formed. Xml parsing in JS is somewhat finicky, so you may want to rely on responseText as a fallback.

defer script execution for some time

Is it possible, in javascript, to defer the execution of a self-execution function that resides at the top level closure? (For you to understand, jQuery uses this. It has a self-execution function at global scope)
My objective here is to make the whole external script to execute at a later time without deferring it's download, such that it downloads as soon as possible and executes after an event (I decide when that event happens).
I found this also:
https://developer.mozilla.org/en-US/docs/DOM/element.onbeforescriptexecute
Sounds like a "part 1" of what I want. If I cancel, the script is not executed. but then... How do I effectively execute it later?
Note1: I have absolutely no control over that external script, so I cannot change it.
Note2: Both me and who requested this does not care if there's slowness in IE due to stuff like this (yeah, true! (s)he's anti-IE like me)
Edit (additional information):
#SLaks The server sends the default headers that apache send (so-it-seems) plus a cache-control header ordering to cache for 12 hours.
From the POV of the rules about domains, it is cross-domain.
I'm not allowed to change the definitions about the other server. I can try to asking for it, though.
Unfortunately it's not possible to do with the <script> tag because you can't get the text of an external script included that way to wrap it in code to delay it. If you could, that would open up a whole new world of possibilities with Cross Site Request Forgery (CSRF).
However, you can fetch the script with an AJAX request as long as it's hosted at the same domain name. Then you can delay its execution.
$.ajax({
url: '/path/to/myscript.js',
success: function(data) {
// Replace this with whatever you're waiting for to delay it
$.ready(function() {
eval(data);
});
}
});
EDIT
I've never used $.getScript() myself since I use RequireJS for including scripts, so I don't know if it will help with what you need, but have a look at this: http://api.jquery.com/jQuery.getScript/
FYI
If you want to know what I'm talking about with the CSRF attacks, Check this out.

How to download entire HTML of a webpage using javascript?

Is it possible to download the entire HTML of a webpage using JavaScript given the URL? What I want to do is to develop a Firefox add-on to download the content of all the links found in the source of current page of browser.
update: the URLs reside in the same domain
It should be possible to do using jQuery ajax. Javascript in a Firefox extension is not subject to the cross-origin restriction. Here are some tips for using jQuery in a Firefox extension:
Add the jQuery library to your extension's chrome/content/ directory.
Load jQuery in the window load event callback rather than including it in your browser overlay XUL. Otherwise it can cause conflicts (e.g. clobbers a user's customized toolbar).
(function(loader){
loader.loadSubScript("chrome://ryebox/content/jquery-1.6.2.min.js"); })
(Components.classes["#mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader));
Use "jQuery" instead of "$". I experienced weird behavior when using $ instead of jQuery (a conflict of some kind I suppose)
Use jQuery(content.document) instead of jQuery(document) to access a page's DOM. In a Firefox extension "document" refers to the browser's XUL whereas "content.document" refers to the page's DOM.
I wrote a Firefox extension for getting bookmarks from my friend's bookmark site. It uses jQuery to fetch my bookmarks in a JSON response from his service, then creates a menu of those bookmarks so that I can easily access them. You can browse the source at https://github.com/erturne/ryebox
You can do XmlHttpRequests (XHR`s) if the combination scheme://domain:port is the same for the page hosting the JavaScript that should fetch the HTML.
Many JS-frameworks gives you easy XHR-support, Jquery, Dojo, etc. Example using DOJO:
function getText() {
dojo.xhrGet({
url: "test/someHtml.html",
load: function(response, ioArgs){
//The repsone is the HTML
return response;
},
error: function(response, ioArgs){
return response;
},
handleAs: "text"
});
}
If you prefer writing your own XMLHttpRequest-handler, take a look here: http://www.w3schools.com/xml/xml_http.asp
For JavaScript in general, the short answer is no, not unless all pages are within the same domain. JavaScript is limited by the same-origin policy, so for security reasons, you cannot do cross-domain requests like that.
However, as pointed out by Max and erturne in the comments, when JavaScript is written as part of an extension/add-on to the browser, the regular rules about same origin policy and cross-domain requests does not seem to apply - at least not for Firefox and Chrome. Therefor, using JavaScript to download the pages should be possible using a XMLHttpRequest, or using some of the wrapper methods included in your favorite JS-library.
If you like me prefer jQuery, you can have a look at jQuery's .load() method, that loads HTML from a given resource, and inject it into an element that you specify.
Edit:
Made some updates to my answer based on the comments about cross-domain requests made by add-ons.
if you only write a text web page downloader with your mind,and you only know html and javascript, you can write a downloader name "download.hta" with html and javascript to control Msxml2.ServerXMLHTTP.6.0 and FSO

jsFiddle Ajax /echo/json not working with plain vanilla JavaScript

I'm trying to use just plain JavaScript within jsFiddle to run a JSON Ajax test...
http://jsfiddle.net/qwYu9/
...but all I get back is an empty object '{}'?
You can see an alternative version by adding /1/ to the end of the above URL - and from that example it breaks completely.
I've looked at the API documentation http://doc.jsfiddle.net/use/echo.html and it's not that helpful (to me anyway).
Can anyone shed any light on this please.
Regards,
Mark
data should be in URL format
/echo/json/?json={"text":"some text","array":[1,2,"three"],"object":{"par1":"another text","par2":[3,2,"one"],"par3":{}}}&delay=3
http://jsfiddle.net/zalun/qwYu9/7/
You are trying to query a domain different from the one the javascript is running in. That's not possible since it might pose a security risk and is blocked at the browser level.
This error was generated:
Unsafe JavaScript attempt to access frame with URL http://jsfiddle.net/qwYu9/ from frame with URL http://fiddle.jshell.net/qwYu9/show/. Domains, protocols and ports must match.
XHR finished loading: "http://fiddle.jshell.net/echo/json/".
As you can see, domains differ from jshell.net and jsfiddle.net

Where in JavaScript is the request coming from?

I am debugging a large, complex web page that has a lot of JavaScript, JQuery, Ajax and so on. Somewhere in that code I am getting a rouge request (I think it is an empty img) that calls the root of the server. I know it is not in the html or the css and am pretty convinced that somewhere in the JavaScript code the reqest is being made, but I can't track it down. I am used to using firebug, VS and other debugging tools but am looking for some way to find out where this is executed - so that I can find the offending line amongst about 150 .js files.
Apart from putting in a gazzillion console outputs of 'you are now here', does anyone have suggestions for a debugging tool that could highlight where in Javascript requests to external resources are made? Any other ideas?
Step by step debugging will take ages - I have to be careful what I step into (jQuery source - yuk!) and I may miss the crucial moment
What about using the step-by-step script debugger in Firebug ?
I also think that could be a very interesting enhancement to Firebug, being able to add a breakpoint on AJAX calls.
You spoke of jQuery source...
Assuming the request goes through jQuery, put a debug statement in the jQuery source get() function, that kicks in if the URL is '/'. Maybe then you can tell from the call stack.
You can see all HTTP request done through JavaScript using the Firebug console.
If you want to track all HTTP requests manually, you can use this code:
$(document).bind('beforeSend', function(event, request, ajaxOptions)
{
// Will be called before every jQuery AJAX call
});
For more information, see jQuery documentation on AJAX events.
If its a HTTPRequest sent to a web server, I would recommend using TamperData plugin on Firefox. Just install the plugin, start tamper data, and every request sent will be prompted to tamper/continue/abort first.
Visit this page at Mozilla website
Just a guess here, but are you using ThickBox? It tries to load an image right at the start of the code.
First thing I would do is check whether this rouge request is an Ajax request or image load request via the Net panel in Firebug.
If it's Ajax, then you can overload the $.ajax function with your own and do a strack trace and include the URL requested before handing off to the original $.ajax.
If it's an image, it's not ideal, but if you can respond to the image request with a server side sleep (i.e. php file that just sleeps for 20 seconds) you might be able to hang the app and get a starting guess as to where the problem might be.

Categories

Resources