diff options
Diffstat (limited to 'src/Resource.js')
| -rw-r--r-- | src/Resource.js | 117 | 
1 files changed, 117 insertions, 0 deletions
diff --git a/src/Resource.js b/src/Resource.js new file mode 100644 index 00000000..c0c6d220 --- /dev/null +++ b/src/Resource.js @@ -0,0 +1,117 @@ +function Route(template, defaults) { +  this.template = template = template + '#'; +  this.defaults = defaults || {}; +  var urlParams = this.urlParams = {}; +  foreach(template.split(/\W/), function(param){ +    if (param && template.match(new RegExp(":" + param + "\\W"))) { +      urlParams[param] = true; +    } +  }); +} + +Route.prototype = { +  url: function(params) { +    var path = []; +    var self = this; +    var url = this.template; +    params = params || {}; +    foreach(this.urlParams, function(value, urlParam){ +      var value = params[urlParam] || self.defaults[urlParam] || ""; +      url = url.replace(new RegExp(":" + urlParam + "(\\W)"), value + "$1"); +    }); +    url = url.replace(/\/?#$/, ''); +    var query = []; +    foreach(params, function(value, key){ +      if (!self.urlParams[key]) { +        query.push(encodeURI(key) + '=' + encodeURI(value)); +      } +    }); +    return url + (query.length ? '?' + query.join('&') : ''); +  } +}; + +function ResourceFactory(xhr) { +  this.xhr = xhr; +} + +ResourceFactory.DEFAULT_ACTIONS = { +  'get':    {method:'GET'}, +  'save':   {method:'POST'}, +  'query':  {method:'GET', isArray:true}, +  'remove': {method:'DELETE'}, +  'delete': {method:'DELETE'} +}; + +ResourceFactory.prototype = { +  route: function(url, idPaths, actions){ +    var self = this; +    var route = new Route(url); +    actions = $.extend({}, ResourceFactory.DEFAULT_ACTIONS, actions); +    function extractIds(data){ +      var ids = {}; +      foreach(idPaths, function(path, id){ +        ids[id] = Scope.getter(data, path); +      }); +      return ids; +    } + +    function Resource(value){ +      copy(value || {}, this); +    }; + +    foreach(actions, function(action, name){ +      var isGet = action.method == 'GET'; +      var isPost = action.method == 'POST'; +      Resource[name] = function (a1, a2, a3) { +        var params = {}; +        var data; +        var callback = noop; +        switch(arguments.length) { +        case 3: callback = a3; +        case 2: +          if (typeof a2 == 'function') { +            callback = a2; +          } else { +            params = a1; +            data = a2; +            break; +          } +        case 1: if (isPost) data = a1; else params = a1; break; +        case 0: break; +        default: +          throw "Expected between 0-3 arguments [params, data, callback], got " + arguments.length + " arguments." +        } + +        var value = action.isArray ? [] : new Resource(data); +        self.xhr.method(action.method, route.url($.extend({}, action.params || {}, extractIds(data), params)), data, function(response) { +          if (action.isArray) { +            foreach(response, function(item){ +              value.push(new Resource(item)); +            }); +          } else { +            copy(response, value); +          } +          (callback||noop)(value); +        }); +        return value; +      }; + +      if (!isGet) { +        Resource.prototype['$' + name] = function(a1, a2){ +          var params = {}; +          var callback = noop; +          switch(arguments.length) { +          case 2: params = a1, callback = a2; +          case 1: if (typeof a1 == 'function') callback = a1; else params = a1; +          case 0: break; +          default: +            throw "Expected between 1-3 arguments [params, data, callback], got " + arguments.length + " arguments." +          } +          Resource[name](params, this, callback); +        }; +      } +    }); +    return Resource; +  } +}; +  | 
