折りたたみJS
HTMLソース側を極力汚さない折りたたみJavaScript
Published on
本ページで示すのは、良くあるJavaScriptによる折りたたみをJavaScriptとDOMとCSSで実現する手順である。jQueryなどの外部ライブラリを必要とせず、このスクリプト単独で動作する。
折りたたみというのは、ある要素をクリックすると隠れていた部分が見え、もう一度クリックするとまた隠れるというヤツである。
demo
例えばこんな感じ
HTMLソース側はclassを付与するだけにとどめ、クリーンでStrictなHTMLコーディングを保ったまま実現できるよう配慮している。また、JavaScriptを切った環境では、要素は折り畳まれず、中身も読むことができるようになっている他、キーボードで操作している場合の対処もしているので、それなりにアクセシビリティも確保してあると言える。
あと、いちいちid振らなくてもいいあたりが良いんじゃないかと思う。
このスクリプトは、以下のブラウザで正常に作動することが確認されている。
- Safari 2.0.4 (iOS含む)
- Firefox 1.0.4
- Opera 8.0
- iCab 3.0β
- InternetExplorer 6 / InternetExplorer for Mac 5.2
このページは、HTMLとCSSの書き方は分かっているが、JavaScriptはそんなに得意ではない(私のような)人向けにTipsとして書いたものだ。
さらに簡潔にするためにtrigger要素に何も書かなくても良いように改良しました。ソース
まず、以下に最小限の基本ソースコードを示す。
HTML
<element class="show">
<element class="trigger">trigger</element>
<element class="target">target</element>
</element>
# "element" は要素の代表。実際にはどの要素でも可
JavaScript
外部ファイル(推奨)にするか、head要素内に書く。
// initialize on page load
window.onload = initExpand;
// toggle class when trigger is clicked
function toggleExpand(t) {
for (var i=0; i<3; i++) {
var t = t.parentNode
if (t.className == 'hide') {
t.className = 'show';
break;
} else if (t.className == 'show') {
t.className = 'hide';
break;
}
}
}
// initialize
function initExpand() {
var e = document.getElementsByTagName('*');
for (var i=0; i<e.length; i++) {
// change all show classes to hide
if (e[i].className == 'show') {
e[i].className = 'hide';
}
// set JavaScript triggers
if (e[i].className == 'trigger') {
e[i].setAttribute('onclick', 'toggleExpand(this)');
e[i].setAttribute('onkeypress','toggleExpand(this)');
}
}
}
window.onload
を使っているので他のスクリプトとバッティングする場合はそれぞれ対処すること。
CSS
.trigger { cursor:pointer }
.hide .target { display:none }
解説
該当部分のHTMLは以下のような構造になっている。
基本は、triggerをクリックすることによりそれを包括する.showと.hideが書き変わるという単純なものだ。
以下便宜上、trigger
をクラスとして持つ要素をtrigger、target
をクラスとして持つ要素をtargetと呼ぶ。
詳細
HTMLファイルが読み込まれると、まずinitExpand()
が作動し、HTML中のshowクラスをhideに書き換える。コレにより、JavaScriptが有効な場合のみ折りたたまれ、初期状態では中身が見えなくなる。さらにtriggerにonclick
属性とonkeypress
属性を付与しクリッカブルなボタンとして機能するようにする。
triggerをクリックするとtoggleExpand()
が作動し、triggerの親要素、またはその更に親の要素のクラスがhideかshowのものを上位3階層分まで探しにいく。見つけると、そのクラスがhideならshowへ、showならhideに書き変える。CSS側で.hide .target
の場合をdisplay:none
にしてあげれば、targetは親要素がhideの間非表示となる。
この折りたたみセットは1ページ中何回出現しても構わない。
CSSで.trigger
にはtext-decoration:underline
などクリッカブルなスタイルを付与すると良い。triggerにshowとhideの時で異なったスタイルを提供することも可能である。
注意点としては、このスクリプトではshowクラスを付与する要素に他のクラスを併記すること(<div class="show section">
など)はできない。
使用例
demo
このようにtrigger(この場合 "demo" を内容とするh2
要素)をクリックするとtarget(p
要素)が表示される。また、開いてる状態でtriggerを再度クリックすると、また折り畳まれ、targetは非表示になる。
このときtriggerも.hideと.showで別々のスタイルを付与すれば、開いているときと閉じているときでスタイルが変化する。
HTML
<div class="show">
<h2 class="trigger">demo</h2>
<p class="target">このようにtrigger …略… は非表示になる。</p>
<p class="target">このときtriggerも …略… スタイルが変化する。</p>
</div>
CSS
.hide .target { display:none }
.trigger { color:#069 ; cursor:pointer }
.trigger:hover { color:#c33 }
.trigger:after { content:url(hide.png) ; padding-left:0.3em }
.hide .trigger:after { content:url(show.png) }
著作権は破棄していませんが、使用、改変は自由です。適当にいじって使って下さい。