`
liss
  • 浏览: 844231 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

IE6的base标签导致页面结构大混乱

阅读更多

这是一个非常隐秘也是非常强大的bug,我真不知微软的IE开发人员是怎么搞出来的。此bug的触发条件是,当页面存在一个自闭合的base节点,它就会把其“下面”所有的元素都拷到它内部。这里的下面非childNodes,children所能描述,它连body节点都能编入其中。

<!doctype html>
<html>
  <head>
    <meta charset="utf-8"/>
    <meta content="IE=8" http-equiv="X-UA-Compatible"/>
    <meta name="keywords" content="IE6 base bug" />
    <base href='http://www.cnblogs.com/rubylouvre/' />
    <script type="text/javascript" id="test">
      window.onload = function(){
        var meta = document.createElement("meta");
        meta.name = "description";
        meta.content = "IE6 base bug by 司徒正美"
        var head = document.documentElement.firstChild;
        head.appendChild(meta);
        alert("meta.parentNode : "+meta.parentNode.tagName);
        var base = document.getElementsByTagName("base")[0];
        alert("base.childNodes.length : "+base.childNodes.length)
        alert("body.parentNode : "+document.body.parentNode.tagName)
        var script = document.getElementById("test");
        alert("script.parentNode : "+script.parentNode.tagName)
      }
    </script>
    <title>IE 复制节点 bug</title>
  </head>
  <body>
    <h1>请在IE6下运行</h1>
    <script type='text/javascript'
  </body>
  
</html>

运行代码

运行代码下,我们发现完全乱套了,原本父节点为head的meta元素(动态生成)与父节点为html的body元素(原来就存在),它们的父节点都变成base节点。下面是用firebug lite截到的图:

jQuery在使用globalEval方法动态解析脚本时,就遇到这个问题,它取巧地把动态生成的script节点插入到base节点之前。

globalEval: function( data ) {
    if ( data && rnotwhite.test(data) ) {
        var head = document.getElementsByTagName("head")[0] || document.documentElement,
        script = document.createElement("script");
        script.type = "text/javascript";
        if ( jQuery.support.scriptEval ) {
            script.appendChild( document.createTextNode( data ) );
        } else {
            script.text = data;
        }
        head.insertBefore( script, head.firstChild );
        head.removeChild( script );
    }
},

但还是不妥当,因为始终留着个陷阱给人踩。想了想,base标签无碍乎只有两个属性,用于对页面上所有的URL进行统一设置,如img.src,form.action,a.href等等。通常只有一个就够了,如果它只存在于body中,不管,如果存在于head就会为害人间了,我们需要将它强制添加一个闭合标签。即,将它由

转换为

<base href='http://www.cnblogs.com/rubylouvre/' ></base>

虽然IE6解析base的半闭合形式出错,但它不会不济到解析一个全新的节点出错吧,它理应会把新节点转换为它不会出错的形式,换言之,是第二种形式。创建新节点的方法有许多种,但我们很需要原节点的属性,恰好IE的cloneNode什么也能复制。之后就是插入节点的问题了,我们使用它的一个私有实现replaceNode,不用知晓其父节点,它也将用于区分IE与非IE。

下面是我的fixbug程序:

//by 司徒正美
//此bug在IE7中修复,详见:
        if(document.replaceNode && !window.XMLHttpRequest){
          var head = document.getElementsByTagName("head")[0],
          base = head.getElementsByTagName("base")[0],
          headFrag = document.createDocumentFragment(),
          bodyFrag = headFrag.cloneNode(),el;
           if(base && base.childNodes.length){
            for (; el =base.childNodes[0];) {
              if(el.tagName === "BODY"){
                bodyFrag.appendChild(el);
                break;
              }else{
                headFrag.appendChild(el)
              }
            }
            base.replaceNode(base.cloneNode())
            head.appendChild(headFrag);
            document.documentElement.appendChild(bodyFrag)
          }
        }

运行代码

搞定!不过,我的globalEval函数用不着这个,直接用execScript一了百了,连script标签也不用插入。

分享到:
评论

相关推荐

    javascript中BASE标签作用

    虽然`&lt;base&gt;`标签本身并不直接涉及JavaScript,但在处理页面动态生成的链接或资源时,JavaScript会依赖于`&lt;base&gt;`标签所设定的基准URL。例如,在JavaScript函数中获取当前文档的基准URL: ```javascript function ...

    struts中base标签的target属性

    当页面中有多个链接指向同一域名下的资源时,使用 `&lt;s:base&gt;` 标签可以极大地减少重复代码,并且当需要更改网站的基本 URL 时,只需要修改 `&lt;s:base&gt;` 标签即可,无需逐个更改页面中的链接。 #### Target 属性的...

    HTML中的base标签 中文WORD版

    特别是在Firefox和IE浏览器中,如果在文档加载过程中动态插入`&lt;base&gt;`标签,浏览器可能在标签生效前就已经尝试加载资源,导致错误的URL请求。如: ```html &lt;!DOCTYPE html&gt; document.write('&lt;base href=...

    HTML base 标签的 href 属性

    这个标签主要用于设定网页中所有相对链接的基准,对于管理和简化页面的链接结构有着重要作用。当我们处理大型网站或者需要统一管理链接时,`&lt;base&gt;`标签尤其有用。 `&lt;base&gt;`标签有两个主要属性: 1. `href`属性:...

    HTML5 对各个标签的定义与规定:base

    通过使用`&lt;base&gt;`标签,开发者可以在不修改每个链接的情况下,统一改变文档内所有相对链接的基准URL,从而实现更灵活的页面设计。此外,通过设置`target`属性,还可以方便地控制链接打开的方式,这对于创建用户友好...

    6_base.apk

    6_base.apk

    JavaScript获得页面base标签中url的方法

    如果页面中确实有`&lt;base&gt;`标签定义,`baseElement`就不会是`null`,进而可以通过`baseElement.href`获取到`&lt;base&gt;`标签的href属性值,并通过`document.write()`方法输出。 需要注意的是,如果页面中有多个`&lt;base&gt;`...

    Base64转二进制文件,Base64 To File

    通过Base64编码,可以将图像文件编码为文本形式,然后插入到`&lt;img&gt;`标签的`data:`URI中,实现页面上的图片内联显示。 2. EML附件提取:电子邮件的EML文件通常是以纯文本格式存储的,包括邮件的头部信息、正文和附件...

    6_base.apk.1

    6_base.apk.1

    BASE64编码解码页面

    网上下载的Base64编码加密.htm页面,对base64编码解码支持不好,主要是对中文无法正确执行。 换了解码函数后,对中文英文编码解码都支持了,测试通过。 另外再增加了将base64编码中的回车换行符去掉的功能,这样对...

    pb9_base64_pb调用base64.dll_PB9base64_Base64.dll_glass8y6_pbbase64

    标签中的"pb调用base64.dll"可能是指在其他情况下,PowerBuilder应用程序可能会通过动态链接库(DLL)的方式来调用Base64编码服务。DLL文件是一个包含可由多个程序同时使用的代码和数据的库,当一个DLL被创建后,...

    base(6).apk

    base(6).apk

    base 64 encode image in ie7 and under

    在早期的浏览器版本中,如IE7,由于对某些现代Web技术的支持不足,开发者经常使用Base64编码将图片嵌入到页面中,以避免跨域问题或其他兼容性问题。 在描述中提到的博文链接指向了一篇名为“iteye”的博客文章,...

    6_base.apk.1.1

    6_base.apk.1.1

    VB JPG转base64和base64转JPG.rar

    由于2^6 = 64,因此有64种可能的字符组合,通常使用大小写字母、数字以及"+"和"/",最后用"="作为填充符来保证输出字符串的长度是8位的倍数。 接下来,我们将讨论如何在VB6.0中实现Base64与JPG图片的转换: 1. **...

    jsp base标签与meta标签学习小结

    `base`标签通常放在`&lt;head&gt;`标签内,用于定义页面的基准URL。这意味着所有相对链接(如图片、CSS文件、JavaScript文件等)都将相对于这个基准URL解析。例如,在提供的代码中,`&lt;base href="&lt;%=basePath%&gt;"&gt;`中的`...

    base64 jsp版本加密及调用

    首先,Base64的原理是将每3个字节的数据(24位)分为4个6位的块,并将每个6位块转换为一个字符,范围从'0'到'9','A'到'Z','a'到'z',以及'+'和'/'。为了确保所有数据都能正确表示,最后可能会添加一个或两个等号...

    上传图片预览-兼容IE6,IE7,IE8,FF

    标题中的“上传图片预览-兼容IE6,IE7,IE8,FF”指的是一个Web开发的技术解决方案,目的是实现图片上传前的预览功能,并确保该功能在早期版本的Internet Explorer(IE6、IE7、IE8)以及Firefox浏览器上都能正常工作...

Global site tag (gtag.js) - Google Analytics