CodeZine(コードジン)

特集ページ一覧

マウスでポイントされたデータ グリッド行をハイライト表示する簡単な方法

JavascriptによるDataGridの見た目改善

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2005/04/01 00:00

DataGridの見た目をもっと良くする1つが、現在Yahoo! MailやHotmailなどのサイトで利用されているのが、マウスでポイントされた行を自動的にハイライト表示するというテクニックだ。

はじめに

 DataGridコントロールはデータを表示するための非常に強力で汎用的なコントロールであり、ASP.NET開発者にもお馴染みである(DataGridの扱いに慣れていない人は、まずScott Mitchellの記事「An Extensive Examination of the DataGrid Control」を読むことをお勧めする)。私はこれまで多くのプロジェクトでDataGridコントロールを使用し、DataGridの見た目をもっと良くしようとしてきた。そんな中の1つで現在Yahoo! MailやHotmailなどのサイトで利用されているのが、マウスでポイントされた行を自動的にハイライト表示するというテクニックだ。つまり、エンドユーザーがDataGridのデータ上にマウスを持ってきたときに、マウスが現在置かれているDataGrid行の背景は他の行とは違う色になるわけだ。

 DataGridコントロールを拡張してこの機能を追加する方法については、既に数多くの記事が書かれているので、中にはマウスの動きに応じて行をハイライト表示する方法を既に知っている人も多いかもしれない。この方法の一例が、Scottの「Creating a Row-Selectable DataGrid Control」だ。この記事やその他の多くの記事で取り上げているのが、DataGridを拡張するカスタムASP.NETサーバーコントロールを作成するというソリューションで、カスタムサーバーコントロールから、行をハイライト表示するためのクライアントサイドスクリプトを発行するという形式だ(特に、<tr>HTML要素にはonmouseover属性とonmouseout属性が追加されている)。

 カスタムサーバーコントロールを作成する方法は、簡単だし役立つ情報も多い。しかし私は、もっと単純なアプローチで、標準のDataGridコントロールをいっさい変更せずに動作するようなものを作りたいと考えた。これを実現する方法は、AListApartのWebサイトで、CSSだけでドロップダウンメニューを作成する方法についての記事を読んだ後で思いついた。このコンセプトは単純で、「CSSのhoverスタイルを利用して、さまざまな階層形式のリストの表示/非表示を切り替える」というものだった。私はその単純さと斬新なコンセプトに心ひかれ、これに少し手を加えれば、DataGridの行もハイライト表示できるのではないかと思いついた。

 私がどのようにクライアントサイドCSSのhover機能を利用して、標準のDataGridに行のハイライト表示機能を追加したかについて説明する。完成するまでの過程でいくつかの問題があったが、その問題と回避方法についても説明する。続きを読む前に、まず実際のデモを見ていただきたい。

はじめの一歩:DataGridにデータを表示する

 当然ながら、DataGrid内の行をハイライト表示するためには、操作対象となるDataGridが必要である。以下は、データをDataGridにバインドするサンプルとして作成したページのコードで、上記のデモページは、このページに機能を追加して完成させたものである。

<%@ Page Language = "C#" %>
<%@ Import Namespace = "System.Data" %>

<html>
  <head>
    <title>DataGrid Sample</title>
    
    <script runat = "server">
      private void Page_Load(object sender, EventArgs e)
      {
        if (!Page.IsPostBack)
          BindGrid();
      }
      
      private void BindGrid()
      {
        DataTable table = new DataTable("Users");
        table.Columns.Add("firstName");
        table.Columns.Add("lastName");
        table.Columns.Add("emailAddress");
        
        AddRow(table, "Bugs", "Bunny", "bbunny@wb.com");
        AddRow(table, "Mickey", "Mouse", "mmouse@disney.com");
        AddRow(table, "Donald", "Duck", "dduck@disney.com");
        AddRow(table, "Dan", "Marino", "dmarino@dolphins.com");
        AddRow(table, "Steve", "Stchur", "sstchur@yahoo.com");
        
        myGrid.DataSource = new DataView(table);
        myGrid.DataBind();
      }
      
      private void AddRow(DataTable table, string firstName,
                          string lastName, string email)
      {
        DataRow row = table.NewRow();
        row["firstName"] = firstName;
        row["lastName"] = lastName;
        row["emailAddress"] = email;
        table.Rows.Add(row);
      }
    </script>
  </head>
    
  <body>
    <asp:DataGrid id = "myGrid"
                  CellPadding = "5"
                  AutoGenerateColumns = "false"
                  Font-Name = "verdana"
                  Font-Size = "10pt"
                  runat = "server">
                  
      <HeaderStyle BackColor = "#336699"
                 ForeColor = "#ffffff" Font-Bold = "true" />
      <AlternatingItemStyle BackColor = "#eeeeee" />
                  
      <Columns>
        <asp:BoundColumn HeaderText = "First Name"
                            DataField = "firstName" />
        <asp:BoundColumn HeaderText = "Last Name"
                            DataField = "lastName" />
        <asp:BoundColumn HeaderText = "Email"
                            DataField = "emailAddress" />
      </Columns>
    </asp:DataGrid>
  </body>
