レスポンシブサイトでブレイクポイントによってjavascriptの挙動が変わることって多いと思います。
例えばPCサイトではメガメニューがサイドバーの横から出てくるけど、
タブレットではヘッダの上から出てくるとか
問題のある実装1
$('.button').on('click', function() {
if($(window).width() >= 1200) {
// PCの処理
}else if(this.$window.width() < 768) {
// SPの処理
}
})
$('.button2').on('click', function() {
if($(window).width() >= 1200) {
// PCの処理
}else if(this.$window.width() < 768) {
// SPの処理
}
})
上記の実装のようにイベント発火時にWindowの横幅を調べる実装だと
ブレイクポイントが変更や追加された場合
色々な箇所で変更の必要があり、
DRYの原則に反し拡張性、メンテナンス性が悪いです
問題のある実装2
$('.button').on('click', function() {
// $('.hunbergerMenu')はSP時のみ表示されるHTML要素
if(! $('.hunbergerMenu').is(':visible') {
// PCの処理
}else {
// SPの処理
}
})
$('.button2').on('click', function() {
if(! $('.hunbergerMenu').is(':visible') {
// PCの処理
}else{
// SPの処理
}
})
上記実装のように、ブレイクポイント毎に表示される固有のDOMの表示非表示にて
現在のブレイクポイントを判定する処理の場合
判定用のDOMが仕様変更等により無くなる可能性があり、
さらにタブレットやミニPC等の判定が必要にあるとelse ifが増えていくことになります。
また問題のある実装1と同様、色々な箇所で同様の記述が必要となり
DRYの原則に反し拡張性、メンテナンス性が悪いです
別オブジェクトに切り出して実装すれば良い
ブレイクポイント変更検知専用のオブジェクトを作成し、ブレイクポイント変更時には
カスタムトリガーをWindowに対して発火させ、変更検知したいオブジェクトでそのカスタムトリガーを受ければ良い
ChangeBreakPoint = {
init: function() {
this.setParameters();
this.bindEvents();
},
setParameters: function() {
this.$window = $(window);
this.pageDivision = this.judgePageDivision();// 初回起動時に現在のブレイクポイントを取得する
},
bindEvents: function() {
var self = this;
var thisPagedivision = '';
// Windowのリサイズ時に現在のWindow幅を調べ、
// ブレイクポイントが変更されれば、Windowオブジェクトに対して
// 「changeBreakPoint」カスタムトリガーを発火させ、
// 引数に変更後のブレイクポイントを渡す
this.$window.on('resize', function() {
thisPagedivision = self.judgePageDivision();
if(self.pageDivision != thisPagedivision) {
self.pageDivision = thisPagedivision
self.$window.trigger('changeBreakPoint', [thisPagedivision]);
}
});
},
getPageDivision: function() {
return this.pageDivision;
},
judgePageDivision: function() {
if(this.$window.width() >= 1200) {
thisPageDivision = 'pc';
}
if(this.$window.width() < 1200 && this.$window.width() >= 980) {
thisPageDivision = 'minipc';
}
if(this.$window.width() < 980 && this.$window.width() >= 768) {
thisPageDivision = 'tb';
}
if(this.$window.width() < 768) {
thisPageDivision = 'sp';
}
return thisPageDivision;
}
}
$(function() {
ChangeBreakPoint.init();
});
HOGE = {
bindEvents: function() {
var self = this;
// changeBreakPointの第2引数が変更されたbreakpointなのでそれを変数等に格納
$(window).on('changeBreakPoint', function(event, breakpoint) {
self. breakpoint = breakpoint;
});
}
}
上記実装の場合、使いたいオブジェクトに対しカスタムトリガーを仕込むだけで、ブレイクポイントの変更を検知でき、ブレイクポイントの数が増えた場合もChangeBreakPointオブジェクトの修正のみで対応可能なためDRYの原則にも反しません。