Step.101 - ツリーメニュー(TreeMenu)の表示


ツリーメニューを作って、ページ内の項目表示をコンパクトにまとめてみます。

Step テーマ
● replace (文字列の置換)
● unicode の扱い

実行例

⊞ メニューA
⊞ メニューB


リスト


<script type="text/javascript"><!--
function myTree( myIdParent , myIdChild ){
myObjParent = document.getElementById( myIdParent );// 親IDのオブジェクト
myObjChild = document.getElementById( myIdChild ).style;// 子IDのスタイルシートオブジェクト
if (myObjChild.display == "none"){// 子が非表示だったら
myObjChild.display = "block";// 子を表示
myObjParent.innerHTML = myObjParent.innerHTML.replace( "\u229E" , "\u229F" ); // 親のボタン文字 [+] → [-]
}else{// 子が表示してたら
myObjChild.display = "none";// 子を非表示
myObjParent.innerHTML = myObjParent.innerHTML.replace( "\u229F" , "\u229E" ); // 親のボタン文字 [-] → [+]
}
}
// --></script>
<div id="idMenuA" onclick="myTree( 'idMenuA' , 'idMenuA_1' )">&#x229E; メニューA</div>
<div style="margin-left:2em;">
<div id="idMenuA_1" style="display:none;">
<div>項目A-1</div>
<div>項目A-2</div>
<div>項目A-3</div>
</div>
</div>
<div id="idMenuB" onclick="myTree( 'idMenuB' , 'idMenuB_1' )">&#x229E; メニューB</div>
<div style="margin-left:2em;">
<div id="idMenuB_1" style="display:none;">
<div>項目B-1</div>
<div>項目B-2</div>
<div id="idMenuB_2" onclick="myTree( 'idMenuB_2' , 'idMenuB_3' )">&#x229E; メニューBB</div>
<div style="margin-left:2em;">
<div id="idMenuB_3" style="display:none;">
<div>項目BB-1</div>
<div>項目BB-2</div>
</div>
</div>
</div>
</div>

↓ このフォームには、上記のリストと同じものが入っています。[CTRL]+[A]で全選択して、コピーできます。

サンプルだけの HTMLは こちらへ

説明


ツリーメニューの考え方ですが、
⊞ メニューA
のように、⊞ボタンとメニューが表示されています。
⊞ボタンを押すと、
⊟ メニューA
項目A-1
項目A-2
項目A-3
のように、メニューAの下の階層項目があらわれて、メニューボタンが ⊟に変わります。
⊟ボタンを押すと、
⊞ メニューA
のように、下階層の項目が閉じて、メニューボタンが ⊞に戻ります。

ということで、ボタンが押されたら、項目の表示・非表示とボタンの変更をする myTree() 関数を作りました。
myTree() 関数のやってることは、
上記の理屈どおりに、⊞ボタンで押されたら項目の表示と⊟ボタンへ変更、⊟ボタンで押されたら項目の非表示と⊞ボタンへ変更しているだけです。

タグの書き方ですが、上記の説明の場合だったら以下のようになります。
<div id="idMenuA" onclick="myTree( 'idMenuA' , 'idMenuA_1' )">&#x229E; メニューA</div>
<div style="margin-left:2em;">
<div id="idMenuA_1" style="display:none;">
<div>項目A-1</div>
<div>項目A-2</div>
<div>項目A-3</div>
</div>
</div>

一番上がメニュー用のタグです。
<div id="idMenuA" onclick="myTree( 'idMenuA' , 'idMenuA_1' )">&#x229E; メニューA</div>
⊞ メニューA
id に、このメニューのIDを振って、クリック時に myTree()関数を呼んでいます。
myTree()関数の第1パラメータに自分自身のID、第2パラメータに下階層の項目のIDを渡しています。
  myTree( 'idMenuA' , 'idMenuA_1' )

