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>
by WebSurfer
5. April 2014 15:47
Ajax Control Toolkit の ModalPopupExtender をドラッグできない(正確には、ドラッグはできるが元の位置に戻ってしまう)ケースがあります。その理由と対処法を書きます。

検証用に、上の画像のような Button コントロールを一つだけ配置したような aspx ページを作ったとします。
Button クリックで ModalPopup が現れ、デフォルトではウィンドウの中央に表示されるはずです。
これをマウスでクリックして任意の位置にドラッグすることができますが、離すと元の位置に戻ってしまいます。
その理由は、ModalPopup のドラッグが有効なのは body の中だけなので、ボタン一つだけというように body のサイズが極端に小さくなる場合、ドラッグしても元の位置に戻ってしまうということになります。
通常はボタン一つだけというようなページを作ることはないので、このような問題に遭遇することはないかもしれませんが、もし body のサイズが極端に小さくなる場合があれば、CSS で body のサイズを指定してやることで問題を回避できます。
上の画像のサンプルは、実際に動かして試すことができるよう 実験室 にアップしましたが、これは body に height: 300px; width: 600px; というスタイルを適用しています。
height: 300px; width: 600px; の範囲(赤い線で囲った部分)内だけでドラッグして移動できる(範囲外にドラッグした場合は元の位置に戻ってしまう)ことが分かりますので、興味のある方は試してみてください。
サンプルのコードは以下の通りです。
<%@ 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 runat="server">
<title>WebSurfer's Page - 実験室</title>
<style type="text/css">
.modalBackground {
background-color: Gray;
filter: alpha(opacity=70);
opacity: 0.7;
}
.modalPopup {
height: 150px;
width: 400px;
background-color: White;
}
.modalDraggableArea {
cursor: move;
background-color: #DDDDDD;
border: solid 1px Gray;
}
body {
height: 300px;
width: 600px;
border: 1px solid red;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:ToolkitScriptManager ID="Manager1" runat="server">
</asp:ToolkitScriptManager>
<asp:ModalPopupExtender ID="ModalPopupExtender1"
runat="server"
TargetControlID="Button1"
PopupControlID="Panel1"
PopupDragHandleControlID="Panel2"
BackgroundCssClass="modalBackground"
OkControlID="Button2"
CancelControlID="Button3">
</asp:ModalPopupExtender>
<asp:Button ID="Button1"
runat="server" Text="ModalPopup 表示" />
<asp:Panel ID="Panel1"
runat="server"
CssClass="modalPopup">
<asp:Panel ID="Panel2"
runat="server"
CssClass="modalDraggableArea">
<p style="text-align: center;">
********* ここをつかんでドラッグ *********
</p>
</asp:Panel>
<p style="text-align: center;">ModalPopup</p>
<p style="text-align: center;">
<asp:Button ID="Button2" runat="server" Text="OK" />
<asp:Button ID="Button3" runat="server" Text="Cancel" />
</p>
</asp:Panel>
</form>
</body>
</html>
by WebSurfer
27. January 2013 16:52
Ajax Control Toolkit の ModalPopup 内の iframe に別ページを表示し、その別ページに配置されているボタンをクリックして ModalPopup を非表示にする方法の紹介です。
ModalPopup はクライアントスクリプトで非表示にできます。それには、Modalpopup をページに配置するとダウンロードされるクライアントスクリプトに定義されている hide メソッドを使います。
従って、iframe に表示するページの適当な DOM に click イベントのリスナーを仕掛けて、それで hide メソッドを起動すれば ModalPopup を非表示にできます。
ただし、iframe に表示するページは親ページと同じドメインのものでないと DOM が取得できないので注意してください(クロスサイトスクリプト対策だそうです)。
そのサンプルコードを以下に書いておきます。また、実際に動かして試すことができるよう 実験室 にアップしました。興味のある方は試してみてください。
親ページ
<%@ 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 runat="server">
<title></title>
<script type="text/javascript">
//<![CDATA[
// iframe 内の document オブジェクトを取得。
// contentWindow は IE 用。
// contentDocument は Firefox 用。
function iframeRef(frameRef) {
return frameRef.contentWindow ?
frameRef.contentWindow.document :
frameRef.contentDocument;
}
function hideModalPopup() {
var modalPopup =
$find('programmaticModalPopupBehavior');
modalPopup.hide();
}
function showModalPopup() {
var ifm = iframeRef($get('iframe1'));
var btn = ifm.getElementById('hideButton');
// hide するとリスナーも解除されてしまうので、
// (btn.click が null になることで確認できる)
// ModalPopup を表示するたびリスナーをアタッチ
// する必要がある。
if (btn.onclick == null) {
if (window.addEventListener) {
btn.addEventListener('click',
hideModalPopup,
false);
} else if (window.attachEvent) {
btn.attachEvent('onclick',
hideModalPopup);
}
}
var modalPopup =
$find('programmaticModalPopupBehavior');
modalPopup.show();
}
//]]>
</script>
<style type="text/css">
/*Modal Popup*/
.modalBackground
{
background-color: Gray;
filter: alpha(opacity=70);
opacity: 0.7;
}
.popup
{
background-color: White;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:ToolkitScriptManager
ID="ToolkitScriptManager1"
runat="server">
</asp:ToolkitScriptManager>
<h1>ModalPopup Test</h1>
<asp:Button ID="DummyButton"
runat="server"
style="display: none;" />
<input type="button"
value="Show ModalPopup"
onclick="showModalPopup();" />
<asp:Panel
ID="Panel1"
runat="server"
CssClass="popup">
<iframe
id="iframe1"
src="190-PageIniframe.aspx">
</iframe>
</asp:Panel>
<asp:ModalPopupExtender
ID="ModalPopupExtender1"
runat="server"
TargetControlID="DummyButton"
BehaviorID="programmaticModalPopupBehavior"
BackgroundCssClass="modalBackground"
PopupControlID="Panel1">
</asp:ModalPopupExtender>
</form>
</body>
</html>
iframe に表示するページ
<%@ Page Language="C#" %>
<!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 runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Page in iframe</h1>
<input type="button"
id="hideButton"
value="Hide ModalPopup" />
</div>
</form>
</body>
</html>