PDA

View Full Version : [OPEN] [FIXED-129][2.x/3.x] Opera 10 upload form



sanny
4 Sep 2009, 6:39 PM
Hello.

I have a problem appeared in Opera 10 only. I have a form with uploadFile:true I'm submitting and waiting for the answer:


new Ext.FormPanel({
border:false,
title:false,
id:'formpan5',
cls:'normalcolor',
fileUpload:true,
autoHeight:true,
reader:new Ext.data.JsonReader({
root: "rows"
},Code),
Ext.getCmp('formpan5').getForm().submit({
url:'/account/mygetcode.html',
params: {
id:selectedRow,
paytype:Ext.getCmp('paytype1').getGroupValue(),
dyntype:Ext.getCmp('dyntype1').getGroupValue(),
logotype:Ext.getCmp('logotype1').getGroupValue(),
design:radio_val(document.getElementById('design1').form.xdesign),
link:radio_val(document.getElementById('link1').form.xlink),
paycost:Ext.getCmp('paycost1').getGroupValue(),
roundcost:Ext.getCmp('roundcost1').getGroupValue(),
cost:Ext.getCmp('cost').getValue(),
linktext:Ext.getCmp('linktext').getValue()
},
waitMsg:'????????? HTML-????',
waitTitle:'????????? ? ???????',
success:function(form, action){
codeTab=9;
for(var x=1;x<=9;x++){Ext.getCmp('codepan'+x).setVisible(0)}
Ext.getCmp('code').setValue(action.result.code);
Ext.getCmp('codepan9').setVisible(1);
Ext.getCmp('nextBtn5').setText('???????');
},
failure:function(form, action){
Ext.Msg.alert("??????",action.result.status);
}
})I have the problem on the Ext.getCmp('code').setValue(action.result.code); line as in Opera I don't have action.result at all. Please take a look at attached screenshot. The problem appears in Opera 10 only.

Animal
4 Sep 2009, 10:45 PM
Result is decoded from response. What's response? Go back through the call stack to the load handler of the iframe that receives the response document, and have a look round there.

sanny
5 Sep 2009, 6:02 PM
Ok, I'll try. The only thing I know is that the response is absolutely OK. I checked that with sniffer and at least that works in any other browser.

sanny
10 Sep 2009, 9:36 AM
I checked everyting and should say iframe is loaded without any problem. Iframe contents is ok. The same contents works in any other browser. So I should say it seems to be a bug.

Animal
10 Sep 2009, 9:56 AM
Find this function in ext-all-debug.js:



function cb(){
var me = this,
// bogus response object
r = {responseText : '',
responseXML : null,
argument : o.argument},
doc,
firstChild;

try{
doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
if(doc){
if(doc.body){
if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ // json response wrapped in textarea
r.responseText = firstChild.value;
}else{
r.responseText = doc.body.innerHTML;
}
}
//in IE the document may still have a body even if returns XML.
r.responseXML = doc.XMLDocument || doc;
}
}
catch(e) {}

Ext.EventManager.removeListener(frame, LOAD, cb, me);

me.fireEvent(REQUESTCOMPLETE, me, r, o);

function runCallback(fn, scope, args){
if(Ext.isFunction(fn)){
fn.apply(scope, args);
}
}

runCallback(o.success, o.scope, [r, o]);
runCallback(o.callback, o.scope, [o, true, r]);

if(!me.debugUploads){
setTimeout(function(){Ext.removeNode(frame);}, 100);
}
}


Set a break in it and step through it and watch how it creates the synthetic XHR.

sanny
10 Sep 2009, 5:13 PM
It seems quite strange. If I pause script execution anywhere in this code, everything seems ok - responseText and result looks good and script works.
If I just execute the script without using Opera debugger, there is no responseText.

Animal
10 Sep 2009, 11:16 PM
OK, so sounds like a timing issue?

What if you executed that callback on a delay?

Look at the line immediately after than function definition which adds it as a load listener:



Ext.EventManager.on(frame, LOAD, cb, this);


Change it to



Ext.EventManager.on(frame, LOAD, cb, this, {delay: 100});


Which will delay execution of the cb function for 100ms after the frame fires its ready event.

sanny
10 Sep 2009, 11:57 PM
You are right! I put 4000 delay and it works. Thanj you!
Anyway I'm still sure this is a bug which should be fixed.

aep
11 Sep 2009, 3:57 AM
i worked around this by rerequesting the response in onSucess. form uploads response appears to be unrelyable in general.

Condor
11 Sep 2009, 4:19 AM
Apparently in Opera the 'load' event fires before the DOM is ready (and an extra DOMContentLoaded event handler is probably needed).

Animal
11 Sep 2009, 6:24 AM
So this should be moved to the Bugs folder really, as a 2.x/3.x bug?

ljadrbln
21 Sep 2009, 4:37 AM
I had same problems for opera 10.
My temporary solution is:
Ext.SSL_SECURE_URL = 'about:dummy.html'; instead of default value

hendricd
24 Sep 2009, 5:00 AM
After some futher testing, the onload handler was handling the load event for the initial src attrib set when the frame was created. It would be best to set the reset URL AFTER the frame was added to the DOM.

Thus, the fix:



// private
doFormUpload : function(o, ps, url){
var id = Ext.id(),
doc = document,
frame = doc.createElement('iframe'),
form = Ext.getDom(o.form),
hiddens = [],
hd,
encoding = 'multipart/form-data',
buf = {
target: form.target,
method: form.method,
encoding: form.encoding,
enctype: form.enctype,
action: form.action
};

Ext.fly(frame).set({
id: id,
name: id,
className: 'x-hidden'
});
//Add to DOM first
doc.body.appendChild(frame);

//Reset the Frame to neutral domain
Ext.fly(frame).set({
src : Ext.SSL_SECURE_URL
});

// This is required so that IE doesn't pop the response up in a new window.
if(Ext.isIE){
document.frames[id].name = id;
}


..should do it.

Condor
24 Sep 2009, 5:45 AM
So the src needs to be set after the frame is added to the document? Otherwise there is no difference with the current Ext 3.x implementation.

However, I just noticed that Ext 2.x only sets the src for IE and not for other browsers!

ps. You don't need the Ext.isIE && Ext.isSecure check, because Ext.SSL_SECURE_URL is already defined as:

Ext.SSL_SECURE_URL = isSecure && isIE ? 'javascript:""' : 'about:blank';

hendricd
24 Sep 2009, 5:56 AM
Yep, your right, after testing on Browsers, Ext.SSL_SECURE_URL should be just fine.

Fix amended. ;)

hendricd
18 Nov 2009, 9:10 AM
This has not made it in to SVN yet...

Bumping

shprota
8 Dec 2009, 3:24 PM
I would really appreciate this fix being added to the next release. For now I have to do with the modified by hand version which leaves me vulnerable to future updates.
Without this fix the upload dialogs do not work in Opera.

hendricd
9 Jan 2010, 7:32 AM
Fixed in SVN Core for 3.x.

Redsandro
2 Jun 2011, 4:22 PM
Took me forever to find out, but ergo conclusio: Fix never made it to stable?

In ExtJS 3.3.1 and 4.0.0, upload confirmation is STILL not working for Opera 10 and Opera 11. Uploads will never end, even though they are successfully finished.

Safari/Firefox no problem. Is there a workaround?

sormy
23 Jun 2011, 8:37 AM
// Ext 3.3.1
// Opera 10.x/11.x upload problem
// http://www.sencha.com/forum/showthread.php?79640-FIXED-129-2.x-3.x-Opera-10-upload-form/page2
(function(){
var BEFOREREQUEST = "beforerequest",
REQUESTCOMPLETE = "requestcomplete",
REQUESTEXCEPTION = "requestexception",
UNDEFINED = undefined,
LOAD = 'load',
POST = 'POST',
GET = 'GET',
WINDOW = window;

Ext.override(Ext.data.Connection, {
// private
doFormUpload : function(o, ps, url){
var id = Ext.id(),
doc = document,
frame = doc.createElement('iframe'),
form = Ext.getDom(o.form),
hiddens = [],
hd,
encoding = 'multipart/form-data',
buf = {
target: form.target,
method: form.method,
encoding: form.encoding,
enctype: form.enctype,
action: form.action
};

/*
* Originally this behaviour was modified for Opera 10 to apply the secure URL after
* the frame had been added to the document. It seems this has since been corrected in
* Opera so the behaviour has been reverted, the URL will be set before being added.
*/
Ext.fly(frame).set({
id: id,
name: id,
cls: 'x-hidden'//, // patch
//src: Ext.SSL_SECURE_URL // patch
});

doc.body.appendChild(frame);

// patch
Ext.fly(frame).set({
src : Ext.isOpera ? 'about:dummy.html' : Ext.SSL_SECURE_URL
});

// This is required so that IE doesn't pop the response up in a new window.
if(Ext.isIE){
document.frames[id].name = id;
}


Ext.fly(form).set({
target: id,
method: POST,
enctype: encoding,
encoding: encoding,
action: url || buf.action
});

// add dynamic params
Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
hd = doc.createElement('input');
Ext.fly(hd).set({
type: 'hidden',
value: v,
name: k
});
form.appendChild(hd);
hiddens.push(hd);
});

function cb(){
var me = this,
// bogus response object
r = {responseText : '',
responseXML : null,
argument : o.argument},
doc,
firstChild;

try{
doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
if(doc){
if(doc.body){
if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ // json response wrapped in textarea
r.responseText = firstChild.value;
}else{
r.responseText = doc.body.innerHTML;
}
}
//in IE the document may still have a body even if returns XML.
r.responseXML = doc.XMLDocument || doc;
}
}
catch(e) {}

Ext.EventManager.removeListener(frame, LOAD, cb, me);

me.fireEvent(REQUESTCOMPLETE, me, r, o);

function runCallback(fn, scope, args){
if(Ext.isFunction(fn)){
fn.apply(scope, args);
}
}

runCallback(o.success, o.scope, [r, o]);
runCallback(o.callback, o.scope, [o, true, r]);

if(!me.debugUploads){
setTimeout(function(){Ext.removeNode(frame);}, 100);
}
}

Ext.EventManager.on(frame, LOAD, cb, this);
form.submit();

Ext.fly(form).set(buf);
Ext.each(hiddens, function(h) {
Ext.removeNode(h);
});
}
});
})();

Redsandro
19 Sep 2011, 7:43 PM
Is this merged into ExtJS 3.4?
I am wondering if I could simply replace 3.3 with 3.4 on the webserver or if it will break things.