Web 應用常需模態對話框阻擋背景操作。window.showModalDialog() 侷限於 IE 且無法自訂內容。本文實作跨瀏覽器(IE/Firefox/Chrome)的半透明遮罩層 + 自訂內容彈出層,支援委托回呼更新父頁面。
div 遮罩層:position:fixed; top:0; left:0; width:100%; height:100%; background:#000; opacity:0.5; z-index:9999;position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); z-index:10000;window.opener 或 postMessage 通知<%@ Page Language="C#" %>
<!DOCTYPE html>
<html>
<head>
<title>父頁面</title>
<style>
.modal-overlay {
display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: #000; opacity: 0.5; z-index: 9999;
}
.modal-dialog {
display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
background: #fff; padding: 20px; border-radius: 4px; box-shadow: 0 2px 10px rgba(0,0,0,0.3);
z-index: 10000; min-width: 400px; max-width: 80%; max-height: 80vh; overflow: auto;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<h1>主頁面內容</h1>
<button type="button" onclick="openModal('Child.aspx', 600, 400)">開啟彈出視窗</button>
<div id="result">等待子頁面回傳...</div>
<!-- 遮罩與對話框容器 -->
<div id="overlay" class="modal-overlay"></div>
<div id="dialog" class="modal-dialog">
<iframe id="modalFrame" src="about:blank" frameborder="0" style="width:100%; height:100%; min-height:300px;"></iframe>
</div>
</form>
<script>
var modalCallback = null; // 儲存回呼函數
function openModal(url, width, height) {
var overlay = document.getElementById('overlay');
var dialog = document.getElementById('dialog');
var frame = document.getElementById('modalFrame');
frame.src = url;
dialog.style.width = width + 'px';
dialog.style.height = height + 'px';
overlay.style.display = 'block';
dialog.style.display = 'block';
// ESC 關閉
document.onkeydown = function(e) {
if (e.key === 'Escape') closeModal();
};
}
function closeModal() {
document.getElementById('overlay').style.display = 'none';
document.getElementById('dialog').style.display = 'none';
document.getElementById('modalFrame').src = 'about:blank';
document.onkeydown = null;
}
// 供子頁面呼叫的回呼註冊
window.registerModalCallback = function(callback) {
modalCallback = callback;
};
// 子頁面呼叫此函數傳回資料
window.modalReturn = function(data) {
if (modalCallback) modalCallback(data);
closeModal();
};
</script>
</body>
</html>
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html>
<head>
<title>彈出內容頁面</title>
</head>
<body>
<h2>自訂彈出內容</h2>
<p>這裡可以放置任何 ASP.NET 控制項、表單、GridView 等</p>
<asp:Button ID="btnConfirm" runat="server" Text="確定" OnClick="btnConfirm_Click" />
<asp:Button ID="btnCancel" runat="server" Text="取消" OnClientClick="parent.closeModal(); return false;" />
</body>
</html>
protected void Page_Load(object sender, EventArgs e) {
// 頁面載入時向父頁面註冊回呼
ClientScript.RegisterStartupScript(this.GetType(), "registerCallback",
"parent.registerModalCallback(function(data) { alert('父頁面收到: ' + data); });", true);
}
protected void btnConfirm_Click(object sender, EventArgs e) {
// 執行伺服端邏輯...
string resultData = "用戶確認操作 @" + DateTime.Now;
// 呼叫父頁面 modalReturn 關閉並傳值
ClientScript.RegisterStartupScript(this.GetType(), "returnData",
"parent.modalReturn('" + resultData.Replace("'", "\\'") + "');", true);
}
// 父頁面
window.addEventListener('message', function(e) {
if (e.origin !== 'https://trusted.domain') return; // 驗證來源
if (e.data.type === 'modalReturn') {
modalCallback(e.data.payload);
closeModal();
}
});
// 子頁面
function sendToParent(data) {
window.parent.postMessage({ type: 'modalReturn', payload: data }, 'https://parent.domain');
}
function openAjaxModal(url) {
$.get(url, function(html) {
$('#dialog').html(html).show();
$('#overlay').show();
});
}
// 子頁面表單提交
$('#childForm').submit(function(e) {
e.preventDefault();
$.post(this.action, $(this).serialize(), function(result) {
parent.modalReturn(result);
});
});
@media (max-width: 480px) { .modal-dialog { width: 95%; left: 2.5%; transform: none; } }transition: opacity 0.2s, transform 0.2s; 配合 .show { opacity: 1; transform: translate(-50%, -50%) scale(1); }role="dialog" aria-modal="true" aria-labelledby="dialogTitle"