using window.open instead of window.showModalDialog
前言
在最近維護舊專案中,發現到處都有使用Javascript的window.showModalDialog來另開視窗給user操作
但是在Chrome、Filefox等瀏覽器已不再支援window.showModalDialog,只剩風中殘燭的IE支援它
大概在以前的時代,開發人員沒想到當時主流的IE到了今天會沒落,所以寫了window.showModalDialog這種只有IE支援的Javascript語法
實作
想把window.showModalDialog改寫成window.open前,得先瞭解兩者的輸入、回傳參數
↑劃紅線的地方為值得留意在window.open中無法使用的參數
1.在window.showModalDialog中,可以透過第二個參數,傳遞任何Javascript的值給子視窗,包含字串、數字、JS物件、陣列、DOM元素....
然後在子視窗透過window.dialogArguments即可取得父視窗傳遞的值。
2.在window.showModalDialog裡的子視窗關閉後,父視窗可以透過上述的returnVal(一個變數) 來接收子視窗的回傳值(可能是字串、JS物件、DOM元素等等)
但換成呼叫window.open,returnVal則變成回傳子視窗window物件(但IE會返回undefined)
先看window.showModalDialog範例寫法↓
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A.aspx.cs" Inherits="WebApplication1showmodal.A" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>父視窗 </title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="另開視窗" id="btnParent" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnParent").on("click", function () {
let parentParam = "我是老爸";//父視窗要傳給子視窗的值
let ret = window.showModalDialog("B.aspx", parentParam, "dialogWidth=500px;dialogHeight=500px");
alert("子視窗回傳值:" + ret);
});
});
</script>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="B.aspx.cs" Inherits="WebApplication1showmodal.B" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>子視窗</title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="關閉子視窗" id="btnSub" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
//取得父視窗傳遞的值
let parentParam = window.dialogArguments;
alert(parentParam);
$("#btnSub").on("click", function () {
window.returnValue = "我是子視窗的回傳值";
window.close();
});
});
</script>
</form>
</body>
</html>
或把父視窗的DOM元素傳給子視窗,讓子視窗操作↓
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A.aspx.cs" Inherits="WebApplication1showmodal.A" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>父視窗 </title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="另開視窗" id="btnParent" />
<!--父視窗的DOM元素-->
<div id="divParent"></div>
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnParent").on("click", function () {
let ret = window.showModalDialog("B.aspx", document.getElementById("divParent"), "dialogWidth=500px;dialogHeight=500px");
alert("子視窗回傳值:" + ret);
});
});
</script>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="B.aspx.cs" Inherits="WebApplication1showmodal.B" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>子視窗</title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="關閉子視窗" id="btnSub" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
//取得父視窗傳遞的DOM元素
let divParentDom = window.dialogArguments;
divParentDom.innerHTML = "被子視窗操作了~";
$("#btnSub").on("click", function () {
window.returnValue = "我是子視窗的回傳值";
window.close();//關閉子視窗
});
});
</script>
</form>
</body>
</html>
再來看改寫成window.open的幾種方式↓
1.從子視窗(B.aspx)回傳值給父視窗(A.aspx)
在子視窗透過window.opener來存取父視窗並給予值
↓子視窗操作父視窗DOM元素範例
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A.aspx.cs" Inherits="WebApplication1showmodal.A" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>父視窗 </title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="另開視窗" id="btnParent" />
<!--父視窗的DOM元素-->
<div id="divParent"></div>
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnParent").on("click", function () {
//另開popup window
window.open("B.aspx", "_blank", "width=500px,height=500px,scrollbars=1");//scrollbars=1,給IE看的
});
});
</script>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="B.aspx.cs" Inherits="WebApplication1showmodal.B" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>子視窗</title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="關閉子視窗" id="btnSub" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnSub").on("click", function () {
//操作父視窗的DOM元素
window.opener.document.getElementById("divParent").innerHTML = "兒子給的值";
window.close();//關閉子視窗
});
});
</script>
</form>
</body>
</html>
↓子視窗把值傳給父視窗的function去執行
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A.aspx.cs" Inherits="WebApplication1showmodal.A" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>父視窗 </title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="另開視窗" id="btnParent" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnParent").on("click", function () {
//另開popup window
window.open("B.aspx", "_blank", "width=500px,height=500px,scrollbars=1");//scrollbars=1給IE看的
});
});
//注意父視窗要宣告成global function
function windowOpenReturnFunc(ret) {
//ret為子視窗回傳的值
alert("子視窗回傳的值:"+ret);
}
</script>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="B.aspx.cs" Inherits="WebApplication1showmodal.B" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>子視窗</title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="關閉子視窗" id="btnSub" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnSub").on("click", function () {
let subParam = "兒子的值";
window.opener.windowOpenReturnFunc(subParam);//執行父視窗的function
window.close();//關閉子視窗
});
});
</script>
</form>
</body>
</html>
2.從父視窗(A.aspx)傳值給子視窗(B.aspx)
雖然有人提出使用QueryString來實作,但我覺得QueryString是給Server端讀取,就不介紹此種辦法XD
有興趣的人自行看文章:window.open()改写showModalDialog()参数传递总结
第一種方法:子視窗透過window.opener來取得父視窗的值
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A.aspx.cs" Inherits="WebApplication1showmodal.A" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>父視窗 </title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="另開視窗" id="btnParent" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
//注意要用var宣告變數並且放在global區域,才會變成window的屬性
var parentParam = "我是老爸";
$(function () {
$("#btnParent").on("click", function () {
//另開popup window
window.open("B.aspx", "_blank", "width=500px,height=500px,scrollbars=1");//scrollbars=1給IE看的
});
});
</script>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="B.aspx.cs" Inherits="WebApplication1showmodal.B" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>子視窗</title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="關閉子視窗" id="btnSub" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
//取得父視窗傳遞的值
alert(window.opener.parentParam);
$("#btnSub").on("click", function () {
window.close();//關閉子視窗
});
});
</script>
</form>
</body>
</html>
父視窗要傳遞DOM元素給子視窗的情況↓
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A.aspx.cs" Inherits="WebApplication1showmodal.A" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>父視窗 </title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="另開視窗" id="btnParent" />
<!--父視窗的DOM元素-->
<div id="divParent"></div>
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnParent").on("click", function () {
//另開popup window
window.open("B.aspx", "_blank", "width=500px,height=500px,scrollbars=1");//scrollbars=1給IE看的
});
});
</script>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="B.aspx.cs" Inherits="WebApplication1showmodal.B" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>子視窗</title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="關閉子視窗" id="btnSub" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
//取得父視窗的DOM
window.opener.document.getElementById("divParent").innerHTML = "被子視窗操作了~"
$("#btnSub").on("click", function () {
window.close();//關閉子視窗
});
});
</script>
</form>
</body>
</html>
第二種:父視窗呼叫window.open後會馬上回傳一個子視窗物件,父視窗再對那個子視窗物件寫值,即可讓子視窗讀得到值
※不過此種方法在IE反而回傳undefined,所以不推
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="A.aspx.cs" Inherits="WebApplication1showmodal.A" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>父視窗 </title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="另開視窗" id="btnParent" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnParent").on("click", function () {
//另開popup window
let subWindow = window.open("B.aspx", "_blank", "width=500px,height=500px,scrollbars=1");//scrollbars=1給IE看的
subWindow.myParam = "從老爸給的值";
});
});
</script>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="B.aspx.cs" Inherits="WebApplication1showmodal.B" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>子視窗</title>
</head>
<body>
<form id="form1" runat="server">
<input type="button" value="關閉子視窗" id="btnSub" />
<!--引用jQuery-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function () {
//取得父視窗給的值
alert(window.myParam);
$("#btnSub").on("click", function () {
window.close();//關閉子視窗
});
});
</script>
</form>
</body>
</html>
剩下window.showModalDialog的第三個參數options 和 window.open的第三個參數 features
這兩者都是控制子視窗的特性(例如視窗大小、要不要捲軸、工具列、狀態列、選單列要不要出現等等),留意window.showModalDialog使用;分號分隔,window.open使用,逗號分隔
window.showModalDialog使用dialogWidth、dialogHeight,而window.open改使用width、height即可。
其他都大同小異,請自行參考「Window open() Method from w3schools.com 」
結論
總之在window.open情況下,一切都在子視窗使用window.opener來存取父視窗即可,這樣很好記XD