运用javascript的成员访问特性来实现通用版的兼容所有浏览器的打开对话框功能
打开网页对话框,一般有三种方法:window.open、window.showModalDialog、window.showModelessDialog,每一种都有它的优点与不足。第一种方法:window.open是大家常用的方法,它兼容所有的浏览器,打开一个新网页窗口很简单,但这种方法打开的“对话框”它默认的情况下是不支持交互(比如:获得返回值)与挂起操作(即:打开后若没有关闭,则其它网页窗口均无法操作,处于挂起等待状态);第二、第三种方法:window.showModalDialog、window.showModelessDialog支持交互操作且若使用showModalDialog还支持模式对话框,能够实现其它网页窗口被挂起,符合对话框的标准,但由于这两种方法只支持IE浏览器,所以除非是要求用户指定在IE下浏览操作网页,否则不建议使用。对话框其实在实际的网站类系统中必不可少,为了解决对话框的兼容与交互功能,我针对javascript的成员访问特性(所有的成员均以键值对的形式保存,可以通过成员访问符.来访问,如:window.alert,也可以通过键来访问,如:window["alert"])来实现可交互的通用对话框。
一、先来定义对话框的页面内容,代码如下:
WinDialog.html
<!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></title>
</head>
<body>
<table id="optionstable">
<thead>
<tr>
<th>工 号</th>
<th>姓 名</th>
<th>性 别</th>
<th>学 历</th>
</tr>
</thead>
<tbody>
<tr>
<td>0001</td>
<td>张三</td>
<td>男</td>
<td>本科</td>
</tr>
<tr>
<td>0002</td>
<td>张巧</td>
<td>女</td>
<td>本科</td>
</tr>
<tr>
<td>0003</td>
<td>李四</td>
<td>男</td>
<td>专科</td>
</tr>
<tr>
<td>0004</td>
<td>赵六</td>
<td>男</td>
<td>博士</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
var request = getRequest();
var cancel = true; window.onload = function () {
var tbody = document.getElementById("optionstable").getElementsByTagName("tbody").item(0);
for (var i = 0; i < tbody.rows.length; i++) {
var row = tbody.rows[i];
row.onmouseover = function () {
this.style.backgroundColor = "red";
}
row.onmouseout = function () {
this.style.backgroundColor = "";
}
row.onclick = function () {
if (request["complete"]) {
window.opener[request["complete"]](getSelectValues(this)); //回调父窗口的方法
window.cancel = false;
window.close();
}
}
}
} window.onunload = function () {
if (cancel && request["cancel"]) {
window.opener[request["cancel"]](); //回调父窗口的方法
}
} //获取URL参数
function getRequest() {
var url = location.search; //获取url中"?"符后的字串
var theRequest = new Object();
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("&");
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = (strs[i].split("=")[1]);
}
}
return theRequest;
} //获取当前选中行的单元格的内容数组
function getSelectValues(row) {
var values = [];
for (var i = 0; i < row.cells.length; i++) {
values[i] = row.cells[i].innerHTML;
}
return values;
}
</script>
</body>
</html>
上述代码中关键的地方就是回调父窗口的方法语句:window.opener[request["complete"]](getSelectValues(this));及 window.opener[request["cancel"]]();也可以使用eval的形式来动态调用。
二、接下来看父窗口(即:调用窗口)如何来弹出该对话框并实现交互,代码如下:
WinOpner.html
<!DOCTYPE html>
<html>
<head>
<title>父窗口</title>
</head>
<body>
<p>
<input id="Text1" type="text" /><input id="Button1" type="button" value="打开子窗口" />
</p>
<script type="text/javascript">
window.onload = function () {
document.getElementById("Button1").onclick = function () {
var WinDialog = window.open("WinDialog.html?complete=dialog_complete&cancel=dialog_cancel",//参数中指定回调方法
"_blank","toolbar=no,menubar=no,scrollbars=auto,resizable=no,location=no,status=no,depended=yes,width=600,height=500,left=" + (screen.width - 600) / 2 + ",top=" + (screen.height - 500) / 2);
};
} function dialog_complete(result) { //完成时回调方法
alert(result);
} function dialog_cancel() {//对话框关闭时回调方法
alert("cancel!");
}
</script>
</body>
</html>
上述代码中除了使用window.open方法来打开新窗口外,特别需要注意的是URL中需包含WinDialog.html对话框网页中约定的回调方法参数:complete=dialog_complete&cancel=dialog_cancel,这样在对话框打开后执行选择就会自动回调dialog_complete方法,若取消关闭就会回调dialog_cancel方法。
先来看一下效果截图:
打开对话框:

选择一行(单击)数据,回调了父窗口中的dialog_complete方法,弹出选择的数据,当然你可以将数据写入到文本框中:

若不选择直接关闭(即:取消),回调了父窗口中的dialog_cancel:

看到这些,有没有觉得不错,我觉得还是可以的,当然也有人可能会说上面的URL需包含回调方法参数,若参数名或方法名写错了,就会造成回调不成功,这是个问题,还有每个调用页面要重复写一堆的Window.open参数很不好,能不能封装成一个对象?当然,这些我都想到了,而且也实现了,请看下面的封装代码:
WebDialog.js中定义成WebDialog对象:
var WebDialog = function (url, width, height, resizeable) {
this.left = (screen.width - width) / 2;
this.top = (screen.height - height) / 2;
this.complete = function (result) { };
this.cancel = function () { };
var _self = this;
this.show = function () {
var _features = "toolbar=no,menubar=no,scrollbars=auto,resizable=" + resizeable + ",location=no,status=no,depended=yes,width=" + width + ",height=" + height + ",left=" + _self.left + ",top=" + _self.top;
var winDialog = window.open(url, "WebDialogWindow", _features);
winDialog.dialog_complete = _self.complete;
winDialog.dialog_cancel = _self.cancel;
}
}
上述代码中将window.open返回的窗口对象赋值给winDialog变量,然后为其指定dialog_complete及dialog_cancel方法
WinDialog2.html 定义对话框显示的内容:
<!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></title>
</head>
<body>
<table id="optionstable">
<thead>
<tr>
<th>工 号</th>
<th>姓 名</th>
<th>性 别</th>
<th>学 历</th>
</tr>
</thead>
<tbody>
<tr>
<td>0001</td>
<td>张三</td>
<td>男</td>
<td>本科</td>
</tr>
<tr>
<td>0002</td>
<td>张巧</td>
<td>女</td>
<td>本科</td>
</tr>
<tr>
<td>0003</td>
<td>李四</td>
<td>男</td>
<td>专科</td>
</tr>
<tr>
<td>0004</td>
<td>赵六</td>
<td>男</td>
<td>博士</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
var cancel = true; window.onload = function () {
var tbody = document.getElementById("optionstable").getElementsByTagName("tbody").item(0);
for (var i = 0; i < tbody.rows.length; i++) {
var row = tbody.rows[i];
row.onmouseover = function () {
this.style.backgroundColor = "red";
}
row.onmouseout = function () {
this.style.backgroundColor = "";
}
row.onclick = function () {
var dialog_complete = window["dialog_complete"];//获取回调方法
if (dialog_complete && typeof dialog_complete != "undefined") {
dialog_complete(getSelectValues(this));
window.cancel = false;
window.close();
}
}
}
} window.onunload = function () {
var dialog_cancel = window["dialog_cancel"]; //获取回调方法
if (cancel && dialog_cancel && typeof dialog_cancel != "undefined") {
dialog_cancel();
}
} //获取当前选中行的单元格的内容数组
function getSelectValues(row) {
var values = [];
for (var i = 0; i < row.cells.length; i++) {
values[i] = row.cells[i].innerHTML;
}
return values;
} </script>
</body>
</html>
上述代码中,通过window["dialog_complete"]、window["dialog_cancel"]来获取回调方法,然后通过判断是否有获取成功,若获取成功则直接调用,调用的方法与前面封装的指定的回调方法签名必需保持一致。
最后再来看如何通过WebDialog对象调用完成相同的交互功能,代码如下:
WinOpner2.html
<!DOCTYPE html>
<html>
<head>
<title>父窗口</title>
<script type="text/javascript" src="WebDialog.js?v1"></script>
</head>
<body>
<p>
<input id="Text1" type="text" /><input id="Button1" type="button" value="打开子窗口" />
</p>
<script type="text/javascript">
document.getElementById("Button1").onclick=function(){
var dlg = new WebDialog("WinDialog2.html", 600, 500, "yes");
dlg.complete=function(result){//完成时回调方法
alert(result);
};
dlg.cancel=function() {//取消时回调方法
alert("cancel!");
};
dlg.show();
} </script>
</body>
</html>
最终实现的效果与没有封装前的方法相同,在此就不重复截图了。
如果说嫌回调方法太麻烦了,不想每个父窗口中都写回调方法,只需要简单的打开对话框,并且把选中的值赋给指定的文本框即可,行不行?当然可以,为WebDialog增加一个refillInputId属性用于存入回填文本框的ID,如下:
//部份代码:
this.refillInputId = null;//回填文框ID
var _self = this;
this.show = function () {
var _features = "toolbar=no,menubar=no,scrollbars=auto,resizable=" + resizeable + ",location=no,status=no,depended=yes,width=" + width + ",height=" + height + ",left=" + _self.left + ",top=" + _self.top;
var winDialog = window.open(url, "WebDialogWindow", _features);
winDialog.dialog_complete = _self.complete;
winDialog.dialog_cancel = _self.cancel;
winDialog.refillInputId = _self.refillInputId;
}
然后在对话框内容页面中加入选择时回填值即可,如下:
row.onclick = function () {
var dialog_complete = window["dialog_complete"]; //获取回调方法
if (dialog_complete && typeof dialog_complete != "undefined") {
dialog_complete(getSelectValues(this));
}
var refillInputId = window["refillInputId"]; //回填文本框
if (typeof refillInputId == "string") {
window.opener.document.getElementById(refillInputId).value = getSelectValues(this)[0];
}
window.cancel = false;
window.close();
这样在父窗口中调用的时候,你若需要自行处理选择的结果,你可以指定回调方法,否则省略掉,直接指定回填文本框即可,如下:
document.getElementById("Button1").onclick = function () {
var dlg = new WebDialog("WinDialog2.html", 600, 500, "yes");
// dlg.complete=function(result){//完成时回调方法
// alert(result);
// };
// dlg.cancel=function() {//取消时回调方法
// alert("cancel!");
// };
dlg.refillInputId = "Text1";
dlg.show();
}
最终的效果如下:

好了,对话框研究得差不多了,我所说的方法不一定最好,但一定可以满足基本要求,关于文中一开头提到的除了交互,还有就是挂起,这个目前还没有想到办法,应该是浏览器限制的因素,因为如果有人恶意制作无数个挂起窗口,那电脑就会崩溃掉的,当然如果有更好的方法,欢迎交流,谢谢!
运用javascript的成员访问特性来实现通用版的兼容所有浏览器的打开对话框功能的更多相关文章
- JavaScript 数据属性和访问器属性
在JavaScript中对象被定义为"无序属性的集合,其属性可以包含基本值.对象或函数."通俗点讲,我们可以把对象理解为一组一组的名值对,其中值可以是数据或函数. 创建自定义对象通 ...
- 理解Javascript的动态语言特性
原文:理解Javascript的动态语言特性 理解Javascript的动态语言特性 Javascript是一种解释性语言,而并非编译性,它不能编译成二进制文件. 理解动态执行与闭包的概念 动态执行: ...
- java基础-类成员访问权限控制
一 前言 这篇文章是很基础的一文,没多大深度,对于开发人员必然是熟练于心.本篇文章的主题是为什么java要设置类成员访问级别?其原因也很简单,就是为了面向对象的封装特性:将类成员使用不同的访问级别控制 ...
- Java基础进阶:多态与接口重点摘要,类和接口,接口特点,接口详解,多态详解,多态中的成员访问特点,多态的好处和弊端,多态的转型,多态存在的问题,附重难点,代码实现源码,课堂笔记,课后扩展及答案
多态与接口重点摘要 接口特点: 接口用interface修饰 interface 接口名{} 类实现接口用implements表示 class 类名 implements接口名{} 接口不能实例化,可 ...
- Java基础详解 (一)Java的类成员访问权限修饰词(以及类访问权限)
在一个类的内部,其成员(包括成员变量和成员函数)能否被其他类所访问,取决于该成员的修饰词.Java的类成员访问权限修饰词有四类:private,无(默认情况下),protected和public.其权 ...
- Java 声明和访问控制(三) finalize方法 成员访问修饰符
finalize()方法是Object类的一个方法,在垃圾回收器执行的时候,会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源的回收,例如文件关闭等. 成员访问修饰符: 默认访问:包访问 ...
- JavaScript对象属性访问的两种方式
JavaScript对象属性访问的两种方式 object.attribute object["attribute"] 例如: var employees = [ { "f ...
- c/c++ 重载运算符 关系,下标,递增减,成员访问的重载
重载运算符 关系,下标,递增减,成员访问的重载 为了演示关系,下标,递增减,成员访问的重载,创建了下面2个类. 1,类StrBlob重载了关系,下标运算符 2,类StrBlobPtr重载了递增,抵减, ...
- 【转】C++对成员访问运算符->的重载
运算符->的重载比较特别,它只能是非静态的成员函数形式,而且没有参数. 1.如果返回值是一个原始指针,那么就将运算符的右操作数当作这个原始指针所指向类型的成员进行访问: 2.如果返回值是另一个类 ...
随机推荐
- C#的函数柯里化
前面说到了C#的泛型委托和闭包函数,在函数是程序设计里还有一个重要特征是柯里化... 柯里化就是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结 ...
- 使用ASP.NET Web API 2创建OData v4 终结点
开放数据协议(Open Data Protocol[简称OData])是用于Web的数据访问协议.OData提供了一种对数据集进行CRUD操作(Create,Read,Update,Delete)的统 ...
- 设计模式之美:Product Trader(操盘手)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Product Trader 的示例实现. 意图 使客户程序可以通过命名抽象超类和给定规约来创建对象. Product Trad ...
- Unity 热更新实例一、C#Light 和UI系统使用实例
接下来我会运用热更新的机制,逐步制作一些例子来阐释脚本系统如何和Unity结合. 脚本不限于使用C#Lite,但是C#Lite会有一些便利之处,请往下看. 结合机制也不限于这一种,但是C#Lite的设 ...
- python 对象
python 对象 在python中,对象就是为C中的结构体在堆上申请的一块内存,一般来说,对象是不能被静态初始化的,并且不能再栈空间上生存.本文主要对Python的基本数据类型做简单的介绍. PyO ...
- [每日电路图] 1、基于AT89C52单片机最小系统接口电路【转】
come from:http://www.21ic.com/dianlu/basis/interface/2015-04-21/621607.htm AT89C52是美国Atmel ...
- 使用Notepad++开发C#,一个复杂点的csscript脚本
使用Notepad++开发C#,一个复杂点的csscript脚本: //css_dir ..\..\lib; //css_ref Geb.Image.dll; //css_ref Geb.Image. ...
- 小议map排序问题
map有序无序?如果说有序, 这个顺序是怎么定义的? 安装put的先后顺序吗? 还是被put元素的内容呢? 经观察,应该是后者,跟put先后顺序无关, 跟内部实现有关(可能是hash排序的, 非大小排 ...
- 分割超大Redis数据库例子
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/124.html?1455853509 薄荷 App 上的伙伴功能大量使用了 ...
- Atititi.名字 姓名 name 起名naming spec 的构成结构规范v2 qc2.docx
Atititi.名字 姓名 name 起名naming spec 的构成结构规范v2 qc2.docx 1.1. 职业名 官职等 amir 阿米尔 放前面1 1.2. 本名1 1.3. 父名,祖名,一 ...