Iframe Tips ABC

通常我们用 js 脚本创建 iframe 时,会这样写:

var iframe = document.createElement('iframe');

之后我们可能会定义 id、name、border 等属性,这些看似简单,其实 IE 与非 IE 浏览器之间、IE 和 IE 高版本之间的迥异,使得 iframe 的相关兼容性操作非常地有文章。

牛A:frameborder

现象:使用 (iframe.frameBorder = 数值) 或(iframe.setAttribute(‘frameborder’,数值)) 在 IE 浏览器下无效
原因:IE 浏览器区分属性名称大小写
解决方法:iframe.setAttribute(‘frameBorder’,'0′) Or iframe.setAttribute(‘frameborder’,'0′,0),兼容所有浏览器。

注:经测试,IE8已经修复此问题

牛B:动态将Form target到iframe

背景:假设现在我们要让一个 Form 表单结果提交到一个 HTML 结构中已存在的 iframe,会这样做:

<form id="form" name="form" target="相应iframe的name:iframeNB" method="post" >
</form>
<iframe name="iframeNB" ></iframe>

OK,什么问题也没有,再假设我们需要提交到脚本动态生成的 iframe 中,会这样做:

<form id="form" name="form" target="iframeNB" method="post" >
</form>
<script>
var iframe = document.createElement('iframe');
iframe.name = 'iframeNB';
...
someParent.appendChild(iframe);
</script>

去 IE 浏览器里试试,你会发现 Form 会在新窗口显示提交结果,Why?
原因:
我为此尝试了很久,结果是IE此前版本不能通过(iframe.name=)这种方式给 iframe 设置 name 值,也就是说生成的 iframe 是没有 name 值的,但却可以 alert 出来,这很诡异;当然,这也并不是没有解决办法。
解决方法,为此我们得为 IE 单独写一行代码:

  /*only for ie */
    var iframe = document.createElement('<iframe name="iframeNB">');

看到这行代码,我们笑了,这是天大的杯具(喜剧?)~~不管IE有多么搓的问题,他总会有自己一套解决之……
而且这行代码会在其他非 IE 浏览器抛出异常,所以我们可以利用这点来做最终版:

    var iframe;
    try{
        iframe = document.createElement('<iframe name="iframeNB">');
    }catch(e){
        iframe = document.createElement('iframe');
    }
    iframe.name = 'iframeNB';
    ...
    someParent.appendChild(iframe);
    ...

[2009-12-9]补充:最佳实践 – YUI 是如何 creat iframe 的

    /**
    * @description Creates an iframe to be used for form file uploads.  It is remove from the
    * document upon completion of the upload transaction.
    * @method createFrame
    * @private
    * @static
    * @param {string} optional qualified path of iframe resource for SSL in IE.
    * @return {void}
    */
    function _createFrame(secureUri){
    // IE does not allow the setting of id and name attributes as object
    // properties via createElement().  A different iframe creation
    // pattern is required for IE.
    var frameId = 'yuiIO' + this._transaction_id,io;
    if(YAHOO.env.ua.ie){
        io = document.createElement('<iframe id="' + frameId + '"name="' + frameId + '" />');
        // IE will throw a security exception in an SSL environment if the
        // iframe source is undefined.
        if(typeof secureUri == 'boolean'){
            io.src = 'javascript:false';
        }
    }else{
        io = document.createElement('iframe');
        io.id = frameId;
        io.name = frameId;
    }
    io.style.position = 'absolute';
    io.style.top = '-1000px';
    io.style.left = '-1000px';
    document.body.appendChild(io);
    YAHOO.log('File upload iframe created. Id is:' + frameId, 'info', 'Connection');
    }

这里需要额外注意到的一点是:

// IE will throw a security exception in an SSL environment if the
// iframe source is undefined.
if(typeof secureUri == 'boolean'){
io.src = 'javascript:false';
}

姑且算是牛D吧 =.=!

牛C:iframe.onload

关于 onload 这点大家可以参考怿飞师父的文章:判断 iframe 是否加载完成的完美方法,在此纯引用一次代码:

var iframe = document.createElement("iframe");
iframe.src = "http://www.planabc.net";
if (iframe.attachEvent) {
    iframe.attachEvent("onload", function () {
        alert("Local iframe is now loaded.");
    });
} else {
    iframe.onload = function () {
        alert("Local iframe is now loaded.");
    };
}
document.body.appendChild(iframe);

需要注意到的是:

  • IE8也不支持iframe.onload
  • Opera两者均可,所以使用此方法会绑定前者
  • 即使我们不预设iframe.src = some urls,也会默认执行一次onload事件,可以通过分析 src 规避。

附测试文件:
1.iframe_ie_ugly.html
2.iframe_fixed.html
以上,我认为 ABC 中最牛的就是 B 了,这也是我标题的亮点=.=! 斯密达们认为呢?

, , , ,
Trackback

4 comments untill now

  1. B的确很有意思, 我第一次看见这样用是在看YUI源码的时候.

  2. 第一次看见B这样的用法, 是在看YUI的时候, 当时就被雷了, 扛伤斯密达!

    nunumick 于 2009-12-9 9:30:20 回复

    没错,YUI的setform方法就在upload时用到了这个技巧,的确是个很好的例子,稍候补上。

  3. 学习下了

  4. 嘻嘻嘻 @ 2009-12-26 09:09

    // IE will throw a security exception in an SSL environment if the
    // iframe source is undefined.
    if(typeof secureUri == ‘boolean’){
    io.src = ‘javascript:false’;
    }

    这个还是没看明白
    能解析一下么

Add your comment now

Please wrap all source codes with [code][/code] tags.