PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/qum/www/touch/src/data/proxy/JsonP.js

https://gitlab.com/cruxrebels/queue-manager
JavaScript | 292 lines | 76 code | 24 blank | 192 comment | 8 complexity | f2b87dfc2c7477946f8dd58e90afddf8 MD5 | raw file
  1. /**
  2. * @author Ed Spencer
  3. *
  4. * The JsonP proxy is useful when you need to load data from a domain other than the one your application is running on. If
  5. * your application is running on http://domainA.com it cannot use {@link Ext.data.proxy.Ajax Ajax} to load its data
  6. * from http://domainB.com because cross-domain ajax requests are prohibited by the browser.
  7. *
  8. * We can get around this using a JsonP proxy. JsonP proxy injects a `<script>` tag into the DOM whenever an AJAX request
  9. * would usually be made. Let's say we want to load data from http://domainB.com/users - the script tag that would be
  10. * injected might look like this:
  11. *
  12. * <script src="http://domainB.com/users?callback=someCallback"></script>
  13. *
  14. * When we inject the tag above, the browser makes a request to that url and includes the response as if it was any
  15. * other type of JavaScript include. By passing a callback in the url above, we're telling domainB's server that we want
  16. * to be notified when the result comes in and that it should call our callback function with the data it sends back. So
  17. * long as the server formats the response to look like this, everything will work:
  18. *
  19. * someCallback({
  20. * users: [
  21. * {
  22. * id: 1,
  23. * name: "Ed Spencer",
  24. * email: "ed@sencha.com"
  25. * }
  26. * ]
  27. * });
  28. *
  29. * As soon as the script finishes loading, the 'someCallback' function that we passed in the url is called with the JSON
  30. * object that the server returned.
  31. *
  32. * JsonP proxy takes care of all of this automatically. It formats the url you pass, adding the callback parameter
  33. * automatically. It even creates a temporary callback function, waits for it to be called and then puts the data into
  34. * the Proxy making it look just like you loaded it through a normal {@link Ext.data.proxy.Ajax AjaxProxy}. Here's how
  35. * we might set that up:
  36. *
  37. * Ext.define('User', {
  38. * extend: 'Ext.data.Model',
  39. * config: {
  40. * fields: ['id', 'name', 'email']
  41. * }
  42. * });
  43. *
  44. * var store = Ext.create('Ext.data.Store', {
  45. * model: 'User',
  46. * proxy: {
  47. * type: 'jsonp',
  48. * url : 'http://domainB.com/users'
  49. * }
  50. * });
  51. *
  52. * store.load();
  53. *
  54. * That's all we need to do - JsonP proxy takes care of the rest. In this case the Proxy will have injected a script tag
  55. * like this:
  56. *
  57. * <script src="http://domainB.com/users?callback=callback1"></script>
  58. *
  59. * # Customization
  60. *
  61. * This script tag can be customized using the {@link #callbackKey} configuration. For example:
  62. *
  63. * var store = Ext.create('Ext.data.Store', {
  64. * model: 'User',
  65. * proxy: {
  66. * type: 'jsonp',
  67. * url : 'http://domainB.com/users',
  68. * callbackKey: 'theCallbackFunction'
  69. * }
  70. * });
  71. *
  72. * store.load();
  73. *
  74. * Would inject a script tag like this:
  75. *
  76. * <script src="http://domainB.com/users?theCallbackFunction=callback1"></script>
  77. *
  78. * # Implementing on the server side
  79. *
  80. * The remote server side needs to be configured to return data in this format. Here are suggestions for how you might
  81. * achieve this using Java, PHP and ASP.net:
  82. *
  83. * Java:
  84. *
  85. * boolean jsonP = false;
  86. * String cb = request.getParameter("callback");
  87. * if (cb != null) {
  88. * jsonP = true;
  89. * response.setContentType("text/javascript");
  90. * } else {
  91. * response.setContentType("application/x-json");
  92. * }
  93. * Writer out = response.getWriter();
  94. * if (jsonP) {
  95. * out.write(cb + "(");
  96. * }
  97. * out.print(dataBlock.toJsonString());
  98. * if (jsonP) {
  99. * out.write(");");
  100. * }
  101. *
  102. * PHP:
  103. *
  104. * $callback = $_REQUEST['callback'];
  105. *
  106. * // Create the output object.
  107. * $output = array('a' => 'Apple', 'b' => 'Banana');
  108. *
  109. * //start output
  110. * if ($callback) {
  111. * header('Content-Type: text/javascript');
  112. * echo $callback . '(' . json_encode($output) . ');';
  113. * } else {
  114. * header('Content-Type: application/x-json');
  115. * echo json_encode($output);
  116. * }
  117. *
  118. * ASP.net:
  119. *
  120. * String jsonString = "{success: true}";
  121. * String cb = Request.Params.Get("callback");
  122. * String responseString = "";
  123. * if (!String.IsNullOrEmpty(cb)) {
  124. * responseString = cb + "(" + jsonString + ")";
  125. * } else {
  126. * responseString = jsonString;
  127. * }
  128. * Response.Write(responseString);
  129. *
  130. * ###Further Reading
  131. * [Sencha Touch Data Overview](../../../core_concepts/data/data_package_overview.html)
  132. * [Sencha Touch Store Guide](../../../core_concepts/data/stores.html)
  133. * [Sencha Touch Models Guide](../../../core_concepts/data/models.html)
  134. * [Sencha Touch Proxy Guide](../../../core_concepts/data/proxies.html)
  135. */
  136. Ext.define('Ext.data.proxy.JsonP', {
  137. extend: 'Ext.data.proxy.Server',
  138. alternateClassName: 'Ext.data.ScriptTagProxy',
  139. alias: ['proxy.jsonp', 'proxy.scripttag'],
  140. requires: ['Ext.data.JsonP'],
  141. config: {
  142. defaultWriterType: 'base',
  143. /**
  144. * @cfg {String} callbackKey
  145. * See {@link Ext.data.JsonP#callbackKey}.
  146. * @accessor
  147. */
  148. callbackKey : 'callback',
  149. /**
  150. * @cfg {String} recordParam
  151. * The param name to use when passing records to the server (e.g. 'records=someEncodedRecordString').
  152. * @accessor
  153. */
  154. recordParam: 'records',
  155. /**
  156. * @cfg {Boolean} autoAppendParams
  157. * `true` to automatically append the request's params to the generated url.
  158. * @accessor
  159. */
  160. autoAppendParams: true
  161. },
  162. /**
  163. * Performs the read request to the remote domain. JsonP proxy does not actually create an Ajax request,
  164. * instead we write out a `<script>` tag based on the configuration of the internal Ext.data.Request object
  165. * @param {Ext.data.Operation} operation The {@link Ext.data.Operation Operation} object to execute.
  166. * @param {Function} callback A callback function to execute when the Operation has been completed.
  167. * @param {Object} scope The scope to execute the callback in.
  168. * @return {Object}
  169. * @protected
  170. */
  171. doRequest: function(operation, callback, scope) {
  172. // <debug>
  173. var action = operation.getAction();
  174. if (action !== 'read') {
  175. Ext.Logger.error('JsonP proxies can only be used to read data.');
  176. }
  177. // </debug>
  178. //generate the unique IDs for this request
  179. var me = this,
  180. request = me.buildRequest(operation),
  181. params = request.getParams();
  182. // apply JsonP proxy-specific attributes to the Request
  183. request.setConfig({
  184. callbackKey: me.getCallbackKey(),
  185. timeout: me.getTimeout(),
  186. scope: me,
  187. callback: me.createRequestCallback(request, operation, callback, scope)
  188. });
  189. // Prevent doubling up because the params are already added to the url in buildUrl
  190. if (me.getAutoAppendParams()) {
  191. request.setParams({});
  192. }
  193. request.setJsonP(Ext.data.JsonP.request(request.getCurrentConfig()));
  194. // Set the params back once we have made the request though
  195. request.setParams(params);
  196. operation.setStarted();
  197. me.lastRequest = request;
  198. return request;
  199. },
  200. /**
  201. * @private
  202. * Creates and returns the function that is called when the request has completed. The returned function
  203. * should accept a Response object, which contains the response to be read by the configured Reader.
  204. * The third argument is the callback that should be called after the request has been completed and the Reader has decoded
  205. * the response. This callback will typically be the callback passed by a store, e.g. in proxy.read(operation, theCallback, scope)
  206. * theCallback refers to the callback argument received by this function.
  207. * See {@link #doRequest} for details.
  208. * @param {Ext.data.Request} request The Request object.
  209. * @param {Ext.data.Operation} operation The Operation being executed.
  210. * @param {Function} callback The callback function to be called when the request completes. This is usually the callback
  211. * passed to doRequest.
  212. * @param {Object} scope The scope in which to execute the callback function.
  213. * @return {Function} The callback function.
  214. */
  215. createRequestCallback: function(request, operation, callback, scope) {
  216. var me = this;
  217. return function(success, response, errorType) {
  218. delete me.lastRequest;
  219. me.processResponse(success, operation, request, response, callback, scope);
  220. };
  221. },
  222. // @inheritdoc
  223. setException: function(operation, response) {
  224. operation.setException(operation.getRequest().getJsonP().errorType);
  225. },
  226. /**
  227. * Generates a url based on a given Ext.data.Request object. Adds the params and callback function name to the url
  228. * @param {Ext.data.Request} request The request object.
  229. * @return {String} The url.
  230. */
  231. buildUrl: function(request) {
  232. var me = this,
  233. url = me.callParent(arguments),
  234. params = Ext.apply({}, request.getParams()),
  235. filters = params.filters,
  236. filter, i, value;
  237. delete params.filters;
  238. if (me.getAutoAppendParams()) {
  239. url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
  240. }
  241. if (filters && filters.length) {
  242. for (i = 0; i < filters.length; i++) {
  243. filter = filters[i];
  244. value = filter.getValue();
  245. if (value) {
  246. url = Ext.urlAppend(url, filter.getProperty() + "=" + value);
  247. }
  248. }
  249. }
  250. return url;
  251. },
  252. /**
  253. * @inheritdoc
  254. */
  255. destroy: function() {
  256. this.abort();
  257. this.callParent(arguments);
  258. },
  259. /**
  260. * Aborts the current server request if one is currently running.
  261. */
  262. abort: function() {
  263. var lastRequest = this.lastRequest;
  264. if (lastRequest) {
  265. Ext.data.JsonP.abort(lastRequest.getJsonP());
  266. }
  267. }
  268. });