SimManager.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /**
  2. * @author Don Griffin
  3. *
  4. * This singleton manages simulated Ajax responses. This allows application logic to be
  5. * written unaware that its Ajax calls are being handled by simulations ("simlets"). This
  6. * is currently done by hooking {@link Ext.data.Connection} methods, so all users of that
  7. * class (and {@link Ext.Ajax} since it is a derived class) qualify for simulation.
  8. *
  9. * The requires hooks are inserted when either the {@link #init} method is called or the
  10. * first {@link Ext.ux.ajax.Simlet} is registered. For example:
  11. *
  12. * Ext.onReady(function () {
  13. * initAjaxSim();
  14. *
  15. * // normal stuff
  16. * });
  17. *
  18. * function initAjaxSim () {
  19. * Ext.ux.ajax.SimManager.init({
  20. * delay: 300
  21. * }).register({
  22. * '/app/data/url': {
  23. * stype: 'json', // use JsonSimlet (stype is like xtype for components)
  24. * data: [
  25. * { foo: 42, bar: 'abc' },
  26. * ...
  27. * ]
  28. * }
  29. * });
  30. * }
  31. *
  32. * As many URL's as desired can be registered and associated with a {@link Ext.ux.ajax.Simlet}. To make
  33. * non-simulated Ajax requests once this singleton is initialized, add a `nosim:true` option
  34. * to the Ajax options:
  35. *
  36. * Ext.Ajax.request({
  37. * url: 'page.php',
  38. * nosim: true, // ignored by normal Ajax request
  39. * params: {
  40. * id: 1
  41. * },
  42. * success: function(response){
  43. * var text = response.responseText;
  44. * // process server response here
  45. * }
  46. * });
  47. */
  48. Ext.define('Ext.ux.ajax.SimManager', {
  49. singleton: true,
  50. requires: [
  51. 'Ext.data.Connection',
  52. 'Ext.ux.ajax.SimXhr',
  53. 'Ext.ux.ajax.Simlet',
  54. 'Ext.ux.ajax.JsonSimlet'
  55. ],
  56. /**
  57. * @cfg {Ext.ux.ajax.Simlet} defaultSimlet
  58. * The {@link Ext.ux.ajax.Simlet} instance to use for non-matching URL's. By default, this will
  59. * return 404. Set this to null to use real Ajax calls for non-matching URL's.
  60. */
  61. /**
  62. * @cfg {String} defaultType
  63. * The default `stype` to apply to generic {@link Ext.ux.ajax.Simlet} configuration objects. The
  64. * default is 'basic'.
  65. */
  66. defaultType: 'basic',
  67. /**
  68. * @cfg {Number} delay
  69. * The number of milliseconds to delay before delivering a response to an async request.
  70. */
  71. delay: 150,
  72. /**
  73. * @prop {Boolean} ready
  74. * True once this singleton has initialized and applied its Ajax hooks.
  75. * @private
  76. */
  77. ready: false,
  78. constructor: function () {
  79. this.simlets = {};
  80. },
  81. getSimlet: function (url) {
  82. // Strip down to base URL (no query parameters or hash):
  83. var me = this,
  84. index = url.indexOf('?');
  85. if (index < 0) {
  86. index = url.indexOf('#');
  87. }
  88. if (index > 0) {
  89. url = url.substring(0, index);
  90. }
  91. return me.simlets[url] || me.defaultSimlet;
  92. },
  93. getXhr: function (method, url, options, async) {
  94. var simlet = this.getSimlet(url);
  95. if (simlet) {
  96. return simlet.openRequest(method, url, options, async);
  97. }
  98. return null;
  99. },
  100. /**
  101. * Initializes this singleton and applies configuration options.
  102. * @param {Object} config An optional object with configuration properties to apply.
  103. * @return {Ext.ux.ajax.SimManager} this
  104. * @markdown
  105. */
  106. init: function (config) {
  107. var me = this;
  108. Ext.apply(me, config);
  109. if (!me.ready) {
  110. me.ready = true;
  111. if (!('defaultSimlet' in me)) {
  112. me.defaultSimlet = new Ext.ux.ajax.Simlet({
  113. status: 404,
  114. statusText: 'Not Found'
  115. });
  116. }
  117. me._openRequest = Ext.data.Connection.prototype.openRequest;
  118. Ext.data.Connection.override({
  119. openRequest: function (options, requestOptions, async) {
  120. var xhr = !options.nosim &&
  121. me.getXhr(requestOptions.method, requestOptions.url, options, async);
  122. if (!xhr) {
  123. xhr = this.callParent(arguments);
  124. }
  125. return xhr;
  126. }
  127. });
  128. if (Ext.data.JsonP) {
  129. Ext.data.JsonP.self.override({
  130. createScript: function (url, params, options) {
  131. var fullUrl = Ext.urlAppend(url, Ext.Object.toQueryString(params)),
  132. script = !options.nosim &&
  133. me.getXhr('GET', fullUrl, options, true);
  134. if (!script) {
  135. script = this.callParent(arguments);
  136. }
  137. return script;
  138. },
  139. loadScript: function (request) {
  140. var script = request.script;
  141. if (script.simlet) {
  142. script.jsonpCallback = request.params[request.callbackKey];
  143. script.send(null);
  144. } else {
  145. this.callParent(arguments);
  146. }
  147. }
  148. });
  149. }
  150. }
  151. return me;
  152. },
  153. openRequest: function (method, url, async) {
  154. var opt = {
  155. method: method,
  156. url: url
  157. };
  158. return this._openRequest.call(Ext.data.Connection.prototype, {}, opt, async);
  159. },
  160. /**
  161. * Registeres one or more {@link Ext.ux.ajax.Simlet} instances.
  162. * @param {Array/Object} simlet Either a {@link Ext.ux.ajax.Simlet} instance or config, an Array
  163. * of such elements or an Object keyed by URL with values that are {@link Ext.ux.ajax.Simlet}
  164. * instances or configs.
  165. * @markdown
  166. */
  167. register: function (simlet) {
  168. var me = this;
  169. me.init();
  170. function reg (one) {
  171. var simlet = one;
  172. if (!simlet.isSimlet) {
  173. simlet = Ext.create('simlet.' + (simlet.stype || me.defaultType), one);
  174. }
  175. me.simlets[one.url] = simlet;
  176. simlet.manager = me;
  177. }
  178. if (Ext.isArray(simlet)) {
  179. Ext.each(simlet, reg);
  180. } else if (simlet.isSimlet || simlet.url) {
  181. reg(simlet);
  182. } else {
  183. Ext.Object.each(simlet, function (url, s) {
  184. s.url = url;
  185. reg(s);
  186. });
  187. }
  188. return me;
  189. }
  190. });