カテゴリー:
JavaScript
タグ:
 JavaScript iPhone iOS Safari focus hover

このエントリーをはてなブックマークに追加
更新日時:
2014年04月29日(火)
作成日時:
2014年04月29日(火)

前の記事 / 次の記事

クリックしたら色を変えてもう一度クリックしたら色を戻すという処理をしたい時に
iPhoneのSafari(というかiOSのSafari?)だとhoverを外せなかったので頑張ったメモ。

まずPC用ブラウザでの動作は次のような動作を想定して、
その通りに動かすことができた。

  1. マウスカーソルが重なると色が変わる
  2. クリックするとメニューがびろーんと出てくる
  3. もう一度クリックするとメニューが畳まれる
  4. マウスカーソルが離れると色が元に戻る

次のような要素があった時、

%button.menu-toggle メニューを開く
:sass
  .menu-toggle
    color: #999
  .menu-toggle:hover, .menu-toggle:focus
    color: #fff

マウスカーソルが離れるとホバーは外れるけど
どこか他のところをクリックするまではフォーカスが外れないので、
JavaScriptでフォーカスを外す。

:coffee
  $(document).on "click", ".menu-toggle", ->
    $(this).blur() if $(this).hasClass?("collapsed")
  # メニューを展開するJavaScriptで、 
  # メニューが展開されてない時はcollapsedクラスが付与される。

で、これをiPhoneのタッチ操作で動かそうとすると、
フォーカスを外すところまではできるけどホバーを外せない。
外せないというか一度タッチしたら他の要素をホバーするまでずっとホバーしてる。

なので、タッチ操作だけ別に処理を書いてみることにした。
タッチ操作の検知にはjQueryで touchstart と touchend を使うことができる。

参考

で、touchstart と touchend が発火するタイミングは click の前っぽいので
これを利用してクリックが発火する前に仕込みをしてタッチ操作されたことを
知らせるようにしてみた。

:coffee
  $(document).on "touchend", ".menu-toggle", ->
    if $(this).hasClass?("collapsed")
      $(this).removeClass("touched")
    else
      $(this).addClass("touched")

で、最初に書いたスクリプトを

:coffee
  $(document).on "click", ".menu-toggle", ->
    if $(this).hasClass?("collapsed")
      $(this).blur()
      $(this).addClass("touch-collapsed") if $(this).hasClass?("touched")
    else
      $(this).removeClass("touch-collapsed")

更に、CSSを

%button.menu-toggle メニューを開く
:sass
  .menu-toggle, .menu-toggle:touch-collapsed:hover
    color: #999
  .menu-toggle:hover, .menu-toggle:focus
    color: #fff

とした。
完成した記述は次の通り。

%button.menu-toggle メニューを開く

:sass
  .menu-toggle, .menu-toggle:touch-collapsed:hover
    color: #999
  .menu-toggle:hover, .menu-toggle:focus
    color: #fff

:coffee
  $(document).on "click", ".menu-toggle", ->
    if $(this).hasClass?("collapsed")
      $(this).blur()
      $(this).addClass("touch-collapsed") if $(this).hasClass?("touched")
    else
      $(this).removeClass("touch-collapsed")
  $(document).on "touchend", ".menu-toggle", ->
    if $(this).hasClass?("collapsed")
      $(this).removeClass("touched")
    else
      $(this).addClass("touched")

ちなみにJavaScriptで直接色を変更しても同様のことはできるけど、
それだと疑似要素に対応できないのでクラスを付け替える方法にした。