JSON Remote Loader
Background
There are a lot of libraries and tools to load data from the server asynchronously, they use different techniques starting with XHR, hiddeniframes, images and so on.
The only problem with all that code is that dues to security restricions most of it can't be used in scenario where loading page and data source are located on different domains.
Usually this problem is being solved by creating some proxying code on receiving server that will fetch data from remote server and send it to the browser. Although an easy solution, sometimest it's not feasible if code developers don't have control over servers where code will be distributed. Good examples are bookmarklets or JavaScript widgets or in cases when you don't want to use double traffic.
I attempted to create a simple library that allows to do that similarly to traditional same-domain libraries but keeping in mind all the difficulties that come with remote server security restrictions.
Some key assumptions
- First of all, it's only possible to load remote data if it's being loaded and executed as JavaScript code. This means that your code on remote server must be formatted as JSON wrapped in a function call (see example below).
- Secondly, there needed to be an asynchronous way to run multiple downloads at the same time so I created a queue that is used to track callbacks so if you're doing multiple requests at the same time, use remote callback with unique identifier to let main code know which chunk of code was succesfully loaded (unfortunately I couldn't find any way to avoid this and will be happy if someone can suggest something useful). Unique identifier is optional, but you can't run multiple unidentified data downloads simultaniously - this might be useful if you don't have control over data source and all you can do is specify a callback function name.
- After all, I didn't find a way to listen on
loadevent for a<script>tag (when remote script is being loaded) and therefore had to use timeouts as error triggers. This means thatonFailurelistener will be called upon timeout. - I was inspired by Douglas Crockford's lectures which I came across collecting material for TechPresentations' JavaScript section so I'm trying to use JSLint to perfect the code, Firebug to debug it and event-driven model to feel mainstreem.
Example
<html> <head> <title>Remote loader example</title> <script type="text/javascript" language="javascript" src="remoteloader.js"></script> <script type="text/javascript" language="javascript"> function load_good_info() { window.document.getElementById('goodinfocontainer').innerHTML = ' '; window.document.getElementById('error').innerHTML = ' '; SERGEYCHE.remoteloader.load( { url: 'http://www.dataprovider.com/goodinfo.js', onSuccess: function(data) { window.document.getElementById('goodinfocontainer').innerHTML = data; }, onFailure: function(request_id) { window.document.getElementById('error').innerHTML = 'Cant load data - loader timed out (' + request_id + ')'; }, onCancel: function(request_id) { window.document.getElementById('error').innerHTML = 'Cancelled (' + request_id + ')'; }, timeout: 3000 }, 'good info' ); } </script> <style type="text/css"> #goodinfocontainer { padding: 5px; border: 1px solid black; background: #EFEFEF; } #error { padding: 5px; border: 1px solid black; color: red; background: #EFEFEF; } </style> </head> <body> <h1>Showing good info</h1> <div> <input type="button" onclick="load_good_info();" value="click here to load good info"/> <input type="button" onclick="SERGEYCHE.remoteloader.cancel('good info')" value="click here to cancel"/> </div> <h2>Info:</h2> <div id="goodinfocontainer"> </div> <h2>Errors:</h2> <div id="error"> </div> </body> </html>
And http://www.dataprovider.com/goodinfo.js will look like this:
SERGEYCHE.remoteloader.callback('this is good stuff', 'good info');
Demo
Enter the URL and this form will make a request to del.icio.us JSON api endpoint.
This demo doesn't use unique request_id because del.icio.us only allows to specify callback function but not additional parameters. This means that you can only call it one at a time.
Download
Human-readable version of the code: remoteloader.js (gz, zip)
Or it's minified version: remoteloader-min.js (gz, zip)
Security considerations
Since loading side has no control over the content of the script that is being executed from remote server, it's highly recommended to use this code only in cases when you trust data provider to have only legitimate code that only executes SERGEYCHE.remoteloader.callback function passing data to it.
Open Source
This project is maintained using Google code project hosting and code is distributed using LGPL.
Please submit all bugs into bug tracking system.