在Web开发中经常会遇到需要使用弹出窗口的情况,使用弹出窗口可以分散主页面的信息量,使用户操作更加简洁清晰,增强用户体验,但在使用浏览器弹出窗口时应该考虑到各种不同的浏览器对弹出方式的支持方式的兼容性问题,例如window.showModalDialog方法只能被IE浏览器支持,那么FireFox的用户就无法看到弹出的浏览器窗口。本文进行了在客户端多种弹出窗口的两种尝试,每种方式都在IE和FF下进行并通过了测试,下面将逐一介绍各种不同的实现方式:
方式1:使用window.open()方法
虽然window.showModalDialog()方法是IE独有的,但window.open()方法却是IE和FF都支持的,因此我们考虑使用这个方法实现弹出窗口,首先看一下这个方法的函数原型:
oNewWindow = window.open( [sURL] [, sName] [, sFeatures] [, bReplace])
其中sURL是要打开的页面的路径,sName是打开新页面的窗体或框架的名称(_blank,_parent,_self等,也可以跟框架集中的框架名称)字符串,sFeature是对弹出窗口的属性描述的字符串,可以设置弹出窗口的各种属性,包括是否有菜单栏,是否有工具栏,状态栏等,该字符串的格式为“属性名=值,属性名=值”(关于sFeature的详细内容,参考下面的介绍),bReplace为true时表明弹出的窗口在浏览器历史记录中增加一条新的记录,为false时不增加。
sFeature可选的属性和值列表如下:
channelmode = { yes | no | 1 | 0 } | Specifies whether to display the window in theater mode and show the channel band. The default is no. |
directories = { yes | no | 1 | 0 } | Specifies whether to add directory buttons. The default is yes. |
fullscreen = { yes | no | 1 | 0 } | Specifies whether to display the browser in full-screen mode. The default is no. Use full-screen mode carefully. Because this mode hides the browser's title bar and menus, you should always provide a button or other visual clue to help the user close the window. ALT+F4 closes the new window. A window in full-screen mode must also be in theater mode (channelmode). |
height = number | Specifies the height of the window, in pixels. The minimum value is 100. |
left = number | Specifies the left position, in pixels. This value is relative to the upper-left corner of the screen. The value must be greater than or equal to 0. |
location = { yes | no | 1 | 0 } | Specifies whether to display the input field for entering URLs directly into the browser. The default is yes. |
menubar = { yes | no | 1 | 0 } | Specifies whether to display the menu bar. The default is yes. |
resizable = { yes | no | 1 | 0 } | Specifies whether to display resize handles at the corners of the window. The default is yes. |
scrollbars = { yes | no | 1 | 0 } | Specifies whether to display horizontal and vertical scroll bars. The default is yes. |
status = { yes | no | 1 | 0 } | Specifies whether to add a status bar at the bottom of the window. The default is yes. |
titlebar = { yes | no | 1 | 0 } | Specifies whether to display a title bar for the window. This parameter is ignored unless the calling application is an HTML Application or a trusted dialog box. The default is yes. |
toolbar = { yes | no | 1 | 0 } | Specifies whether to display the browser toolbar, making buttons such as Back, Forward, and Stop available. The default is yes. |
top = number | Specifies the top position, in pixels. This value is relative to the upper-left corner of the screen. The value must be greater than or equal to 0. |
width = number | Sets the width of the window, in pixels. The minimum value is 100. |
有了上面的参考,我们就可以弹出一个我们希望的窗口了。示例代码如下:
var ref=open('Dialog1.aspx',null,'directories=yes,height=240px,width=320px,menubar=no,toolbar=no');
}
其中ref返回的是对弹出窗口的引用,在父窗口中,我们可以根据ref来操作弹出窗口中的对象,就像用弹出窗口的window对象一样。现在要解决的是如何实现弹出窗口与父窗口之间的交互问题。首先要搞清楚如何获取父窗口的引用。通过尝试,发现在这种方式下用子窗口的window.parent获取的对象并不是父窗口,而是子窗口本身,而在弹出窗口中获取父窗口的正确方法是使用window.opener属性。获取了父窗口的引用,我们就可以实现两个窗口之间的交互了。下面这段示例代码将弹出窗口的uinput的值传给父窗口的uinput,并关闭弹出窗口。
opener.document.getElementById('uinput').value=document.getElementById('uinput').value;
window.close();
}
至此我们已经实现了两个窗口之间最简单的交互。现在我们让弹出窗口弹出,在文本框中输入一些内容,然后再次触发弹出窗口弹出,这时并没有弹出一个新的窗口,但是我们看到弹出窗口中我们输入的内容已经被清空了(这里实际把弹出窗口重新加载了一次,只不过是在同一个窗口中),我们采用刚才提到的弹出窗口引用来解决这个问题:当弹出窗口时保存弹出窗口的引用,当弹出窗口关闭时清空该值,那么我们就可以知道是否已经有一个窗口打开了,根据这种思路,我们在上面的代码里添加如下修改:
// 触发弹出窗口的代码
function fnPopup(){
if(ref==null)
// 保存弹出窗口的窗体引用
ref=open('Dialog1.aspx',null,'directories=yes,height=240px,width=320px,menubar=no,toolbar=no');
}
// 弹出窗口中的处理逻辑
function fnCloseWin(){
opener.document.getElementById('uinput').value=document.getElementById('uinput').value;
// 修改父窗口的标志
opener.ref=null;
window.close();
}
通过这种方式我们可以解决上面描述的这种问题。
方式2:使用iframe
除了使用实际的弹出窗口,还可以使用控制一个div的display属性来模拟一个弹出窗口的操作,这里使用在Div里放一个iFrame的方式,主要考虑到可以在需要的时候加载弹出窗口的内容,减少主窗口的数据量。通是还要考虑的一个问题就是用户在完成一次选择后,当重复打开选择框时,如何保存用户上次选择的状态:例如用户在弹出窗口中从A-E5个选项中选择了AB两个,当再次打开时,应该保证AB两个是选中的。首先来看弹出窗口的实现,html代码和脚本如下:
html
<iframe id="myFrame" src="" style="width:100%;height:100%;"></iframe>
</div>
这里要注意iFrame的src属性留空了(其实默认值为about:blank),而且display属性为none,在弹出窗口没有打开时iFrame没有页面,div也不可见。
javascript
document.getElementById('popup').style.display='block';
window.frames[0].location.href="Dialog1.aspx";
}
这里用了window的frames对象,这个对象获取在当前页面中定义的frame或iFrame,当前页面只有一个iframe所以直接用window.frames[0]获取出对iframe的引用,通过设置location.href属性,就在iframe中打开希望的弹出窗口,同时设置div可见,则弹出窗口呈现给用户。
在iFrame的虚拟弹出窗口中,可以使用window.parent与父窗口进行交互了,弹出窗口中负责交互的部分代码如下:
parent.document.getElementById('uinput').value=document.getElementById('uinput').value;
parent.document.getElementById('popup').style.display='none';
}
完成交互后把 div隐藏,模拟弹出窗口关闭。现在要解决弹出窗口状态保存的问题。考虑有两种方案,第一种方案为用查询字符串把值传到弹出窗口中,由弹出窗口做相应的处理;后一种方案为用户完成选择后,只是隐藏弹出窗的div,下次再打开时只将div显示,而不重新加载页面,这样也可以实现状态的保存。但采用后一种方式,在主页面发生反送动作后,状态同样也会丢失(这是后一种方案的问题)。后一种方案的实现为在fnPopup函数中做如下修改:
document.getElementById('popup').style.display='block';
// 只有在第一次显示时加载页面
if(window.frames[0].location.href=='about:blank')
window.frames[0].location.href="Dialog1.aspx";
}
该种方案旨在说明如何在父窗口中判断子窗口的状态,具体的使用过程中还是使用查询字符串的方式更为理想。