bootstrapのdropdownを自動開閉 のバックアップの現在との差分(No.2)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[公開メモ]]

* Bootstrap の dropdown menu をマウスオーバーで自動開閉したい [#t0231e31]
* Bootstrap3 の dropdown menu をマウスオーバーで自動開閉したい [#t0231e31]

http://dora.bk.tsukuba.ac.jp/event/ICSPM24/index

これのメニューの所で、クリックしなくてもメニューが開くようにしたかったのです。

* よく知られた方法もあるようなのですが・・・ [#h930abee]

例えばこちらで紹介されていました。

- http://photoshopvip.net/archives/69687

css に以下を追加するだけで、ほぼ望み通りの動作をします。

 LANG:css
 @media only screen and (min-width : 768px) {
   /* デスクトップ表示ではホバー操作でドロップダウンを表示 */
   .dropdown:hover .dropdown-menu {
     display: block;
   }
 }

同じページでは、親要素のクリックでリンク先に飛ぶためのハックも記載されています。
ただ、それを追加してしまうとタッチデバイスでドロップダウンを開けなくなってしまうため、
モバイルファーストで開発するなら親要素にリンクを張るのはやめた方が良いと思います。

** 上記コードで気になる点 [#g80a29e9]

試したところ、いくつか難点がありそうです。

+ モバイルデバイスで親要素をタップしてメニューを開いた後、
もう一度親要素をタップしてもメニューが閉じない
+ マウスオーバーでメニューが開いた際に親要素がハイライトされない

2. はまだしも、 1. は期待する動作と異なるため、ユーザーが戸惑うのではないかと思います。

以下のコードは車輪の再発明っぽくはありますが、
タップデバイスの動作が変化していないところに、
少しだけメリットがあると思います。

** 下記コードで気になる点 [#h025260b]

一方、下記のコードでは親要素をマウスクリックするといろいろおかしなことが起きます。
- Firefox, IE では親要素をクリックすればメニューが閉じますが、Chrome では2回クリックしないと閉じません
- クリックでメニューを閉じると、親要素のハイライトが残ってしまいます

今のところマウスオーバーで開いたメニューをマウスクリックで閉じなくてもいいでしょ、
ということで、目をつぶっています。。。
** 基本を確認 [#h1bcb5ca]

ドロップダウンの開閉を行うコードはこの部分です。

https://github.com/twbs/bootstrap/blob/master/js/dropdown.js

を見ると、li.dropdown に .open を付けてやればメニューが開くことが分かります。


open というクラスを追加すれば良いことが分かります。

** とりあえず開く [#m0016bcc]

hover で open を追加するコードを書きました。

#gist(osamutake/1681a6abb9069e00591a/ad21a53950b29db5955e55e6097dbaa70690271d)

ただこれだと2つ問題があって、
+ スマホだとメニューが開かない
+ タッチデバイスではメニューが開かない
+ 画面幅が狭くなって collapse したメニューでもマウスオーバーで開いてしまう

** スマホへの対応 [#a3d83332]
** タッチデバイスへの対応 [#a3d83332]

そもそもスマホではマウスオーバーが無いので自動開閉はしなくて良いのですが、
上野コードだとタップでもメニューが開かなくなってしまいます。
そもそもスマホなどのタッチデバイスではマウスオーバーが無いので自動開閉はしなくて良いのですが、
上のコードだと親要素をタップでもメニューが開かなくなってしまいます。

というか、1回目は開かず、2回目は開きます。
というか、1回目は開かず、2回目で開きます。

これは、スマホでの画面タップでは
これは、タッチデバイスでの画面タップでは
- mouseover が発生 -> open
- mouseclick が発生 -> toggle すなわち close

が同時に起こるためです。
が連続して起きるためです。

これを回避するために次のようにしました。

#gist(osamutake/1681a6abb9069e00591a/74b081678ba6b7499cb4b7356f06f0a41d53cd61)

mouseover ではなく 「mousemove の2回目」 でメニューを開きます。

タップでは mouseclick 前に mousemove が1回しか起きないので、
これで正しくメニューを開けます。

マウスカーソルの移動では mousemove の1回目で開いても2回目で開いても体感的には遅れは感じられません。

** collapse では開かないようにする [#i824944d]

非 collapse 状態では li.dropdown が float:left なので、
それを利用すればいいように思いました。

 LANG:javascript
     if ( $this.css('float')!='left' ) return;

を1行加えました。

** 最終版 [#p013e3cb]

次のコードで動いているようです。

#gist(osamutake/1681a6abb9069e00591a)

** 動作デモ [#g44934a9]

http://jsbin.com/vomatazizi/edit?output

* コメント・質問 [#s6bf5d0b]

#article_kcaptcha


Counter: 9903 (from 2010/06/03), today: 1, yesterday: 2