Skip to content

Instantly share code, notes, and snippets.

@hasenj
Created April 13, 2013 14:37
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 hasenj/5378660 to your computer and use it in GitHub Desktop.
Save hasenj/5378660 to your computer and use it in GitHub Desktop.
Experimental "ajax" library
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&param2=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