JavaScriptでツリーメニュー

よく使われる方法ですが DHTMLなツリーメニュー の方法です。しかし、ここに掲載している方法は JavaScript の部分に標準的な DOM Level 1 のメソッドを 使用していますので、WindowsのIE でしか開けないといったようなOSや ブラウザに依存する不具合はありません。 よほど古いブラウザでない限り動作するはずですので安心してご利用頂けます。 また、後半ではアクセシビリティの面も考慮したツリーメニューを掲載しています。

※ ツリーメニューに限った話ではありませんが、IDを設定した要素をDOM Level 1の document.getElementById を介さずに直接JavaScriptで参照したり、document.all で参照したりするものは非標準ですので、当然ながらブラウザが標準準拠モードの ときには動作しません。(いい加減な方法を掲載しているサイトも少なくないので 注意が必要です)
※ IDの設定不要なタイプも用意しました。→ 簡単でシンプルなツリーメニュー

下の「クリック1」、「クリック2」、「クリック3」をクリックする度にメニュー等 の表示・非表示を繰り返します。 (ちなみにこのツリーメニューのリンク先はありませんので悪しからず)

クリック1
クリック2
クリック3

以下方法と適当な解説です。

まず、<head> 〜 </head>の中には次のスクリプトを置きます。 この部分でツリーを表示なら非表示に、非表示なら表示と切替えています。 この部分はクリック1、2、3とも共通です。

<script type="text/javascript"><!--
function tree(id) {
 if (document.getElementById(id).style.display == "block")
  document.getElementById(id).style.display="none";
 else document.getElementById(id).style.display="block";
}
// --></script>
※ このスクリプトはクリックのときに実行されるfunctionのみですので、 headではなくbody要素の中に置いても問題ありません。
※ document.getElementById は JavaScript の動作する全ての現行ブラウザに実装 されていますが、 IE 4.xやネットスケープ 4.x等の古い年代のブラウザには 実装されていません。(IEは5以上、ネットスケープは6以上で実装)

クリック1のツリーメニューでは、aタグを使用してhref="javascript:○○○"で JavaScriptを作動させています。 通常のリンクのような感じでスタンダードな方法です。

"未設定"の部分はリンク先URL、"未定"の部分はリンク先を表示するフレーム名 (またはウィンドウ名)を記入します。

<a href="javascript:tree('click1');" title="クリック!">クリック1</a><br>
<div id="click1" style="display:none;">
├<a href="未設定" title="作成中です" target="未定">妖しいページ </a><br>
└<a href="未設定" title="教えられません" target="未定">秘密のページ </a><br>
</div>
※ このツリーメニューはaタグを使用しているためにリンクに下線が付きますが、 CSSで a { text-decoration: none; } とすれば見た目はクリック2のツリーメニュー と同等になります。

クリック2のツリーメニューは、spanタグにonclickでJavaScriptを作動させています。 これはspan要素以外にも使えそうです。 また、クリック出来ることが分かり易いようにスタイルシートでカーソルの形状を 指定しています。 CSSではpointerで良いはずですが、IE バージョン5.5以下では認識されないため IE専用のhandを続けて指定しています。 (cursor:pointer; cursor:hand; の指定の順番が逆になると認識されません)

ツリーメニューとは関係無いですが、この例ではツリーメニューの表示/非表示となる リンクの部分(紫色の部分)を aタグではなくonclickによる window.name.location.href というJavaScriptのオブジェクトで指定しています。 未設定 の部分はリンク先URL、未定 の部分はリンク先を表示するフレーム名を指定 します。フレーム名はインラインフレームに対してはインラインフレーム名、 通常のフレームはこの例の場合JavaScriptですので parent.フレーム名 や top.フレーム名 のように書きます。
※ このリンクの部分はクリック1の該当部分を入れても構いません。 (クリック3はこの部分に別のものを入れた例です)

