PageRenderTime 39ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs/restangular/0.4.5/restangular.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 290 lines | 201 code | 46 blank | 43 comment | 24 complexity | f085f6d16b5f9a874e4376ecbf75ff2d MD5 | raw file
  1. /**
  2. * Restfull Resources service for AngularJS apps
  3. * @version v0.4.4 - 2013-04-16
  4. * @link https://github.com/mgonto/restangular
  5. * @author Martin Gontovnikas <martin@gonto.com.ar>
  6. * @license MIT License, http://www.opensource.org/licenses/MIT
  7. */
  8. var module = angular.module('restangular', ['ngResource']);
  9. module.provider('Restangular', function() {
  10. // Configuration
  11. /**
  12. * Those are HTTP safe methods for which there is no need to pass any data with the request.
  13. */
  14. var safeMethods= ["get", "head", "options", "trace"];
  15. function isSafe(operation) {
  16. return _.contains(safeMethods, operation);
  17. }
  18. /**
  19. * This is the BaseURL to be used with Restangular
  20. */
  21. this.baseUrl = "";
  22. this.setBaseUrl = function(baseUrl) {
  23. this.baseUrl = baseUrl;
  24. }
  25. /**
  26. * Sets the extra fields to keep from the parents
  27. */
  28. this.extraFields = [];
  29. this.setExtraFields = function(extraFields) {
  30. this.extraFields = extraFields;
  31. }
  32. /**
  33. * Sets the URL creator type. For now, only Path is created. In the future we'll have queryParams
  34. **/
  35. this.urlCreator = "path";
  36. this.setUrlCreator = function(name) {
  37. if (!_.has(urlCreatorFactory, name)) {
  38. throw new Error("URL Path selected isn't valid");
  39. }
  40. this.urlCreator = name;
  41. }
  42. /**
  43. * You can set the restangular fields here. The 3 required fields for Restangular are:
  44. *
  45. * id: Id of the element
  46. * route: name of the route of this element
  47. * parentResource: the reference to the parent resource
  48. *
  49. * All of this fields except for id, are handled (and created) by Restangular. By default,
  50. * the field values will be id, route and parentResource respectively
  51. */
  52. this.restangularFields = {
  53. id: "id",
  54. route: "route",
  55. parentResource: "parentResource",
  56. restangularCollection: "restangularCollection"
  57. }
  58. this.setRestangularFields = function(resFields) {
  59. this.restangularFields = _.extend(this.restangularFields, resFields);
  60. }
  61. /**
  62. * Sets the Response parser. This is used in case your response isn't directly the data.
  63. * For example if you have a response like {meta: {'meta'}, data: {name: 'Gonto'}}
  64. * you can extract this data which is the one that needs wrapping
  65. *
  66. * The ResponseExtractor is a function that receives the response and the method executed.
  67. */
  68. this.responseExtractor = function(response, method) {
  69. return response;
  70. }
  71. this.setResponseExtractor = function(extractor) {
  72. this.responseExtractor = extractor;
  73. }
  74. //Internal values and functions
  75. var urlCreatorFactory = {};
  76. /**
  77. * This is the Path URL creator. It uses Path to show Hierarchy in the Rest API.
  78. * This means that if you have an Account that then has a set of Buildings, a URL to a building
  79. * would be /accounts/123/buildings/456
  80. **/
  81. var Path = function(baseUrl, restangularFields) {
  82. this.baseUrl = baseUrl;
  83. this.restangularFields = restangularFields;
  84. }
  85. Path.prototype.base = function(current) {
  86. var __restangularFields = this.restangularFields;
  87. return this.baseUrl + _.reduce(this.parentsArray(current), function(acum, elem) {
  88. var currUrl = acum + "/" + elem[__restangularFields.route];
  89. if (!elem[__restangularFields.restangularCollection]) {
  90. currUrl += "/" + elem[__restangularFields.id];
  91. }
  92. return currUrl;
  93. }, '');
  94. }
  95. Path.prototype.parentsArray = function(current) {
  96. var parents = [];
  97. while(!_.isUndefined(current)) {
  98. parents.push(current);
  99. current = current[this.restangularFields.parentResource];
  100. }
  101. return parents.reverse();
  102. }
  103. Path.prototype.fetchUrl = function(what, current) {
  104. return this.base(current) + "/" + what.toLowerCase();
  105. }
  106. Path.prototype.resource = function(current, $resource, headers) {
  107. return $resource(this.base(current) + "/:what" , {}, {
  108. getArray: {method: 'GET', params: {}, isArray: true, headers: headers || {}},
  109. get: {method: 'GET', params: {}, isArray: false, headers: headers || {}},
  110. put: {method: 'PUT', params: {}, isArray: false, headers: headers || {}},
  111. post: {method: 'POST', params: {}, isArray: false, headers: headers || {}},
  112. remove: {method: 'DELETE', params: {}, isArray: false, headers: headers || {}},
  113. head: {method: 'HEAD', params: {}, isArray: false, headers: headers || {}},
  114. trace: {method: 'TRACE', params: {}, isArray: false, headers: headers || {}},
  115. options: {method: 'OPTIONS', params: {}, isArray: false, headers: headers || {}},
  116. patch: {method: 'PATCH', params: {}, isArray: false, headers: headers || {}}
  117. });
  118. }
  119. urlCreatorFactory.path = Path;
  120. this.$get = ['$resource', '$q', function($resource, $q) {
  121. var urlHandler = new urlCreatorFactory[this.urlCreator](this.baseUrl, this.restangularFields);
  122. var __extraFields = this.extraFields;
  123. var __responseExtractor = this.responseExtractor;
  124. var __restangularFields = this.restangularFields;
  125. function restangularizeBase(parent, elem, route) {
  126. elem[__restangularFields.route] = route;
  127. if (parent) {
  128. var restangularFieldsForParent = _.chain(__restangularFields)
  129. .pick(['id', 'route', 'parentResource'])
  130. .values()
  131. .union(__extraFields)
  132. .value();
  133. elem[__restangularFields.parentResource]= _.pick(parent, restangularFieldsForParent);
  134. }
  135. return elem;
  136. }
  137. function restangularizeElem(parent, elem, route) {
  138. var localElem = restangularizeBase(parent, elem, route);
  139. localElem[__restangularFields.restangularCollection] = false;
  140. localElem.get = _.bind(getFunction, localElem);
  141. localElem.getList = _.bind(fetchFunction, localElem);
  142. localElem.put = _.bind(putFunction, localElem);
  143. localElem.post = _.bind(postFunction, localElem);
  144. localElem.remove = _.bind(deleteFunction, localElem);
  145. localElem.head = _.bind(headFunction, localElem);
  146. localElem.trace = _.bind(traceFunction, localElem);
  147. localElem.options = _.bind(optionsFunction, localElem);
  148. localElem.patch = _.bind(patchFunction, localElem);
  149. return localElem;
  150. }
  151. function restangularizeCollection(parent, elem, route) {
  152. var localElem = restangularizeBase(parent, elem, route);
  153. localElem[__restangularFields.restangularCollection] = true;
  154. localElem.post = _.bind(postFunction, localElem, null);
  155. localElem.head = _.bind(headFunction, localElem);
  156. localElem.trace = _.bind(traceFunction, localElem);
  157. localElem.options = _.bind(optionsFunction, localElem);
  158. localElem.patch = _.bind(patchFunction, localElem);
  159. localElem.getList = _.bind(fetchFunction, localElem, null);
  160. return localElem;
  161. }
  162. function fetchFunction(what, params, headers) {
  163. var search = what ? {what: what} : {};
  164. var __this = this;
  165. var deferred = $q.defer();
  166. urlHandler.resource(this, $resource, headers).getArray(_.extend(search, params), function(resData) {
  167. var data = __responseExtractor(resData, 'get');
  168. var processedData = _.map(data, function(elem) {
  169. if (!__this[__restangularFields.restangularCollection]) {
  170. return restangularizeElem(__this, elem, what);
  171. } else {
  172. return restangularizeElem(null, elem, __this[__restangularFields.route]);
  173. }
  174. });
  175. if (!__this[__restangularFields.restangularCollection]) {
  176. deferred.resolve(restangularizeCollection(__this, processedData, what));
  177. } else {
  178. deferred.resolve(restangularizeCollection(null, processedData, __this[__restangularFields.route]));
  179. }
  180. }, function error() {
  181. deferred.reject(arguments)
  182. });
  183. return deferred.promise;
  184. }
  185. function elemFunction(operation, params, obj, headers) {
  186. var __this = this;
  187. var deferred = $q.defer();
  188. var resParams = params || {};
  189. var resObj = obj || this;
  190. var okCallback = function(resData) {
  191. var elem = __responseExtractor(resData, operation) || resObj;
  192. if (operation === "post" && !__this[__restangularFields.restangularCollection]) {
  193. deferred.resolve(restangularizeElem(__this, elem, resParams.what));
  194. } else {
  195. deferred.resolve(restangularizeElem(__this[__restangularFields.parentResource], elem, __this[__restangularFields.route]));
  196. }
  197. };
  198. var errorCallback = function() {
  199. deferred.reject(arguments)
  200. };
  201. if (isSafe(operation)) {
  202. urlHandler.resource(this, $resource, headers)[operation](resParams, okCallback, errorCallback);
  203. } else {
  204. urlHandler.resource(this, $resource, headers)[operation](resParams, resObj, okCallback, errorCallback);
  205. }
  206. return deferred.promise;
  207. }
  208. function getFunction(params, headers) {
  209. return _.bind(elemFunction, this)("get", params, undefined, headers);
  210. }
  211. function deleteFunction(params, headers) {
  212. return _.bind(elemFunction, this)("remove", params, {}, headers);
  213. }
  214. function putFunction(params, headers) {
  215. return _.bind(elemFunction, this)("put", params, undefined, headers);
  216. }
  217. function postFunction(what, elem, params, headers) {
  218. return _.bind(elemFunction, this)("post", _.extend({what: what}, params), elem, headers);
  219. }
  220. function headFunction(params, headers) {
  221. return _.bind(elemFunction, this)("head", params, undefined, headers);
  222. }
  223. function traceFunction(params, headers) {
  224. return _.bind(elemFunction, this)("trace", params, undefined, headers);
  225. }
  226. function optionsFunction(params, headers) {
  227. return _.bind(elemFunction, this)("options", params, undefined, headers);
  228. }
  229. function patchFunction(params, headers) {
  230. return _.bind(elemFunction, this)("patch", params, undefined, headers);
  231. }
  232. var service = {};
  233. service.one = function(route, id) {
  234. var elem = {};
  235. elem[__restangularFields.id] = id;
  236. return restangularizeElem(null, elem , route);
  237. }
  238. service.all = function(route) {
  239. return restangularizeCollection(null, {} , route, true);
  240. }
  241. return service;
  242. }];
  243. }
  244. );