japan.internet.comThe Internet & IT Network
RSS
  • ニュース
  • コラム
  • リサーチ
  • ヘッドライン
  • 特集
  • ブログ
  • プレスリリース
  • 専門チャンネル
  • イベント
  • ランキング
  • ニュースメール
2008年9月6日
文字サイズ文字サイズ小文字サイズ中文字サイズ大
デベロッパー2005年10月4日 22:20

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

海外海外internet.com発の記事
  • このエントリーを含むはてなブックマーク
  • この記事をクリップ!
  • Buzzurlにブックマーク
  • Yahoo!ブックマークに登録
  • newsing it!

はじめに

 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についての非常に有意義な内容なので、ぜひお読みになることをお勧めする。

 プログラマーに幸あれ!

著者紹介

Steve Stchur(Steve Stchur)
関連テーマ
最新トップニュース
データメーション
【データメーション】
OSについて気に入らないこと(9月5日)
ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」
【ベンチャー専門家の目利きブログ「なぜこの企業は伸びるのか?」】
「導入期〜成長期へ!一歩一歩と前進を目指す『Annoii(アノイ)』」/maka hou,Inc.(9月5日)
最新テクノロジーの意外な処方箋
【最新テクノロジーの意外な処方箋】
グリッドコンピューティング技術でETに遭遇(9月5日)
Graphic Design Forum
【Graphic Design Forum】
古い Emigre を探して (9月3日)
エンジニアの独り言
【エンジニアの独り言】
データをローカルに保存するWebアプリケーション(8月22日)
デスマーチからの脱却
【デスマーチからの脱却】
30min. iPhoneアプリリリース(8月18日)
最新ハイテク講座
最新ハイテク講座
なぜ勝った? 世界No.1シェアをつかんだ“Windows”(9月5日)
developer.com
developer.com
デザインパターンの使い方: Composite(9月5日)
最新アフィリエイト事例にみる成功の法則
最新アフィリエイト事例にみる成功の法則
コンバージョンレートを高めよう!(9月5日)
百式のネットビジネス研究
百式のネットビジネス研究
ガジェット購入時に将来の買取保証プランを提供する「TechForward」(9月5日)
週刊-サイト別アクセス状況データ
週刊-サイト別アクセス状況データ
ビデオリサーチインタラクティブ調査(月間インターネットオーディエンスデータ)(9月4日)
「IT の耳」
「IT の耳」
【書評】『検索にガンガンヒットさせる SEO の教科書』――SEO テクニックで効果的に PR する(9月4日)
検索エンジンマーケティング
検索エンジンマーケティング
果たしてモバイル SEO は必要なのか?(9月4日)
Eメールマーケティング事情
Eメールマーケティング事情
読者が迷惑メールと認識する時…(9月3日)
日本と韓国のインターネットビジネス最新動向調査
日本と韓国のインターネットビジネス最新動向調査
日本と韓国の動画サイト比較1―現状(9月3日)
SNSをビジネスに活用しよう
SNSをビジネスに活用しよう
「しまじろう」に学ぶ企業内コミュニティの活性化のポイント(9月2日)
海外のインターネットコムアメリカ韓国ドイツトルコ
Copyright 2008 Jupitermedia Corporation All Rights Reserved.http://www.internet.com/