/lib/ajax.js

https://github.com/ronnylt/spine · JavaScript · 204 lines · 204 code · 0 blank · 0 comment · 17 complexity · b2409a7c3700691c45fae55341e0ef12 MD5 · raw file

  1. (function() {
  2. var $, Ajax, Base, Collection, Extend, Include, Model, Singleton;
  3. var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
  4. for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
  5. function ctor() { this.constructor = child; }
  6. ctor.prototype = parent.prototype;
  7. child.prototype = new ctor;
  8. child.__super__ = parent.prototype;
  9. return child;
  10. };
  11. if (typeof Spine === "undefined" || Spine === null) {
  12. Spine = require('spine');
  13. }
  14. $ = Spine.$;
  15. Model = Spine.Model;
  16. Ajax = {
  17. getURL: function(object) {
  18. return object && (typeof object.url === "function" ? object.url() : void 0) || object.url;
  19. },
  20. enabled: true,
  21. pending: false,
  22. requests: [],
  23. disable: function(callback) {
  24. this.enabled = false;
  25. callback();
  26. return this.enabled = true;
  27. },
  28. requestNext: function() {
  29. var next;
  30. next = this.requests.shift();
  31. if (next) {
  32. return this.request(next);
  33. } else {
  34. return this.pending = false;
  35. }
  36. },
  37. request: function(callback) {
  38. return (callback()).complete(__bind(function() {
  39. return this.requestNext();
  40. }, this));
  41. },
  42. queue: function(callback) {
  43. if (!this.enabled) {
  44. return;
  45. }
  46. if (this.pending) {
  47. this.requests.push(callback);
  48. } else {
  49. this.pending = true;
  50. this.request(callback);
  51. }
  52. return callback;
  53. }
  54. };
  55. Base = (function() {
  56. function Base() {}
  57. Base.prototype.defaults = {
  58. contentType: 'application/json',
  59. dataType: 'json',
  60. processData: false
  61. };
  62. Base.prototype.ajax = function(params, defaults) {
  63. return $.ajax($.extend({}, this.defaults, defaults, params));
  64. };
  65. Base.prototype.queue = function(callback) {
  66. return Ajax.queue(callback);
  67. };
  68. return Base;
  69. })();
  70. Collection = (function() {
  71. __extends(Collection, Base);
  72. function Collection(model) {
  73. this.model = model;
  74. this.errorResponse = __bind(this.errorResponse, this);
  75. this.recordsResponse = __bind(this.recordsResponse, this);
  76. }
  77. Collection.prototype.findAll = function(params) {
  78. return this.ajax(params, {
  79. type: 'GET',
  80. url: Ajax.getURL(this.model)
  81. }).success(this.recordsResponse).error(this.errorResponse);
  82. };
  83. Collection.prototype.fetch = function(params) {
  84. return this.findAll(params).success(__bind(function(records) {
  85. return this.model.refresh(records);
  86. }, this));
  87. };
  88. Collection.prototype.recordsResponse = function(data, status, xhr) {
  89. return this.model.trigger('ajaxSuccess', null, status, xhr);
  90. };
  91. Collection.prototype.errorResponse = function(xhr, statusText, error) {
  92. return this.model.trigger('ajaxError', null, xhr, statusText, error);
  93. };
  94. return Collection;
  95. })();
  96. Singleton = (function() {
  97. __extends(Singleton, Base);
  98. function Singleton(record) {
  99. this.record = record;
  100. this.errorResponse = __bind(this.errorResponse, this);
  101. this.blankResponse = __bind(this.blankResponse, this);
  102. this.recordResponse = __bind(this.recordResponse, this);
  103. this.model = this.record.constructor;
  104. }
  105. Singleton.prototype.find = function(params) {
  106. return this.ajax(params, {
  107. type: 'GET',
  108. url: this.url
  109. });
  110. };
  111. Singleton.prototype.create = function(params) {
  112. return this.queue(__bind(function() {
  113. return this.ajax(params, {
  114. type: 'POST',
  115. data: JSON.stringify(this.record),
  116. url: Ajax.getURL(this.model)
  117. }).success(this.recordResponse).error(this.errorResponse);
  118. }, this));
  119. };
  120. Singleton.prototype.update = function(params) {
  121. return this.queue(__bind(function() {
  122. return this.ajax(params, {
  123. type: 'PUT',
  124. data: JSON.stringify(this.record),
  125. url: Ajax.getURL(this.record)
  126. }).success(this.recordResponse).error(this.errorResponse);
  127. }, this));
  128. };
  129. Singleton.prototype.destroy = function(params) {
  130. return this.queue(__bind(function() {
  131. return this.ajax(params, {
  132. type: 'DELETE',
  133. url: Ajax.getURL(this.record)
  134. }).success(this.recordResponse).error(this.errorResponse);
  135. }, this));
  136. };
  137. Singleton.prototype.recordResponse = function(data, status, xhr) {
  138. this.record.trigger('ajaxSuccess', this.record, status, xhr);
  139. if (Spine.isBlank(data)) {
  140. return;
  141. }
  142. data = this.model.fromJSON(data);
  143. return Ajax.disable(__bind(function() {
  144. if (data.id && this.record.id !== data.id) {
  145. this.record.changeID(data.id);
  146. }
  147. return this.record.updateAttributes(data.attributes());
  148. }, this));
  149. };
  150. Singleton.prototype.blankResponse = function(data, status, xhr) {
  151. return this.record.trigger('ajaxSuccess', this.record, status, xhr);
  152. };
  153. Singleton.prototype.errorResponse = function(xhr, statusText, error) {
  154. return this.record.trigger('ajaxError', this.record, xhr, statusText, error);
  155. };
  156. return Singleton;
  157. })();
  158. Model.host = '';
  159. Include = {
  160. ajax: function() {
  161. return new Singleton(this);
  162. },
  163. url: function() {
  164. var base;
  165. base = Ajax.getURL(this.constructor);
  166. if (base.charAt(base.length - 1) !== '/') {
  167. base += '/';
  168. }
  169. base += encodeURIComponent(this.id);
  170. return base;
  171. }
  172. };
  173. Extend = {
  174. ajax: function() {
  175. return new Collection(this);
  176. },
  177. url: function() {
  178. return "" + Model.host + "/" + (this.className.toLowerCase()) + "s";
  179. }
  180. };
  181. Model.Ajax = {
  182. extended: function() {
  183. this.change(function(record, type) {
  184. return record.ajax()[type]();
  185. });
  186. this.fetch(function() {
  187. var _ref;
  188. return (_ref = this.ajax()).fetch.apply(_ref, arguments);
  189. });
  190. this.extend(Extend);
  191. return this.include(Include);
  192. }
  193. };
  194. Model.Ajax.Methods = {
  195. extended: function() {
  196. this.extend(Extend);
  197. return this.include(Include);
  198. }
  199. };
  200. Spine.Ajax = Ajax;
  201. if (typeof module !== "undefined" && module !== null) {
  202. module.exports = Ajax;
  203. }
  204. }).call(this);