很多人一直都有个想法,要是可以随心所欲的操作iframe就好了。这样静态页面也就有了相当于后台动态页面php,jsp,asp中include,require实现统一多页面布局 的能力。
通过Javascript的帮忙我们可以像后台一样动态加载操作iframe对象属性src指向的html页面的内容。这样的操作需要提供两个页面,一个页面是iframe所在页面(页面名称:iPage.html ),另一个页面是iframe属性src指向页面(页面名称:srcPage.html )。
iPage.html,<body>里dom:
- < iframe id = “ iId “ name = “ iName “ src = “ srcPage.html “ scrolling = “ no “ frameborder = “ 0 “ ></ iframe >
srcPage.html,<body>里dom:
- < h1 > 妹妹的一天 </ h1 >
- < p > 早上吃早点,中午约会吃饭,下午K歌,晚上和哥哥瞎折腾 </ p >
下面讨论ie下JS是怎么操作以上两个页面,再讨论firefox的做法,最后给出兼容ie,firefox浏览器操作iframe对象的方法。
一、ie下访问操作iframe里内容
大家都知道iframe是非标准html标签,它是由ie浏览器推出的多布局标签, 随后Mozilla也支持了这个标签。(闲话,嘿嘿)
1. ie通过document.frames["IframeName"]获取它,例子:我们在iPage.html里输出srcPage.html里h1的内容,JS如下:
- alert ( document . frames [ " iName " ] . document . getElementsByTagName ( ‘ h1 ‘ )[ 0 ] . firstChild . data ) ;
你会发现这样在页面里加入代码,好像并没有输出想要的东东,为什么呢?这个我也没有搞清楚,只是习惯性的加入了window.onload就有输出 了(注:JS代码都写到这个事件里去),知道的人士可否告诉我下。why?更改之后代码ie下有了输出,firefox下document.frames 没有定义错误提示:
- window . onload = ( function () {
- alert ( document . frames [ " iName " ] . document . getElementsByTagName ( ‘ h1 ‘ )[ 0 ] . firstChild . data ) ;
- }) ;
2. ie另一种方法contentWindow获取它,代码:
- window . onload = ( function () {
- var iObj = document . getElementById ( ‘ iId ‘ ) . contentWindow ;
- alert ( iObj . document . getElementsByTagName ( ‘ h1 ‘ )[ 0 ] . firstChild . data ) ;
- }) ;
此方法经过ie6,ie7,firefox2.0,firefox3.0测试都通过,好事啊!嘿嘿。(网上一查,发现Mozilla Firefox iframe.contentWindow.focus缓冲区溢出漏洞,有脚本注入攻击的危险。
后来听说可以在后台防止这样的事情发生,算是松了口气。不过还是希望firefox新版本可以解决这样的危险。)
3.改变srcPage.html里h1标题内容,代码:
- iObj . document . getElementsByTagName ( ‘ h1 ‘ )[ 0 ] . innerHTML = ‘ 我想变成她一天的一部分 ‘ ;
通过contentWindow后访问里面的节点就和以前一样了。
二、firefox下访问操作iframe里内容
Mozilla支持通过IFrameElmRef.contentDocument 访问iframe的document对象的W3C标准,通过标准可以少写一个document,代码:
- var iObj = document . getElementById ( ‘ iId ‘ ) . contentDocument ;
- alert ( iObj . getElementsByTagName ( ‘ h1 ‘ )[ 0 ] . innerHTML = ‘ 我想变成她一天的一部分 ‘ ) ;
- alert ( iObj . getElementsByTagName ( ‘ p ‘ )[ 0 ] . firstChild . data ) ;
兼容这两种浏览器的方法,现在也出来了,就是使用contentWindow这个方法。
嘿嘿!操作iframe是不是可以随心所欲了呢?如果还觉得不爽,你甚至可以重写iframe里的内容。
三、重写iframe里的内容
通过designMode(设置文档为可编辑设计模式)和contentEditable(设置内容为可编辑),你可以重写iframe里的内容。代码:
- var iObj = document . getElementById ( ‘ iId ‘ ) . contentWindow ;
- iObj . document . designMode = ‘ On ‘ ;
- iObj . document . contentEditable = true ;
- iObj . document . open () ;
- iObj . document . writeln ( ‘ <html><head> ‘ ) ;
- iObj . document . writeln ( ‘ <style>body {background:#000;font-size:9pt;margin: 2px; padding: 0px;}</style> ‘ ) ;
- iObj . document . writeln ( ‘ </head><body></body></html> ‘ ) ;
- iObj . document . close () ;
这两个对象的资料可参考:http://msdn.microsoft.com/en-us/library/ms533720(VS.85).aspx
firebug测试以上代码性能,如图
注释掉 iObj.document.designMode = ‘On’;
iObj.document.contentEditable = true;
如图:
效果没有变,时间效率是注释前的将近三倍。嘿嘿。那两个对象是参考网络一些人的写法,重写iframe里内容,其实没有必要用designMode和contentEditable,除非有其他的需求。
四、iframe自适应高度
有了上面的原理要实现这个相当简单,就是把iframe的height值设置成它里面文档的height值就可以。代码:
- window . onload = ( function () {
- var iObj = document . getElementById ( ‘ iId ‘ ) ;
- iObj . height = iObj . contentWindow . document . documentElement . scrollHeight ;
- }) ;
现在对JS操作iframe你已经有了全新的认识,说不定那天会因为这个有什么新的web技术名词,嘿嘿,臭美下!
参考资料:
https://developer.mozilla.org/cn/Migrate_apps_from_Internet_Explorer_to_Mozilla
http://msdn.microsoft.com/en-us/library/ms533690(VS.85).aspx
http://www.kuqin.com/webpagedesign/20080516/8536.html
http://www.nohack.cn/jsj/safe/2006-10-05/8156.html