<span onclick="tree('click2');" title="クリック!" style="cursor:pointer; cursor:hand;">クリック2</span><br>
<div id="click2" style="display:none;">
├<span onclick="未定.location.href='未設定';" title="作成中です" style="cursor:pointer; cursor:hand;">妖しいページ</span><br>
└<span onclick="未定.location.href='未設定';" title="教えられません" style="cursor:pointer; cursor:hand;">秘密のページ</span><br>
</div>

クリック3のソースは割愛しますが、これはクリック2の表示/非表示となるリンクの 代わりに画像や文字を入れたものです。 つまりツリーメニュー以外にも折り畳み、開閉するような仕組みのものに応用出来る ということを示す例です。

idで指定したタグ<div id="idの値" style="display:none;"> 〜 </div> の範囲内が表示/非表示となります。 style="display:none;"は(初期状態が)非表示であるという事です。 div等のタグに設定したidは tree('idの値');で操作する事によりdisplay:none;(非表示) の状態をdisplay:block;(表示)へ可逆的に変化させます。

ツリーメニューを複数設置するときはidが重複しないように気をつけないと誤動作して しまいます。 (id属性の値は同一ページで重複してはならないので当り前ですが)
また、idの値に使用する文字は半角で、頭文字は必ずアルファベットで始め、 数字・アルファベット・ハイフン・アンダースコア・コロン・ピリオドのいずれかの 組合せにする必要があります。

クリック2、3で使っているようなonclick属性等の組込みイベントを使用するときは、 そのイベントにより呼び出されるスクリプトがJavaScriptであることを明記する必要が あり、ページの<head> 〜 </head>部分に <meta http-equiv="Content-Script-Type" content="text/javascript"> を記入します。(HTML4.01仕様書によると未記入は不正) しかし、特に指定しなくとも通常はJavaScriptと認識されるようです。


ツリーメニューのアクセシビリティ

JavaScriptが無効または実装されていない環境では、当然ですがクリックしても ツリーメニューが展開表示されません。 スタイルシートを無効にすれば表示することは出来ますが… しかし、次のように display:none; とする部分のスタイルをJavaScriptで 出力するように工夫すると、そういった環境でも閲覧の支障が無くなります。 (ツリーメニューは展開された状態で表示されます)
※ クリック2のツリーメニューはリンク(紫色の部分)もJavaScriptで記述して いますので、アクセシビリティの面では最低です。 (スタイルシートを無効にしてツリーメニューを展開してもリンクが動作しない)

クリック4
クリック5

document.getElementById が実装されている(ツリーメニューが動作する) ブラウザに限り document.write() でクラス名treeを非表示とするCSSを出力する行を スクリプトに追加します。 styleタグごと出力しますので document.styleSheets のようなブラウザの違いによる 依存性の心配もありません。

<script type="text/javascript"><!--
if (document.getElementById)
 document.write('<style type="text/css"> .tree { display: none; }<'+'/style>');

function tree(id) {
 if (document.getElementById(id).style.display == "block")
  document.getElementById(id).style.display="none";
 else document.getElementById(id).style.display="block";
}
// --></script>
※ このスクリプトはページが読み込まれたときにCSSを出力する部分がありますので、 必ずhead要素の中に置きます。
終了タグの </ はscript要素内で使用するとき <\/ とします。 ページの文字コードがShift_JISエンコーディングのときKHTML(KonquerorやSafari)で \ がエスケープに使用出来ない不具合があるようですので分割するように変更しました。

ツリーメニューの部分は style="display:none;" を削除し、 class="tree" として先程のクラス名を設定します。

<a href="javascript:tree('click4');" title="クリック!">クリック4</a><br>
<div id="click4" class="tree">
├<a href="未設定" title="作成中です" target="未定">妖しいページ </a><br>
└<a href="未設定" title="教えられません" target="未定">秘密のページ </a><br>
</div>
<span onclick="tree('click5');" title="クリック!" style="cursor:pointer; cursor:hand;">クリック5</span><br>
<div id="click5" class="tree">
├<a href="未設定" title="作成中です" target="未定">妖しいページ </a><br>
└<a href="未設定" title="教えられません" target="未定">秘密のページ </a><br>
</div>