- 发现问题
近来在自己瞎捣鼓中发现extjs4.1.1中在带有uploadfield的form中使用form.submit方法在firefox中存在bug,也就是上传文件时.
具体情况是:
我在写ajax请求是使用的方法是
var form = ....//from from panel get baseForm .....//init and validate other data form.duSubmit({ url:'getUsers.req', ....//other params success:function(fp,o){ alert(o.result.dataMsg); }, failure:function(fp,o){ alert(o.result.errorMs); } });
这个方法在ie中完全没有问题,但是在firefox中总是不正常,点击完提交按钮后,就一直停在正在处理的那个画面里转呀转的,就是不返回成功或失败的提示.
- 研究问题
在百度上google了好久好久都没找到一点有用的资料,有的大多是一些相关的问题,但没有人解决了.想想 如果不能解决这个问题,当碰到类似的功能时就不能再firefox上调试,就觉得后果很可怕,一狠心就决定自己从头开始分析这个问题,
在firefox的firebug中我看到有一条错误信息,意思是 result is undefined,然后还有个链接,点进去是
ext-all-debug.js文件中的Ext.form.action.Submit 的onSuccess 的方法(我开发时使用的debug版的extjs)
onSuccess: function(response) { var form = this.form, success = true, result = this.processResponse(response); if (result !== true && !result.success) { if (result.errors) { form.markInvalid(result.errors); } this.failureType = Ext.form.action.Action.SERVER_INVALID; success = false; } form.afterAction(this, success); },
再通过firebug调试js中发现result 确实为undefined,但是为什么在ie中又正常了呢.于是我想到了可能是两个浏览器对某些对象的封装赋值存在差异,所以我继续查看processResponse方法,这个方法是其父类Ext.form.action.Action的方法
processResponse : function(response){ this.response = response; if (!response.responseText && !response.responseXML) { return true; } return (this.result = this.handleResponse(response)); },
其中又使用到了Ext.form.action.Submit类中的handleResponse方法
handleResponse: function(response) { var form = this.form, errorReader = form.errorReader, rs, errors, i, len, records; if (errorReader) { rs = errorReader.read(response); records = rs.records; errors = []; if (records) { for(i = 0, len = records.length; i < len; i++) { errors[i] = records[i].data; } } if (errors.length < 1) { errors = null; } return { success : rs.success, errors : errors }; } return Ext.decode(response.responseText); }
在这个方法中我看到了
Ext.decode(response.responseText);
而在调试过成功,我看到response中的responseText确实是undefined.
到此我就郁闷了,为什么它是undefined,它既然在ie中能正常,那说明在ie中这个肯定有值,于是我想到了谁为responseText在什么时候赋值的呢?
又是进过一番查找,终于在Ext.data.Connection的onUploadComplete方法中我找到了为responseText赋值的语句
onUploadComplete: function(frame, options) { var me = this, response = { responseText: '', responseXML: null }, doc, contentNode; try { doc = frame.contentWindow.document || frame.contentDocument || window.frames[frame.id].document; if (doc) { if (doc.body) { if ((contentNode = doc.body.firstChild) && /pre/i.test(contentNode.tagName)) { response.responseText = contentNode.innerText; } else if (contentNode = doc.getElementsByTagName('textarea')[0]) { response.responseText = contentNode.value; } else { response.responseText = doc.body.textContent || doc.body.innerText; } } response.responseXML = doc.XMLDocument || doc; } } catch (e) { } me.fireEvent('requestcomplete', me, response, options); Ext.callback(options.success, options.scope, [response, options]); Ext.callback(options.callback, options.scope, [options, true, response]); setTimeout(function() { Ext.removeNode(frame); }, 100); },
在这个方法中我注意到
if ((contentNode = doc.body.firstChild) && /pre/i.test(contentNode.tagName)) { response.responseText = contentNode.innerText; }
于是我又在调试的过程中去查看response的信息,发现在firefox中doc.body.firstChild没有innerText这个属性而是一个innerHTML的属性,并且它的值刚好是我在后台想要抛过来的信息,内容大概是{success:"true",data:"",errorMsg:"",dataMsg:""}. 于是我猜我找到解决此问题的办法了.
- 解决问题
于是我果断的将上段的代码改成
if ((contentNode = doc.body.firstChild) && /pre/i.test(contentNode.tagName)) { response.responseText = contentNode.innerText||contentNode.innerHTML; }
将修改后的ext-all-debug.js文件覆盖原来的文件,重新编译重新部署重启服务器,并默默的祈祷能解决这个问题.打开页面,点选要上传的文件,提交............ok,久违的熟悉的画面终于出现了.
几个小时的努力终于有点点成果了.