// jXHR.js (JSON-P XHR) | |
// v0.1 (c) Kyle Simpson | |
// MIT License | |
(function(global){ | |
var SETTIMEOUT = global.setTimeout, // for better compression | |
doc = global.document, | |
callback_counter = 0; | |
global.jXHR = function() { | |
var script_url, | |
script_loaded, | |
jsonp_callback, | |
scriptElem, | |
publicAPI = null; | |
function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } } | |
function reset() { | |
script_loaded = false; | |
script_url = ""; | |
removeScript(); | |
scriptElem = null; | |
fireReadyStateChange(0); | |
} | |
function ThrowError(msg) { | |
try { publicAPI.onerror.call(publicAPI,msg,script_url); } catch (err) { throw new Error(msg); } | |
} | |
function handleScriptLoad() { | |
if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; } | |
this.onload = this.onreadystatechange = null; // prevent memory leak | |
script_loaded = true; | |
if (publicAPI.readyState !== 4) ThrowError("Script failed to load ["+script_url+"]."); | |
removeScript(); | |
} | |
function fireReadyStateChange(rs,args) { | |
args = args || []; | |
publicAPI.readyState = rs; | |
if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args); | |
} | |
publicAPI = { | |
onerror:null, | |
onreadystatechange:null, | |
readyState:0, | |
open:function(method,url){ | |
reset(); | |
internal_callback = "cb"+(callback_counter++); | |
(function(icb){ | |
global.jXHR[icb] = function() { | |
try { fireReadyStateChange.call(publicAPI,4,arguments); } | |
catch(err) { | |
publicAPI.readyState = -1; | |
ThrowError("Script failed to run ["+script_url+"]."); | |
} | |
global.jXHR[icb] = null; | |
}; | |
})(internal_callback); | |
script_url = url.replace(/=\?/,"=jXHR."+internal_callback); | |
fireReadyStateChange(1); | |
}, | |
send:function(){ | |
SETTIMEOUT(function(){ | |
scriptElem = doc.createElement("script"); | |
scriptElem.setAttribute("type","text/javascript"); | |
scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);}; | |
scriptElem.setAttribute("src",script_url); | |
doc.getElementsByTagName("head")[0].appendChild(scriptElem); | |
},0); | |
fireReadyStateChange(2); | |
}, | |
setRequestHeader:function(){}, // noop | |
getResponseHeader:function(){return "";}, // basically noop | |
getAllResponseHeaders:function(){return [];} // ditto | |
}; | |
reset(); | |
return publicAPI; | |
}; | |
})(window); |