Are you one of those that include jQuery or any other library only to be able to use some JSONP in your website? In that case this might be the code for you to read and try to understand. I won’t post any detailed explainations right now but feel free to comment if you wonder anything. I’ve also included a minified version in the bottom.
Update: Fixed scoping problem as found by Damon Oehlman (see comment)
Feel free to use this script for anything that you like, commercial or non-commercial, but please keep the comment and link to this site.
Oh and by the way, the script has been tested successfully in the following browsers:
Chrome 4,5,6
Firefox 3.x
Internet Explorer 6,7,8
Opera 9.6+10
Androids webkit-based browser
Symbian S60 browser
First an example of how to use it, to show the simplicity, then the actual code.
JSONP.fetch( 'someUrl.php', {param1:'123', param2:'456'}, function(data){ //do something with data, which is the JSON object you output from someUrl.php //into the callback javascript method specified by the "callback" value in the querystring });
A simple example of the someUrl.php (please observe this example does not include any security checks what so ever, just to show the principle):
$myData = fetchSomeData(); echo $_GET['callback']; echo "("; echo json_encode($myData); echo ")";
The actual code for the Lightweight JSONP functionality.
Around 1.1kb without gzip.
//Lightweight JSONP fetcher - www.nonobtrusive.com var JSONP = (function(){ var counter = 0, head, query, key, window = this; function load(url) { var script = document.createElement('script'), done = false; script.src = url; script.async = true; script.onload = script.onreadystatechange = function() { if ( !done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") ) { done = true; script.onload = script.onreadystatechange = null; if ( script && script.parentNode ) { script.parentNode.removeChild( script ); } } }; if ( !head ) { head = document.getElementsByTagName('head')[0]; } head.appendChild( script ); } function jsonp(url, params, callback) { query = "?"; params = params || {}; for ( key in params ) { if ( params.hasOwnProperty(key) ) { query += key + "=" + params[key] + "&"; } } var jsonp = "json" + (++counter); window[ jsonp ] = function(data){ callback(data); window[ jsonp ] = null; try { delete window[ jsonp ]; } catch (e) {} }; load(url + query + "callback=" + jsonp); return jsonp; } return { get:jsonp }; }());
The minified version (677bytes (without gzip) including my comment/link)
//Lightweight JSONP fetcher - www.nonobtrusive.com var JSONP=(function(){var a=0,c,f,b,d=this;function e(j){var i=document.createElement("script"),h=false;i.src=j;i.async=true;i.onload=i.onreadystatechange=function(){if(!h&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){h=true;i.onload=i.onreadystatechange=null;if(i&&i.parentNode){i.parentNode.removeChild(i)}}};if(!c){c=document.getElementsByTagName("head")[0]}c.appendChild(i)}function g(h,j,k){f="?";j=j||{};for(b in j){if(j.hasOwnProperty(b)){f+=b+"="+j[b]+"&"}}var i="json"+(++a);d[i]=function(l){k(l);d[i]=null;try{delete d[i]}catch(m){}};e(h+f+"callback="+i);return i}return{get:g}}());
#1 by Damon Oehlman on July 20th, 2010
Fantastic work – exactly what I am looking for. I’ll have a look at integrating this into an application and some underlying javascript libraries that I am writing at the moment.
Library is released under MIT-style licence and code is available on github:
http://github.com/sidelab/grunt
I’ll make sure appropriate links back to your site are included in the source if I include it.
Cheers,
Damon.
#2 by Erik Karlsson on July 23rd, 2010
Hi and thanks for your comment. I’ve applied the fix for the jsonp scoping problem you ran into and updated the post. Good luck with the rest of your library and I’m glad that you found this useful
#3 by Andrew Lewin on July 30th, 2010
Thanks for this great Lightweight JSONP javascript library. Exactly what I was looking for.
Cheers
#4 by Joe Gutierrez on August 7th, 2010
@Andrew – Could you specifically state what caused your scoping problems? How did you identify them? I can’t find any reference for that here.
#5 by Joe Gutierrez on August 7th, 2010
OOPs! Not @Andrew, but @Erik. Sorry for that.
#6 by Erik Karlsson on August 7th, 2010
Hi Joe, the blogpost is updated but I made an example of the broken vs fixed (as seen in the post right now) versions. The thing is that the last call breaks when doing multiple calls quickly due to the jsonp variable behaves like a static in the first version. In the broken version below you’ll see a javascript error being thrown for “jsonp10 is not defined”. Please note that I’ve added a 1 second delay to the response on the server.
http://nonobtrusive.com/wp-content/uploads/2010/jsonp/broken/
http://nonobtrusive.com/wp-content/uploads/2010/jsonp/fixed/
#7 by Erik Karlsson on August 7th, 2010
I just updated the minified version in the blogpost to reflect the fixed version, just copy paste it!