PDA

View Full Version : Cross-domain Ext.Ajax/Ext.data.Connection



Animal
9 Nov 2007, 1:09 AM
Here, I've extended Ext.data.Connection (and therefore Ext.Ajax, because that is an instance of Ext.data.Connection) to retrieve data, and pass it to your callback function from another domain.

Of course, since it uses a script tag, the server-side script you invoke must wrap the returned data in a call to a callback function. So text must be passed back as a quoted string parameter to a function.

Also, the method is always GET, so all parameters are sent on the URL.

HTTP headers cannot be set on the request, or read from the response.

It creates a bogus XHR containing responseText and responseXML by parsing the resulting data object.

I have successfully retrieved an XML document through this. The servlet quoted the string according to javascript conventions, and wrapped it thus:



w = response.getWriter();
w.write(callback + "('");
byte[] buffer = getReportXML();
w.write(Utils.javascriptString(buffer.toString()));
w.write("');");


It still needs some work on aborting transactions because the abort code in Ext.data.Connection assumes XHR transport. I can fix that to test what the "trans" object looks like and do different things. But this works:



Ext.Ajax.request({
url: 'http://localhost:8080/aspicio/getxml.do',
params: {
listId: 'CountryListManager141Grid509',
format: 'xml'
},
scriptTag: true, // Use script tag transport
success: function(r) {
console.log(r);
}
});


Here is the override:




Ext.lib.Ajax.isCrossDomain = function(u) {
var match = /(?:(\w*:)\/\/)?([\w\.]*(?::\d*)?)/.exec(u);
if (!match[1]) return false; // No protocol, not cross-domain
return (match[1] != location.protocol) || (match[2] != location.host);
};

Ext.override(Ext.data.Connection, {

request : function(o){
if(this.fireEvent("beforerequest", this, o) !== false){
var p = o.params;

if(typeof p == "function"){
p = p.call(o.scope||window, o);
}
if(typeof p == "object"){
p = Ext.urlEncode(p);
}
if(this.extraParams){
var extras = Ext.urlEncode(this.extraParams);
p = p ? (p + '&' + extras) : extras;
}

var url = o.url || this.url;
if(typeof url == 'function'){
url = url.call(o.scope||window, o);
}

if(o.form){
var form = Ext.getDom(o.form);
url = url || form.action;

var enctype = form.getAttribute("enctype");
if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
return this.doFormUpload(o, p, url);
}
var f = Ext.lib.Ajax.serializeForm(form);
p = p ? (p + '&' + f) : f;
}

var hs = o.headers;
if(this.defaultHeaders){
hs = Ext.apply(hs || {}, this.defaultHeaders);
if(!o.headers){
o.headers = hs;
}
}

var cb = {
success: this.handleResponse,
failure: this.handleFailure,
scope: this,
argument: {options: o},
timeout : this.timeout
};

var method = o.method||this.method||(p ? "POST" : "GET");

if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
}

if(typeof o.autoAbort == 'boolean'){ // options gets top priority
if(o.autoAbort){
this.abort();
}
}else if(this.autoAbort !== false){
this.abort();
}
if((method == 'GET' && p) || o.xmlData || o.jsonData){
url += (url.indexOf('?') != -1 ? '&' : '?') + p;
p = '';
}
if (o.scriptTag || this.scriptTag || Ext.lib.Ajax.isCrossDomain(url)) {
this.transId = this.scriptRequest(method, url, cb, p, o);
} else {
this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
}
return this.transId;
}else{
Ext.callback(o.callback, o.scope, [o, null, null]);
return null;
}
},

scriptRequest : function(method, url, cb, data, options) {
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};

url += (url.indexOf("?") != -1 ? "&" : "?") + data + String.format("&{0}={1}", options.callbackParam || this.callbackParam || 'callback', trans.cb);

var conn = this;
window[trans.cb] = function(o){
conn.handleScriptResponse(o, trans);
};

// Set up the timeout handler
trans.timeoutId = this.handleScriptFailure.defer(cb.timeout, this, [trans]);

var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
script.setAttribute("id", trans.scriptId);
document.getElementsByTagName("head")[0].appendChild(script);

return trans;
},

handleScriptResponse : function(o, trans){
this.transId = false;
this.destroyScriptTrans(trans, true);
var options = trans.options;

// Attempt to parse a string parameter as XML.
var doc;
if (typeof o == 'string') {
if (window.ActiveXObject) {
doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(o);
} else {
doc = new DOMParser().parseFromString(o,"text/xml");
}
}

// Create the bogus XHR
response = {
responseObject: o,
responseText: (typeof o == "object") ? Ext.util.JSON.encode(o) : String(o),
responseXML: doc,
argument: options.argument
}
this.fireEvent("requestcomplete", this, response, options);
Ext.callback(options.success, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, true, response]);
},

handleScriptFailure: function(trans) {
this.transId = false;
this.destroyScriptTrans(trans, false);
var options = trans.options;
response = {
argument: options.argument,
status: 500,
statusText: 'Server failed to respond',
responseText: ''
};
this.fireEvent("requestexception", this, response, options, {
status: -1,
statusText: 'communication failure'
});
Ext.callback(options.failure, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, false, response]);
},

// private
destroyScriptTrans : function(trans, isLoaded){
document.getElementsByTagName("head")[0].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){}
};
}
}
});

CPliskin
9 Nov 2007, 4:00 AM
Hi!

You are the greatest :)
I've needed to create SSL authentication request in my application and I think that I've found solution :)

Animal
9 Nov 2007, 5:16 AM
It's a bit more code, but if Ext.data.Connection were updated to include this capability, then SctiptTagProxy would be very small. It would just call Ext.Ajax.request with scriptTag:true

galdaka
9 Nov 2007, 5:24 AM
Thanks Animal,

Is posible a small live example?

Excellent work!!

Animal
9 Nov 2007, 5:48 AM
I don't have a website.

Animal
9 Nov 2007, 5:49 AM
Actually, I could just drop something into here which will drop into examples/form.... hang on...

Animal
9 Nov 2007, 5:59 AM
OK, drop this into examples/<whatever>



<html>
<head>
<title>Script Tag Ajax</title>
<!-- LIBS -->
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<!-- ENDLIBS -->

<script type="text/javascript" src="../../ext-all.js"></script>

<script type="text/javascript">
Ext.override(Ext.data.Connection, {

request : function(o){
if(this.fireEvent("beforerequest", this, o) !== false){
var p = o.params;

if(typeof p == "function"){
p = p.call(o.scope||window, o);
}
if(typeof p == "object"){
p = Ext.urlEncode(p);
}
if(this.extraParams){
var extras = Ext.urlEncode(this.extraParams);
p = p ? (p + '&' + extras) : extras;
}

var url = o.url || this.url;
if(typeof url == 'function'){
url = url.call(o.scope||window, o);
}

if(o.form){
var form = Ext.getDom(o.form);
url = url || form.action;

var enctype = form.getAttribute("enctype");
if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
return this.doFormUpload(o, p, url);
}
var f = Ext.lib.Ajax.serializeForm(form);
p = p ? (p + '&' + f) : f;
}

var hs = o.headers;
if(this.defaultHeaders){
hs = Ext.apply(hs || {}, this.defaultHeaders);
if(!o.headers){
o.headers = hs;
}
}

var cb = {
success: this.handleResponse,
failure: this.handleFailure,
scope: this,
argument: {options: o},
timeout : this.timeout
};

var method = o.method||this.method||(p ? "POST" : "GET");

if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
}

if(typeof o.autoAbort == 'boolean'){ // options gets top priority
if(o.autoAbort){
this.abort();
}
}else if(this.autoAbort !== false){
this.abort();
}
if((method == 'GET' && p) || o.xmlData || o.jsonData){
url += (url.indexOf('?') != -1 ? '&' : '?') + p;
p = '';
}
if (o.scriptTag) {
this.transId = this.scriptRequest(method, url, cb, p, o);
} else {
this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
}
return this.transId;
}else{
Ext.callback(o.callback, o.scope, [o, null, null]);
return null;
}
},

scriptRequest : function(method, url, cb, data, options) {
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};

url += (url.indexOf("?") != -1 ? "&" : "?") + data + String.format("&{0}={1}", options.callbackParam || 'callback', trans.cb);

var conn = this;
window[trans.cb] = function(o){
conn.handleScriptResponse(o, trans);
};

// Set up the timeout handler
trans.timeoutId = this.handleScriptFailure.defer(cb.timeout, this, [trans]);

var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
script.setAttribute("id", trans.scriptId);
document.getElementsByTagName("head")[0].appendChild(script);

return trans;
},