</html>

 実際のデモを表示

 この時点のDataGridは、ハードコーディングされたデータにバインドされた、ごく単純なものだ。実際のデモを見てもわかるとおり、この例ではHeaderStyleで見出し行の背景色を落ち着いた青に設定し、AlternatingItemStyleプロパティで行の背景色を1行おきに明るい灰色に設定している。

最初の実験

 行を"ハイライト表示可能"にするために、まず単純に、ページ上のすべてのTR(table row)要素に次のようなCSSスタイルを追加してみた。

<style type = "text/css">
   tr:hover { background-color: #ffccff; }
</style>

 DataGrid内の各行は<tr>要素で表現されているので、このCSSを適用すれば、ユーザーがDataGridの行をマウスでポイントしたときに行の背景がピンク(#ffccff)になるだろうと考えたのだ。この方法をまずWebブラウザのFirefoxでテストしたところ、マウスでポイントするとDataGridの行がハイライト表示された。しかし問題は、見出し行も含めた、すべてのDataGridの行がハイライト表示されることだった。また、このCSSをInternet Explorer(IE)でテストすると、まったくハイライト表示されないことがわかった。

Internet Explorerでも動作するように修正

 調べた結果、IEはハイパーリンク(<a>タグ)にのみ:hoverをサポートしていることがわかった。幸いこの問題は、一部のJavaScriptとCSSスタイルシートに少し手を加えるだけで簡単に解決できた。具体的には、trのレベルにoverというクラスを定義し、:hoverと同じCSSを適用したのだ。その結果、CSSスタイルシートは次のようになった。

<style type = "text/css">
   tr:hover, tr.over { background-color: #ffccff; }
</style>  

 当然ながら、この変更だけでは問題は解決できていない。まだ他に、DataGridの<tr>要素をoverクラスに関連付けるという作業が残っている。行がマウスでポイントされたときに各<tr>要素のclass属性をoverに設定するためには、ちょっとしたJavaScriptを記述する必要がある。

<script language = "javascript">
  startHighlight = function()
  {
    if (document.all && document.getElementById)
    {  
      navRoot = document.getElementById(ID of DataGrid);
      
      // Get a reference to the TBODY element
      tbody = navRoot.childNodes[0];
      
      for (i = 0; i < tbody.childNodes.length; i++)
      {
        node = tbody.childNodes[i];
        if (node.nodeName == "TR")
        {
          node.onmouseover=function()
          {
            this.className = "over";
          }
          
          node.onmouseout=function()
          {
            this.className = this.className.replace("over", "");
          }
        }
      }
    }
  }
  
  window.onload = startHighlight;
</script>

 実際のデモを表示

 上記のスクリプトでは、DataGridのすべての子要素について検索を開始するようブラウザに指示している(注:ID of DataGridの部分は、DataGridに基づいて描画される<table>コントロールのクライアントサイドIDに置き換える必要がある。DataGridがユーザーコントロール、別のDataGrid、またはその他の名前付きコンテナ内に置かれていない場合、このIDはDataGrid WebコントロールのIDプロパティと等しくなる)。このスクリプトは、ノード名がTRのDataGrid要素を見つけると、その要素にonmouseover関数とonmouseout関数を追加する。これらの関数を追加する目的は、単純に<tr>がマウスでポイントされているかどうかに応じて、そのCSSクラスをoverまたはnothingに設定することた。

 このコードをIEでテストすると、奇妙な点に気付く。表内の行が1行おきにしかハイライト表示されないのだ。これは、AlternatingItemStyleによって、行の背景色を1行おきに明るい灰色(#eeeeee)にするようDataGridに指示しているからである。ASP.NETはこのスタイルをインラインで描画するため、このスタイルの方がJavaScriptで指定したCSSクラスよりも優先される。事実、ItemStyleを同様に指定した場合には、まったく同じ理由で行が1つもハイライト表示されなかった。

 この問題を解決するにはどうしたらいいだろうか。答えは簡単だ。TRがマウスでポイントされているときに、すべてのTD要素(TRの子要素)が、それにアタッチされたCSSクラスoverを受け取るようにすればよい。TD要素に設定されたスタイルは親(TR要素)のスタイルよりも優先されるので、この方法で正しく表示される。

 修正後のCSSは次のようになる。

<style type = "text/css">
   tr:hover, tr.over td { background-color: #ffccff; }
</style> 

ヘッダー行のハイライト表示の抑制

 IE固有の問題はこれで解決した。しかし、まだ見出し行がハイライト表示されてしまう問題が残っている。さてどうしたものか。気付いた方もいるかもしれないが、IE対応のJavaScriptのコードでは、テーブル(DataGrid)内のすべての行を1つずつループ処理している。そこで、次のように行インデックスを0ではなく1から開始して、1行目(ヘッダー行)をスキップすることでこの問題は簡単に解決する。

// In the startHighlight function...
for (i = 1; i < tbody.childNodes.length; i++)
{
    // this code stays the same
}  

 実際のデモを表示

 このコードをIEでテストすると、ヘッダー行をマウスでポイントしてもハイライト表示されないようになる。また、CSSスタイルシートにtdを追加したため、IEでもDataGrid内の行が1行おきではなくすべてハイライト表示されるようになっている。

 では、Firefox(やその他のIE以外のブラウザ)ではどうしたらよいだろうか。この問題を解決するには、特定のTR要素にのみhoverスタイルを適用することをブラウザに指示する必要がある。もっとも、CSSでは簡単に実現できる。具体的には次のようになる。

<style type = "text/css">
   tr.row:hover, tr.over td { background-color: #ffccff; }
</style>

 このCSSでは、CSSクラスがrowであるTR要素にのみhoverスタイルを適用することをブラウザに指示している。

なぜ2種類の方法を使うのか
 ここでは、DataGridの行をハイライト表示するために、ブラウザの種類に応じて2種類の方法を使用した。FireFox用にはCSSのみを使用する方法、IE用にはCSSとJavaScriptを組み合わせる方法だ。しかし、2つの代表的なブラウザをサポートするために別々の方法を用意するというのも面倒な話だ。
 回避するためには、前述のJavaScriptコードをFireFoxでも動くように書き直すという方法も考えられる。私もその方法を検討してみたが、やはり私はCSSの信奉者なので、CSSの方が優れたアプローチであり"正道"だと思う。JavaScriptは小手先の処理のように感じられてしまうのだ。
 というわけで、私は可能な場合にはいつでも"正道"を進み、どうしても必要な場合にのみJavaScriptに頼るようにしている。もちろん、ここで紹介したJavaScriptをFireFoxで動作するように修正してもまったく問題はない。ただ個人的なポリシーとして、ここではCSSのみを使う方向性を貫いた。

 ここまででは、DataGrid内のTR要素にCSSクラスが関連付けられていないので、このままではうまく動作しない。これを修正するには、DataGridのAlternatingItemStyleセクションとItemStyleセクションに次のようなCssClassプロパティを指定する。

<AlternatingItemStyle BackColor = "#eeeeee" CssClass = "row" />
<ItemStyle BackColor = "#ffffff" CssClass = "row" />  

 実際のデモを表示

まとめ

 これで完成である。簡単にDataGrid内の行をハイライト表示することができ、コードの量もこれまでに見たり実装したことのある他の方法よりかなり少ないはずである。ただ1つ断っておきたいのは、私が動作検証したのはIE 6.0とFirefox 1.0のみであるということだ。他のブラウザでどのような動作になるかはわからない(Netscape 7とIE 5.5ではおそらく正常に動作すると思う)。他のブラウザで正常に動作しない場合は、JavaScriptを使うことになる。紹介したコードを修正するだけで、きっと正常に動作するようになるだろう。

 最後になったが、本稿のJavaScriptコードは私が作成したものではない。私が一部修正を加えているものの、大部分はAListApart.Comに掲載されたPatrick GriffithsとDan Webbの記事「Suckerfish Dropdown」から借用したものだ。この記事にはCSSについての非常に有意義な内容なので、ぜひお読みになることをお勧めする。

 プログラマーに幸あれ!



  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

バックナンバー

連載:japan.internet.com翻訳記事

もっと読む

All contents copyright © 2005-2020 Shoeisha Co., Ltd. All rights reserved. ver.1.5