Created
April 13, 2013 14:37
-
-
Save hasenj/5378660 to your computer and use it in GitHub Desktop.
Experimental "ajax" library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
echo = function(areq) { console.log(areq.response) }; | |
requests = (function() { | |
var module = {}; | |
var AsyncRequest = XMLHttpRequest; | |
// takes a dict and returns a string "a=b&c=d" | |
var toUrlParams = function(dict) { | |
var res = []; | |
for(var key in dict) { | |
var value = encodeURIComponent(dict[key]) | |
res.push(key + "=" + value); | |
} | |
return res.join("&"); | |
} | |
// takes a path and a params dict and returns a string "/path/?param1=val1¶m2=val2" | |
var makeUrl = function(path, params) { | |
var params = toUrlParams(params); | |
if(params) { | |
return path + "?" + params; | |
} else { | |
return path; | |
} | |
} | |
// get the hostname from a url/path the same way that the hostname is extracted from the location in window.href.hostname | |
// from: http://stackoverflow.com/a/8498668/35364 | |
var pathHost = function(url) { | |
var a = document.createElement('a'); | |
a.href = url; | |
return a.hostname; | |
} | |
// call all the callbacks/hooks without failing | |
var call = function(callback_array, this_arg, args) { | |
for(var index = 0; index < callback_array.length; index++) { | |
try { | |
// call the callback using fn.apply | |
callback_array[index].apply(this_arg, args); | |
} catch(e) { | |
// pass | |
console.log("callback error"); | |
} | |
} | |
} | |
var before_hooks = []; | |
module.before_send = function(fn) { | |
before_hooks.push(fn); | |
return module; // allow chaining; | |
} | |
// constructor | |
var JsonRequest = function(pmethod, ppath) { | |
var self = this; | |
var method = pmethod.toUpperCase(); | |
var path = ppath; | |
var data = {}; | |
var params = {}; | |
var headers = []; | |
var success_hooks = []; | |
var error_hooks = []; | |
var complete_hooks = []; | |
// this one is a getter only! | |
self.path = function() { | |
return path; | |
} | |
self.method = function() { | |
return method; | |
} | |
// the rest are only setters | |
self.header = function(key, value) { | |
var h = {key: key, value: value}; | |
headers.push(h); | |
return self; | |
} | |
self.data = function(pdata) { | |
data = pdata; | |
return self; | |
} | |
self.params = function(pparams) { | |
params = pparams; | |
return self; | |
} | |
self.success = function(fn) { | |
success_hooks.push(fn); | |
return self; | |
} | |
self.error = function(fn) { | |
error_hooks.push(fn); | |
return self; | |
} | |
self.complete = function(fn) { | |
complete_hooks.push(fn); | |
return self; | |
} | |
self.send = function() { | |
// call before_send hooks | |
// we must call it here before we start building the request and setting headers, etc | |
// because these hooks are meant for addings headers, etc | |
call(before_hooks, self, [self]); | |
var areq = new AsyncRequest(); | |
var url = makeUrl(path, params); | |
areq.open(method, url); | |
// force json | |
areq.setRequestHeader("Content-Type", "application/json"); | |
// set the ajax header | |
areq.setRequestHeader("X-Requested-With", "XMLHttpRequest"); | |
// set headers | |
// Traverse the headers list by the order of insertion | |
// Note: Do this after forcing the json header so that users can override it | |
for(var i = 0; i < headers.length; i++) { | |
var header = headers[i]; | |
areq.setRequestHeader(header.key, header.value) | |
} | |
// TODO: have option to send datatypes other than json? | |
var json_data = JSON.stringify(data); | |
areq.send(json_data); | |
areq.onreadystatechange = function() { | |
if(areq.readyState == areq.DONE) { | |
call(complete_hooks, areq, [areq]); | |
if(areq.status == 200) { | |
call(success_hooks, areq, [areq]); | |
} else { | |
call(error_hooks, areq, [areq]); | |
} | |
} | |
} | |
return self; | |
} | |
// utilities/helpers | |
/// Check if the path is going to a different domain | |
self.isCrossOrigin = function() { | |
if(path.charAt(0) === "/" && path.charAt(1) !== "/") { | |
return false; | |
} | |
// path has a domain; check if it's different from current domain | |
if(pathHost(path) == window.location.hostname) { | |
return false; | |
} | |
// has a host but not the same as this one; so it's cross-domain | |
return true; | |
} | |
self.isSameOrigin = function() { | |
return !self.isCrossOrigin(); | |
} | |
} | |
module.request = function(method, path) { | |
return new JsonRequest(method, path); | |
} | |
module.get = function(path) { | |
return module.request("get", path); | |
} | |
module.post = function(path) { | |
return module.request("post", path); | |
} | |
module.put = function(path) { | |
return module.request("put", path); | |
} | |
module.del = function(path) { | |
return module.request("delete", path); | |
} | |
return module; | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment