Skip to content

Instantly share code, notes, and snippets.

@dandean
Created July 14, 2009 20:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dandean/147172 to your computer and use it in GitHub Desktop.
Save dandean/147172 to your computer and use it in GitHub Desktop.
JSONP for PrototypeJS
// See an updated version of this in it's own git repo:
// http://github.com/dandean/Ajax.JSONRequest
/* JSON-P implementation for Prototype.js somewhat by Dan Dean (http://www.dandean.com)
*
* *HEAVILY* based on Tobie Langel's version: http://gist.github.com/145466.
* Might as well just call this an iteration.
*
* This version introduces:
* - onCreate and onFailure callback options.
* - option to not invoke request upon instantiation.
*
* Tested in Firefox 3/3.5, Safari 4
*
* Note: while I still think JSON-P is an inherantly flawed technique,
* there are some valid use cases which this can provide for.
*
* See examples below for usage.
*/
Ajax.JSONRequest = Class.create(Ajax.Base, (function() {
var id = 0, head = document.getElementsByTagName('head')[0];
return {
initialize: function($super, url, options) {
$super(options);
this.options.url = url;
this.options.callbackParamName = this.options.callbackParamName || 'callback';
this.options.timeout = this.options.timeout || 10000; // Default timeout: 10 seconds
this.options.invokeImmediately = (!Object.isUndefined(this.options.invokeImmediately)) ? this.options.invokeImmediately : true ;
this.responseJSON = {};
if (this.options.invokeImmediately) {
this.request();
}
},
/**
* Ajax.JSONRequest#_cleanup() -> "undefined"
*
* Cleans up after the request
**/
_cleanup: function() {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
if (this.script && Object.isElement(this.script)) {
this.script.remove();
this.script = null;
}
},
/**
* Ajax.JSONRequest#request() -> "undefined"
*
* Invokes the JSON-P request lifecycle
**/
request: function() {
// Define local vars
var key = this.options.callbackParamName,
name = '_prototypeJSONPCallback_' + (id++);
// Add callback as a parameter and build request URL
this.options.parameters[key] = name;
var url = this.options.url + ((this.options.url.include('?') ? '&' : '?') + Object.toQueryString(this.options.parameters));
// Define callback function
window[name] = function(json) {
this._cleanup(); // Garbage collection
window[name] = undefined;
if (Object.isFunction(this.options.onComplete)) {
this.responseJSON = json;
this.options.onComplete.call(this, this);
}
}.bind(this);
this.script = new Element('script', { type: 'text/javascript', src: url });
if (Object.isFunction(this.options.onCreate)) {
this.options.onCreate.call(this, this);
}
head.appendChild(this.script);
this.timeout = setTimeout(function() {
this._cleanup();
window[name] = Prototype.emptyFunction;
if (Object.isFunction(this.options.onFailure)) {
this.options.onFailure.call(this, this);
}
}.bind(this), this.options.timeout);
}
};
})());
//
// EXAMPLES
//
document.observe("dom:loaded", function(e) {
// Should succeed
new Ajax.JSONRequest('http://api.flickr.com/services/feeds/photos_public.gne', {
onCreate: function(instance) {
console.log("create", this);
},
onComplete: function(instance) {
console.log("complete", this);
},
onFailure: function(instance) {
console.log("fail", this);
},
callbackParamName: "jsoncallback",
parameters: {
tags: 'cat',
tagmode: 'any',
format: 'json'
}
});
// Timeout is super short, should fail
new Ajax.JSONRequest('http://api.flickr.com/services/feeds/photos_public.gne', {
onCreate: function(instance) {
console.log("create", this);
},
onComplete: function(instance) {
console.log("complete", this);
},
onFailure: function(instance) {
console.log("fail", this);
},
// Adding super short timeout
timeout: 100,
callbackParamName: "jsoncallback",
parameters: {
tags: 'cat',
tagmode: 'any',
format: 'json'
}
});
// Invalid URL never calls onComplete. Times out in 10 seconds causing onFailure.
new Ajax.JSONRequest('http://api.flickr.com/services/feeds/asdfasdfasdfasdfasdfsdf', {
onCreate: function(instance) {
console.log("create", this);
},
onComplete: function(instance) {
console.log("complete", this);
},
onFailure: function(instance) {
console.log("fail", this);
},
callbackParamName: "jsoncallback",
parameters: {
tags: 'cat',
tagmode: 'any',
format: 'json'
}
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment