jQueryでhoverをbindさせる覚書きと、メニューに利用するための小技
jQueryでhoverをbindする場合に、mouseenterとmouseleaveの存在をよく忘れるので、覚書き。
あと、これを利用してスマホ・タブレットのタッチ端末でメニューに利用するための小技を記載しておく。
まず、hoverをbindの形態で書く際は以下のような書き方をする。
$('li.menu').bind({ mouseenter: function(){ // メニュー開く処理 }, mouseleave: function(){ // メニュー閉じる処理 }, });
上記のelement.bind(fn)したものはhoverと全く同様の動きをする。
PCの場合はロールオーバー・ロールアウトでそれぞれのイベントが走ることは言わずもがな。
スマホなどのタッチ端末ではli.menuの要素をタッチするとmouseenterの挙動が行われ、他のリンクなどのクリッカブル領域(言い方古ぅ!)を押すとmouseleaveとそれぞれのイベントが走る。
mouseenterとmouseleaveと「mouse」の文字がついているが、タッチ端末でもきちんとイベントとして認識されている。
ただ、よく陥りやすい問題が、li.menuの直下にリンクとしてaタグがあり、li.menuの配下(aタグの兄弟)としてulが続いた場合。
この場合、li.menuのmouseenterイベントは走るものの、間髪入れずしてaタグに設定されたリンクへ飛ばされる。element.hover(fn)でもこれは同様。
まぁイベント伝搬の問題なので、このへんは仕様として覚えておく必要がある。
もし、あくまでこれらのイベントの挙動にこだわるのであれば、以下のような小技で書いてあげる必要がある。
$('li.menu').bind({ mouseenter: function(){ // ここにメニュー開く処理 var t = $(this); var st = setTimeout(function(){ t.addClass('menu-link-active'); st = null, t = null; }, 250); }, mouseleave: function(){ // ここにメニュー閉じる処理 var t = $(this); var st = setTimeout(function(){ t.removeClass('menu-link-active'); st = null, t = null; }, 250); }, }); $('li.menu').children('a').bind('click', function{ if( ! $(this).parent().hasClass('menu-link-active') ) { return false; } });
こだわらずに、イベントそのものを端末ごとに切り替えれば済む話やないかって場合。
var ua = window.navigator.userAgent.toLowerCase(); if( ua.indexOf('windows') > -1 || ua.indexOf('macintosh') > -1 || ua.indexOf('cros') > -1 || (ua.indexOf('linux') > -1 && ua.indexOf('i686')) || (ua.indexOf('linux') > -1 && ua.indexOf('x86_64')) ){ $('li.menu').bind({ mouseenter: function(){ $(this).addClass('menu-active'); // ここにメニュー開く処理 }, mouseleave: function(){ $(this).removeClass('menu-active'); // ここにメニュー閉じる処理 }, }); }else{ $('li.menu').bind('click', function{ if($(this).hasClass('menu-active')){ location.href = $(this).children('a').attr('href'); } if(! $(this).hasClass('menu-active')){ $(this).addClass('menu-active'); // ここにメニュー開く処理 }else{ $(this).removeClass('menu-active'); // ここにメニュー閉じる処理 } }); $('li.menu').children('a').bind('click', function{ return false; }); }
まぁおおよそのフレームとしてはこんな感じなんやろか。
他にも方法はいっぱいあるので色々試してみよう(´・ω・`)