handleScriptResponse : function(o, trans){
this.transId = false;
this.destroyScriptTrans(trans, true);
var options = trans.options;

// Attempt to parse a string parameter as XML.
var doc;
if (typeof o == 'string') {
if (window.ActiveXObject) {
var doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(o);
} else {
var doc = new DOMParser().parseFromString(o,"text/xml");
}
}

// Create the bogus XHR
response = {
responseObject: o,
responseText: (typeof o == "object") ? Ext.util.JSON.encode(o) : String(o),
responseXML: doc,
argument: options.argument
}
this.fireEvent("requestcomplete", this, response, options);
Ext.callback(options.success, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, true, response]);
},

handleScriptFailure: function(trans) {
this.trans = false;
this.destroyScriptTrans(trans, false);
var options = trans.options;
response = {
argument: options.argument
};
this.fireEvent("requestexception", this, response, options, new Error("Timeout"));
Ext.callback(options.failure, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, false, response]);
},

// private
destroyScriptTrans : function(trans, isLoaded){
document.getElementsByTagName("head")[0].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){}
};
}
}
});

Ext.onReady(function() {
Ext.Ajax.request({
url: 'http://extjs.com/forum/topics-remote.php',
scriptTag: true,
params: {
query: 'Animal',
limit: 10,
start: 0
}, success: function(response) {
Ext.get("json-result").update(response.responseText);
}
});
});
</script>
</head>
<body>
<h1>Request data from the ExtJs forum search service</h1>
<h3>Code:</h3>
<code><pre>
Ext.Ajax.request({
url: 'http://extjs.com/forum/topics-remote.php',
scriptTag: true,
params: {
query: 'Animal',
limit: 10,
start: 0
}, success: function(response) {
Ext.get("json-result").update(response.responseText);
}
});
</pre></code>
<h3>Response:</h3>
<code><pre id="json-result"></pre></code>
</body>
</html>

galdaka
9 Nov 2007, 9:06 AM
Excellent example!

Thanks!!

galdaka
15 Nov 2007, 12:18 AM
Animal,

I

hendricd
15 Nov 2007, 7:54 AM
The browser is trying to process valid javascript source within the generated <script> tag. You're loading raw XML into it, thus failing.

If you have some level of control of the cross-domain server response, the response will have to be scripted to pass your XML to the callback function you should have specified with the callback parameter in the request.

galdaka
15 Nov 2007, 9:39 AM
Sorry for my English.

I understand.

I try to change by easy way this code:


script.setAttribute("type", "text/javascript");

for this:


script.setAttribute("type", "text/xml");

I have no errors, but "handleresponse" never fires.

Is posible by changes in your override code, proccesing the two most popular types of reponses in client? (JSON and XML). Now only processing JSON?

I think that your override should be included in future versions of Ext. The cross-domain request are in the top of actual web applicattions.

Thanks in advance,

MoShAn480
15 Nov 2007, 11:26 AM
Im trying to use the override too. I am able to run the example just fine, but when i run my own application code i get the following error in fireBug which says invalidLabel? Anyone have any ideas? Thanks!

JeffHowden
15 Nov 2007, 12:22 PM
What does your response look like?

MoShAn480
15 Nov 2007, 12:43 PM
Here is my response:

chrome://firebug/content/blank.gif{"status":"success","connectionId":"6F2A9B03326B26DC"}


Also, I missed this earlier, but i guess my response has to be wrapped in a callback function. If this is the case, it seems i have to set this up on the server so my response should be:

myCallBack ('{"status":"success","connectionId":"6F2A9B03326B26DC"}')

This ok when i have control of the server response, but about the case where I am accessing data from a server whihc is out of my control. Please correct me if I'm not understanding this correctly. Thanks.

MoShAn480
15 Nov 2007, 12:56 PM
oops my original response string was:

{"status":"success","connectionId":"6F2A9B03326B26 DC"}

Thanks...

gkassyou
15 Nov 2007, 1:44 PM
Animal. Will this work with the 1.1.1 release?

Thx

JeffHowden
15 Nov 2007, 3:08 PM
Also, I missed this earlier, but i guess my response has to be wrapped in a callback function. If this is the case, it seems i have to set this up on the server so my response should be:


myCallBack ('{"status":"success","connectionId":"6F2A9B03326B26DC"}');

That's correct. A callback is absolutely necessary. The reason is that you're just dynamically including a JavaScript file and without the response wrapped with a function call there's no way for the response to get injected back into whatever it is you need to have it in. Additionally, without it being wrapped in a callback, the response (whether pure JSON or XML) will cause errors as it's invalid JavaScript on its own.


This ok when i have control of the server response, but about the case where I am accessing data from a server whihc is out of my control.

If the server response is out of your control, often there are means for instructing the server (by the parameters sent to it) to include a callback. In some cases you can specify the name of the callback function. In others, the callback is not adjustable and you must indicate in your request parameters what the name of the callback will be so Ext can setup a function by that name that's waiting to be called. In situations where there's no means for the server to include a callback, you'll have to proxy the request from your server to their server and back.

galdaka
15 Nov 2007, 11:15 PM
Sorry for my English.

I understand.

I try to change by easy way this code:


script.setAttribute("type", "text/javascript");

for this:


script.setAttribute("type", "text/xml");

I have no errors, but "handleresponse" never fires.

Is posible by changes in your override code, proccesing the two most popular types of reponses in client? (JSON and XML). Now only processing JSON?

I think that your override should be included in future versions of Ext. The cross-domain request are in the top of actual web applicattions.

Thanks in advance,

Any ideas about only client-side solution for XML request?

Thanks in advance,

markpele
16 Nov 2007, 8:08 AM
I`m using Animal`s override and able to get the callback from the server.

Can I use script tag the same as normal AJAX calls in the sense that I can make two asynch requests?

I`m creating two connections objects con1 and con2.
Requests are being sent as a result of user actions.
There could be a state where both con1 and con2 are running so before I`m making a request I`m doing a check:

if(!con1.isLoading()) {
con = con1;
console.log('con1');
return true;
}
else if(!con2.isLoading()) {
con = con2;
console.log('con2');
return true;
}
else return false;

It takes 30 seconds for my server to respond so I can easily control things.
When looking at firebug console and sending requests with a delay time < 30 second I get:

con1
con1
con1
...

Instead of:

con1
con2
con1
con2
...

Is there a problem with isLoading() with this override or maybe I`m not allowed to use it?
I tried the same with normal AJAX calls and I get the expected behaviour.

Is timeout the only error exception I can get when using script tag?

Animal
18 Nov 2007, 9:40 AM
This works.

The server MUST respond by calling the specified callback to get the data "into" Ext.

Here is what I am hoping (probably somewhat pretentiously) will become a "reference implementation" of Ext with cross-domain Ajax. It's a Flickr control Panel.

It's not finished, but try it as far as it goes. It's commented, so you should be able to see what it does. It unzips into examples/<whatever>

2830

http://i131.photobucket.com/albums/p286/TimeTrialAnimal/flickr.jpg

Animal
18 Nov 2007, 9:42 AM
As you can see from my implementation, dozens of requests can be outstanding at once. It posts several flickr calls to get details about each image found.

Timeout is the only error we can detect.

What happens inside a <script> tag is up to what YOU send from the server. All I can detect is that the specified callback did not get called within a given time.

Animal
19 Nov 2007, 12:13 AM
The server must have the ability to wrap the returned data in a callback function in order to be called using a script tag. A script tag pulls in executable code, that is what they do.

The flickr api offers this.

