WEBデザイナーが、Backbone.jsでサービスを作るときにリンク周りではまったこと

WEBデザイナーが、Backbone.jsでサービスを作るときにリンク周りではまったこと

今、Backbone.js + handlebars.js + php + herokuでとある個人的なサイトを作っているのですが、その際に意外なところでハマったのでそのまとめと解決策です。備忘録的に残しておきます。

Ads

実際に起きた問題点

  • クリックされたa要素のdata-idが取得できない!!
  • click(タップ)しても反応しない!!
  • スマホで二回タップしないと反応しない!!

結構はまりました・・・

クリックされたa要素のdata-idが取得できない!!

というのも、例えば以下のようなHTMLがあったとして、全体を囲っているa要素のdata-idを取得したいなんて場合です。

<ul class="c-menu">
    <li class="js-list-id c-menu__item" data-id="">
   	 	<a class="js-player-list-sample c-media u-cf" style="display: inline;" data-id="media-a">
            <p class="c-media__thumb" data-id="media-p1">
            	<img src="hoge.jpg" alt="" width="100%" data-id="media-img">
            </p>
            <div data-id="media-div">
            	<p data-id="media-p2" class="c-media__content__text">テキストテキストテキストテキストテキストテキストテキストテキスト</p>
            	<h3 data-id="media-h3" class="c-media__content__title">タイトルテキストテキストテキストテキストテキストテキストテキストテキストテキスト</h3>
	        </div>
        </a>
    </li>
</ul>

.js-player-list-sampleをクリックしたらその要素のdata-idの中身を取得するというJavaScript(jQuery)を書くとすると・・・

	<script>
	$(function(){
		$('.js-player-list-sample').on('click', function(){
			$hoge = $(this).attr('data-id');
			alert($hoge);
		});
	});
	</script>

だいたいこんな感じ。で、これは思った通りの挙動になります。

MyApp.Views.Player = Backbone.View.extend({

	tmpl: MyApp.Templates.player,
	model: new MyApp.Models.Player,
	events: {
        "click .js-player-list": "modalShow"
    },
	modalShow: function(e){
		e.preventDefault();

		var $id = $(e.target).attr('data-id');
		alert($id);
    },

});

Backboneの場合は「.js-player-list」をクリックしたら[modalShow]が発動されるんですが、「target」を使うことで$(this)のようにクリックされた「.js-player-list」に対してイベントを実行できます!!

ところがここで問題が起きました。実際やってみるとこの場合はクリックされた要素の値が取得されます。もっと詳しく言うと、マウスや指が乗っている要素のdata-idが取得されました。なので、「media-p1」などが返ってきます。

通常であればクリックなどのイベントは、子要素から親要素へと伝播される(バブリング)はずなんですが、Backboneの場合だと子要素で止まっていますね。

なので、aタグで要素を囲った場合に、クリックした要素のdataやtextなどを取得する際は注意が必要そうです。

自分なりの対応策として、クリックされた要素の親要素から取得するようにしたらできました!

<li class="js-list-id c-menu__item" data-id="hogehoge">
var $id = $(e.target).closest('.js-list-id').attr('data-id');

click(タップ)しても反応しない!!

PCでは正常に反応するのですが、スマホだと全く反応しませんでした。

というのも、HTML5ではJavaScriptなどによって動的にリンク先を設定するケースを考慮し、a要素にhref属性が必須とされていないので、省略していました。ですが、hrefを省略したことによってBackbone.jsでは反応しません。おそらくバブリングの問題がここにも及んでいる?

ということで、hrefがないとスマートフォンでいくらタップしても反応しません。

<a href="#"></a>
hoge: function(e){
	e.preventDefault();
}

僕もいろいろ検証してみたんですが、結論から言ってBackboneのtargetを使っていなければ反応します。普通にjavascript書く場合であればhrefがなくても問題はありません。

Backbone.js使ってないならhref省略しても良さそうですが、hrefのないa要素を「プレースホルダー・リンク」というのですが、ここでいう「プレースホルダー」は暫定的に代わりに配置という意味のようで、基本的にはhref属性はあったほうが良いように思います。

スマホで二回タップしないと反応しない!!

これはimgのhover時にopacityで画像を薄くさせる手法はスマートフォンではやらない方がいいですねって話です。

a img:hover{
	opacity: .7;
}

これだと二回タップしないと反応しなくなってしまいます。なので、

@media (min-width: 768px){
	a img:hover{
		opacity: .7;
	}
}

おわりに

今回Backbone.jsで勉強がてらとあるサービスを作っているのですが、そこで起きた問題と自分なりの解決策を書きました。おそらくもっといいやり方あるんだと思うんですが、何かの参考になれば〜

いいなと思ったらシェアお願いします

同じタグで検索

Ads

同じカテゴリーの記事

ページの先頭へ