今天解决的最有成就感的一个Web前端问题IE诡异的行为经常让人捉摸不透。这次遇到的IE问题也很诡异,虽然没有“透”,但捉摸出了解决方法,而且是在几乎无望的情形下捉摸出来的,所以说很有成就感。那“最”从何来呢?在解决过的Web前端问题中,这次是“最”让人兴奋的。 这个问题简单来说就是一个Javascript跨域的问题。那复杂来说呢,请看下面的文字。 <script src="http://common.cnblogs.com/editor/tiny_mce/tiny_mce.js"></script> 博客园博客后台(域名是www.cnblogs.com)用的是TinyMCE编辑器,TinyMCE的js文件的引用是通过 common.cnblogs.com 这个域名(两个好处:1. 实现不同应用重用TinyMCE;2. 可以针对这个域名进行CDN加速)【注:这里虽然涉及两个域名,如果仅仅是js文件引用,不存在跨域问题】。 然后点击“上传图片”按钮,弹出上传图片的窗口(通过一个TinyMCE插件实现的),窗口打开的是 upload.cnblogs.com 这个域名【注:这时也不存在跨域问题】。 然后进行图片上传操作,上传成功之后返回图片地址,并将这个图片地址写入到编辑器文本框中(调用tinyMCEPopup.editor.execCommand),然后关闭这个窗口(调用tinyMCEPopup.close),为了调用这两个TinyMCE函数,必须在上传页面(upload.cnblogs.com)中引用 util.cnblogs.com 域名下的tiny_mce_popup.js文件。【注:跨域问题登场了】为了支持跨域操作,必须要在tiny_mce_popup.js文件开头添加如下的代码: 以前我们就是这样解决跨域问题的。 但这次使用了ajax上传组件Fine Uploader(https://github.com/valums/file-uploader)之后,Chrome, Firefox, IE10标准模式下都没问题,但在IE10的“IE9标准模式”下(估计IE9及以下版本都存在这个问题),上传图片之后,在IE10 develop tools的控制台中却出现这样的错误(图片地址也就无法写入编辑器中): Error when attempting to access iframe during handling of upload response (Error: Access is denied.)
Error when attempting to access iframe during handling of upload response (Error: Access is denied.)
大部分时间都花在找出这个错误的来源上。。。 后来试着在tiny_mce_popup.js中将 document.domain = 'cnblogs.com'; 注释掉,错误就消失了。进一步测试,发现只要在Fine Uploader发起请求之前(注意这里的“请求之前”)有 document.domain = 'cnblogs.com'; 这样的代码,就会出现这个错误。 也就是说在IE9及IE9版本以下(未实际验证,只在IE10的“IE9标准模式”下验证过),Fine Uploader与 document.domain = 'cnblogs.com'; 水火不容。但是不在tiny_mce_popup.js中加 document.domain = 'cnblogs.com'; ,就无法将图片地址添加到TinyMCE文本框(tinyMCEPopup.editor.execCommand)中并关闭图片上传窗口(tinyMCEPopup.close)。而错误信息恰恰就是来自这两个操作【这两个操作是跨域操作,不设置document.domain就无法跨域操作】。 Fine Uploader不允许跨域,而TinyMCE又必须要跨域才能添加内容,本文开头的“几乎无望”说的就是这个时候。。。此处省略解决问题过程中最难熬的阶段 然后,突然想到:tinyMCEPopup.editor.execCommand与tinyMCEPopup.close是在图片上传完成之后fineUploader.complete回调函数中执行的,如果在这里动态加载tiny_mce_popup.js是不是可以解决问题呢? 于是,改为下面的代码(upload.cnblogs.com域名下的上传页面,关键代码是$.getScript): $('#jquery-wrapped-fine-uploader').fineUploader({}) .on('complete', function (event, id, fileName, responseJSON) { if (responseJSON.success) { $.getScript("http://common.cnblogs.com/editor/tiny_mce/tiny_mce_popup.js", function () { tinyMCEPopup.editor.execCommand('mceInsertContent', false, responseJSON.message); tinyMCEPopup.close(); }); } }); 结果得到的是不同的错误信息: SCRIPT5: Access is denied.
SCRIPT5007: Unable to get property 'execCommand' of undefined or null
对于这个错误,当时没有进行仔细分析,只是猜测可能是$.getScript的跨域问题(有经验的朋友帮忙分析一下)。接着,将tiny_mce_popup.js文件复制到upload.cnblogs.com域名下,改为在同一个域名下加载tiny_mce_popup.js,代码如下: $('#jquery-wrapped-fine-uploader').fineUploader({}) .on('complete', function (event, id, fileName, responseJSON) { if (responseJSON.success) { $.getScript("/scripts/tiny_mce_popup.js", function () { tinyMCEPopup.editor.execCommand('mceInsertContent', false, responseJSON.message); tinyMCEPopup.close(); }); } }); 改为这个代码后,问题竟奇迹般地解决了。(当然,tiny_mce_popup.js中的 document.domain = 'cnblogs.com'; 不能少) 写了这么多,不知道没有把问题表述清楚,跨来跨去,人都被跨晕,何况IE呢?可是为什么Chrome, Firefox没有晕? |
|
来自: quasiceo > 《javascript》