`
kaoyudu
  • 浏览: 37403 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

Chrome Safari Firefox 中 IFRAME 元素在文档树中发生变化后父子页面间的某些交互方式会失效

 
阅读更多

  window 对象中的 frames 集合可以返回当前 window 中的子框架列表,这是一个类似数组的集合对象。可以通过整型下标或者子框架元素的 name 属性获取到该集合内对应的子框架 window 对象。
  IFRAME 元素对应的 DOM 对象为 HTMLIframeElement,各浏览器均支持 HTMLIframeElement 接口中的 contentWindow 属性,这个属性返回 IFRAME 引入子页面的 window 对象。
  假设在当前父页面中存在一个 id 和 name 属性为 "ifr" 的 IFRAME 对象,则可以通过 window.frames["ifr"] 或者 document.getElementById("ifr").contentWindow 这两组方法获取到 IFRAME 引入页面的 window 对象。这两种方法在所有主流浏览器中均有很好的兼容性。但是却并不符合 W3C 规范。其中 window.frames 集合算 DOM Level 0 范畴,而 contentWindow 属性为 IE5.5 引入。
  下面分 4 种情况测试当 IFRAME 元素在文档树中发生变化对 IFRAME 内外的子页面与父页面交互的影响。 window.onload 之前,通过 innerHTML 方法改变 IFRAME 元素在文档树中的位置:main1.html。
  window.onload 之前,通过 removeChild、AppendChild 方法改变 IFRAME 元素在文档树中的位置:main2.html。
  window.onload 之后,通过 innerHTML 方法改变 IFRAME 元素在文档树中的位置:main3.html。
  window.onload 之后,通过 removeChild、AppendChild 方法改变 IFRAME 元素在文档树中的位置:main4.html。
  测试代码如下: main1.html iframe { width:450px; height:1800px; }  before window.onload, innerHTML        function $(id) { return document.getElementById(id); } $("div2").innerHTML = $("div1").innerHTML; $("div1").innerHTML = "";  
  main2.html iframe { width:450px; height:1800px; }  before window.onload, appendChild        function $(id) { return document.getElementById(id); } var iframe1 = $("div1").children[0]; var iframe2 = $("div1").children[1]; $("div1").removeChild(iframe1); $("div1").removeChild(iframe2); $("div2").appendChild(iframe1); $("div2").appendChild(iframe2);  
  main3.html iframe { width:450px; height:1800px; }  after window.onload, innerHTML        function $(id) { return document.getElementById(id); } window.onload = function () { $("div2").innerHTML = $("div1").innerHTML; $("div1").innerHTML = ""; }  
  main4.html iframe { width:450px; height:1800px; }  after window.onload, appendChild        function $(id) { return document.getElementById(id); } window.onload = function () { var iframe1 = $("div1").children[0]; var iframe2 = $("div1").children[1]; $("div1").removeChild(iframe1); $("div1").removeChild(iframe2); $("div2").appendChild(iframe1); $("div2").appendChild(iframe2); }  
  sub.html   * { font:12px Arial; } body { margin:0; } span { font-weight:bold; } .g { color:green; } .r { color:red; }      function myEval (code) { var script = document.createElement("script"); script.text = "var ret =" + code; document.body.appendChild(script); var x = ret; document.body.removeChild(script); return x; } function tryObj (obj_text) { var ok = 'OK'; var fail = 'FAIL' try { var f = ""; var ev = myEval(obj_text); try { f = ev.toString(); } catch(e) { f = ""; } return ev ? ok + " " + f : fail + " " + f; } catch(e) { return fail + " " + f; } } var arr = [ 'parent', 'parent.document', 'parent.document.getElementById("ifr1")', 'parent.document.getElementById("ifr1").contentWin dow', 'parent.document.getElementById("ifr1").contentWin dow.document', 'parent.document.getElementById("ifr1").contentWin dow.history', 'parent.document.getElementById("ifr1").contentWin dow.location', 'parent.document.getElementById("ifr1").contentWin dow.navigator', 'parent.document.getElementById("ifr1").contentWin dow.screen', 'parent.document.getElementById("ifr1").contentWin dow.alert', 'parent.document.getElementById("ifr2")', 'parent.document.getElementById("ifr2").contentWin dow', 'parent.document.getElementById("ifr2").contentWin dow.document', 'parent.document.getElementById("ifr2").contentWin dow.history', 'parent.document.getElementById("ifr2").contentWin dow.location', 'parent.document.getElementById("ifr2").contentWin dow.navigator', 'parent.document.getElementById("ifr2").contentWin dow.screen', 'parent.document.getElementById("ifr2").contentWin dow.alert', 'parent.frames', 'parent.frames["ifr1"]', 'parent.frames["ifr1"].document', 'parent.frames["ifr1"].history', 'parent.frames["ifr1"].location', 'parent.frames["ifr1"].navigator', 'parent.frames["ifr1"].screen', 'parent.frames["ifr1"].alert', 'parent.frames["ifr2"]', 'parent.frames["ifr2"].document', 'parent.frames["ifr2"].history', 'parent.frames["ifr2"].location', 'parent.frames["ifr2"].navigator', 'parent.frames["ifr2"].screen', 'parent.frames["ifr2"].alert' ]; for (var i in arr) { document.write('' + arr[i] + ':'); document.write('' + tryObj(arr[i]) + ''); }     
  0.html 
  上面代码中有 4 个主页面 main1.html、main2.html、main3.html、main4.html,分别对应本文分析的 4 中情况,每组代码均包含两个 DIV 元素【div1】与【div2】,其中初始状态【div1】包含 IFRAME 元素【ifr1】及【ifr2】,【div2】中为空。
  【ifr1】引入了子页面 "sub.html" ,【ifr2】引入了子页面 "0.html" 。通过 JavaScript 将【div1】中的【ifr1】及【ifr2】移动到【div2】内。但是 4 个主页面采取了不同的移动方式。
  子页面中,分别判断了 33 个对象的状态,若存在该对象,则显示"OK" 及对象类型,否则显示 "FAIL" 。
  在本地构建 Web 服务器1,将测试代码放入服务器进行测试。   window.onload 之前,通过 innerHTML 方法改变 IFRAME 元素在文档树中的位置
  window.onload 之前,通过 removeChild、AppendChild 方法改变 IFRAME 元素在文档树中的位置
  window.onload 之后,通过 innerHTML 方法改变 IFRAME 元素在文档树中的位置
  window.onload 之后,通过 removeChild、AppendChild 方法改变 IFRAME 元素在文档树中的位置
  IE6 IE7 IE8 Opera
  Firefox
  Chrome Safari
  IE6 IE7 IE8 Opera
  Firefox
  Chrome Safari
  IE6 IE7 IE8 Opera
  Firefox
  Chrome Safari
  IE6 IE7 IE8 Opera
  Firefox
  Chrome Safari
  parent
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr1")
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr1").contentWindow
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById( "ifr1") .contentWindow.document
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr1") .contentWindow.history
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr1") .contentWindow.location
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr1") .contentWindow.navigator
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr1") .contentWindow.screen
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr1") .contentWindow.alert
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2")
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2") .contentWindow
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2") .contentWindow.document
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2") .contentWindow.history
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2") .contentWindow.location
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2") .contentWindow.navigator
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2") .contentWindow.screen
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.document .getElementById("ifr2") .contentWindow.alert
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.frames
  OK OK OK OK OK OK OK OK OK OK OK OK 
  parent.frames["ifr1"]
  OK OK OK2 OK OK OK OK OK OK2 OK OK OK 
  parent.frames["ifr1"].document
  OK OK FAIL OK OK OK OK FAIL FAIL OK FAIL OK 
  parent.frames["ifr1"].history
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr1"].location
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr1"].navigator
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr1"].screen
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr1"].alert
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr2"]
  OK OK OK2 OK OK OK OK OK OK2 OK OK OK 
  parent.frames["ifr2"].document
  OK OK FAIL OK OK OK OK FAIL FAIL OK FAIL OK 
  parent.frames["ifr2"].history
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr2"].location
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr2"].navigator
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr2"].screen
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  parent.frames["ifr2"].alert
  OK OK FAIL OK OK OK OK OK FAIL OK OK OK 
  注1. Chrome 中认为本地页面为跨域,IFRAME 元素父子页面之间的脚本交互是不安全的,会在控制台提示错误:Unsafe JavaScript attempt to access frame with URL [XXX] from frame with URL [XXX]. Domains, protocols and ports must match.
  注2. 与其他浏览器不同,Chrome 和 Safari 此时虽然返回一个有效对象,但此对象类型不是 [window] 而是 [HTMLIframeElement]。 从上表中的结果可见,通过 document.getElementById("IFRAME").contentWindow 的方式获取 IFRAME 元素引入子页面的 window 对象,各浏览器均没有任何问题。而 window.frames 方式则产生了差异: window.onload 之前,通过 innerHTML 方法改变 IFRAME 元素在文档树中的位置:
  在 IE6 IE7 IE8 Firefox Opera 中,子页面均可以获得移动后的【ifr1】及【ifr2】相关对象;
  在 Chrome Safari 中,虽然可以获取到父页面的【ifr1】及【ifr2】相关对象,但是与 IE Firfox Opera 中不同,该对象类型为 "HTMLIframeElement" ,而不是 "Window" ,所以该对象的子对象无法获取。
  window.onload 之前,通过 removeChild、AppendChild 方法改变 IFRAME 元素在文档树中的位置:
  各浏览器中,子页面均可以获得移动后的【ifr1】及【ifr2】相关对象。
  window.onload 之后,通过 innerHTML 方法改变 IFRAME 元素在文档树中的位置:
  在 IE6 IE7 IE8 Opera 中,子页面均可以获得移动后的【ifr1】及【ifr2】相关对象;
  在 Firefox 中,在 window.onload 中移动 IFRAME 却使 IFRAME 的 window 对象中 "document" 对象失效;
  在 Chrome Safari 中,虽然可以获取到父页面的【ifr1】及【ifr2】相关对象,但是与 IE Firefox Opera 中不同,该对象类型为 "HTMLIframeElement" ,而不是 "Window" ,所以该对象的子对象无法获取。
  window.onload 之后,通过 removeChild、AppendChild 方法改变 IFRAME 元素在文档树中的位置:
  在 IE6 IE7 IE8 Opera Chrome Safari 中,子页面均可以获得移动后的【ifr1】及【ifr2】相关对象;
  在 Firefox 中,在 window.onload 中移动 IFRAME 却使 IFRAME 的 window 对象中"document" 对象失效。
  可见,对于 window.frames 方式,使用情况 2,即 window.onload 之前,通过 removeChild、AppendChild 方法改变 IFRAME 元素在文档树中的位置不会出现兼容性问题。 根据上面所得的结果,推荐使用 document.getElementById("IFRAME").contentWindow.do cument 获取 IFRAME 元素内页面的 document 对象,且对于在文档树中移动位置后的 IFRAME 元素也有很好的兼容性。同时应避免对跨域的父子页面交互。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics