• 运用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();
            }
    

    最终的效果如下:

    好了,对话框研究得差不多了,我所说的方法不一定最好,但一定可以满足基本要求,关于文中一开头提到的除了交互,还有就是挂起,这个目前还没有想到办法,应该是浏览器限制的因素,因为如果有人恶意制作无数个挂起窗口,那电脑就会崩溃掉的,当然如果有更好的方法,欢迎交流,谢谢!

  • 相关阅读:
    MySQL自定义函数 1418报错
    MySQL存储过程查询
    MySQL存储过程---游标
    MySQL存储过程---流程控制(循环)
    MySQL存储过程---流程控制(分支)
    设计模式——单例模式
    准备写一个 四川票务网的 检测票自动买汽车票功能,结果登录不上悲伤,继续研究
    python批量下载微信好友头像,微信头像批量下载
    arduino 522样本中文注释
    zabbix服务的部署
  • 原文地址:https://www.cnblogs.com/zuowj/p/4760704.html
Copyright © 2020-2023  润新知