dポイントプレゼントキャンペーン実施中!

クリックで表示して再度クリックすると非表示になるメガメニューを作ろうと思ってます。

下記のページを参考にjQueryでマウスオーバーによるメガメニューは作成しました。
http://www.skuare.net/test/jmegadropdown.html

ただ、jQueryどころかjavascriptも昔少しやった程度しか知識がありませんので、ソースはほぼ上記のページと同じです。

これをクリックでメニュー表示して、再クリックで非表示にするにはどうしたらよいでしょうか?
具体的にはマイクロソフトのページの上にあるようなメニューです。
http://www.microsoft.com/ja-jp/default.aspx

自分の今の知識でjavascriptを使って書いたコードは下記のとおりです。
このように書いていけば出来るとは思うのですが、もっと効率よく出来る方法はあるでしょうか?
よろしくお願いします。

function test1() {
$("#topnav li .products1 .sub").toggle();
$("#topnav li .sale1 .sub").css("display", "none");
}

function test2() {
$("#topnav li .products1 .sub").css("display", "none");
$("#topnav li .sale1 .sub").toggle();
}

<ul id="topnav">
<li>
<a href="#" class="products" onclick="test1()">Products</a>

<div class="products1">

<div style="opacity: 0; display: none; width: 600px;" class="sub">

<ul>
<li><h2><a href="#">menu1</a></h2></li>
<li><a href="#">Link1</a></li>
<li><a href="#">Link2</a></li>
</ul>

<ul>
<li><h2><a href="#">menu2</a></h2></li>
<li><a href="#">Link1</a></li>
<li><a href="#">Link2</a></li>
</ul>

</div>

</div>

</li>
<li>

<a href="#" class="sale" onclick="test2()">Sale</a>

<div class="sale1">

<div style="opacity: 0; display: none; width: 450px;" class="sub">

<ul>
<li><h2><a href="#">menu</a></h2></li>
<li><a href="#">Link - 1</a></li>
<li><a href="#">Link - 2</a></li>
<li><a href="#">Link - 3</a></li>
<li><a href="#">Link - 4</a></li>
</ul>

</div>

</div>

</li>

A 回答 (1件)

>もっと効率よく出来る方法はあるでしょうか?


ご提示の記述法だと、メニューの数が増えていくとスクリプトもその分増えますし、メニューを変更すればスクリプトも変えなければならないので、効率のよい方法はないかというご質問と解釈しました。


例示のスクリプトは、ほぼ同じことを行なうのにid等を用いて個別に指定する形式となっているので、ご質問のようなことが起こります。
処理内容が同じなので、それをどの要素が対象でも成り立つような考え方に一般化して、コード化すればよろしいかと思います。
対象としているメニューの構成には決まりがあるでしょうから、その決まりを利用してクリックされた要素を基準に相対的な要素関係によって処理の内容を記述するようにすれば、メニューの構成が変わらない限り数の増減や項目の入れ替えがあっても、スクリプトは同じままで対応可能とすることができます。

ちょっと気になったのは、ご提示の処理だと個別のメニューをクリックするとそのサブメニューが開/閉するようになっていますが、あるメニューを開いたときに他の開いているメニューを閉じることはしなくても良いのでしょうか?(ご提示のメガメニューの参考サイトでは開いているメニューはいつも一つになるように制御されているようです)


以下、「開閉するのは子要素のみで、孫・ひ孫要素は関係ないものと限定して良い」場合、つまりメニューの階層が1階層に限定できる場合の具体例ですが…
1)イベントの設定
ご提示のソースではHTML内にonclickで記していますが、通常は
 $("#topnav > li > a").click(function(){ ~
のように設定もスクリプトで行なってしまっていると思います。
jQueryの場合、イベント処理の匿名関数から、クリックの対象要素が「this」で参照できるようになっています。

2)一度に開いている要素を一つとして考えて良いのであれば、全部のメニューを閉じるのは、
 $("#topnav div.sub").hide();
で可能ですが、こうするとクリックされた時点の要素の状態がわからなくなってしまうので、先に開閉状態を取得しておいてから全部閉じ、その後、状態に応じて開くことにするなどの方法が考えられます。

例えば
var elm = $("div.sub:hidden", $(this).parent()); //閉じていた場合のみ取得
$("#topnav div.sub:visible").hide(); //一旦全部非表示(:visibleは無くても可)
elm.show(); //最初に閉じていたら表示する
とか。

* ご提示のソースでは初期設定でstyle="opacity:0"を設定していますが、上記のhide/showではopacityを操作していませんので、初期設定のまま(見えないまま)になりますのでご注意。
また、style="opacity:0"はIE系のブラウザでは通じませんので、こちらもご注意。

3)参考サイトのようにhide/showではなくアニメーション(フェード)効果を付けて表示/非表示を切り替えるのであれば、opacityの設定も必要になります。
その場合は、hide()/show()を利用する代わりに、(参考サイトのように)fadeOut()やfadeTo("normal", 1)などをご利用なさるのがよろしいかと。
    • good
    • 0
この回答へのお礼

返事が遅れて申し訳ありません。
詳しい解説ありがとうございます。

jQueryがまだ分からない部分が多く、急いでいたため、長いコードになりましたが、なんとかメニューを作りました。
fujillinさんの解説を参考に、時間がある時に直したいと思います。

本当にありがとうございました。

お礼日時:2011/07/07 09:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!