xoslib wip
[plstackapi.git] / planetstack / core / xoslib / static / js / backbone-tastypie.js
1 /**
2  * Backbone-tastypie.js 0.1
3  * (c) 2011 Paul Uithol
4  * 
5  * Backbone-tastypie may be freely distributed under the MIT license.
6  * Add or override Backbone.js functionality, for compatibility with django-tastypie.
7  */
8 (function( undefined ) {
9         var Backbone = this.Backbone;
10         
11         /**
12          * Override Backbone's sync function, to do a GET upon receiving a HTTP CREATED.
13          * This requires 2 requests to do a create, so you may want to use some other method in production.
14          * Modified from http://joshbohde.com/blog/backbonejs-and-django
15          */
16         Backbone.oldSync = Backbone.sync;
17         Backbone.sync = function( method, model, options ) {
18                 if ( method === 'create' ) {
19                         var dfd = new $.Deferred();
20                         
21                         // Set up 'success' handling
22                         dfd.done( options.success );
23                         options.success = function( resp, status, xhr ) {
24                                 // If create is successful but doesn't return a response, fire an extra GET.
25                                 // Otherwise, resolve the deferred (which triggers the original 'success' callbacks).
26                                 if ( xhr.status === 201 && !resp ) { // 201 CREATED; response null or empty.
27                                         var location = xhr.getResponseHeader( 'Location' );
28                                         return $.ajax( {
29                                                    url: location,
30                                                    success: dfd.resolve,
31                                                    error: dfd.reject
32                                                 });
33                                 }
34                                 else {
35                                         return dfd.resolveWith( options.context || options, [ resp, status, xhr ] );
36                                 }
37                         };
38                         
39                         // Set up 'error' handling
40                         dfd.fail( options.error );
41                         options.error = dfd.reject;
42                         
43                         // Make the request, make it accessibly by assigning it to the 'request' property on the deferred 
44                         dfd.request = Backbone.oldSync( method, model, options );
45                         return dfd;
46                 }
47                 
48                 return Backbone.oldSync( method, model, options );
49         };
50
51         Backbone.Model.prototype.idAttribute = 'resource_uri';
52         
53         Backbone.Model.prototype.url = function() {
54                 // Use the id if possible
55                 var url = this.id;
56                 
57                 // If there's no idAttribute, try to have the collection construct a url. Fallback to 'urlRoot'.
58                 if ( !url ) {
59                         url = this.collection && ( _.isFunction( this.collection.url ) ? this.collection.url() : this.collection.url );
60                         url = url || this.urlRoot;
61                 }
62                 
63                 url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' );
64                 
65                 return url;
66         };
67         
68         /**
69          * Return 'data.objects' if it exists and is an array, or else just plain 'data'.
70          */
71         Backbone.Model.prototype.parse = function( data ) {
72                 return data && data.objects && ( _.isArray( data.objects ) ? data.objects[ 0 ] : data.objects ) || data;
73         };
74         
75         Backbone.Collection.prototype.parse = function( data ) {
76                 return data && data.objects;
77         };
78         
79         Backbone.Collection.prototype.url = function( models ) {
80                 var url = this.urlRoot || ( models && models.length && models[0].urlRoot );
81                 url && ( url += ( url.length > 0 && url.charAt( url.length - 1 ) === '/' ) ? '' : '/' );
82                 
83                 // Build a url to retrieve a set of models. This assume the last part of each model's idAttribute
84                 // (set to 'resource_uri') contains the model's id.
85                 if ( models && models.length ) {
86                         var ids = _.map( models, function( model ) {
87                                         var parts = _.compact( model.id.split('/') );
88                                         return parts[ parts.length - 1 ];
89                                 });
90                         url += 'set/' + ids.join(';') + '/';
91                 }
92                 
93                 return url;
94         };
95 })();