はてなブログ/touch, mouse を振り分け、hover イベントを統一する

はてなブログ/touch, mouse を振り分け、hover イベントを統一する


:hover のないタッチデバイスで同等のイベントをどう実装するかの記事です。

タッチデバイスでの実装については、すでに「はてなブログ/スマホなどタッチデバイスの :hover イベント対応」で記事にしているのですが、レスポンシブデザインで実装するにはマウスデバイスとの振り分けも必要になります。



タッチ、マウスの振り分け

if ("ontouchstart" in window) {
  // タッチデバイス
} else {
  // マウスデバイス
}


これで振り分けられます。window オブジェクトに ontouchstart というプロパティが存在すればタッチデバイスということです。


タッチデバイスの場合のトリガー

はてなブログ/スマホなどタッチデバイスの :hover イベント対応」の記事では、javascript では扱えない疑似要素をトリガーにしたために .archive-entry(画像)のどこをタッチしたかで判定していたのですが、これですと画像を横に並べた場合にかなり煩雑になりますので、今回は javascript で新しく要素を追加することにしました。

ただ、実際に計画中の「そんなには褒めないよ。映画評」への実装では、カテゴリを事実上使用していませんので、.categories を利用する予定でいます。


サンプル

サンプル

(注)サンプルの挙動が変ですね。コードの問題ではないとは思うのですが…。


タッチデバイスの場合は、左下に「i」アイコンが表示されます。また、サンプルですので文字サイズやテキストの位置などは適当な数値になっていますのであまり美しくないと思います。


(注)この下に Codepen のサンプルが表示されますが、読み込みに時間がかかる場合があります。

See the Pen for Hatena-blog-hover3 by ausnichts (@ausnichts) on CodePen.


Javascript

var entries = document.getElementsByClassName('archive-entry');
Array.prototype.forEach.call(entries, function(entry){
  if ("ontouchstart" in window) {
    var trigger = document.createElement('div');
    trigger.classList.add('trigger');
    entry.appendChild(trigger);
    trigger.addEventListener('touchstart', function() {
      entry.classList.toggle('hover');
    });
  } else {
    entry.addEventListener('mouseover', function() {
      entry.classList.add('hover');
    });
      entry.addEventListener('mouseout', function() {
      entry.classList.remove('hover');
    });
  }
});


これで、タッチデバイス、マウスデバイス、どちらの場合でも .archive-entry.hover の下に指定したスタイルが適応されます。Codepen の CSS(sass)を参照してください。