プロが教える店舗&オフィスのセキュリティ対策術

お世話になります。js初心者の者です。
jqueryのアコーディオンメニューを設置したいのですが、親<li>へのマウスオーバーで開く、子<li><ul><li>からのマウスアウトで閉じるという動作がうまくいきません。
また、オープン時はすべて閉じた状態にもしたいのですが。
現状クリックでの開閉です。

htmlのソースです。
<ul class="acc">
<li><a href="1">category1</a>
<ul class="fxmn">
<li><a href="11">menu 1-1</a></li>
<li><a href="12">menu 1-2</a></li>
<li><a href="13">menu 1-3</a></li>
</ul>
</li>
<li><a href="2">category2</a>
<ul class="fxmn">
<li><a href="21">menu 2-1</a></li>
<li><a href="22">menu 2-2</a></li>
<li><a href="23">menu 2-3</a></li>
<li><a href="24">menu 2-4</a></li>
</ul>
</li>
<li><a href="3">category3</a>
<ul class="fxmn">
<li><a href="31">menu 3-1</a></li>
<li><a href="32">menu 3-2</a></li>
<li><a href="33">menu 3-3</a></li>
<li><a href="34">menu 3-4</a></li>
<li><a href="35">menu 3-5</a></li>
</ul>
</li>
</ul>

jqueryのソースです。
var j$ = jQuery;
j$(function(){
j$(".acc").each(function(){
j$("li > a", this).each(function(index){
var $this = j$(this);
if(index > 0) $this.next().hide();
$this.click(function(){
var params = {height:"toggle", opacity:"toggle"};
j$(this).next().animate(params).parent().siblings()
.children("ul:visible").animate(params);
return false;
});
});
});
});

マウスオーバーのみでの開閉は$this.click(function()をmouseoverに書き換えればできるのですが。
また、どのサンプルを見ても必ず初期段階が1項目開いた状態になっているのも、閉じて表示させたいのです。

よろしくご指導お願いします。

A 回答 (2件)

#1です。



>jqueryのアコーディオンメニューを設置したいのですが、親<li>への
>マウスオーバーで開く、子<li><ul><li>からのマウスアウトで閉
>じるという動作がうまくいきません
確かに、ご質問の最初に書いてありましたね。 でも、下のほうに、

>マウスオーバーのみでの開閉は$this.click(function()をmouseover
>に書き換えればできるのですが。
とあったので、それで解決しているのかと、誤読してしまいました。

メニューの階層が2に限定なら比較的簡単ですが、階層が深くても対応可能にしようとすると、少々面倒ですね。
CSSの機能を併用すればやりやすくなると思いますが、改変してよいのか不明でしたので、スクリプトのみでやってみました。
イベント処理のタイミングを遅らせることで、対応していますので、フラグとして"_active"というクラス名をul要素に付与しています。

#1にも書きましたが、jqueryはよくわかってないので、要領が悪いかも知れません。 まぁ、あくまでもご参考までに…
また、この仕様だと、メニューが伸縮するのでマウスの位置が相対的に変わってしまうため、かなりユーザビリティが悪いように思いますが…?
サブメニューがposition absoluteで表示されるような、一般的なタイプのほうが使いやすいのではないでしょうか?

メニュー関連のスクリプトは、数多くライブラリ化されていますので、それらを参考になさるのもよろしいかと思います。
(設置だけが目的なら、ライブラリを利用なさるほうがよろしいかと。)

$(function(){
var active = '_active'; //←仮のクラス名

$('.acc ul').hide();
$('.acc a').hover(
function() {
$(this).parents('ul').addClass(active);
var tmp = $(this).next('ul:first');
var h = tmp.height() + 'px';
tmp.addClass(active).animate({height:'show'});
},
function() {
$(this).parents('ul').removeClass(active);
$(this).next('ul:first').removeClass(active);
});
$('.acc li').mouseout(function() {
setTimeout((function(elm){return function(){close(elm);};})($(this)) , 200);
});
function close(elm) {
var tmp = elm.children('ul:first');
if (!tmp.hasClass(active)) tmp.animate({height:'hide'});
}
});
    • good
    • 0
この回答へのお礼

ありがとうございます!!お礼が遅くなりましてすいません。
いろんなスクリプトを探してみたんですが、希望のものが見つかりませんでした。
確かにロールオーバー、アウトでの挙動はマウスの位置の問題でユーザビリティーは良いとは言えませんよね。
一応設置して様子をみるような感じになると思います。
ありがとうございました。
今年は本格的にjavascriptを勉強するつもりです。

お礼日時:2010/01/11 17:41

jqueryはよく知りませんが…


動作はご提示のままでよくって、最初の状態が全て閉じていればよいという意味でしょうか?

 if(index > 0) $this.next().hide();
の部分で最初の項目(index=0)だけ除外しているから閉じないので、無条件でhideするようにすれば全部閉じますけど…?

意味が違っていたら失礼。

この回答への補足

質問の中に質問があってわかりにくくなりました。
すいません。
メインは
「jqueryのアコーディオンメニューを設置したいのですが、親<li>へのマウスオーバーで開く、子<li><ul><li>からのマウスアウトで閉じるという動作がうまくいきません。」
というところです。
よろしくお願いします。

補足日時:2010/01/07 20:37
    • good
    • 0

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