文章出處

打開網頁對話框,一般有三種方法: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();
        }

最終的效果如下:

好了,對話框研究得差不多了,我所說的方法不一定最好,但一定可以滿足基本要求,關于文中一開頭提到的除了交互,還有就是掛起,這個目前還沒有想到辦法,應該是瀏覽器限制的因素,因為如果有人惡意制作無數個掛起窗口,那電腦就會崩潰掉的,當然如果有更好的方法,歡迎交流,謝謝!


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()