by WebSurfer
6. November 2014 16:46
Ajax Control Toolkit の ModalPopup を Firefox で表示した場合、一旦表示して消した ModalPopup が、別ページに遷移する前に一瞬表示されてしまう問題とその対処方法の紹介です。

上の画像は、[Show ModalPopup]ボタンをクリック ⇒ ModalPopup が表示される ⇒ ModalPopup 上の[Cancel]ボタンクリック ⇒ ModalPopup が非表示になる ⇒[ブログのページへ]のハイパーリンクをクリックした時、遷移先のページからの応答を待っている時のものです。応答を待っている間、本来表示されてはいけない ModalPopup が表示されてしまっています。
この問題は、ブラウザが Firefox の場合で(現時点での最新バージョン 33.0.2 で確認)、かつ、ModalPopup の DropShadow プロパティが true に設定された場合に発生します。
そのメカニズムは以下の通りです。
DropShadow="true" となっていると、ModalPopup の PopupControlID プロパティに設定した Panel の外側が div 要素で囲われ、その style 属性に "display: none;" が追加 / 削除さることによって ModalPopup の非表示 / 表示が切り替えられます。
たとえ Panel の Style プロパティに "display: none;" を設定しておいても、一旦 ModalPopup を表示するとその設定は削除され、その後 ModalPopup を非表示にしても Panel の "display: none;" は復活しません。(その外側の div 要素に動的に追加される "display: none;" によって非表示になる)
Firefox の場合、ハイパーリンクがクリックされて、遷移先のページを要求に行くとき、Panel の外側の div 要素そのものがなくなるか、その div 要素に設定されている "display: none;" の効果がなくなり、要求を出してから応答が帰ってくるまで Panel が表示されてしまうという感じです。(推測です。実際にどうなっているのかは不明)
ハイパーリンクでなくリダイレクトで遷移しても同じで、GET 要求を出してから応答が戻ってくるまで Panel は表示されてしまいます。
なお、この問題は DropShadow="false" になっていると起こりません。なぜなら、その場合は Panel は div 要素で囲われることはなく、Panel に直接 "display: none;" が追加 / 削除され ModalPopup の非表示 / 表示が切り替えられるからです。
対症療法的ですが、ハイパーリンクの onclick イベントで、ModalPopup (Panel) の style 属性に "display:none;" を設定することでこの問題を回避できます。
そのサンプルコードを以下に書いておきます。また、実際に動かして試すことができるよう 実験室 にアップしました。興味のある方は試してみてください。
<%@ Page Language="C#" %>
<%@ Register Assembly="AjaxControlToolkit"
Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>ModalPopup と Firefox</title>
<style type="text/css">
.modalBackground {
background-color: Gray;
filter: alpha(opacity=70);
opacity: 0.7;
}
.modalPopup {
height: 100px;
width: 250px;
background-color: White;
border: solid 2px black;
}
</style>
<script type="text/javascript">
//<![CDATA[
function setDisplayNone() {
var ele = document.getElementById('<%=Panel1.ClientID%>');
ele.setAttribute('style', 'display: none;');
}
//]]>
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ToolkitScriptManager ID="ToolkitScriptManager1"
runat="server">
</asp:ToolkitScriptManager>
<h1>ModalPopup と Firefox</h1>
<asp:Button ID="Button1"
runat="server"
Text="Show ModalPopup"/>
<br />
<asp:HyperLink ID="HyperLink1"
runat="server"
NavigateUrl="~/Default.aspx">
ブログのページへ
</asp:HyperLink>
<br />
<asp:HyperLink ID="HyperLink2"
runat="server"
NavigateUrl="~/Default.aspx"
onclick="setDisplayNone();">
ブログのページへ(display:none 設定)
</asp:HyperLink>
<asp:ModalPopupExtender ID="ModalPopupExtender1"
runat="server"
TargetControlID="Button1"
PopupControlID="Panel1"
BackgroundCssClass="modalBackground"
DropShadow="True"
CancelControlID="CancelButton">
</asp:ModalPopupExtender>
<asp:Panel ID="Panel1"
runat="server"
Style="display: none"
CssClass="modalPopup">
<p style="text-align: center;">ModalPopup</p>
<p style="text-align: center;">
<asp:Button ID="CancelButton"
runat="server" Text="Cancel" />
</p>
</asp:Panel>
</form>
</body>
</html>