dd0210c04b7d08bd16a3c133d81c72761391bb5c.svn-base 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * Ext JS Library 2.0 Copyright(c) 2006-2007, Ext JS, LLC. licensing@extjs.com
  3. *
  4. * http://extjs.com/license
  5. */
  6. /**
  7. * @class Ext.data.ScriptTagProxy
  8. * @extends Ext.data.DataProxy An implementation of Ext.data.DataProxy that
  9. * reads a data object from a URL which may be in a domain other than
  10. * the originating domain of the running page.<br>
  11. * <p>
  12. * <b>Note that if you are retrieving data from a page that is in a
  13. * domain that is NOT the same as the originating domain of the running
  14. * page, you must use this class, rather than HttpProxy.</b><br>
  15. * <p>
  16. * The content passed back from a server resource requested by a
  17. * ScriptTagProxy is executable JavaScript source code that is used as
  18. * the source inside a &lt;script> tag.<br>
  19. * <p>
  20. * In order for the browser to process the returned data, the server
  21. * must wrap the data object with a call to a callback function, the
  22. * name of which is passed as a parameter by the ScriptTagProxy. Below
  23. * is a Java example for a servlet which returns data for either a
  24. * ScriptTagProxy, or an HttpProxy depending on whether the callback
  25. * name was passed:
  26. * <p>
  27. *
  28. * <pre><code>
  29. * boolean scriptTag = false;
  30. * String cb = request.getParameter(&quot;callback&quot;);
  31. * if (cb != null) {
  32. * scriptTag = true;
  33. * response.setContentType(&quot;text/javascript&quot;);
  34. * } else {
  35. * response.setContentType(&quot;application/x-json&quot;);
  36. * }
  37. * Writer out = response.getWriter();
  38. * if (scriptTag) {
  39. * out.write(cb + &quot;(&quot;);
  40. * }
  41. * out.print(dataBlock.toJsonString());
  42. * if (scriptTag) {
  43. * out.write(&quot;);&quot;);
  44. * }
  45. * </code></pre>
  46. *
  47. * @constructor
  48. * @param {Object}
  49. * config A configuration object.
  50. */
  51. Ext.data.ScriptTagProxy = function(config) {
  52. Ext.data.ScriptTagProxy.superclass.constructor.call(this);
  53. Ext.apply(this, config);
  54. this.head = document.getElementsByTagName("head")[0];
  55. };
  56. Ext.data.ScriptTagProxy.TRANS_ID = 1000;
  57. Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
  58. /**
  59. * @cfg {String} url The URL from which to request the data object.
  60. */
  61. /**
  62. * @cfg {Number} timeout (Optional) The number of milliseconds to
  63. * wait for a response. Defaults to 30 seconds.
  64. */
  65. timeout : 30000,
  66. /**
  67. * @cfg {String} callbackParam (Optional) The name of the parameter
  68. * to pass to the server which tells the server the name of the
  69. * callback function set up by the load call to process the
  70. * returned data object. Defaults to "callback".
  71. * <p>
  72. * The server-side processing must read this parameter value,
  73. * and generate javascript output which calls this named
  74. * function passing the data object as its only parameter.
  75. */
  76. callbackParam : "callback",
  77. /**
  78. * @cfg {Boolean} nocache (Optional) Defaults to true. Disable
  79. * cacheing by adding a unique parameter name to the request.
  80. */
  81. nocache : true,
  82. /**
  83. * Load data from the configured URL, read the data object into a
  84. * block of Ext.data.Records using the passed Ext.data.DataReader
  85. * implementation, and process that block using the passed callback.
  86. *
  87. * @param {Object}
  88. * params An object containing properties which are to be
  89. * used as HTTP parameters for the request to the remote
  90. * server.
  91. * @param {Ext.data.DataReader}
  92. * reader The Reader object which converts the data
  93. * object into a block of Ext.data.Records.
  94. * @param {Function}
  95. * callback The function into which to pass the block of
  96. * Ext.data.Records. The function must be passed
  97. * <ul>
  98. * <li>The Record block object</li>
  99. * <li>The "arg" argument from the load function</li>
  100. * <li>A boolean success indicator</li>
  101. * </ul>
  102. * @param {Object}
  103. * scope The scope in which to call the callback
  104. * @param {Object}
  105. * arg An optional argument which is passed to the
  106. * callback as its second parameter.
  107. */
  108. load : function(params, reader, callback, scope, arg) {
  109. if (this.fireEvent("beforeload", this, params) !== false) {
  110. var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
  111. var url = this.url;
  112. url += (url.indexOf("?") != -1 ? "&" : "?") + p;
  113. if (this.nocache) {
  114. url += "&_dc=" + (allGetServerTime().getTime());
  115. }
  116. var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
  117. var trans = {
  118. id : transId,
  119. cb : "stcCallback" + transId,
  120. scriptId : "stcScript" + transId,
  121. params : params,
  122. arg : arg,
  123. url : url,
  124. callback : callback,
  125. scope : scope,
  126. reader : reader
  127. };
  128. var conn = this;
  129. window[trans.cb] = function(o) {
  130. conn.handleResponse(o, trans);
  131. };
  132. url += String.format("&{0}={1}", this.callbackParam,
  133. trans.cb);
  134. if (this.autoAbort !== false) {
  135. this.abort();
  136. }
  137. trans.timeoutId = this.handleFailure.defer(this.timeout,
  138. this, [trans]);
  139. var script = document.createElement("script");
  140. script.setAttribute("src", url);
  141. script.setAttribute("type", "text/javascript");
  142. script.setAttribute("id", trans.scriptId);
  143. this.head.appendChild(script);
  144. this.trans = trans;
  145. } else {
  146. callback.call(scope || this, null, arg, false);
  147. }
  148. },
  149. // private
  150. isLoading : function() {
  151. return this.trans ? true : false;
  152. },
  153. /**
  154. * Abort the current server request.
  155. */
  156. abort : function() {
  157. if (this.isLoading()) {
  158. this.destroyTrans(this.trans);
  159. }
  160. },
  161. // private
  162. destroyTrans : function(trans, isLoaded) {
  163. this.head.removeChild(document.getElementById(trans.scriptId));
  164. clearTimeout(trans.timeoutId);
  165. if (isLoaded) {
  166. window[trans.cb] = undefined;
  167. try {
  168. delete window[trans.cb];
  169. } catch (e) {
  170. }
  171. } else {
  172. // if hasn't been loaded, wait for load to remove it to
  173. // prevent script error
  174. window[trans.cb] = function() {
  175. window[trans.cb] = undefined;
  176. try {
  177. delete window[trans.cb];
  178. } catch (e) {
  179. }
  180. };
  181. }
  182. },
  183. // private
  184. handleResponse : function(o, trans) {
  185. this.trans = false;
  186. this.destroyTrans(trans, true);
  187. var result;
  188. try {
  189. result = trans.reader.readRecords(o);
  190. } catch (e) {
  191. this.fireEvent("loadexception", this, o, trans.arg, e);
  192. trans.callback.call(trans.scope || window, null, trans.arg,
  193. false);
  194. return;
  195. }
  196. this.fireEvent("load", this, o, trans.arg);
  197. trans.callback.call(trans.scope || window, result, trans.arg,
  198. true);
  199. },
  200. // private
  201. handleFailure : function(trans) {
  202. this.trans = false;
  203. this.destroyTrans(trans, false);
  204. this.fireEvent("loadexception", this, null, trans.arg);
  205. trans.callback.call(trans.scope || window, null, trans.arg,
  206. false);
  207. }
  208. });