If you are in control of your server, you can write your server-side script/servlet to detect whether there is a callback function name passed (You can specify what the parameter name for this is in the callbackParam option of the request call.

If you want to return XML, then you will have to return it by passing a STRING, a quoted string into the callback function.

My script handling code will parse this, and you will recieve a responseXML property in the response.

markpele
20 Nov 2007, 11:29 AM
I have some questions:

1. Can you post your code as an extension in the wiki?

2.
if (o.scriptTag || this.scriptTag) {
this.transId = this.scriptRequest(method, url, cb, p, o);
} else {
this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
}

this.transId is actually trans which contains transId inside it. I understand why you named it transId but is it possible to change the name to something more intuitive if it`ll make it into ext.

3. In my case I can`t change the server code and it always name the callback function the same. I modified the code and commented out the part which defines and destroys the function:

var conn = this;
window[trans.cb] = function(o){
conn.handleScriptResponse(o, trans);
};
I also had to change the rest of the code because you send trans to handleScriptResponse and I can`t. Is it possible to add a config option for the code so the user can define if the name of the callback be a constant and in the user responsibility to create and destroy?
Do you think that my case is too special to include in your code?

Best,
Mark Pele

Animal
21 Nov 2007, 12:52 AM
In the latest drop, you can specify what the callback function name is. Use the option callbackName in the request parameter object.

It now has:



...
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};
...


"this.transId" is in the original. It identifies a current Ajax request allowing cancelling. The posted code hasn't been updated to cancel script requests, but I'll get around to it.

markpele
21 Nov 2007, 1:43 AM
Is this a mistake:

handleScriptFailure: function(trans) {
this.trans = false;


or should it be:

handleScriptFailure: function(trans) {
this.transId = false;


I know I can define the callback name.

My problem is that I need to send two requests at the same time but have to use the same callback name. In this case each response will delete the window[trans.cb] function and each request will override the last definition of that function.

Animal
21 Nov 2007, 5:17 AM
You don't create the callback function which the server calls, Ext.Ajax.request does that. It creates a new handler function for each request.

If you want a callback called with that data, you pass it as a success handler into Ext.Ajax.request.

markpele
21 Nov 2007, 5:55 AM
Either I don`t understand something or can`t explain what I`m trying to do.

It`s possible to define the callbackName or to use auto generated one:

scriptRequest : function(method, url, cb, data, options) {
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};


The server wrap the response with options.callbackName or stcCallback+transId.
When the script is loaded it calls the function which is defined here:


var conn = this;
window[trans.cb] = function(o){
conn.handleScriptResponse(o, trans);
};


My server respond every time with the same callback and I can`t change the code. Let`s call it "serverCallback". I can`t send two requests because the second one will run over window[trans.cb]. I have to send my requests in sync.

What I`m trying to do to is to comment out the part that define window[trans.cb] and the part that remove this function and move it outside of the class.

ericd
21 Nov 2007, 8:07 AM
This looks like a nice extension to have, but looking at the code, it seems to only support XML, or am I wrong? What about if a remote server sends JSON vs XML (which is my case)

Animal
21 Nov 2007, 8:56 AM
It supports passing data directly into Javascript, for example "JSON".

See http://extjs.com/forum/showthread.php?t=18653 for an example which uses the flickr and Yahoo REST APIs to receive JSON.

markpele.

You do NOT have to define what that callback is.

Show us your code, and I'll correct it.

ericd
21 Nov 2007, 9:04 AM
Animal,

Thanks for the quick reply, but after looking at your sample (flickr) i have figured it out and you beat me to the punch, btw... that extension is a keeper!

Wolfgang
31 Jan 2008, 2:57 AM
Animal,
some questions about this:

In the latest drop, you can specify what the callback function name is.
...

Is the latest drop the src on page 1 of this posting (the example you have given)?

What happens to the DOM when using scripttagproxy or this version of ext.data.connection in terms of adding scripts dynamically?
I mean, will the script tags add up on each response thus increase memory usage?
If so, can they be removed in a sort of garbage collection, similar to how ext works inernally?

dolittle
31 Jan 2008, 3:32 AM
As far as I know they are destroyed.
Taken from anymal's code:

destroyScriptTrans : function(trans, isLoaded){
document.getElementsByTagName("head")[0].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){}
};
}
}


I wish someone could help me with this (http://extjs.com/forum/showthread.php?t=24610).
It's a cross domain communication that uses a proxy.html file and url fragment identifiers based on YUI.

The proxy.html file is being cached on the client so there is no round trip to the server.

If you have access to the remote server and can place the proxy.html file you can use normal ajax calls which are much better then dynamic script tags.

Wolfgang
31 Jan 2008, 4:57 AM
Thank you.
May you can tell me weher to get the latest drop of the code?

vtswingkid
6 Feb 2008, 7:53 AM
I love it! Thanks!

vtswingkid
6 Mar 2008, 6:31 AM
So the new Ext.lib.Ajax.isCrossDomain should make it so that all requests can now be crossdomain? i.e. TreeLoader with a url http://whatever/x.php would automatically generate a GET request to that crossdomain url? Same with store.load?

I am getting ready to find out for myself...will post back unless someone already knows.

Animal
6 Mar 2008, 7:31 AM
It does work. I had to use it on a project recently where I ran the app locally, but had to pull in data for a TreePanel and a DataView from the client's server in Australia!

vtswingkid
6 Mar 2008, 7:37 AM
I am creating a redundancy server that sits over top of an unlimited number of remote servers. So I have tons of crossdomain.

So when you create grid you specify a url. Can I respecify the url on load with out overriding data.Store.load?
So in otherwords on one refresh the data may be pulled from a remote server. On another refresh, that server may be down and it needs to be pulled from the redundancy server.

Animal
7 Mar 2008, 1:00 AM
If you're using JSON, and the server knows that when a callback name is passed, it has to wrap the data in a call to that name, then it should just work.

vtswingkid
7 Mar 2008, 5:17 AM
I confirmed that uploads work great as you mentioned in the Features Thread. I'll keep my conversation here for now on.

I have an issue where I create a data store and the need to check a status flag to see which url to request data from on each load. So I am using the beforeload event and updating the store.proxy.url. This seems like a good way to achieve this, is there one better?

Animal
7 Mar 2008, 5:57 AM
SHouldn't that be



store.proxy.conn.url


?

MoShAn480
11 Mar 2008, 8:54 AM
I noticed the Ext.data.ScriptTagProxy in Ext 2.0.2. Does this mean that cross domain Ajax requests are supported out of box too? From what I can tell ScriptTagProxy can be used with components that use a data proxy only. If I am wrong, how can I flag the Ajax.request to use ScriptTagProxy?

Animal
11 Mar 2008, 9:17 AM
Proxy classes are used with DataReader clases to load Stores.

Are you loading a Store, or making a one-off request for some data?

MoShAn480
11 Mar 2008, 9:33 AM
I will be making a one-off request for some data periodically.

Animal
11 Mar 2008, 10:35 AM
So use the latest cut of the overrides for Ext.data.Connection from the first post. It detects that the URL is a different domain and uses a script tag.

Your server script which services this request does wrap the data in a function call doesn't it?

MoShAn480
11 Mar 2008, 10:52 AM
Yes it does. Thanks for the clarification. I have been using the override but just downloaded the latest 2.0.2 code. I thought maybe the override had been integrating into the toolkit. Thanks again!

vtswingkid
12 Mar 2008, 11:33 AM
I am noticing that IE7 is not sending session ids durring a cross domain communication. FF does. Anyone else have this problem. Is there a browser setting that can be changed? Or is a work around needed?

EDIT: it looks like a security feature... I wonder if IE6 does this to. I put the session id in the url to work around that problem...

rdbrazil
26 Mar 2008, 11:18 AM
Is it possible to do a cross domain upload based in this solution?

It works fine for me for POST and GET, but when I set "isUpload = true" in my Ext.Ajax.request, it stopped in this part:


if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
return this.doFormUpload(o, p, url);
}
It works in the same domain, but in cross domains the Ajax response objetct is empty.

response {
argument = undefined
responseText = ""
responseXML = null
}

Tku

vtswingkid
26 Mar 2008, 5:18 PM
It worked for me. I didn't do anything special.

Javiera
26 Mar 2008, 7:02 PM
You do NOT have to define what that callback is.

Show us your code, and I'll correct it.

I haven't laughed this hard since.. dunno.. but, :-) Keep up the good work Animal.

rdbrazil
27 Mar 2008, 4:34 AM
It worked for me. I didn't do anything special.

Debugging it, in ext-all-debug.js, doFormUpload method...

function cb(){
var r = {
responseText : '',
responseXML : null
};

r.argument = o ? o.argument : null;

try {
var doc;
if(Ext.isIE){
doc = frame.contentWindow.document;

frame.contentWindow.document returns "Access Denied".

In my tests I use: http://localhost and http://mymachinename. My WebAplication is running in localhost and my js and post page/upload page is in mymachinename.

Do you have any example that I can test the upload between cross domains?

Animal
27 Mar 2008, 8:43 AM
It's browser security. I don't think there's any way round it.

neenhouse
27 Mar 2008, 12:58 PM
I've read this thread several times, and I'm still having problem wrapping my head around it...

Say you have 0 control over server response. Can you just capture response text by hardcoding your call back functions inside your initial request?

Animal
28 Mar 2008, 1:37 AM
No. To use a script tag, the server must cooperate. What gets sent back must be script of course!

JeffHowden
29 Mar 2008, 1:50 AM
No. To use a script tag, the server must cooperate. What gets sent back must be script of course!
And worse, what gets sent back cannot, in any way, interact with the calling page. So, the cross-domain server cannot respond with a page with a <script> block that simply calls your callback function in the parent window. I've played around with this alot and the only way I could achieve it reliably is with redirects.

http://ext.vosandhowden.com/ux/iframe.cfm

As this relies on the URL for transferring the response from the cross-domain server to the local-domain server, as well as a very specific implementation, there are obvious limitations to the size of the message back from the cross-domain server.

lonerzzz
11 Apr 2008, 10:31 PM
Animal, Thanks for the exceptional code. It makes web integration very smooth.

I have augmented the code in what I hope to be a generic manner in order to support complex JSON data responses from servers in addition to XML responses. In particular, I was using the AJAX calls to the Google Web search and found that the callback provided requires 4 parameters.

Thus, I extended the internal callback to handle up to 8 parameters and to wrap the result into a single response object passed back to the user application. Now, many different WEB services should be callable with this interface.

To support extraction of specific response parameters, the following parameter should be added to the Ext.Ajax.request config:

responseParams: { context: 1, response: 4, ... }

The keys, context, response, etc. represent the application-defined names that the parameters will have in the object passed to the callback in the user code. The numbers represent the Nth parameter passed in the server-defined callback function.

If the responseParams parameter is not provided, the first response parameter from the callback is returned.

The updated Connection implementation is attached.


Ext.lib.Ajax.isCrossDomain = function(u) {
var match = /(?:(\w*:)\/\/)?([\w\.]*(?::\d*)?)/.exec(u);
if (!match[1]) return false; // No protocol, not cross-domain
return (match[1] != location.protocol) || (match[2] != location.host);
};

Ext.override(Ext.data.Connection, {

request : function(o){
if(this.fireEvent("beforerequest", this, o) !== false){
var p = o.params;

if(typeof p == "function"){
p = p.call(o.scope||window, o);
}
if(typeof p == "object"){
p = Ext.urlEncode(p);
}
if(this.extraParams){
var extras = Ext.urlEncode(this.extraParams);
p = p ? (p + '&' + extras) : extras;
}

var url = o.url || this.url;
if(typeof url == 'function'){
url = url.call(o.scope||window, o);
}

if(o.form){
var form = Ext.getDom(o.form);
url = url || form.action;

var enctype = form.getAttribute("enctype");
if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
return this.doFormUpload(o, p, url);
}
var f = Ext.lib.Ajax.serializeForm(form);
p = p ? (p + '&' + f) : f;
}

var hs = o.headers;
if(this.defaultHeaders){
hs = Ext.apply(hs || {}, this.defaultHeaders);
if(!o.headers){
o.headers = hs;
}
}

var cb = {
success: this.handleResponse,
failure: this.handleFailure,
scope: this,
argument: {options: o},
timeout : this.timeout
};

var method = o.method||this.method||(p ? "POST" : "GET");

if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
}

if(typeof o.autoAbort == 'boolean'){ // options gets top priority
if(o.autoAbort){
this.abort();
}
}else if(this.autoAbort !== false){
this.abort();
}
if((method == 'GET' && p) || o.xmlData || o.jsonData){
url += (url.indexOf('?') != -1 ? '&' : '?') + p;
p = '';
}
if (o.scriptTag || this.scriptTag || Ext.lib.Ajax.isCrossDomain(url)) {
this.transId = this.scriptRequest(method, url, cb, p, o);
} else {
this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
}
return this.transId;
}else{
Ext.callback(o.callback, o.scope, [o, null, null]);
return null;
}
},

scriptRequest : function(method, url, cb, data, options) {
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};

url += (url.indexOf("?") != -1 ? "&" : "?") + ((data == '')?'':(data+'&')) + String.format("{0}={1}", options.callbackParam || this.callbackParam || 'callback', trans.cb);

var conn = this;
window[trans.cb] = function(o1, o2, o3, o4, o5, o6, o7, o8){
conn.handleScriptResponse(trans, o1, o2, o3, o4, o5, o6, o7, o8);
};

// Set up the timeout handler
trans.timeoutId = this.handleScriptFailure.defer(cb.timeout, this, [trans]);

var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
script.setAttribute("id", trans.scriptId);
document.getElementsByTagName("head")[0].appendChild(script);

return trans;
},

handleScriptResponse : function(trans, o1, o2, o3, o4, o5, o6, o7, o8){
this.transId = false;
this.destroyScriptTrans(trans, true);
var options = trans.options;
var o;

var json = "";
if (options.responseParams) {
var responseParams = options.responseParams;
var paramCount = 0;
for(var key in responseParams) {
var paramIndex = responseParams[key];
switch (paramIndex) {
case 1: o = o1; break;
case 2: o = o2; break;
case 3: o = o3; break;
case 4: o = o4; break;
case 5: o = o5; break;
case 6: o = o6; break;
case 7: o = o7; break;
case 8: o = o8; break;
default: o = o1;
}
json += key+': '+Ext.util.JSON.encode(o)+', ';
paramCount++;
}
if (paramCount == 0) {
o = o1;
}
else if (paramCount != 1) {
json = '{ ' + json.substr(0, json.length -2 ) + ' }';
o = Ext.util.JSON.decode( json );
}
else
{
json = '';
}
}
else
{
o = o1;
}

// Attempt to parse a string parameter as XML.
var doc;
if (typeof o == 'string') {
if (window.ActiveXObject) {
doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(o);
} else {
doc = new DOMParser().parseFromString(o,"text/xml");
}
}

// Create the bogus XHR
response = {
responseObject: o,
responseText: (typeof o == "object") ? ((json.length == 0)?Ext.util.JSON.encode(o):json) : String(o),
responseXML: doc,
argument: options.argument
}
this.fireEvent("requestcomplete", this, response, options);
Ext.callback(options.success, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, true, response]);
},

handleScriptFailure: function(trans) {
this.transId = false;
this.destroyScriptTrans(trans, false);
var options = trans.options;
response = {
argument: options.argument,
status: 500,
statusText: 'Server failed to respond',
responseText: ''
};
this.fireEvent("requestexception", this, response, options, {
status: -1,
statusText: 'communication failure'
});
Ext.callback(options.failure, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, false, response]);
},

// private
destroyScriptTrans : function(trans, isLoaded){
document.getElementsByTagName("head")[0].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){}
};
}
}
});


Any corrections or feedback is appreciated.

lonerzzz

Animal
12 Apr 2008, 1:56 AM
I think you've overthought it.

Ext.Ajax is just to return undifferentiated data blocks.

The situation you describe is basically, you are asking Google to call a certain function of yoiur choosing passing some interesting data in through the 4 parameters.

Try this:



function doSearch(searchTerm, callback, scope) {
var h = document.getElementsByTagName('head')[0];
var s = document.createElement("script");

// create a uniquely named global function which just passes all its
// arguments straight into a callback.
var cbName = Ext.id(null, 'gcallbackfn');
window[cbName] = function() {
callback.apply(scope || window, arguments);
h.removeChild(s);
window[cbName ] = undefined;
try{
delete window[cbName];
}catch(e){}
};

// Up to you how you create the URL - this is a total guess
s.src = 'http://api.google.com/search?q=' + searchTerm + "&callback=' + cbName;
h.appendChild(s);
}

doSearch("test", processSearchResult);

function procesSearchResult(param1, param2, param3, param4) {
}

lonerzzz
12 Apr 2008, 6:23 AM
I see your point with regard to a more direct solution.

I implemented as I did because the remote server is dictating the callback method signature and I wanted to take advantage of the built-in event notifications, connection management and standardized callback approach of Ext.Connection.

Are you then recommending either that JSON data not be retrieved with Ext.Ajax.request or that it is simply not appropriate when the remote server is not responding to requests with a simple one parameter answer?

Thanks for the feedback so far.

Animal
12 Apr 2008, 6:36 AM
Blocks of data can be returned using Ext.Ajax.

If you are calling a service which can only be called through <script> tags and therefore which by the very nature of the service, calls a function anyway, then just have it call your function.

MikeB
19 Jun 2008, 7:17 AM
Animal, great script and I've used it several times on some other projects w/ no problem.
However, I've just come across a project which requires access to a url via HTTPS, and it doesn't seem to work!?!?!

EDIT - Actually yes it does work, the problem was OBD on this end (forgot to make the serverside script add the callback handler name which was passed DUH!!!)

Here's my variation on your original sample application:



<html>
<head>
<title>Script Tag Ajax</title>
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all.js"></script>

<script type="text/javascript" >
// Cross Domain AJAX request extension...
Ext.override(Ext.data.Connection, {
request : function(o){
if(this.fireEvent("beforerequest", this, o) !== false){
var p = o.params;
if(typeof p == "function"){
p = p.call(o.scope||window, o);
}
if(typeof p == "object"){
p = Ext.urlEncode(p);
}
if(this.extraParams){
var extras = Ext.urlEncode(this.extraParams);
p = p ? (p + '&' + extras) : extras;
}
var url = o.url || this.url;
if(typeof url == 'function'){
url = url.call(o.scope||window, o);
}
if(o.form){
var form = Ext.getDom(o.form);
url = url || form.action;
var enctype = form.getAttribute("enctype");
if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
return this.doFormUpload(o, p, url);
}
var f = Ext.lib.Ajax.serializeForm(form);
p = p ? (p + '&' + f) : f;
}
var hs = o.headers;
if(this.defaultHeaders){
hs = Ext.apply(hs || {}, this.defaultHeaders);
if(!o.headers){
o.headers = hs;
}
}
var cb = {
success: this.handleResponse,
failure: this.handleFailure,
scope: this,
argument: {options: o},
timeout : this.timeout
};
var method = o.method||this.method||(p ? "POST" : "GET");
if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
}
if(typeof o.autoAbort == 'boolean'){ // options gets top priority
if(o.autoAbort){
this.abort();
}
}else if(this.autoAbort !== false){
this.abort();
}
if((method == 'GET' && p) || o.xmlData || o.jsonData){
url += (url.indexOf('?') != -1 ? '&' : '?') + p;
p = '';
}
if (o.scriptTag) {
console.log("External");
this.transId = this.scriptRequest(method, url, cb, p, o);
} else {
console.log("Internal");
this.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
}
return this.transId;
}else{
console.log("fireEvent FAILED");
Ext.callback(o.callback, o.scope, [o, null, null]);
return null;
}
},

scriptRequest : function(method, url, cb, data, options) {
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};
url += (url.indexOf("?") != -1 ? "&" : "?") + data;
url += String.format("&{0}={1}", options.callbackParam || 'callback', trans.cb);
var conn = this;
window[trans.cb] = function(o){
conn.handleScriptResponse(o, trans);
};
// Set up the timeout handler
trans.timeoutId = this.handleScriptFailure.defer(cb.timeout, this, [trans]);
var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
script.setAttribute("id", trans.scriptId);
document.getElementsByTagName("head")[0].appendChild(script);
return trans;
},
handleScriptResponse : function(o, trans){
this.transId = false;
this.destroyScriptTrans(trans, true);
var options = trans.options;

// Attempt to parse a string parameter as XML.
var doc;
if (typeof o == 'string') {
if (window.ActiveXObject) {
var doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(o);
} else {
var doc = new DOMParser().parseFromString(o,"text/xml");
}
}
// Create the bogus XHR
var response = {
responseObject: o,
responseText: (typeof o == "object") ? Ext.util.JSON.encode(o) : String(o),
responseXML: doc,
argument: options.argument
}
this.fireEvent("requestcomplete", this, response, options);
Ext.callback(options.success, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, true, response]);
},

handleScriptFailure: function(trans) {
this.trans = false;
this.destroyScriptTrans(trans, false);
var options = trans.options;
var response = {
argument: options.argument
};
this.fireEvent("requestexception", this, response, options, new Error("Timeout"));
Ext.callback(options.failure, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, false, response]);
},

// private
destroyScriptTrans : function(trans, isLoaded){
document.getElementsByTagName("head")[0].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){}
};
}
}
});
</script>

<script type="text/javascript">
// MY Demo code
var url1 = 'http://extjs.com/forum/topics-remote.php';
var url4 = 'https://www.techout.com/techexec/techout.nsf/xDomain';
function Topics( theURL, external ) {
Ext.get("remote-url").update( theURL );
Ext.get("json-result").update("");
Ext.Ajax.request({
url: theURL,
scriptTag: external,
success: function(response) {
Ext.get("json-result").update(response.responseText);
},

failure: function( ) {
Ext.get("json-result").update("<h2>Request Failed!</h2>");
}
});
}
</script>
</head>
<body>
<h1>Request data from the ExtJs forum search service</h1>
<button onclick="Topics( url1, true ); return false;">Test 1</button>
<button onclick="Topics( url4, true ); return false;">Test 2</button>
<h3>Response:</h3>
<code>URL: <pre id="remote-url"></pre></code>
<code>Response:<br><pre id="json-result"></pre></code>
</body>
</html>


I've put 2 buttons in here so that I can try hitting different URI's to see the results. The first button goes against the "extjs/forum/topics" URI from your example, the second button goes against my URI via an https. The first one works the second get's a failure.

Any help would be greatly appreciated.

Thanks
MikeB.

debtman7
4 Sep 2008, 12:27 PM
FYI, don't try to submit a basicform using this, fails in ie. Took me forever to figure out, I'm doing a bunch of requests using this to do some 'webservice lite' type functionality but on one form submit it was breaking. It seems that when you convert existing html forms to a basicform, the dom get's munged up and ext's serializeForm function returns null, so the requests made by this contain no form data.

I got around this by instead doing:



var form = Ext.getDom('dispensing_amounts');
var params = Ext.Ajax.serializeForm(form);
Ext.Ajax.request({
url: form.action + '?' + params,
method: form.method,
success: function( response ) {
...
},
failure: function( response ) {
...
}
});

borillo
20 Sep 2008, 9:14 AM
Hi Animal,

The cross-domain request works fine in my application, but in firebug i see that a GET request was issued when i'm specifying POST. Any ideas?


Ext.Ajax.request({
url: 'http://xxxxxx',
params: { a:'1' },
method: 'POST',
scriptTag: true,
success: function(response){
alert('ok');
}
});

This causes a lot of problems with a very large list of params in IE. The request in GET mode didn't work :(

I'm using extjs 2.2

Animal
20 Sep 2008, 10:46 PM
Any idea how to make the browser download <script src="http://xxxxxx"></script> with a POST?????

borillo
21 Sep 2008, 9:55 AM
Sorry for my ignorance, but there's another way to do a cross-domain POST to an URL with ExtJS to obtain a JSON response?

Thanks :)

Animal
21 Sep 2008, 12:13 PM
Some kind of iframe posting and cross-frame communication. Some people have got such a hacked up thing to work - you could google up something. Personally, I wouldn't torture the software that much and I'd design roiund it.

tuan
23 Sep 2008, 1:20 PM
Hi everyone,
I'm still confused about how Animal's drop in should be used for TreeLoaders and Stores.

var reportTreeLoader = new Ext.tree.TreeLoader({
dataUrl:"http://boe-test:8080/CPR-2.0/CmcBrowser.jsp"
});What's the correct response?

function callback(){return"[{'text':'one','id':'one'},{'text':'two','id':'two'}]";}or

[{'text':'one','id':'one'},{'text':'two','id':'two'}]Do I have to pass the scripTag:true attribute to somewhere, too?

Thank you.

Animal
24 Sep 2008, 2:21 AM
It should just work now it has the switch which detects when it is a cross-domain request.

I have used this to load trees cross-domain on several occasions.

Of course the server must cooperate. You understand how script tag Ajax works don't you? The server must wrap the response data with a call to the specified calback function. See teh API docs on ScriptTagProxy.

7twenty
30 Sep 2008, 8:38 AM
First, great piece of code. I simply dropped into my code the overrides in the original post and successfully loaded a TreeColumn cross domain (not natively supported by Ext) and made Ext.Ajax.request calls cross domain.

However, after 2-3 hours of debugging and digging through wire traces, this approach to crossdomain requests does not work for me. I thought I'd pass along the details. Hopefully it is useful to someone.

As long as the host server is responding, everything works fine. However, if the host server is not responding I get in a state that ALL CROSSDOMAIN REQUESTS FAIL until Firefox times out the bad request (not the timeout managed by the crossdomain Ext code).

In my case, I have a GridPanel that lists servers. When the user selects a server in the GridPanel, I send a cross domain request to that server and retrieve some information and show it in a Panel below the GridPanel. I have several servers in the list currently off line. I am using an Ext.data.Connection to make the crossdomain requests. I have configured autoAbort=true and timeout=5000.

Here are the steps and the issue I see:

1. I click on a server that is online
2. Request sent; Response received (seen via wireshark); success callback fired; data correctly displayed
3. I click on a couple servers that are offline
4. Request sent; No response (seen via wireshark); The cross domain code calls my failure callback because there is no response within the specified timeout
5. I click back on the server that is online
6. Request sent; Response received (I see this in wireshark and Firebug). However, the success callback is NEVER called in Firefox (IE and Chrome work fine). The failure callback is called after 5 seconds (Ext.data.Connection timeout). The script tag is removed from the head (seen via firebug).

If I wait a while (30-90 seconds) without sending any crossdomain requests, I can successfully make crossdomain requests again (no need to refresh page). It just starts working again.

IMO, this seems to be a Firefox issue and not an issue with the code posted in this thread. It seems that Firefox is trying to execute scripts in the order they were requested (which makes sense and is required), however it is not correctly aborting the request if the corresponding script tag is removed from the head tag. Once I send a request to an offline server, all crossdomain requests are blocked until the bad request is timed out by Firefox.

Firefox is receiving the response from the good server, but didn't seem to be processing (executing) the response.

For fun, I commented out destroyScriptTrans (except I needed to leave the clearTimeout call). Then I added a console.log statement at the begining of handleScriptResponse.
1. Click on online server. Everything works.
2. Click on offline server. failure handler correctly called after 5 second timeout;
3. Click on the online server; failure handler incorrectly called after 5 second timeout. I check the HTML tab of firebug. I can see the script tag for the corresponding request. It has the response in the body of the tag. 74 seconds AFTER Firefox has received the response, handleScriptResponse and my success handler are finally called.

I would be interested to see if the iframe approach to crossdomain requests is more robust in this case. Alternativly, it would be nice to see a Ext/Flash bridge that supported cross domain requests. Maybe if I find time. :)

vtswingkid
2 Oct 2008, 9:31 AM
7twenty: My client software is talking to many devices via http gets. At the bear minimum a sync message is sent to each device every couple seconds. If I disconnect a device the sync times out and starts talking to a back up device. Anyway, I am not seeing any major delays like that of what you have described. Maybe I am miss understanding.

So, is there a crossdomain work around for file uploads? The file is posting fine but I need a way to get the response back.

Animal
2 Oct 2008, 10:53 AM
Also remember that browsers generally only allow 2 concurrent HTTP requests to be outstanding. So any request which is waitinh will take up one of those. If you have two requests waiting for a non-responsive server, and fire off a third, it will block because the browser has no more available HTTP requests. All the while its timeout will be running. When the others finally fail, and it gets queued, it might time out before its server responds.

IIRC, scripts will only be executed when the connection is closed from the server.

If you run /examples/form/forum-search.html from your installation directory, that uses a ScriptTagProxy, and works fine.

When I work on Ajax-based systems for clients I always have to use this override to access resources on their systems to load Grids, Trees and DataViews, and I never have problems.

7twenty
2 Oct 2008, 11:07 AM
vtswingkid (http://extjs.com/forum/member.php?u=210): Thanks for the reply. Knowing that it works in some conditions gave me the motivation to do a little more debugging.

I found some interesting data. It still seems that removing a script tag from the head does not actually abort the underlying http request OR allow subsequent requests to be processed until the first request has timed out. However, I found out that Firefox handles different types of timeouts very differently.

In my case, the initial TCP connection was being intercepted by a networking appliance (proxy/caching appliance). Thus, this initial TCP connect succeeded and Firefox received a TCP/ACK from the proxy. After a seeming arbitrary amount of time (50-90 seconds), the proxy returns a HTTP 503 error (service unavaible). After Firefox receives the 503, subsequent requests begin to work.

I changed my code to use a non-standard http port (10999). In this case, the proxy appliance does not intercept the TCP connect request. Firefox sends exactly 3 TCP/SYN and then times out after 3 seconds because it hasn't received a TCP/ACK. Thus, ALL crossdomain requests are still block when trying to contact a non-responsive server, but for only 2-3 seconds.

IMO, it still seems like a bug in Firefox. Especially since it works great in IE, Chrome, and Safari. :)

7twenty
2 Oct 2008, 1:39 PM
Thanks for the reply Animal. I don't think the http connection limit is playing a role in the issue I am seeing. As far as I know the only connection limit is per domain. Each request I make is to a different IP address. In the same way that msnbc.com can concurrently load images from 5 different images servers (thus maintaining 2*5=10 concurrent http connections), I should be able to have many crossdomain connections running concurrently.

I verified this using Wireshark. Firefox does indeed allow me to have 20+ concurrent crossdomain (script tag) connections active to 20+ different servers. My tests show that Firefox 3.0.3 limited me to 6 concurrent requests to a single domain (in contrast to IE's limit of 2).

Like most developers that use lots of xhr, I have run into issues with the connection limit before, but in all cases the browser queues the requests and the requests aren't made until a connection frees up. In my case, the good request is happening immediatly and the response returns immediatly. However, Firefox is not processing that response.

Animal
2 Oct 2008, 11:36 PM
Of course you're right, it' per domain!

Well, you could be encountering an FF bug. It does have bugs in.

If you can demo it in a simple script you could submit it to the Mozilla developers.

Don't use Ext, just standard script calls:



var h = document.getElementsByTagName("head")[0];
var s = document.createElement("script");
s.src = "http://example.com/getScript.do";
s.id = "script" + new Date().valueOf();
setTimeout(function(){console.log("Script " + s.id + " timed out");}, 30);
h.appendChild(s);

vtswingkid
21 Oct 2008, 11:36 AM
Firefox memory leak. What do I need to do to clean up the memory following one of these crossdomain requests? It looks like the function and the script are both removed automatically, but firefox memory usage just keeps on climbing each request. Any ideas?

vtswingkid
24 Oct 2008, 12:26 PM
Bump...Any one else using this and seeing the memory usage climb?

dolittle
27 Oct 2008, 8:04 AM
I'm using this extension heavily and never experienced a memory leak.
Can you please post your code and describe how you notice the memory leak so we can examine it and see if the problem is in the extension or usage?

Thanks

panosru
15 Dec 2008, 3:37 PM
Very nice extension Animal! Thank you!

I just have one question. I have a form which posts some information and an attachment on a file outside of to implement this i did this:



function postForm () {
var form = Ext.getDom('adminForm');
var params = Ext.Ajax.serializeForm(form);
Ext.Ajax.request({,
scriptTag: true,
form: form.id,
success: function(response, options) {
console.info('success');
console.log(response);
},
failure: function(response, options) {
console.info('fail');
console.log(response);
}
});
}


I set my form like this:

<form enctype="multipart/form-data" id="adminForm" name="adminForm" method="post" action="http://x-domain.tld/">

and inside the form i have this button:

<input type="button" onClick="postForm()" value="Upload" class="button"/>

a sample "json" reponse i get is:

demo_callback_function([<p>
A critical error was detected. The error message was:
</p>
<p>
Missing container or contents: ????l
</p>
<p>
An error log has been reported to ???????.
</p>

]);

Because its obvious that this isn't json response it not gonna work so i tried to set the response to xml passing a parameter that defines the response type.

a sample xml response i get is:

<response>
<current_time>2008-12-15T23:15:55Z</current_time>
<timestamp>1229382955086</timestamp>
<status>ERROR</status>
<error>
<code>MISSING_PARAMETER</code>
<message>You must provide a title for your post</message>

</error>

</response>

Everything works fine but i don't know how to get response from the other domain so i could use it to display certain message.

Thanks in advance!

cabron
7 Jan 2009, 3:18 AM
Great Job Animal.

It's works!

Thanks

xantus
14 Jan 2009, 8:52 PM
I created an Ext user extension called Ext.ux.CssProxy (http://xant.us/ext-ux/examples/css-proxy/). It works like the ScriptTag proxy but data is encoded in CSS. This technique is safer because the data isn't executed, it is parsed out.

I even included a demo that loads an Ext grid with the CssProxy and JsonReader.

License: Apache v2

Enjoy!

Here's the thread for this user extension (http://extjs.com/forum/showthread.php?t=57360)

loogw
4 Feb 2009, 6:55 AM
Debugging it, in ext-all-debug.js, doFormUpload method...

function cb(){
var r = {
responseText : '',
responseXML : null
};

r.argument = o ? o.argument : null;

try {
var doc;
if(Ext.isIE){
doc = frame.contentWindow.document;

frame.contentWindow.document returns "Access Denied".

In my tests I use: http://localhost and http://mymachinename. My WebAplication is running in localhost and my js and post page/upload page is in mymachinename.

Do you have any example that I can test the upload between cross domains?

Hi,
I am facing the same problem. Any solution to this issue?? Thanks in advance!

ives
19 Mar 2009, 11:00 PM
I find a problem only occur in ie6, my member status is shown by cross subdomain ajax, when a member login to the website, it redirect to the login page, then show the member status after redirect back to the source page, but I find the step of show the member status is not success after login or logout to redirect back to the source page, but when I refresh the page, the member status show normally again, I trace the code, I find the function "handleScriptResponse" can't be executed and the ajax response right code.

so I make a test, http://k8.housetube.tw/test.html is a test url, and the code is the sample of animal, it can work normally, but when you click the link of "go", it just goto a another subdomain php program and redirect back to the source page, but the ajax response message not show in the page. it just occur in ie6, ff3 and ie7 work fine.

animal can help me?

abhishekmodi
27 Mar 2009, 6:46 AM
Animal is a genius....his code works like magic...

I have a situation where the URL returns data in HTML format. I need to grab a table in that data and display it in Ext datagrid.

Any small hint would be sufficient for me!!

Animal
27 Mar 2009, 8:34 AM
The server MUST return executable script.

Basically we're just creating <script src="Whatever URL you specify"></script>

So the server has to send script.

nande
4 Apr 2009, 8:48 PM
this is very good. it works for doing crosssite load, wich i need to retrieve some data from a 3rd party web.
tahnks

MichaelOstrovsky
6 Apr 2009, 10:08 AM
thanks for the great solution animal.
i have a problem on ie8 , which caches the scripttag calls.
on ff & chrome it works great.
should i add some headers or anything else ?
please help

hendricd
6 Apr 2009, 10:16 AM
@MichaelOstrovsky -- Trying adding a cache-buster your scriptTag urls:

url += '?_cb=" + new Date().getTime();

MichaelOstrovsky
14 Apr 2009, 9:34 AM
our app uses it very heavily ( imagine some sort of commet ) , and such method ( adding cache -buster ) will theoretically bomb the browser .. or am i wrong ?

MichaelOstrovsky
15 Apr 2009, 11:57 PM
i mean ,it will bomb the browser cache.. the browsers cache all the script files, images etc don't they ?

hendricd
17 Apr 2009, 3:29 AM
our app uses it very heavily ( imagine some sort of commet ) , and such method ( adding cache -buster ) will theoretically bomb the browser .. or am i wrong ?


i mean ,it will bomb the browser cache.. the browsers cache all the script files, images etc don't they ?

@MichaelOstrovsky -- Browser caches use the URL of any resource to manage its local resource cache. The key is make make each one unique. Appending a unique parameter to the URL is the only way to ensure you get a non-cached response (when using script tags).

contionjake
23 Apr 2009, 11:30 PM
keep silent!very good example!B)

vtswingkid
12 May 2009, 2:02 PM
I don't know if IE7 and FF have changed or if this scenario has just never occured for me until now. However, if I request 2 or more crossdomain messages to different addresses and the first message times out (1st address no longer exists for example). I find that all of the messages there after also timeout even though responses are coming back from the remain addresses. I can see the script being added to the head. The function is added to window. And the server response from the remaining address is calling the function. But the function never executes?

I am doing this test by looping through the same message and response from 3 servers say every 2 seconds with a 5 second timeout. In the middle of this process I pull the network cable from one server. According to firefox net viewer the other 2 servers are still sending the appropriate responses. But the fail handler is being called instead. It should only be called for the server that I pulled the plug on.

Any ideas?

galdaka
10 Sep 2009, 3:37 AM
Hi,

Anybody have this override working with Ext 3.0.x?

Thanks in advance,

Animal
10 Sep 2009, 3:42 AM
Should work with the next release of Ext (3.0.1 is it?)

They unrolled the privatization of methods in Ext.data.Connection so you can override them.

xantus
10 Sep 2009, 5:35 PM
That's good to hear


Should work with the next release of Ext (3.0.1 is it?)

They unrolled the privatization of methods in Ext.data.Connection so you can override them.

debtman7
25 Sep 2009, 9:25 AM
Another FYI, does not quite work with Ext 3.0. Cross domain requests actually work fine, but normal requests don't call the callback/success/failure handlers. Perhaps this has to do with the 3.0.1 fix mentioned above, however 3.0.1 is not available and 3.0.2 is only available to subscribers, and I've got an app I need to add charts to which also requires cross domain ajax requests.

So, it seems to be an issue with changes to the Ext core connection handlers, I suspect them being private and not available to this override. My solution was to simply copy handleResponse and handleFailure into this override. For the time being everything is happy...

Just add this after the destroyScriptTrans : function() { }



// private
handleResponse : function(response){
this.transId = false;
var options = response.argument.options;
response.argument = options ? options.argument : null;
this.fireEvent("requestcomplete", this, response, options);
if(options.success){
options.success.call(options.scope, response, options);
}
if(options.callback){
options.callback.call(options.scope, options, true, response);
}
},

// private
handleFailure : function(response, e){
this.transId = false;
var options = response.argument.options;
response.argument = options ? options.argument : null;
this.fireEvent("requestexception", this, response, options, e);
if(options.failure){
options.failure.call(options.scope, response, options);
}
if(options.callback){
options.callback.call(options.scope, options, false, response);
}
}

MichaelOstrovsky
8 Nov 2009, 5:24 AM
The override breaks ajax functionality in adobe air . normal requests without script tag ends up in some undefined request exception. unfortunately i didn't found any alternative, so i'm very interested in a fix.

my ext-includes are :

...
<script type="text/javascript" src="lib/ext-2.2.1/ext-base.js"></script>
<script type="text/javascript" src="lib/ext-2.2.1/ext-all-debug.js"></script>
<script type="text/javascript" src="lib/ext-air/ext-air.js"></script>
...

thanks in advance.

UPDATE:
i resolved the issue by small tricky hack:

1. i removed this cross-domain script

2. on ajax 'beforeRequest' handler :


beforeRequest:function(conn,options){
if (options.scriptTag) {
if(!Ext.data.Connection.scriptRequest){
// force callback parameter and 'GET' request type.
options.params.callback='cbk';
options.method='GET';
}
}
},


3. override the handleResponse :



handleResponse : function(response){
this.transId = false;

if(response.argument.options.scriptTag && !Ext.data.Connection.scriptRequest){
// the responceText is in the form of : cbk({a=1,b=2})
response.responseText=response.responseText.slice(4,-1);
}

var options = response.argument.options;
response.argument = options ? options.argument : null;
if (this.fireEvent("requestcomplete", this, response, options) !== false) {
options.forceResponseFail?
options.failure && Ext.callback(options.failure, options.scope, [response, options]):
options.success && Ext.callback(options.success, options.scope, [response, options]);
options.callback && Ext.callback(options.callback, options.scope, [options, !options.forceResponseFail, response]);
}
},

miiisuuu
24 Feb 2010, 7:07 PM
Hi Animal and all,

I used Animal script it work well but I have a case :

If response like : {"allow":false,"approval":1, ....} then I wrapped this response in callback method so everything work like a charm. However, if response is a HTML/jsp/ftl, for examle:

<script>
some function here
</script>
<table>
some html code here
</table>

So the response can not be fired. Please help me to give some advices and how to fix this issue in details. Do I need to wrap HTML content from the response in callback method ?

Thanks a lot in advance !

-suuu

cavalleydude
7 Dec 2010, 10:20 AM
Sorry for my ignorance, but there's another way to do a cross-domain POST to an URL with ExtJS to obtain a JSON response?

Thanks :)

Hi borillo, I know this thread is old, but I have the SAME question as you did. Regarding 'POST' method for cross-domain Ajax calls... What workaround did you use? Anyone have any suggestions on this topic?

Thanks-
cavalleydude

Romanitch
10 Feb 2011, 9:30 AM
Some patches and all work in ext-3.3.1 ( thanks Animal anyway ):



Ext.lib.Ajax.isCrossDomain = function(u) {
var match = /(?:(\w*:)\/\/)?([\w\.]*(?::\d*)?)/.exec(u);
if (!match[1]) return false; // No protocol, not cross-domain
return (match[1] != location.protocol) || (match[2] != location.host);
};

Ext.override(Ext.data.Connection, {

request : function(o){
var me = this;
if(me.fireEvent("beforerequest", me, o)){
if (o.el) {
if(!Ext.isEmpty(o.indicatorText)){
me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
}
if(me.indicatorText) {
Ext.getDom(o.el).innerHTML = me.indicatorText;
}
o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
Ext.getDom(o.el).innerHTML = response.responseText;
});
}

var p = o.params,
url = o.url || me.url,
method,
cb = {success: me.handleResponse,
failure: me.handleFailure,
scope: me,
argument: {options: o},
timeout : Ext.num(o.timeout, me.timeout)
},
form,
serForm;


if (Ext.isFunction(p)) {
p = p.call(o.scope||WINDOW, o);
}

p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);

if (Ext.isFunction(url)) {
url = url.call(o.scope || WINDOW, o);
}

if((form = Ext.getDom(o.form))){
url = url || form.action;
if(o.isUpload || (/multipart\/form-data/i.test(form.getAttribute("enctype")))) {
return me.doFormUpload.call(me, o, p, url);
}
serForm = Ext.lib.Ajax.serializeForm(form);
p = p ? (p + '&' + serForm) : serForm;
}

method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? 'POST' : 'GET');

if(method === 'GET' && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
var dcp = o.disableCachingParam || me.disableCachingParam;
url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
}

o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});

if(o.autoAbort === true || me.autoAbort) {
me.abort();
}

if((method == 'GET' || o.xmlData || o.jsonData) && p){
url = Ext.urlAppend(url, p);
p = '';
}

if (o.scriptTag || this.scriptTag || Ext.lib.Ajax.isCrossDomain(url)) {
me.transId = this.scriptRequest(method, url, cb, p, o);
} else {
me.transId = Ext.lib.Ajax.request(method, url, cb, p, o)
}
return me.transId;

/// return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
}else{
return o.callback ? o.callback.apply(o.scope, [o,undefined,undefined]) : null;
}
},

scriptRequest : function(method, url, cb, data, options) {
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};

url += (url.indexOf("?") != -1 ? "&" : "?") + data + String.format("&{0}={1}", options.callbackParam || this.callbackParam || 'callback', trans.cb);

var conn = this;
window[trans.cb] = function(o){
conn.handleScriptResponse(o, trans);
};

// Set up the timeout handler
trans.timeoutId = this.handleScriptFailure.defer(cb.timeout, this, [trans]);

var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
script.setAttribute("id", trans.scriptId);
document.getElementsByTagName("head")[0].appendChild(script);

return trans;
},

handleScriptResponse : function(o, trans){
this.transId = false;
this.destroyScriptTrans(trans, true);
var options = trans.options;

// Attempt to parse a string parameter as XML.
var doc;
if (typeof o == 'string') {
if (window.ActiveXObject) {
doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(o);
} else {
doc = new DOMParser().parseFromString(o,"text/xml");
}
}

// Create the bogus XHR
response = {
responseObject: o,
responseText: (typeof o == "object") ? Ext.util.JSON.encode(o) : String(o),
responseXML: doc,
argument: options.argument
}
this.fireEvent("requestcomplete", this, response, options);
Ext.callback(options.success, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, true, response]);
},

handleScriptFailure: function(trans) {
this.transId = false;
this.destroyScriptTrans(trans, false);
var options = trans.options;
response = {
argument: options.argument,
status: 500,
statusText: 'Server failed to respond',
responseText: ''
};
this.fireEvent("requestexception", this, response, options, {
status: -1,
statusText: 'communication failure'
});
Ext.callback(options.failure, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, false, response]);
},

// private
destroyScriptTrans : function(trans, isLoaded){
document.getElementsByTagName("head")[0].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){}
};
}
}
});

headkit
18 Apr 2011, 6:37 AM
*subscribe*

xantus
18 Apr 2011, 12:46 PM
*subscribe*

Are you telling us you subscribed, or are you trying to subscribe? :)

M101
4 May 2011, 7:29 AM
Hi,
I have cross domain issue with ext js4.
Does anyone know how to read data from different domain using ext js4 .
or does those code posted in this thread works in ext js 4?

Thanks very much

justinfalk
13 May 2011, 1:14 PM
Modified Romanitch's 3.3.1 patch with minor changes to properly handle restful requests with no params.


Ext.lib.Ajax.isCrossDomain = function(u) {
var match = /(?:(\w*:)\/\/)?([\w\.]*(?::\d*)?)/.exec(u);
if (!match[1]) return false; // No protocol, not cross-domain
return (match[1] != location.protocol) || (match[2] != location.host);
};

Ext.override(Ext.data.Connection, {

request : function(o){
var me = this;
if(me.fireEvent("beforerequest", me, o)){
if (o.el) {
if(!Ext.isEmpty(o.indicatorText)){
me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
}
if(me.indicatorText) {
Ext.getDom(o.el).innerHTML = me.indicatorText;
}
o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
Ext.getDom(o.el).innerHTML = response.responseText;
});
}

var p = o.params,
url = o.url || me.url,
method,
cb = {success: me.handleResponse,
failure: me.handleFailure,
scope: me,
argument: {options: o},
timeout : Ext.num(o.timeout, me.timeout)
},
form,
serForm;


if (Ext.isFunction(p)) {
p = p.call(o.scope||WINDOW, o);
}

p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);

if (Ext.isFunction(url)) {
url = url.call(o.scope || WINDOW, o);
}

if((form = Ext.getDom(o.form))){
url = url || form.action;
if(o.isUpload || (/multipart\/form-data/i.test(form.getAttribute("enctype")))) {
return me.doFormUpload.call(me, o, p, url);
}
serForm = Ext.lib.Ajax.serializeForm(form);
p = p ? (p + '&' + serForm) : serForm;
}

method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? 'POST' : 'GET');

if(method === 'GET' && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
var dcp = o.disableCachingParam || me.disableCachingParam;
url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
}

o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});

if(o.autoAbort === true || me.autoAbort) {
me.abort();
}

if((method == 'GET' || o.xmlData || o.jsonData) && p){
url = Ext.urlAppend(url, p);
p = '';
}

if (o.scriptTag || this.scriptTag || Ext.lib.Ajax.isCrossDomain(url)) {
me.transId = this.scriptRequest(method, url, cb, p, o);
} else {
me.transId = Ext.lib.Ajax.request(method, url, cb, p, o)
}
return me.transId;
}else{
return o.callback ? o.callback.apply(o.scope, [o,undefined,undefined]) : null;
}
},

scriptRequest : function(method, url, cb, data, options) {
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
var trans = {
id : transId,
cb : options.callbackName || "stcCallback"+transId,
scriptId : "stcScript"+transId,
options : options
};

if (!Ext.isEmpty(data))
url = Ext.urlAppend(url, data)
url = Ext.urlAppend(url, String.format("{0}={1}", options.callbackParam || this.callbackParam || 'callback', trans.cb));

var conn = this;
window[trans.cb] = function(o){
conn.handleScriptResponse(o, trans);
};

// Set up the timeout handler
trans.timeoutId = this.handleScriptFailure.defer(cb.timeout, this, [trans]);

var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
script.setAttribute("id", trans.scriptId);
document.getElementsByTagName("head")[0].appendChild(script);

return trans;
},

handleScriptResponse : function(o, trans){
this.transId = false;
this.destroyScriptTrans(trans, true);
var options = trans.options;

// Attempt to parse a string parameter as XML.
var doc;
if (typeof o == 'string') {
if (window.ActiveXObject) {
doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(o);
} else {
doc = new DOMParser().parseFromString(o,"text/xml");
}
}

// Create the bogus XHR
response = {
responseObject: o,
responseText: (typeof o == "object") ? Ext.util.JSON.encode(o) : String(o),
responseXML: doc,
argument: options.argument
}
this.fireEvent("requestcomplete", this, response, options);
Ext.callback(options.success, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, true, response]);
},

handleScriptFailure: function(trans) {
this.transId = false;
this.destroyScriptTrans(trans, false);
var options = trans.options;
response = {
argument: options.argument,
status: 500,
statusText: 'Server failed to respond',
responseText: ''
};
this.fireEvent("requestexception", this, response, options, {
status: -1,
statusText: 'communication failure'
});
Ext.callback(options.failure, options.scope, [response, options]);
Ext.callback(options.callback, options.scope, [options, false, response]);
},

// private
destroyScriptTrans : function(trans, isLoaded){
document.getElementsByTagName("head")[0].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){}
};
}
}
});

headkit
13 May 2011, 11:18 PM
Are you telling us you subscribed, or are you trying to subscribe? :)

you are bored, right?
:-)

johnsonkid
19 May 2011, 9:41 PM
Im trying to use the override too. I am able to run the example just fine, but when i run my own application code i get the following error in fireBug which says invalidLabel? Anyone have any ideas? Thanks!

mystarrocks
11 Sep 2011, 10:06 PM
Ditto that.

I got,

invalid label
and it's pointing to the actual JSON object obtained from the server. No other clue as to where the prob would be. Could anyone guess what's wrong here?

EDIT: Got it. From what Animal said,

Of course, since it uses a script tag, the server-side script you invoke must wrap the returned data in a call to a callback function. So text must be passed back as a quoted string parameter to a function.

But my response.responseText only returns something like:

{"totalCount":4,"locations":[{"nid":"43","title":"location1"},{"nid":"44","title":"location2"},{"nid":"39","title":"location3"},{"nid":"41","title":"location4"}]} from the server. The prob. is can't go about making it look like a string parameter, since I don't have access to modify them. Any workaround like if we can handle it elsewhere?

kulothungan
3 Jul 2012, 11:37 PM
HI,
Please tell me whether the following code is work or not.

Ext.Ajax.request({
params: {Name:'Nigel', Age:20,format: 'xml'},
url: 'http://patentwerkmobile.tambien.nu/ws-Patent.asmx/MyWebMethod',
scriptTag: true,
success: function(response) {
alert("Success");},
failure: function (msg)
{
alert("Failure" + msg);}
});

You can browse the service on browser
http://patentwerkmobile.tambien.nu/ws-Patent.asmx
it will work.

I nee to connect this service from my local machine via Sencha Code.

Please help me ASAP.

Thanks.