PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/app/scripts/vendor/backbone-sharepoint.odata-amd.js

https://github.com/TheWebShop/gallery-walking
JavaScript | 235 lines | 143 code | 52 blank | 40 comment | 29 complexity | bee612a394eb9a84204b9ca5ac0c6e8f MD5 | raw file
  1. define(['backbone', 'underscore', 'jquery'], function (Backbone, _, $) {
  2. /******************************************************************
  3. * Backbone.SharePoint OData proxy
  4. *
  5. * Author: Luc Stakenborg
  6. * Date: Mar 2, 2012
  7. *
  8. * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
  9. * Copyright (c) 2012, Luc Stakenborg, Oxida B.V.
  10. ******************************************************************
  11. */
  12. (function(Backbone, _, $) {
  13. // SharePoint ListData service
  14. var LISTDATA_SERVICE = '_vti_bin/ListData.svc',
  15. url;
  16. // calculate url based on site, list and (optional) id
  17. url = function(options) {
  18. var site = options.site,
  19. list = options.list,
  20. id = options.id,
  21. // remove leading and trailing forward slashes from the site path
  22. path = site.replace(/^\/+|\/+$/g, ''),
  23. url = (path ? '/' + path : '') + '/' + LISTDATA_SERVICE + '/' + list + (id ? '(' + encodeURIComponent(id) + ')' : '');
  24. return url;
  25. };
  26. Backbone.SP = {};
  27. Backbone.SP.Item = Backbone.Model.extend({
  28. // the id attribute of a SharePoint item. Please note capital I
  29. idAttribute: 'Id',
  30. // the SharePoint site on the current server. By default: root
  31. site: '',
  32. initialize: function() {
  33. this._changeSet = {};
  34. this.bind('change', this._updateChangeSet);
  35. },
  36. _updateChangeSet: function() {
  37. var changedAttributes = this.changedAttributes();
  38. // if attributes are set due to server response, the response will contain __metadata
  39. if (changedAttributes.__metadata) {
  40. this._changeSet = {};
  41. } else {
  42. _.extend(this._changeSet, this.changedAttributes());
  43. }
  44. },
  45. url: function() {
  46. var options = {
  47. site: this.site,
  48. list: this.list
  49. };
  50. if (!this.isNew()) {
  51. options.id = this.id;
  52. }
  53. return url(options);
  54. },
  55. unset: function(attr, options) {
  56. var result = Backbone.Model.prototype.unset.call(this, attr, options);
  57. if (result) {
  58. delete this._changeSet[attr];
  59. }
  60. return result;
  61. },
  62. clear: function(attr, options) {
  63. var result = Backbone.Model.prototype.clear.call(this, attr, options);
  64. if (result) {
  65. this._changeSet = {};
  66. }
  67. return result;
  68. },
  69. sync: function(method, model, options) {
  70. var metadata = model.get("__metadata"),
  71. methodMap = {
  72. 'create': 'POST',
  73. // OData requires MERGE for partial updates
  74. // We will use Method tunneling throug POST because
  75. // MERGE isn't supported by IE7 + IE8
  76. 'update': 'POST',
  77. 'delete': 'DELETE',
  78. 'read': 'GET'
  79. },
  80. type = methodMap[method],
  81. // Default JSON-request options.
  82. params = _.extend({
  83. type: type,
  84. dataType: 'json',
  85. processData: (type === 'GET')
  86. }, options);
  87. // Ensure that we have a URL.
  88. if (!params.url) {
  89. params.url = model.url();
  90. }
  91. // Ensure that we have the appropriate request data.
  92. if (!params.data && model && (method === 'create' || method === 'update')) {
  93. params.contentType = 'application/json';
  94. if (method === 'create') {
  95. params.data = JSON.stringify(model.toJSON());
  96. }
  97. if (method === 'update') {
  98. params.data = JSON.stringify(model._changeSet || {});
  99. params.headers = {
  100. // header required for Method tunneling
  101. 'X-HTTP-Method': 'MERGE',
  102. // header required for concurrency control
  103. 'If-Match': metadata ? metadata.etag : '*'
  104. };
  105. }
  106. }
  107. // transfer special url parameters like select and
  108. // orderby to the params.data hash
  109. if (method === 'read') {
  110. params.data = params.data || {};
  111. _(['filter', 'select', 'orderby', 'top', 'skip', 'expand', 'inlinecount'])
  112. .each(function(keyword) {
  113. if (options[keyword]) {
  114. params.data['$' + keyword] = options[keyword];
  115. }
  116. });
  117. }
  118. // Create a success handler to:
  119. // (1) set etag
  120. // (2) normalize the response, so a model.fetch() does not require a parse()
  121. var success = options.success;
  122. params.success = function(resp, status, xhr) {
  123. // OData responds with an updated Etag
  124. var etag = xhr.getResponseHeader('Etag');
  125. // always clear changeSet after a server response
  126. model._changeSet = {};
  127. // Instead of passing resp, we'll pass resp.d
  128. // make sure we cover 204 response (resp is empty) on Delete and Update
  129. // This way we don't need to override the model.parse() method
  130. if (success) {
  131. if (Backbone.VERSION === '0.9.9' || Backbone.VERSION === '0.9.10') {
  132. success(model, resp && resp.d, options);
  133. } else {
  134. success(resp && resp.d, status, xhr);
  135. }
  136. }
  137. if (etag) {
  138. // Backbone doesn't support setting/getting nested attributes
  139. // Updating etag attribute directly instead
  140. model.attributes.__metadata.etag = etag;
  141. }
  142. };
  143. var error = options.error;
  144. params.error = function(xhr, status, errorText) {
  145. if (error) {
  146. // Include the error text in xhr so it's available to the callback
  147. if (errorText) {
  148. xhr.errorText = errorText;
  149. }
  150. error(model, xhr, options);
  151. }
  152. };
  153. // Make the request.
  154. return $.ajax(params);
  155. }
  156. });
  157. Backbone.SP.List = Backbone.Collection.extend({
  158. url: function() {
  159. // use the Model's url method, if available
  160. if (this.model && this.model.list) {
  161. return this.model.prototype.url();
  162. }
  163. // otherwise use site and list settings of this collection
  164. return url({
  165. site: this.site,
  166. list: this.list
  167. });
  168. },
  169. sync: function(method, model, options) {
  170. return this.model.prototype.sync(method, model, options);
  171. },
  172. parse: function(response) {
  173. if (response.__count) {
  174. this._count = parseInt(response.__count, 10);
  175. } else {
  176. delete this._count;
  177. }
  178. return response.results;
  179. }
  180. });
  181. }(Backbone, _, $));
  182. return {};
  183. });