またまたお世話になります。 2002.5.5.Sun No.3398
こんばんわ。またまた質問です。色々試してどうしてもうまくいかないので・・。
<script LANGUAGE=javascript>
<!---
function Menu(M1){
var span="";
var menu="";
if(M1 == 1){
menu = '<A onClick="Menu(0)">▲</A>';
span = span + '<LI><A href="http://aaa">aaa</A>';
span = span + '<LI><A href="http://bbb">bbb</A>';
span = span + '<LI><A href="http://ccc">ccc</A>';
}
if(M1 == 0){
span = "";
menu = '<A onClick="Menu(1)">▼</A>';
}
document.all.span.innerHTML = span;
document.all.menu.innerHTML = menu;
}
function Menu2(M2){
var span2="";
var menu2=""
if(M2 == 1){
menu2 = '<A onClick="Menu2(0)">▲</A>';
span2 = span2 + '<LI><A href="http://ddd">ddd</A>';
span2 = span2 + '<LI><A href="http://eee">eee</A>';
span2 = span2 + '<LI><A href="http://fff">fff</A>';
}
if(M2 == 0){
menu2 = '<A onClick="Menu2(1)">▼</A>';
}
document.all.span2.innerHTML = span2;
document.all.menu2.innerHTML = menu2;
}
//--->
</script>
−− 中略 −−
<UL style="list-style-type:none;"><SPAN id="menu"><A onClick='Menu(1)'>▼</A></SPAN>メニュー1
<SPAN id="span"></SPAN>
</UL>
<UL style="list-style-type:none;"><SPAN id="menu2"><A onClick='Menu2(1)'>▼</A></SPAN>メニュー2
<SPAN id="span2"></SPAN>
</UL>
の様なプルダウンメニューを作成したんですが、これだとメニューを増やすとその度に同じ様なJavaScriptの記述をしなければなりません。
これを引数とかをうまく使って、一つのルーチンで出来ないものでしょうか?
# ルーチンって言って良いのかな?JavaScript の function{} を言いたい。
# う〜ん、はがゆい。文字で説明するのはきついなぁ。もっと説明したいけど
# どう書けば良いのか分からない・・・。
Re:またまたお世話になります。 ぴろあき 2002.5.5.Wed No.3401
似たような処理を一本化して、できるだけコンパクトに組む…というのは、プログラマ(スクリプタ?)として腕の見せどころですよね。
ちょっと根っこからの組み直しになってしまいますが、こういうのはどうでしょう?
IE4以降の他、Netscape6 にも対応して、さらに Netscape4 や JavaScript がOFFの時はメニューが最初から全部表示されている、いわゆるクロスブラウザ仕様です。
http://faq.creasus.net/02/0505/
># ルーチンって言って良いのかな?JavaScript の function{} を言いたい。
関数(function)を「サブルーチン」、それ以外は「メインルーチン」、総合して「ルーチン」で、大体は通じると思います。
># う〜ん、はがゆい。文字で説明するのはきついなぁ。もっと説明したいけど
># どう書けば良いのか分からない・・・。
自分の少ない少ない回答経験から思いますに、
この要点を押さえておくと、伝わる可能性がかなり高くなります。
ありがとうございます。 2002.5.7.Tue No.3411
上記を参考にして自分のものにしてみます。
ちょっと、今日はもう時間がないので明日にでも早速。
結果はのちほどご報告いたします。
いや〜、勉強になるなぁ。
▼をクリックするとメニューが開きます。
innerHTML
式での実行結果まったく同じ動作をしてるのがわかるかと思います。
それでいてソースも簡潔で、しかもクロスブラウザ対応ですから、大変お得です。
なお、マージンの違いはタグ構造によるものですので、支障がある場合はスタイルシートなどで調整してください。
元のスクリプトはクリックされたら innerHTML
で中身を書き換えるようになっていますが、このサンプルではスタイルシートで中身を「非表示」にしておき、クリックされたら「表示」に切り替えるようにしています。
また、非対応ブラウザでは「表示」のままにしておくことで、JavaScript がOFFでも支障がなくなります。
var brwCheck = false;
if ((document.all && document.selection) ||
(navigator.product && navigator.product == "Gecko") ||
(window.opera && document.createEvent)) {
brwCheck = true;
document.write("<style type='text/css'> .none { display:none;} <\/style>");
}
<head>
の中に書きます。IE4以降・Netscape6以降・Opera7以降でのみ、折りたたむ部分をスタイルシートで非表示にしておきます。それ以外のブラウザだったり、JavaScript がOFFの時は、メニューが非表示になりません。brwCheck
は、ブラウザを識別した結果を入れておくフラグです。
<ul style="list-style-type:none;">
<li><span onclick="clickMenu('menuList1', this)">▼</span>メニュー1</li>
<li><div class="none" id="menuList1">
<a href="http://aaa">aaa</a><br>
<a href="http://bbb">bbb</a><br>
<a href="http://ccc">ccc</a>
<li></div>
</ul>
<ul style="list-style-type:none;">
<li><span onclick="clickMenu('menuList2', this)">▼</span>メニュー2</li>
<li><div class="none" id="menuList2">
<a href="http://eee">eee</a><br>
<a href="http://fff">fff</a>
<li></div>
</ul>
<ul>
を使う場合、正しい文法に従うとこういった感じになります。<ul>
や <li>
を削除して <span>
と <div>
だけにしちゃっても、(動作的には)支障ありません。<ul>
〜 </ul>
をそのまま複写して onclick="clickMenu('ID名', this)"
と <div id="ID名">
のID名を変えるだけです。いくらでも簡単に増やせます。
<a onclick="">
を使う必要はありません。href
属性がないと onclick=""
が無視されるからです。<span onclick="">
を使う方が適した書き方です。(<a>
は本来アンカー(リンク)を示す要素ですし)
onclick="clickMenu('menuList1', this)"
では、表示を切り替える <div>
のID名を引数で渡します。第2引数にある this
は、クリックされた <span>
タグ自体をオブジェクトとして関数に渡します。これは▲と▼を書き換えるために使います。
function clickMenu(idName, spanObj) {
if (brwCheck) {
with (document.all ? document.all(idName).style : document.getElementById(idName).style) {
if (display == "block") {
display = "none";
spanObj.innerHTML = "▲";
} else {
display = "block";
spanObj.innerHTML = "▼";
}
}
}
}
<head>
内に入れる関数です。メニューがいくら増えても、この関数を変更する必要はありません。innerHTML
で内容を変更するのではなく、スタイルシートの表示/非表示を切り替えます。onclick="clickMenu('ID名', this)"
からID名を引数で渡してもらい、それを元に目的の <div>
へアクセスします。innerHTML
を使ってますが、this
を使って <span>
のオブジェクトを丸々渡してもらってるので、ID名を経由しなくてもダイレクトにアクセスできます。
function clickMenu(idName, spanObj) {
if (brwCheck) { //ブラウザ判定
var obj; //<div>オブジェクトを格納する一時変数
if (document.all) {
obj = document.all(idName); //IE4以降の時
} else {
obj = document.getElementById(idName); //Netscape6の時(IE5以降はこの方法でも可)
}
if (obj.style.display == "block") { //オブジェクトのCSSが「表示」になっていたら
obj.style.display = "none"; //「非表示」にする
spanObj.innerHTML = "▲"; //<span>の中身を▲に書き換える
} else {
obj.style.display = "block"; //「表示」にする
spanObj.innerHTML = "▼";
}
}
}
document.all
でオブジェクトIDへアクセスするには、
document.all.idName
: プロパティ型document.all(idName)
: メソッド型document.all[idName]
: 連想配列型の3通りの構文があります。プロパティ型は処理速度が速い反面、融通が利きません。メソッド型と連想配列型は、文字列をコードへ変換する処理が加わりますが、ID名に変数を使えるのは絶大なメリットです。
いずれも、負荷の高いスクリプトでもない限り、速度にたいした差はありません。通常はメソッド型か連想配列型の使用が良いかと思います。
このページの質疑応答部分も「タイトルをクリックすると記事を表示する」というものですが、このサンプルより遥かに高度な手法を使っています。(該当ソースのどこを見ても onclick
はない)
でも「クリックするたびに display
を none
と block
で切り替える」という仕組み自体は同じです。
このページは、質疑応答掲示板で使用した回答の残骸です。検索エンジンに捕まったりリサイクルしたりすることもあろうので、なんとなく残してあります。広く公開しているページではありませんが、第3者の閲覧を禁止するものでもありません。
恒久的なURIは保証できないものの、よほどのことがない限り削除されることはないでしょう。心配性な人はページの保存をおすすめします。(IEは mht 形式でないと保存できないかも)