WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

ModalPopup と Firefox の問題

by WebSurfer 2014年11月6日 16:46

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

遷移前に一瞬表示された 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>

Tags: , ,

AJAX

ModalPopup のドラッグ可能範囲

by WebSurfer 2014年4月5日 15:47

Ajax Control Toolkit の ModalPopupExtender をドラッグできない(正確には、ドラッグはできるが元の位置に戻ってしまう)ケースがあります。その理由と対処法を書きます。

ModalPopup のドラッグ可能範囲

検証用に、上の画像のような 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>

Tags: ,

AJAX

CalendarExtender の日付の表示

by WebSurfer 2013年7月26日 11:48

Ajax Control Toolkit の CalendarExtender で日本語形式の日付を表示するにはどうすればよいかという話です。

まず、ToolkitScriptManager と CalendarExtender の設定がデフォルト状態(Visual Studio でドラッグ&ドロップしただけの状態)の場合は下の画像のような表示になります。

デフォルトでのカレンダーの表示

カルチャは ja-JP と認識されていますが、(1) TextBox に入力される日付の形式が M/d/yyyy(米国式)、(2) カレンダーの曜日が英語、(3) カレンダーのタイトルと今日の日付の表示が米国式になってしまいます。

特に問題になるのが「(1) TextBox に入力される日付の形式が M/d/yyyy」です。M/d/yyyy 形式では、CompareValidator による検証や、サーバー側での DateTime 型への変換の際などにパースがうまくいかず、期待した結果にならないということがあります。

カルチャが ja-JP の時に TextBox に入力される日付が yyyy/MM/dd 形式となるようにするには、ToolkitScriptManager の EnableScriptGlobalization プロパティを true に設定してやります。その結果が下の画像です。

EnableScriptGlobalization を true に設定

MSDN ライブラリによると、"EnableScriptGlobalization プロパティを true に設定すると、グローバル化された JavaScript 関数がカルチャ固有の情報を表示します" とのことです。

カルチャは、ブラウザ、サーバーコード、または Web サイトの構成ファイルで設定できます。例えば、@ Page ディレクティブで Culture, UICulture を "auto" に設定した場合、ASP.NET がリクエスト情報に含まれる Accept-Language ヘッダの内容から判断して、自動的にカルチャを特定してくれます。

なので、EnableScriptGlobalization プロパティが true に設定してあると、「(1) TextBox に入力される日付の形式」は、カルチャが ja-JP の場合は yyyy/MM/dd 形式、en-US の場合は M/d/yyyy となります。

「(2) カレンダーの曜日」も、カルチャが ja-JP の場合は日本語、en-US の場合は英語で表示されます。下の画像はカルチャが en-US の場合のものです。カルチャが ja-JP の場合のもの(上の画像)と比較してみてください。

カルチャが en-US の場合

なお、TextBox に入力される日付の形式は、CalendarExtender コントロールの Format プロパティで明示的に設定できます。当然、EnableScriptGlobalization プロパティの設定より、こちらの方が優先されます。なので、カルチャに依存させないで固定的に日付の形式を設定したい場合は Format="yyyy/MM/dd" のようにすることができます。

以上の対応で、上記の問題の (1) と (2) は解決できます。しかし、「(3) カレンダーのタイトルと今日の日付の表示」は依然として米国形式のままです。これを解決するには、CalendarExtender コントロールの DaysModeTitleFormat, TodaysDateFormat プロパティで書式を指定してやります。

下の画像は、DaysModeTitleFormat="yyyy年M月" TodaysDateFormat="yyyy年M月d日" とした時のものです。

タイトルと今日の日付を日本語形式に

ただし、Format, DaysModeTitleFormat, TodaysDateFormat プロパティで書式を指定してしまうのは、グローバル化と逆行することになる(他のカルチャに対応できなくなる)ので、そうすることが良いのかどうかはよく考えた方がよさそうです。

参考に、上の画像のカレンダーを表示したコードを載せておきます。

<%@ Page Language="C#" Culture="auto" UICulture="auto" %>
<%@ Import Namespace="System.Threading" %>

<%@ 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">

  protected void Page_Load(object sender, EventArgs e)
  {
    Label1.Text = "CurrentCulture: " +
        Thread.CurrentThread.CurrentCulture.ToString();
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
</head>
<body>
  <form id="form1" runat="server">
  <asp:ToolkitScriptManager ID="ToolkitScriptManager1" 
    runat="server" 
    EnableScriptGlobalization="True">
  </asp:ToolkitScriptManager>
  <div>
    <asp:Label ID="Label1" runat="server">
    </asp:Label>
    <br />
    <asp:TextBox ID="TextBox1" runat="server">
    </asp:TextBox>
    <asp:CalendarExtender ID="TextBox1_CalendarExtender" 
      runat="server" 
      Enabled="True" 
      TargetControlID="TextBox1"            
      DaysModeTitleFormat="yyyy年M月" 
      TodaysDateFormat="yyyy年M月d日"
      Format="yyyy/MM/dd" >
    </asp:CalendarExtender>
  </div>
  </form>
</body>
</html>

Tags: ,

AJAX

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2017年10月  >>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar