チェ・ゲバムラの日記

脱犬の道を目指す男のブログ

【JS】モーダルウィンドウをモダンに書く勉強

コンストラクタ関数、プロトタイプの考え方で書いたやつ。

HTMLではリンクにdata属性で番号を付与、画像を押して拡大した画像が次へボタンとかでちゃんと移動できる。
ウィンドウのロード、リサイズ時も対応済み。

ただしあくまで静的なHTMLにのみ対応してる。

imagesフォルダと画像はコードに合わせて作ればすぐ動くはず。
Jquery必須。


■HTML

    <div id="container">
      <ul id="modal-thumb"><!--
        --><li><a href="images/photo-01.JPG" data-index="0"><img alt="" src="images/photo-01.JPG" width="160" class="img-thumbnail"></a></li><!--
        --><li><a href="images/photo-02.JPG" data-index="1"><img alt="" src="images/photo-02.JPG" width="160" class="img-thumbnail"></a></li><!--
        --><li><a href="images/photo-03.JPG" data-index="2"><img alt="" src="images/photo-03.JPG" width="160" class="img-thumbnail"></a></li><!--
        --><li><a href="images/photo-04.JPG" data-index="3"><img alt="" src="images/photo-04.JPG" width="160" class="img-thumbnail"></a></li><!--
      --></ul>
    </div>
    <div id="modal">
      <div id="modal-container">
        <div id="modal-contents"></div>
        <div id="modal-close"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></div>
        <div id="modal-prev"><span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span></div>
        <div id="modal-next"><span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span></div>
      </div>
    </div>
    <div id="modal-overlay"></div>


■JS

//コンストラクタ
function Modal(el){
this.initialize(el);
}

//初期設定
Modal.prototype.initialize = function(el){
this.$el =el;
this.$container = $('#modal');
this.$contents = $('#modal-contents');
this.$close = $("#modal-close");
this.$next = $("#modal-next");
this.$prev = $("#modal-prev");
this.$overlay = $("#modal-overlay");
this.$window = $(window);
this.handleEvents();
};

//イベントリスナー登録(ここに想定されるイベントを記載)
Modal.prototype.handleEvents = function() {
var self = this;
this.$el.on("click", function(e) {
self.show(e);
return false;
});

//閉じるボタン
this.$close.on("click", function(e) {
self.hide(e);
return false;
});
//オーバーレイの背景
this.$overlay.on("click", function(e) {
self.hide(e);
return false;
});

this.$next.on("click", function(e) {
self.next(e);
return false;
});

this.$prev.on("click", function(e) {
self.prev(e);
return false;
});

//リサイズ
this.$window.on("resize", function(e) {
self.resize();
});
//読み込み時(リサイズと同じ)
this.$window.on("load", function(e) {
self.resize();
});
};

//サムネイル画像がクリックされたとき
Modal.prototype.show = function(e) {

//拡大表示したい画像パス取得
var $target = $(e.currentTarget), //aリンク含めたhtml文字列が入る
src = $target.attr("href"); //href=●●部分、画像パスが入る

this.$contents.html("<img src=\"" + src + "\" />");
this.$container.fadeIn();
this.$overlay.fadeIn();

//data属性にアクセスしてindex番号を取得
var index = $target.data('index');

//countChangeにはcreateCounter内で定義している関数そのものが入る
this.countChange = this.createCounter(index, this.$el.length);
return false;
};

//拡大画像を閉じる
Modal.prototype.hide = function(e) {
this.$container.fadeOut();
this.$overlay.fadeOut();
};

//次へ、前へを押したとき共通で使用するメソッド
Modal.prototype.slide = function(index) {
this.$contents.find("img").fadeOut({
complete: function() {
var src = $("[data-index=\"" + index + "\"]").find("img").attr("src");
$(this).attr("src", src).fadeIn();
}
});
};

Modal.prototype.createCounter = function(index, len){
return function(num) {
return index = (index + num + len) % len;
};
};

//次へボタン
Modal.prototype.next = function() {
this.slide(this.countChange( 1 ));
};

//前へボタン
Modal.prototype.prev = function() {
this.slide(this.countChange( -1 ));
};

//リサイズ(読み込み時もここ)
Modal.prototype.resize = function() {
var w = this.$window.width();
if(w<640){
this.$container.css({"width":"320", "height":"213"});
}else{
this.$container.css({"width":"750", "height":"500"});
}
};


var modal = new Modal($("#modal-thumb a"));