1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
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(_, 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, paramDefaults, actions){
var self = this;
var route = new Route(url);
actions = extend({}, ResourceFactory.DEFAULT_ACTIONS, actions);
function extractParams(data){
var ids = {};
foreach(paramDefaults || {}, function(value, key){
ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
});
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(action.method, route.url(extend({}, action.params || {}, extractParams(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;
};
Resource.bind = function(additionalParamDefaults){
return self.route(url, extend({}, paramDefaults, additionalParamDefaults), actions);
};
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.";
}
var self = this;
Resource[name](params, this, function(response){
copy(response, self);
callback(self);
});
};
}
});
return Resource;
}
};
|