text: /*
   * Ext JS Library 2.0.2
   * Copyright(c) 2006-2008, Ext JS, LLC.
   * licensing@extjs.com
   * 
   * http://extjs.com/license
   */
  
  /**
   * @class Ext.data.ScriptTagProxy
   * @extends Ext.data.DataProxy
   * An implementation of Ext.data.DataProxy that reads a data object from a URL which may be in a domain
   * other than the originating domain of the running page.<br>
   * <p>
   * <b>Note that if you are retrieving data from a page that is in a domain that is NOT the same as the originating domain
   * of the running page, you must use this class, rather than HttpProxy.</b><br>
   * <p>
   * The content passed back from a server resource requested by a ScriptTagProxy is executable JavaScript
   * source code that is used as the source inside a &lt;script> tag.<br>
   * <p>
   * In order for the browser to process the returned data, the server must wrap the data object
   * with a call to a callback function, the name of which is passed as a parameter by the ScriptTagProxy.
   * Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy
   * depending on whether the callback name was passed:
   * <p>
   * <pre><code>
  boolean scriptTag = false;
  String cb = request.getParameter("callback");
  if (cb != null) {
      scriptTag = true;
      response.setContentType("text/javascript");
  } else {
      response.setContentType("application/x-json");
  }
  Writer out = response.getWriter();
  if (scriptTag) {
      out.write(cb + "(");
  }
  out.print(dataBlock.toJsonString());
  if (scriptTag) {
      out.write(");");
  }
  </code></pre>
   *
   * @constructor
   * @param {Object} config A configuration object.
   */
  Ext.data.ScriptTagProxy = function(config){
      Ext.data.ScriptTagProxy.superclass.constructor.call(this);
      Ext.apply(this, config);
      this.head = document.getElementsByTagName("head")[0];
  };
  
  Ext.data.ScriptTagProxy.TRANS_ID = 1000;
  
  Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
      /**
       * @cfg {String} url The URL from which to request the data object.
       */
      /**
       * @cfg {Number} timeout (Optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
       */
      timeout : 30000,
      /**
       * @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells
       * the server the name of the callback function set up by the load call to process the returned data object.
       * Defaults to "callback".<p>The server-side processing must read this parameter value, and generate
       * javascript output which calls this named function passing the data object as its only parameter.
       */
      callbackParam : "callback",
      /**
       *  @cfg {Boolean} nocache (Optional) Defaults to true. Disable cacheing by adding a unique parameter
       * name to the request.
       */
      nocache : true,
  
      /**
       * Load data from the configured URL, read the data object into
       * a block of Ext.data.Records using the passed Ext.data.DataReader implementation, and
       * process that block using the passed callback.
       * @param {Object} params An object containing properties which are to be used as HTTP parameters
       * for the request to the remote server.
       * @param {Ext.data.DataReader} reader The Reader object which converts the data
       * object into a block of Ext.data.Records.
       * @param {Function} callback The function into which to pass the block of Ext.data.Records.
       * The function must be passed <ul>
       * <li>The Record block object</li>
       * <li>The "arg" argument from the load function</li>
       * <li>A boolean success indicator</li>
       * </ul>
       * @param {Object} scope The scope in which to call the callback
       * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
       */
      load : function(params, reader, callback, scope, arg){
          if(this.fireEvent("beforeload", this, params) !== false){
  
              var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
  
              var url = this.url;
              url += (url.indexOf("?") != -1 ? "&" : "?") + p;
              if(this.nocache){
                  url += "&_dc=" + (new Date().getTime());
              }
              var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
              var trans = {
                  id : transId,
                  cb : "stcCallback"+transId,
                  scriptId : "stcScript"+transId,
                  params : params,
                  arg : arg,
                  url : url,
                  callback : callback,
                  scope : scope,
                  reader : reader
              };
              var conn = this;
  
              window[trans.cb] = function(o){
                  conn.handleResponse(o, trans);
              };
  
              url += String.format("&{0}={1}", this.callbackParam, trans.cb);
  
              if(this.autoAbort !== false){
                  this.abort();
              }
  
              trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
  
              var script = document.createElement("script");
              script.setAttribute("src", url);
              script.setAttribute("type", "text/javascript");
              script.setAttribute("id", trans.scriptId);
              this.head.appendChild(script);
  
              this.trans = trans;
          }else{
              callback.call(scope||this, null, arg, false);
          }
      },
  
      // private
      isLoading : function(){
          return this.trans ? true : false;
      },
  
      /**
       * Abort the current server request.
       */
      abort : function(){
          if(this.isLoading()){
              this.destroyTrans(this.trans);
          }
      },
  
      // private
      destroyTrans : function(trans, isLoaded){
          this.head.removeChild(document.getElementById(trans.scriptId));
          clearTimeout(trans.timeoutId);
          if(isLoaded){
              window[trans.cb] = undefined;
              try{
                  delete window[trans.cb];
              }catch(e){}
          }else{
              // if hasn't been loaded, wait for load to remove it to prevent script error
              window[trans.cb] = function(){
                  window[trans.cb] = undefined;
                  try{
                      delete window[trans.cb];
                  }catch(e){}
              };
          }
      },
  
      // private
      handleResponse : function(o, trans){
          this.trans = false;
          this.destroyTrans(trans, true);
          var result;
          try {
              result = trans.reader.readRecords(o);
          }catch(e){
              this.fireEvent("loadexception", this, o, trans.arg, e);
              trans.callback.call(trans.scope||window, null, trans.arg, false);
              return;
          }
          this.fireEvent("load", this, o, trans.arg);
          trans.callback.call(trans.scope||window, result, trans.arg, true);
      },
  
      // private
      handleFailure : function(trans){
          this.trans = false;
          this.destroyTrans(trans, false);
          this.fireEvent("loadexception", this, null, trans.arg);
          trans.callback.call(trans.scope||window, null, trans.arg, false);
      }
  });