Aタグで作る場合は、
<a id="idMenuA" href="javascript:myTree( 'idMenuA' , 'idMenuA_1' )">&#x229E; メニューA</a>
onclickを使わずに hrefでmyTree()を呼びます。

&#x229E; は、⊞ のunicodeです (&#x229F; は、⊟)。 unocode一覧表

2行目からは、下階層の項目のタグです。
<div style="margin-left:2em;">
は、下階層の項目をインデント(字下げ)するための外枠のタグです。

<div id="idMenuA_1" style="display:none;">
は、下階層の項目のグループ枠です。ここで、下階層の項目のIDを振っています。
CSSで、display:none 、つまり、下階層の項目を非表示にしています。

このタグの次の行から、項目を好きなようにカキカキしていきます。
<div>項目A-1</div>
<div>項目A-2</div>
<div>項目A-3</div>


myTree()関数の説明に移ります。
myTree()関数が呼ばれたときに、⊞ボタンが押された時なのか、⊟ボタンで押された時なのかを判断するのに
if (myObjChild.display == "none"){// 子が非表示だったら
のように、下階層の項目の displayの状態で判断しました。
display の値が "none"だったら非表示なので、display を "block" に変更して表示させます。
myObjChild.display = "block";// 子を表示

⊞ を ⊟ に変更するために、innerHTMLでメニューの文章("&#x229E; メニューA")を読み込んで、replaceを使って置換しています。
myObjParent.innerHTML = myObjParent.innerHTML.replace( "\u229E" , "\u229F" ); // 親のボタン文字 [+] → [-]


● replace関数
replace関数は、文字列内の文字を置換してくれる関数です。
s = "abcABCabcABC";
の場合、
s = s.replace( "ABC" , "XYZ" );
とすると、s の内容は、"abcXYZabcABC" に置換されます。
最初に見つけた "ABC" が "XYZ" に置換されました。

文字列内のすべての "ABC" を "XYZ" に置換したければ、
s = s.replace( /ABC/g , "XYZ" );
とすると、s の内容は、"abcXYZabcXYZ" と、すべての "ABC" が ”XYZ”に置換されました。

大文字小文字の区別なしに置換したければ、
s = s.replace( /ABC/gi , "XYZ" );
とすると、s の内容は、"XYZXYZXYZXYZ" と、すべての "abc" / "ABC" が ”XYZ”に置換されました。


myObjParent.innerHTML = myObjParent.innerHTML.replace( "\u229E" , "\u229F" ); // 親のボタン文字 [+] → [-]
<div>&#x229E; メニューA</div>
タグで上記のように unicode で &#x229E; と書きましたが、
innerHTMLで取り込んだら、⊞ という1文字になっているので、
s.replace( "&#x229E;" , "&#x229F;" );
とするのではなく、
s.replace( "\u229E" , "\u229F" );
のように記述します。(⊞ という文字があったら、⊟ という文字に置換する)
JavaScript内で unicode1文字をコード表記する場合は、\u に続いて unicodeを書きます。


階層の階層・・のようなパターンは、メニューBのようにしていけば、何層にでもできます。
<div id="idMenuB" onclick="myTree( 'idMenuB' , 'idMenuB_1' )">&#x229E; メニューB</div>
<div style="margin-left:2em;">
<div id="idMenuB_1" style="display:none;">
<div>項目B-1</div>
<div>項目B-2</div>
<div id="idMenuB_2" onclick="myTree( 'idMenuB_2' , 'idMenuB_3' )">&#x229E; メニューBB</div>
<div style="margin-left:2em;">
<div id="idMenuB_3" style="display:none;">
<div>項目BB-1</div>
<div>項目BB-2</div>
</div>
</div>
</div>
</div>


● 参考ステップ
Step.44 日付と時間をリアルタイムに表示してみましょう document.getElementById().innerHTML
Step.45 文字色をリアルタイムに変更してみましょう document.getElementById().style

● リファレンス
replace
エスケープ文字 ("\unnnn")
CSS - display
CSS - margin-left
unicode一覧表
▲TOP