在html中普通的父容器调用子容器中的方法十分简单
因为这两个容器的所有方法和属性都在同一个dom模型中
可以直接控制和使用
但是如果子容器中是一个iframe标签又是怎样的情况?
iframe请求另外一个页面并显示
这时候父子容器的方法和属性等都不在一个dom模型中了
有些情况又要求父子容器能够互相调用方法来实现某一功能
这时候要怎么实现这个要求呢
其实一个html页面内的所有方法等最后都会被加载到该页面dom模型的window内
例如经常使用的
window.onload()//在页面加载完成后执行的事件/方法
如果在一个页面内定义了一个js方法
function DoSomething(){...}
那么这个方法最后会被加载到window下面
可以通过这个window点出来并使用这个方法
那么,现在只要能够拿到子容器iframe内部页面的window就可以在父容器中调用子容器的方法了
例子:
HtmlPage1.html页面中
<input type="button" id="btnShowChild" value="点击弹出子容器"/> <div id="divChild"> <iframe id="ifmChild" src="javascript:void(0)"></iframe> </div>
页面如下:
很简单就一个按钮的页面
点击这按钮,弹出id为divChild的div
在这个div中包含一个iframe
在点击按钮弹出div的同时设置iframe的src属性为HtmlPage2.html
为了方便操作使用到了jquery easyui的插件
在该页面中输入以下js代码:
//在窗体加载完成后 $(function () { //获得div var divChild = $("#divChild"); //刚开始的时候设置div隐藏 divChild.css("display", "none"); //按钮点击事件 $("#btnShowChild").click(function () { //设置iframe的src属性为HtmlPage2.html $("#ifmChild").attr("src", "HtmlPage2.html"); //显示div divChild.css("display", "block"); //将div以对话框的形式弹出(easyui) divChild.dialog({ title: "我是父容器", buttons: [{ //确认按钮 text: '提交子容器中的表单', iconCls: "icon-ok", handler: function () { //点击该按钮之后执行的方法 } }, { //关闭按钮 text: '关闭', handler: function () { $("#divChild").dialog('close'); } }] }); }); });
HtmlPage2.html页面:
<form id="fmSubmit"> <table> <tr> <td colspan="2"> 我其实是一个Iframe标签,是一个子容器 </td> </tr> <tr> <td> 用户名: </td> <td> <input type="text" id="txtUid" name="txtUid"/> </td> </tr> <tr> <td> 密码: </td> <td> <input type="password" id="txtPwd" name="txtPwd"/> </td> </tr> </table> </form>
一个表单包含一个table的简单布局
现在回到HtmlPage1.html页面
点击页面上的按钮:
这时候已经将HtmlPage2.html页面通过一个iframe标签以子容器的形式显示在HtmlPage1.html页面中
这时我们需要的效果是
点击“提交子容器中的表单”按钮
使HtmlPage2.html中的表单异步提交
成功提交之后再HtmlPage1.html中关闭这个子容器,并将HtmlPage1.html页面上的按钮值显示为“完成”
首先要通过点击父容器中的一个按钮来执行子容器中的一个方法使表单提交
可以通过获得子容器的window来得到并执行这个方法
所以在HtmlPage2.html中定义这样一个js方法:
//提交表单方法 function SubmitForm() { //获得页面文本框的值 var txtUid = $("#txtUid").val(); var txtPwd = $("#txtPwd").val(); //通过jquery异步提交表单 $.ajax({ url: "Handler1.ashx", data: "Uid=" + txtUid + "&&Pwd=" + txtPwd, type: "Get", success: function(res) { if (res == "ok") { //提交成功之后执行的方法 } else { alert("子容器iframe异步提交出错!"); } } }); }通过一个一般处理程序来接收数据并简单的判断然后返回数据
context.Response.ContentType = "text/plain"; if (context.Request.QueryString["Uid"] == "111" && context.Request.QueryString["Pwd"] == "111") { context.Response.Write("ok"); } else { context.Response.Write("error"); }
此时在HtmlPage1.html并不知道怎么来获得子容器的window
但是可以知道ifram标签肯定是重要的目标,因为是它在承载显示另外一个页面
所以可以在页面1中的“提交子容器中的表单”按钮事件先获得这个iframe标签,然后观察它的属性
divChild.dialog({ title: "我是父容器", buttons: [{ //确认按钮 text: '提交子容器中的表单', iconCls: "icon-ok", handler: function () { //点击该按钮之后执行的方法 //获得子容器的iframe标签 var ifmChild = $("#ifmChild"); } }, { //关闭按钮 text: '关闭', handler: function () { $("#divChild").dialog('close'); } }] });
在浏览器中打开页面1,并进行调试
点击“弹出子容器”按钮
并点击对话框中的“提交子容器中的表单”按钮,命中断点,将ifmChild添加监视查看
可以看到,这个ifame标签似乎是一个数组,而且只有一个元素
那么打开这唯一一个元素看看里面有没有window属性
但是找了全部找了一遍好像没有发现window这个属性
但是却找到了一个contentWindow,它在这里
可以看到这个contentWindow后面还跟着一个[object Window]
先不管这是啥意思
反正跟window有关先拿来用看看
还是修改对话框中按钮的事件
divChild.dialog({ title: "我是父容器", buttons: [{ //确认按钮 text: '提交子容器中的表单', iconCls: "icon-ok", handler: function () { //点击该按钮之后执行的方法 //获得子容器的iframe标签 //var ifmChild = $("#ifmChild"); var childWindow = $("#ifmChild")[0].contentWindow; childWindow.SubmitForm(); } }, { //关闭按钮 text: '关闭', handler: function () { $("#divChild").dialog('close'); } }] });
其实到这里很明了了,如果有装R#插件的同学可以甚至直接在childWindow点出子容器中的SubmitForm方法
然后转到页面2
在表单提交成功后的事件中
获得当前window的parent属性
这个属性就是页面1的window,因为页面1就是页面2的父容器
如此一来,就可以再页面2中直接使用父容器页面1中的方法了
//通过jquery异步提交表单 $.ajax({ url: "Handler1.ashx", data: "Uid=" + txtUid + "&&Pwd=" + txtPwd, type: "Get", success: function(res) { if (res == "ok") { //提交成功之后执行的方法 window.parent.AfterChildSubmit(); } else { alert("子容器iframe异步提交出错!"); } } });
所以要在页面1中准备一个AfterChildSubmit方法
function AfterChildSubmit() { //关闭对话框 $("#divChild").dialog('close'); //消息提示 alert("子容器成功调用父容器的AfterChildSubmit方法"); //修改按钮的值 $("#btnShowChild").val("完成"); }
最后测试如下: