`
yiminghe
  • 浏览: 1460307 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

javascript 与 iframe

阅读更多

iframe是 xhtml strict 模式下 禁用 的标签,因此 不建议使用 ,故javascript对它的操作也比较模糊。但是旧系统仍然大量使用iframe以及无刷新体验的文件上传,一般设置 transitional ,操作还是要记下来。特别是控制iframe具体包含内容的方法:

 

1.控制 iframe 跳转

 

1.1 原始的控制iframe方法

 

<iframe name='f1' height='100'>
</iframe>
//使用  
window .frames['f1'] .location  ==  window.f1.location == f1.location 
 

这种取到的window.f1相当于iframe包含页面的窗口的window变量,于是不能取得iframe 对象本身的属性,比如height,width 等

 

 

1.2 DOM控制iframe方法

 

<iframe id='f2' height='100'>
</iframe>
//使用 
 document.getElementById('f2').src
//或
 document.getElementById('f2').contentWindow.location

 

 

这种document.getElementById('f2') 取到的是页面的 iframe 标签dom对象,可以取得 dom对象的一些属性,比如 height,width

document.getElementById('f2').contentWindow才是iframe所包含页面的窗window

 

document.getElementById('f2').contentWindow== window .frames['f1']

 

2.监控iframe装载完毕

 

2.1 DOM1事件模型方法

 

      若是动态监控,ie,ff各有不同

 

// ff 要 
document.getElementById('f1').onload =function () {
    alert('只有ff识别');
};   

//ie 要
document.getElementById('f1').onreadystatechange = function () {
    //loading ... interactive....comlete..
   alert('只有ie识别 x.x ' + this.readyState);
};
 

2.2  DOM2 事件模型方法

 

      则没有区别,只不过ie用attachEvent,ff用addEventListener,监控load事件即可

 

2.3 具体各种测试看例子

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>label2</title>
<script src='file:\\\F:\code\lib\ext-2.2.1\adapter\ext\ext-base.js'></script>
<script src='file:\\\F:\code\lib\ext-2.2.1\ext-all.js'></script>
<script>
function t() {
    alert(document.getElementById('f1').contentWindow.location);
    alert(document.getElementById('f1').height);
    alert(window.f2.location);
    alert(window.f2.height);
    //document.getElementById('f1').src='http://www.baidu.com';
    //f1.location='http://www.baidu.com';
    window.f2.location = 'http://www.baidu.com';
}
var addE = function () {
    if (window.addEventListener) {
        return function (el, eventName, fn, capture) {
            el.addEventListener(eventName, fn, (capture));
        };
    } else if (window.attachEvent) {
        return function (el, eventName, fn, capture) {
            el.attachEvent("on" + eventName, fn);
        };
    } else {
        return function () {};
    }
}();
window.onload = function () {
    //	只有ie识别
    /*
	document.getElementById('f1').onreadystatechange = function () {
	    //loading ... interactive....comlete..
	    alert('只有ie识别 x.x ' + this.readyState);
	 };
    */
    //	只有ff识别
    /*
	document.getElementById('f1').onload =function () {
	     alert('只有ff识别');
	};	
    */
    // DOM 添加事件监听的方法 ie5.5 6 7 ff 全部兼容
    addE(document.getElementById('f1'), 'load', function () {
        alert('全部兼容');
    });
};        
</script>
</head>
<body>
<input id='b' type='button' value="测试4" onclick="t();" />
<br/>
<iframe id='f1' name='f2' height="200" />
<!-- iframe 不用 dom 监控 onload ie 5,6 ,7 识别 判断 readyState==c omplete 即可
        onreadystatechange="alert('只有ie识别' +this.readyState);" //ie5.5 6 7 ff 全部兼容
        ,但是必须写在html 中,onload 不能动态添加 onload="alert('只有ie识别');" -->
<script>
//放下面不行,一定要放上面
/*
	window.onload=function () {
	addE( document.getElementById('f1'),'load',function () {
			alert(1);
		});
	};
*/     
</script>
</body>
</html>
 

3.iframe载入后的自适应高度

 

     主要还是利用页面载入后以及iframe onload后的一些操作,关于界面载入见

页面加载判断与onload 研究

function DOMOk(readyOk) {
    /* for Mozilla */
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", readyOk, false);
    }
    /* for Internet Explorer */
    if (window.attachEvent) {
        document.write("<s" + 'cript id="ie-deferred-loader" defer="defer" src="/' + '/:"></s' + "cript>");
        var defer = document.getElementById("ie-deferred-loader");
        defer.onreadystatechange = function () {
            if (this.readyState == "complete") {
                readyOk();
            }
        };
    }
}
var addE = function () {
    if (window.addEventListener) {
        return function (el, eventName, fn, capture) {
            el.addEventListener(eventName, fn, (capture));
        };
    } else if (window.attachEvent) {
        return function (el, eventName, fn, capture) {
            el.attachEvent("on" + eventName, fn);
        };
    } else {
        return function () {};
    }
}();
DOMOk(function () {
    addE(document.getElementById('frame_mz'), 'load', function () {
        //高度自适应呢
        document.getElementById('frame_mz').height = Math.max(
        document.getElementById('frame_mz').contentWindow.document.body.scrollHeight, 
document.getElementById('frame_mz').contentWindow.document.documentElement.scrollHeight);
    });
    frame_mz.location = 'xx.html';
});
 

所以一般来说,我建议使用DOM2控制iframe的方法,作用更宽泛

 

ps : 关于 ff iframe 长高后不会再缩回去的解答


http://ued.koubei.com/?p=243

 

所谓iframe自适应高度,就是,基于界面美观和交互的考虑,隐藏了iframe的border和scrollbar,让人看不出它是个 iframe。如果iframe始终调用同一个固定高度的页面,我们直接写死iframe高度就可以了。而如果iframe要切换页面,或者被包含页面要 做DOM动态操作,这时候,就需要程序去同步iframe高度和被包含页的实际高度了。

顺便说下,iframe在迫不得已的时候才去用,它会给前端开发带来太多的麻烦。

传统做法大致有两个:
方法一,在每个被包含页在本身内容加载完毕之后,执行JS取得本页面的高度,然后去同步父页面的iframe高度。
方法二,在主页面iframe的onload事件中执行JS,去取得被包含页的高度内容,然后去同步高度。
在代码维护角度考虑,方法二是优于方法一的,因为方法一,每个被包含页都要去引入一段相同的代码来做这个事情,创建了好多副本。

两个方法都只处理了静的东西,就是只在内容加载的时候执行,如果JS去操作DOM引起的高度变化,都不太方便。

如果在主窗口做一个Interval,不停的来获取被包含页的高度,然后做同步,是不是即方便,又解决了JS操作DOM的问题了呢?答案是肯定的。

Demo页面:主页面 iframe_a.html ,被包含页面 iframe_b.htm iframe_c.html


主页面代码示例:

 

<iframe id="frame_content" src="iframe_b.html" scrolling="no" frameborder="0"></iframe>
<script type="text/javascript">
function reinitIframe() {
    var iframe = document.getElementById("frame_content");
    try {
        iframe.height = iframe.contentWindow.document.documentElement.scrollHeight;
    } catch(ex) {}
}
window.setInterval("reinitIframe()", 200);
</script>
 

一直执行,效率会不会有问题?
我做了测试,同时开5个窗口(IE6、IE7、FF、Opera、Safari)执行这个代码,不会对CPU有什么影响,甚至调整到2ms,也没影响(基本维持在0%占用率)。

下面谈谈各浏览器的兼容性问题,如何获取到正确的高度,主要是对body.scrollHeight和 documentElement.scrollHeight两个值得比较。注意本文用的是这个doctype,不同的doctype应该不会影响结果,但 是假如你的页面没有申明doctype,那还是先去加一个吧。

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 

在主页面追加以下测试代码,以输出这两个值,代码示例:

 

<div><button onclick="checkHeight()">Check Height</button></div>
<script type="text/javascript">
function checkHeight() {
    var iframe = document.getElementById("frame_content");
    var bHeight = iframe.contentWindow.document.body.scrollHeight;
    var dHeight = iframe.contentWindow.document.documentElement.scrollHeight;
    alert("bHeight:" + bHeight + ", dHeight:" + dHeight);
}
</script>

 

被加载页面,可以切换一个绝对定位的层,来使页面高度动态改变。如果层展开,则会撑高页面高度。代码示例:

 

<div><button onclick="toggleOverlay()">Toggle Overlay</button>
</div>
<div style="height:160px;position:relative">
<div id="overlay" style="position:absolute;width:280px;height:280px;display:none;"></div>
</div>
<script type="text/javascript">
function toggleOverlay() {
    var overlay = document.getElementById('overlay');
    overlay.style.display = (overlay.style.display == 'none') ? 'block' : 'none';
}
</script>
 

下面列出以上代码在各浏览器的测试值:
(bHeight = body.scrollHeight, dHeight = documentElement.scrollHeight, 红色 = 错误值, 绿色 = 正确值)

 

/ 层隐藏时 层展开时 bHeight dHeight bHeight dHeight
IE6 184 184 184 303
IE7 184 184 184 303
FF 184 184 184 303
Opera 181 181 300 300
Safari 184 184 303 184

 

暂且无视Opera比别人少3像素的问题…可以看出,如果没有绝对定位的东西,两个值是相等的,取哪个都无所谓。
但是如果有,那么各个浏览器的表现不太相同,单取哪个值都不对。但可以找到了一条规律,那就是取两个值得最大值可以兼容各浏览器。所以我们的主页面代码就要改造成这样了:

 

function reinitIframe() {
    var iframe = document.getElementById("frame_content");
    try {
        var bHeight = iframe.contentWindow.document.body.scrollHeight;
        var dHeight = iframe.contentWindow.document.documentElement.scrollHeight;
        var height = Math.max(bHeight, dHeight);
        iframe.height = height;
    } catch(ex) {}
}
window.setInterval("reinitIframe()", 200);
 

这样子,基本解决了兼容性问题。顺便说下,不光绝对定位的层会影响到值,float也会导致两个值的差异。

如果你演示Demo后,会发现,除了IE,其他浏览器中,当层展开后再隐藏,取到的高度值还是维持在展开的高度303,而非隐藏回去的真正值 184,就是说长高了之后缩不回去了。这个现象在不同被包含页面之间做切换也会发生,当从高的页面切换到矮页面的时候,取到的高度还是那个高的值。
可以归纳为,当iframe窗体高度高于文档实际高度的时候,高度取的是窗体高度,而当窗体高度低于实际文档高度时,取的是文档实际高度。因此,要想办法 在同步高度之前把高度设置到一个比实际文档低的值。所以,在iframe的添加 onload=”this.height=100″,让页面加载的时候先缩到足够矮,然后再同步到一样的高度。
这个值,在实际应用中决定,足够矮但又不能太矮,否则在FF等浏览器里会有很明显的闪烁。DOM操作的时候主页面无法监听到,只能DOM操作完了之后把高度变小了。
在我的一个实际项目中,在成本和收益之间权衡,我并没有做这个事情,因为每个DOM函数中都要插入这个代码,代价太高,其实层缩回去不缩掉也不是那么致命。包括Demo里,也没有去做这个事情。如果读者有更好的方法,请告诉我。

这是最终的主页面的代码:

 

<iframe id="frame_content" src="iframe_b.html" scrolling="no" frameborder="0" onload="this.height=100"></iframe>
<script type="text/javascript">
function reinitIframe() {
    var iframe = document.getElementById("frame_content");
    try {
        var bHeight = iframe.contentWindow.document.body.scrollHeight;
        var dHeight = iframe.contentWindow.document.documentElement.scrollHeight;
        var height = Math.max(bHeight, dHeight);
        iframe.height = height;
    } catch(ex) {}
}
window.setInterval("reinitIframe()", 200);
</script>
 

附Demo页面: 主页面 iframe_a.html ,被包含页面 iframe_b.htm iframe_c.html

如果只考虑FX和IE,并且,iframe里面内容也不进行DOM操作,那仍然可以用最简单的传统处理方式:

 

<iframe id="frame_content" src="iframe_b.html" 
scrolling="no" frameborder="0"
 onload="this.height=this.contentWindow.document.documentElement.scrollHeight"
>
</iframe>
分享到:
评论

相关推荐

    通过JavaScript+IFRAME实现页面分屏加载

    JavaScript 与 IFRAME 结合 使用JavaScript,我们可以动态地创建和修改IFRAME,实现更灵活的分屏加载。以下是一些关键步骤: - **检测加载状态**:通过监听IFRAME的 `load` 事件,判断内容是否已加载完成。 - **...

    关于Javascript与iframe的那些事儿

    JavaScript与iframe的交互操作和安全问题 Iframe是一种在网页中嵌入另一个HTML页面的方式,它可以在同一个浏览器窗口中打开多个独立的网页。Iframe的使用非常广泛,它可以让网页设计者很方便地组织页面结构,提升...

    js调用-嵌入iframe

    综上所述,"js调用-嵌入iframe"涉及到的主要知识点包括IFrame的基本使用、JavaScript与IFrame的交互以及测试中的注意事项。理解并掌握这些内容,对于网页开发尤其是动态内容加载和页面组件的复用具有重要意义。

    javascript经典特效---滚动的iframe页面.rar

    总的来说,这个压缩包文件提供了一个关于JavaScript操作iframe滚动效果的实例,对于学习和理解JavaScript与iframe的交互,以及如何通过编程手段实现动态滚动效果具有很好的参考价值。开发者可以通过解压文件,查看源...

    JavaScript实现IFrame子窗口调用父窗口的全局变量

    JavaScript实现IFrame子窗口调用父窗口的全局变量

    javascript动态调整iframe高度

    由于同源策略的限制,只有当`iframe`的源与包含它的页面在同一域下时,我们才能直接访问`iframe`的内容。若不在同一域,我们需要通过`window.postMessage`进行跨域通信。假设我们在同源环境下,可以通过`iframe....

    JS获取iframe内容【简化版】

    2. **JavaScript与iframe交互**: - JavaScript可以通过DOM(Document Object Model)操作iframe元素。 - 主要通过`window.frames`或者`document.getElementById('iframeId').contentWindow`来访问iframe内的窗口...

    Iframe模拟Jquery.Ajax

    5. **通信机制**:使用`window.postMessage`方法实现Iframe与主页面间的通信。这个方法允许跨窗口的数据传递,即使它们来自不同的源。发送端使用`postMessage`发送数据,接收端通过`message`事件监听数据。 6. **...

    JAVASCRIPT让IFRAME框架的高度自适应

    通过使用JavaScript来让IFRAME框架的高度自适应,我们可以实现IFRAME框架的高度自动调整,以提高用户体验。同时,我们也可以使用这个方法来实现其他类型的高度自动调整,以满足不同的需求。 在实际应用中,我们可以...

    js操作iframe的一些知识

    这个“js操作iframe的一些知识”主题涵盖了如何利用JavaScript与iframe进行交互,包括创建、访问、修改以及通信等多个方面。下面我们将深入探讨这些关键知识点。 1. **创建iframe**:首先,你需要在HTML中声明一个...

    javascript小练习

    这部分练习可能涉及如何利用JavaScript与IFrame通信、动态加载和更新框架内容等技巧。 3. **javaScriptProject**:这部分可能是实际的小项目,用于检验JavaScript基础知识的运用,比如计时器、动画效果、表单验证...

    javascript 获取iframe里页面中元素值的方法

    IE方法:document.frames[‘myFrame’].document.getElementById(‘test’).value; 火狐方法:document.getElementById(‘myFrame’).contentWindow.document.getElementById(‘test’).value; ...

    javascript iframe parent?

    总结,JavaScript中的iframe与parent通信是Web开发中的关键技术,涉及到跨域策略、事件监听和安全措施等多个方面。理解和熟练掌握这些技术对于创建动态、交互性强的网页应用至关重要。在实际项目中,我们需要根据...

    javascript 关闭iframe外层的div容器

    在JavaScript编程中,有时我们需要处理嵌入在页面中的`iframe`元素,并可能需要与外部页面交互,例如关闭`iframe`外部的某个`div`容器。这个需求通常出现在弹窗或者模态框的场景中,`iframe`用于承载特定的内容,而...

    跨框架示例(iframe).rar

    - `frames.htm`可能是主页面,它包含一个或多个iframe,并可能通过JavaScript与iframe内的页面(如x.html)进行交互。 - `x.html`可能是被嵌入到iframe中的子页面,它可能包含一个触发弹出层显示的按钮或其他元素...

    javascript写的可拖动的iframe

    在本文中,我们将深入探讨如何使用JavaScript实现一个可拖动的iframe。JavaScript是一种强大的客户端脚本语言,常用于网页交互和动态效果的实现。在这个案例中,我们将关注于利用JavaScript来增强iframe的功能,使其...

    PHP网站使用JavaScript和Iframe简单实现部分刷新效果1

    对于页面的隐藏与显示效果,JavaScript发挥了关键作用。在`main_left.php`中,通常会使用表格(table)结构来构建菜单,并通过JavaScript函数控制菜单项的可见性。例如,当用户点击某个菜单项时,对应的子菜单可以...

    javascript经典特效---IFRAME间链接变换.rar

    5. **事件监听与传递**:为了实现IFRAME间的交互,你可能需要监听IFRAME外的链接点击事件,然后传递给IFRAME内,或者相反。可以使用`addEventListener`添加事件监听器,使用`dispatchEvent`或`window.postMessage`...

    [导入]Javascript获取IFrame内容(兼容IE&FF)

    在JavaScript编程中,有时我们需要获取Iframe(内联框架)中的内容,这在处理嵌套页面、跨域通信或者实现动态加载时非常常见。本文将详细介绍如何在各种浏览器,包括Internet Explorer(IE)和Firefox(FF)等主流...

Global site tag (gtag.js) - Google Analytics