source: Dev/branches/rest-dojo-ui/client/rft/store.js @ 408

Last change on this file since 408 was 407, checked in by hendrikvanantwerpen, 13 years ago

Added build infrastructure and reorganised code to match it.

Page navigation is now done by the rft/app/Controller class. pages
inherit generally from rft/app/Page, which is a BorderContainer?. The
Page uses normal widget mechanism like templateString, all data-rft-*
are obsolete, use normal data-dojo-* options again in templates.
This is done so the pages of the app can be included in the build.
URLs are linked to pages through registration, which is done in
run.js. The routes are defined in the routes.js file. Page class names
and URLs are now independent.

Reduced includes in index.html to one CSS file and two JS files. Dojo
stylesheets are now included thorugh externals.css.

Dojo 1.8 doesn't require the dotted names in declares anymore. All these
are now removed (redundant with module path and JS filename anyway)
and in templates a module id is used, so iso 'dijit.form.Form' use
'dijit/form/Form' now. This is more consistent with requires in the JS
code and they are picked up by the build system.

Removed any old-style dojo.<function> code and use loaded modules
everywhere.

Lots of whitespace unification.

File size: 9.4 KB
Line 
1define([
2    'dojo/_base/array',
3    'dojo/_base/declare',
4    'dojo/_base/Deferred',
5    'dojo/_base/json',
6    'dojo/_base/lang',
7    'dojo/_base/xhr',
8    'dojo/store/util/QueryResults'
9],function(array,declare,Deferred,json,lang,xhr,QueryResults){
10   
11    var CouchStore = declare(null, {
12        /** dojo Store implementation for CouchDB
13         *
14         * See for details on the REST API, the wiki
15         * at http://wiki.apache.org/couchdb/HTTP_Document_API.
16         */
17        target: "",
18        accepts: "application/json",
19        idProperty: "_id",
20        revProperty: "_rev",
21        _responseIdProperty: "id",
22        _responseRevProperty: "rev",
23        constructor: function(options){
24            declare.safeMixin(this, options);
25        },
26        getIdentity: function(object){
27            return object[this.idProperty];
28        },
29        getRevision: function(object){
30            return object[this.revProperty];
31        },
32        get: function(id){
33            var dfd = new Deferred();
34            xhr("GET", {
35                url: this.target + id,
36                handleAs: "json",
37                headers: {
38                    Accept: this.accepts
39                }
40            }).then(function(result){
41                if ( result.error ) {
42                    dfd.reject(result.reason);
43                } else {
44                    dfd.resolve(result);
45                }
46            }, function(err){
47                dfd.reject(err);
48            });
49            return dfd.promise;
50        },
51        put: function(object, options){
52             // summary:
53             //     put an object in CouchDB
54             // object: Object
55             //     The object to put
56             // options: Object
57             //     Options object as
58             //         id: String
59             //
60            options = options || {};
61
62            var dfd = new Deferred();
63            var id = options.id ? options.id : this.getIdentity(object);
64            var hasId = typeof id != "undefined";
65            xhr(hasId ? "PUT" : "POST", {
66                url: hasId ? this.target + id : this.target,
67                postData: json.toJson(object),
68                handleAs: "json",
69                headers:{
70                    "Content-Type": "application/json",
71                    Accept: this.accepts
72                }
73            }).then(lang.hitch(this,function(result){
74                if ( result.error ) {
75                    dfd.reject(result.reason);
76                } else {
77                    object[this.idProperty] = result[this._responseIdProperty];
78                    object[this.revProperty] = result[this._responseRevProperty];
79                    dfd.resolve(object);
80                }
81            }), function(err){
82                dfd.reject(err);
83            });
84            return dfd.promise;
85        },
86        add: function(object, options){
87            return this.put(object,options);
88        },
89        remove: function(id,rev){
90            var dfd = new Deferred();
91            xhr("DELETE",{
92                url: this.target + id,
93                headers: {
94                    'If-Match': rev
95                }
96            }).then(function(result){
97                if ( result.error ) {
98                    dfd.reject(result.reason);
99                } else {
100                    dfd.resolve();
101                }
102            },function(err){
103                dfd.reject(err);
104            });
105            return dfd.promise;
106        },
107        query: function(query, options){
108            // summary:
109            //    query a couchdb view
110            // query: String
111            //    name of a couchdb view you want to query, relative to the current database
112            // options: Object
113            //     options object as
114            //        start: Number
115            //            Start results at this item
116            //        count: Number
117            //            Number of items to return
118            //        sort: [{attribute:'key',descending:true|false}]
119            //            CouchDB only support sorting by key, so only 'key'
120            //            is allowed as attribute value. Multiple sort items
121            //            are ignored.
122            //        key: String|Array|Object
123            //            Return only values with this key.
124            //            Excludes start/endkey usage.
125            //        startkey: String|Array|Object
126            //            Return values starting from this key.
127            //        endkey: String|Array|Object
128            //            Return values with key lower than this key.
129            //        include_docs: true|false
130            //            Return the full documents instead of the view
131            //            values.
132            //        reduce: true|false
133            //            Execute reduce on the view or not. Default depends
134            //            on if a reduce function is defined on the view.
135            //        group: true|false
136            //            Should values be grouped per key or not? Default
137            //            is false.
138            //        group_level: Number
139            //            When group = true and the key is an array,
140            //            determines which elements starting from the first
141            //            are used for grouping. Default is 0.
142            //        get_keys: true|false
143            //            Instead of returning the values or documents,
144            //            return the array of keys as the result.
145            //            This does not affect the forPairs function.
146            options = options || {};
147
148            var dfd = new Deferred();
149            var queryOpts = {};
150            if ( !query ) {
151                query = '_all_docs';
152            }
153
154            if (!lang.isString(query)) {
155                console.warn("Query must be a view name");
156            }
157
158            // Standard options
159            if (options.start >= 0) {
160                queryOpts.skip = options.start;
161            }
162            if (options.count >= 0) {
163                queryOpts.limit = options.count;
164            }
165            if (options.sort) {
166                if (options.sort[0]) {
167                    if (options.sort[0].attribute && options.sort[0].attribute !== "key") {
168                        console.warn("Can only sort on key");
169                    }
170                    if (options.sort[0].descending) {
171                        queryOpts.descending = true;
172                    }
173                }
174                if (options.sort.length > 1) {
175                    console.warn("multiple sort fields not supported");
176                }
177            }
178
179            // Custom options
180            if (options.key !== undefined) {
181                queryOpts.key = options.key;
182            } else if (options.keys !== undefined) {
183                queryOpts.keys = options.keys;
184            } else if (options.startkey !== undefined || options.endkey !== undefined) {
185                queryOpts.startkey = options.startkey;
186                queryOpts.endkey = options.endkey;
187            }
188            if (options.include_docs !== undefined) {
189                queryOpts.include_docs = options.include_docs;
190            }
191            if (options.reduce !== undefined) {
192                queryOpts.reduce = options.reduce;
193            }
194            if (options.group !== undefined) {
195                queryOpts.group = options.group;
196                if (options.group_level !== undefined) {
197                    queryOpts.group_level = options.group_level;
198                }
199            }
200
201            for (var qp in queryOpts) {
202                queryOpts[qp] = json.toJson(queryOpts[qp]);
203            }
204            query += '?' + xhr.objectToQuery(queryOpts);
205
206            xhr("GET", {
207                url: this.target + query,
208                handleAs: "json",
209                headers: {
210                    Accept: this.accepts
211                }
212            }).then(function(result){
213                if (result.error) {
214                    dfd.reject(result.reason);
215                } else  {
216                    var results;
217                    var values = array.map(result.rows,function(result){
218                        return options.include_docs === true ? result.doc : result.value;
219                    });
220                    var keys = array.map(result.rows,function(result){
221                        return result.key;
222                    });
223                    if (options.get_keys === true) {
224                        results = keys;
225                        results.values = values;
226                    } else {
227                        results = values;
228                        results.keys = keys;
229                    }
230                    dfd.resolve(results);
231                }
232            },function(err){
233                dfd.reject(err);
234            });
235            return CouchResults(dfd.promise);
236        }
237    });
238
239    function CouchResults(results) {
240        results = QueryResults(results);
241        results.forPairs = function(callback,thisObject) {
242            callback = lang.hitch(thisObject,callback);
243            return Deferred.when(results,function(results) {
244                var values = results.values || results;
245                var keys = results.keys || results;
246                return array.forEach(values, function(value,index) {
247                    callback(value,keys[index],index);
248                });
249            });
250        };
251        return results;
252    }
253
254    return new CouchStore({target: 'data/rft/'});
255
256});
Note: See TracBrowser for help on using the repository browser.