Ext.apply(Ext, {
/**
* Returns the current document body as an {@link Ext.core.Element}.
* @ignore
* @memberOf Ext
* @return Ext.core.Element The document body
*/
getHead : function() {
var head;
return function() {
if (head === undefined) {
head = Ext.get(document.getElementsByTagName("head")[0]);
}
return head;
};
}()
});
/**
* @author Ed Spencer
* @class Ext.data.ScriptTagProxy
* @extends Ext.data.ServerProxy
*
* ScriptTagProxy is useful when you need to load data from a domain other than the one your application is running
* on. If your application is running on http://domainA.com it cannot use {@link Ext.data.AjaxProxy Ajax} to load its
* data from http://domainB.com because cross-domain ajax requests are prohibited by the browser.
*
* We can get around this using a ScriptTagProxy. ScriptTagProxy injects a <script> tag into the DOM whenever
* an AJAX request would usually be made. Let's say we want to load data from http://domainB.com/users - the script tag
* that would be injected might look like this:
*
<script src="http://domainB.com/users?callback=someCallback"></script>
*
* When we inject the tag above, the browser makes a request to that url and includes the response as if it was any
* other type of JavaScript include. By passing a callback in the url above, we're telling domainB's server that we
* want to be notified when the result comes in and that it should call our callback function with the data it sends
* back. So long as the server formats the response to look like this, everything will work:
*
someCallback({
users: [
{
id: 1,
name: "Ed Spencer",
email: "[email protected]"
}
]
});
*
* As soon as the script finishes loading, the 'someCallback' function that we passed in the url is called with the
* JSON object that the server returned.
*
* ScriptTagProxy takes care of all of this automatically. It formats the url you pass, adding the callback
* parameter automatically. It even creates a temporary callback function, waits for it to be called and then puts
* the data into the Proxy making it look just like you loaded it through a normal {@link Ext.data.AjaxProxy AjaxProxy}.
* Here's how we might set that up:
*
Ext.regModel('User', {
fields: ['id', 'name', 'email']
});
var store = new Ext.data.Store({
model: 'User',
proxy: {
type: 'scripttag',
url : 'http://domainB.com/users'
}
});
store.load();
*
* That's all we need to do - ScriptTagProxy takes care of the rest. In this case the Proxy will have injected a
* script tag like this:
*
<script src="http://domainB.com/users?callback=stcCallback001" id="stcScript001"></script>
*
* Customization
*
* Most parts of this script tag can be customized using the {@link #callbackParam}, {@link #callbackPrefix} and
* {@link #scriptIdPrefix} configurations. For example:
*
var store = new Ext.data.Store({
model: 'User',
proxy: {
type: 'scripttag',
url : 'http://domainB.com/users',
callbackParam: 'theCallbackFunction',
callbackPrefix: 'ABC',
scriptIdPrefix: 'injectedScript'
}
});
store.load();
*
* Would inject a script tag like this:
*
<script src="http://domainB.com/users?theCallbackFunction=ABC001" id="injectedScript001"></script>
*
* Implementing on the server side
*
* The remote server side needs to be configured to return data in this format. Here are suggestions for how you
* might achieve this using Java, PHP and ASP.net:
*
* Java:
*
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(");");
}
*
* PHP:
*
$callback = $_REQUEST['callback'];
// Create the output object.
$output = array('a' => 'Apple', 'b' => 'Banana');
//start output
if ($callback) {
header('Content-Type: text/javascript');
echo $callback . '(' . json_encode($output) . ');';
} else {
header('Content-Type: application/x-json');
echo json_encode($output);
}
*
* ASP.net:
*
String jsonString = "{success: true}";
String cb = Request.Params.Get("callback");
String responseString = "";
if (!String.IsNullOrEmpty(cb)) {
responseString = cb + "(" + jsonString + ")";
} else {
responseString = jsonString;
}
Response.Write(responseString);
*
*/
Ext.define('Ext.data.ScriptTagProxy', {
extend: 'Ext.data.ServerProxy',
alias: 'proxy.scripttag',
statics: {
TRANS_ID: 1000
},
defaultWriterType: 'base',
/**
* @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".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 {String} scriptIdPrefix
* The prefix string that is used to create a unique ID for the injected script tag element (defaults to 'stcScript')
*/
scriptIdPrefix: 'stcScript',
/**
* @cfg {String} callbackPrefix
* The prefix string that is used to create a unique callback function name in the global scope. This can optionally
* be modified to give control over how the callback string passed to the remote server is generated. Defaults to 'stcCallback'
*/
callbackPrefix: 'stcCallback',
/**
* @cfg {String} recordParam
* The param name to use when passing records to the server (e.g. 'records=someEncodedRecordString').
* Defaults to 'records'
*/
recordParam: 'records',
/**
* Reference to the most recent request made through this Proxy. Used internally to clean up when the Proxy is destroyed
* @property lastRequest
* @type Ext.data.Request
*/
lastRequest: undefined,
/**
* @cfg {Boolean} autoAppendParams True to automatically append the request's params to the generated url. Defaults to true
*/
autoAppendParams: true,
constructor: function(){
this.addEvents(
/**
* @event exception
* Fires when the server returns an exception
* @param {Ext.data.Proxy} this
* @param {Ext.data.Request} request The request that was sent
* @param {Ext.data.Operation} operation The operation that triggered the request
*/
'exception'
);
Ext.data.ScriptTagProxy.superclass.constructor.apply(this, arguments);
},
/**
* @private
* Performs the read request to the remote domain. ScriptTagProxy does not actually create an Ajax request,
* instead we write out a