]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dojo/store/JsonRest", ["../_base/xhr", "../_base/lang", "../json", "../_base/declare", "./util/QueryResults" /*=====, "./api/Store" =====*/ |
2 | ], function(xhr, lang, JSON, declare, QueryResults /*=====, Store =====*/){ | |
3 | ||
4 | // No base class, but for purposes of documentation, the base class is dojo/store/api/Store | |
5 | var base = null; | |
6 | /*===== base = Store; =====*/ | |
7 | ||
8 | /*===== | |
9 | var __HeaderOptions = { | |
10 | // headers: Object? | |
11 | // Additional headers to send along with the request. | |
12 | }, | |
13 | __PutDirectives = declare(Store.PutDirectives, __HeaderOptions), | |
14 | __QueryOptions = declare(Store.QueryOptions, __HeaderOptions); | |
15 | =====*/ | |
16 | ||
17 | return declare("dojo.store.JsonRest", base, { | |
18 | // summary: | |
19 | // This is a basic store for RESTful communicating with a server through JSON | |
20 | // formatted data. It implements dojo/store/api/Store. | |
21 | ||
22 | constructor: function(options){ | |
23 | // summary: | |
24 | // This is a basic store for RESTful communicating with a server through JSON | |
25 | // formatted data. | |
26 | // options: dojo/store/JsonRest | |
27 | // This provides any configuration information that will be mixed into the store | |
28 | this.headers = {}; | |
29 | declare.safeMixin(this, options); | |
30 | }, | |
31 | ||
32 | // headers: Object | |
33 | // Additional headers to pass in all requests to the server. These can be overridden | |
34 | // by passing additional headers to calls to the store. | |
35 | headers: {}, | |
36 | ||
37 | // target: String | |
38 | // The target base URL to use for all requests to the server. This string will be | |
39 | // prepended to the id to generate the URL (relative or absolute) for requests | |
40 | // sent to the server | |
41 | target: "", | |
42 | ||
43 | // idProperty: String | |
44 | // Indicates the property to use as the identity property. The values of this | |
45 | // property should be unique. | |
46 | idProperty: "id", | |
47 | ||
48 | // sortParam: String | |
49 | // The query parameter to used for holding sort information. If this is omitted, than | |
50 | // the sort information is included in a functional query token to avoid colliding | |
51 | // with the set of name/value pairs. | |
52 | ||
53 | get: function(id, options){ | |
54 | // summary: | |
55 | // Retrieves an object by its identity. This will trigger a GET request to the server using | |
56 | // the url `this.target + id`. | |
57 | // id: Number | |
58 | // The identity to use to lookup the object | |
59 | // options: Object? | |
60 | // HTTP headers. For consistency with other methods, if a `headers` key exists on this object, it will be | |
61 | // used to provide HTTP headers instead. | |
62 | // returns: Object | |
63 | // The object in the store that matches the given id. | |
64 | options = options || {}; | |
65 | var headers = lang.mixin({ Accept: this.accepts }, this.headers, options.headers || options); | |
66 | return xhr("GET", { | |
67 | url: this.target + id, | |
68 | handleAs: "json", | |
69 | headers: headers | |
70 | }); | |
71 | }, | |
72 | ||
73 | // accepts: String | |
74 | // Defines the Accept header to use on HTTP requests | |
75 | accepts: "application/javascript, application/json", | |
76 | ||
77 | getIdentity: function(object){ | |
78 | // summary: | |
79 | // Returns an object's identity | |
80 | // object: Object | |
81 | // The object to get the identity from | |
82 | // returns: Number | |
83 | return object[this.idProperty]; | |
84 | }, | |
85 | ||
86 | put: function(object, options){ | |
87 | // summary: | |
88 | // Stores an object. This will trigger a PUT request to the server | |
89 | // if the object has an id, otherwise it will trigger a POST request. | |
90 | // object: Object | |
91 | // The object to store. | |
92 | // options: __PutDirectives? | |
93 | // Additional metadata for storing the data. Includes an "id" | |
94 | // property if a specific id is to be used. | |
95 | // returns: dojo/_base/Deferred | |
96 | options = options || {}; | |
97 | var id = ("id" in options) ? options.id : this.getIdentity(object); | |
98 | var hasId = typeof id != "undefined"; | |
99 | return xhr(hasId && !options.incremental ? "PUT" : "POST", { | |
100 | url: hasId ? this.target + id : this.target, | |
101 | postData: JSON.stringify(object), | |
102 | handleAs: "json", | |
103 | headers: lang.mixin({ | |
104 | "Content-Type": "application/json", | |
105 | Accept: this.accepts, | |
106 | "If-Match": options.overwrite === true ? "*" : null, | |
107 | "If-None-Match": options.overwrite === false ? "*" : null | |
108 | }, this.headers, options.headers) | |
109 | }); | |
110 | }, | |
111 | ||
112 | add: function(object, options){ | |
113 | // summary: | |
114 | // Adds an object. This will trigger a PUT request to the server | |
115 | // if the object has an id, otherwise it will trigger a POST request. | |
116 | // object: Object | |
117 | // The object to store. | |
118 | // options: __PutDirectives? | |
119 | // Additional metadata for storing the data. Includes an "id" | |
120 | // property if a specific id is to be used. | |
121 | options = options || {}; | |
122 | options.overwrite = false; | |
123 | return this.put(object, options); | |
124 | }, | |
125 | ||
126 | remove: function(id, options){ | |
127 | // summary: | |
128 | // Deletes an object by its identity. This will trigger a DELETE request to the server. | |
129 | // id: Number | |
130 | // The identity to use to delete the object | |
131 | // options: __HeaderOptions? | |
132 | // HTTP headers. | |
133 | options = options || {}; | |
134 | return xhr("DELETE", { | |
135 | url: this.target + id, | |
136 | headers: lang.mixin({}, this.headers, options.headers) | |
137 | }); | |
138 | }, | |
139 | ||
140 | query: function(query, options){ | |
141 | // summary: | |
142 | // Queries the store for objects. This will trigger a GET request to the server, with the | |
143 | // query added as a query string. | |
144 | // query: Object | |
145 | // The query to use for retrieving objects from the store. | |
146 | // options: __QueryOptions? | |
147 | // The optional arguments to apply to the resultset. | |
148 | // returns: dojo/store/api/Store.QueryResults | |
149 | // The results of the query, extended with iterative methods. | |
150 | options = options || {}; | |
151 | ||
152 | var headers = lang.mixin({ Accept: this.accepts }, this.headers, options.headers); | |
153 | ||
154 | if(options.start >= 0 || options.count >= 0){ | |
155 | headers.Range = headers["X-Range"] //set X-Range for Opera since it blocks "Range" header | |
156 | = "items=" + (options.start || '0') + '-' + | |
157 | (("count" in options && options.count != Infinity) ? | |
158 | (options.count + (options.start || 0) - 1) : ''); | |
159 | } | |
160 | var hasQuestionMark = this.target.indexOf("?") > -1; | |
161 | if(query && typeof query == "object"){ | |
162 | query = xhr.objectToQuery(query); | |
163 | query = query ? (hasQuestionMark ? "&" : "?") + query: ""; | |
164 | } | |
165 | if(options && options.sort){ | |
166 | var sortParam = this.sortParam; | |
167 | query += (query || hasQuestionMark ? "&" : "?") + (sortParam ? sortParam + '=' : "sort("); | |
168 | for(var i = 0; i<options.sort.length; i++){ | |
169 | var sort = options.sort[i]; | |
170 | query += (i > 0 ? "," : "") + (sort.descending ? '-' : '+') + encodeURIComponent(sort.attribute); | |
171 | } | |
172 | if(!sortParam){ | |
173 | query += ")"; | |
174 | } | |
175 | } | |
176 | var results = xhr("GET", { | |
177 | url: this.target + (query || ""), | |
178 | handleAs: "json", | |
179 | headers: headers | |
180 | }); | |
181 | results.total = results.then(function(){ | |
182 | var range = results.ioArgs.xhr.getResponseHeader("Content-Range"); | |
183 | return range && (range = range.match(/\/(.*)/)) && +range[1]; | |
184 | }); | |
185 | return QueryResults(results); | |
186 | } | |
187 | }); | |
188 | ||
189 | }); |