モーダルウィンドウを実装してみよう(応用編) ウィンドウ内表示対応

モーダルウィンドウを実装してみよう(応用編) ウィンドウ内表示対応

  • このエントリーをはてなブックマークに追加

モーダルウィンドウを実装してみよう、の記事の続きです。

前回の記事では基本形の実装を紹介しました。今回は以下の実装について説明していきたいと思います。

  • ページ内に、モーダルを表示するためのトリガを複数設定する。
  • スクロールしている場合は、表示中のウィンドウの位置にモーダルウィンドウが表示されるようにする。

デモ

まず最初に、今回の「応用編Step1」を実装した完成形をお見せします。
ソースは https://github.com/kokoe/modal/ こちらにあげております。

モーダルウィンドウ応用編-Step1 デモ

スクロールをした状態でモーダルウィンドウを表示しても、ページ内にモーダルウィンドウがちゃんと表示されていることがわかります。
また、トリガ(「クリックするとモーダルが開くよ」)のリンクが、ページ内に2つあり、どちらのリンクもクリックした際、モーダルウィンドウがきちんと表示されています。

HTML

基本構造は、基本形と変わりません。
つきましては、以下URLからindex.htmlをダウンロードして上書きしていただくとよいかと思います。
https://github.com/kokoe/modal/blob/master/src/step1/index.html

トリガのエレメント選択をIDからクラス指定へ

前回は、以下のようにIDを指定してエレメントを選択していましたが、今回はトリガが2つになりますので、エレメントはクラスで選択するように変更します。
※Javascriptの処理になりますが、.openModalを指定しているエレメントをすべて取得し、各エレメントに対してイベントハンドラ(onclick)を指定していくように処理を変更するため。

続きを読む

- <a id="openModal" href="javascript:void(0)">クリックするとモーダルが開くよ</a>
+ <a class="openModal" href="javascript:void(0)">クリックするとモーダルが開くよ</a><br>

Javascript

まず、複数トリガの設定をします。

ページ内に、モーダルを表示するためのトリガを複数設定する。

エレメントの指定を、以下のように変更します。

- var openTrigger  = document.getElementById('openModal');
+ var openTriggers = document.querySelectorAll('#wrap .openModal')

これで、変数openTriggersには、#wrap内の.openModalのエレメントすべてが格納(参照)されました。

次に、bindOpenModal関数(トリガのリンクをクリックした際に実行される処理)に変更を加えます。
前回のソースでは、イベントリスナの対象エレメントが#openModalに固定されていましたが、引数に対象エレメントを指定できるように修正します。

/**
 * 「クリックするとモーダルが開くよ」をクリックしたときの処理
 */
- function bindOpenModal() {
+ function bindOpenModal(openTrigger) {
    openTrigger.addEventListener('click', function(event) {
        // デフォルトのイベント(ここではa要素のイベント)をキャンセル
        event.preventDefault();
        // モーダルを表示
        showModal();
    }, false);
}

次に、先ほど修正したbindOpenModalとopenTriggerを使って、各トリガにイベントリスナを設定してみます。

for (var i = 0, len = openTriggers.length; i < len; i++) {
    // モーダルを開くためのイベントリスナを設定
    bindOpenModal(openTriggers[i]);
}

これで、複数トリガ設定については修正完了です。2つのリンク、どちらをクリックしてもモーダルウィンドウが表示されるようになったかと思います。

スクロールしている場合は、表示中のウィンドウの位置にモーダルウィンドウが表示されるようにする。

次に、上記タイトルの実装をしていきます。
まずは、上記タイトルの機能を実装せずに、スクロールをした状態で、モーダルウィンドウがどのように表示されるか見て見ましょう。

モーダルウィンドウ説明画像1 モーダルウィンドウ説明画像2

画面内にモーダルウィンドウが表示がされていないことがわかります。

まず、なぜ画面内にモーダルウィンドウが表示されないかの説明になりますが、モーダルウィンドウは、ドキュメント(正確には、.modalBaseLayer)を基準として、top:10pxの位置で表示しており、画面に対してtop:10pxの位置で表示させているわけではないことが原因になります。

※以下、HTML/CSSの構造参照。

■HTML構造
#wrap
  └ .modalBaseLayer
      └ .modal
#wrap {
    posision: relative;
}

/* モーダルウィンドウ・ベースレイヤ */
.modalBaseLayer {
    posision: absolute;
    top: 0;
}

/* モーダルウィンドウ */
.modal {
    posision: absolute;
    top: 10px
}

では、画面に対してtop:10pxの位置で表示させるにはどうしたらよいか?

画面に対してtop:10pxの位置で表示させるということは、つまり、以下の図のように、モーダルウィンドウのtop値を、「スクロールY値」+「余白(top:10px)」に変えればよい、ということになります。

モーダルウィンドウ説明画像3

それでは、実装してみましょう。
まず、余白値を定義します。(.modalのtop値を動的にとってくるのが理想ですが、説明が複雑になるので今回は10px固定でいきます。)

+ // デフォルトの余白値
+ var defaultMargin = 10;

スクロールY値がとれなければ話が始まりません。スクロールY値を返す関数を追加します。

+ /**
+  * window.scrollYを返す
+  * https://developer.mozilla.org/ja/docs/Web/API/window.scrollY
+  */
+ function getScrollY() {
+     return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
+ }

モーダルウィンドウの、style属性・topプロパティに、「スクロールY値」+「余白(top:10px)」をセットする関数を追加します。(style属性としてセットする。)

+ /**
+  * モーダルウィンドウのTOP値に、スクロールY値を加算した値をセットする
+  */
+ function setModalTop() {
+     // スクロールY値を加算した値をセットする
+     modal.style.top = defaultMargin + getScrollY() + 'px';
+ }

一応、style属性・topプロパティをクリアする関数も作ります。

+ /**
+  * モーダルウィンドウのTOP値をクリアする
+  * 表示する度にtop値指定しているから、この処理いらない気もするけど
+  * なんか設定したものはクリアしないと気持ち悪い
+  */
+ function clearModalTop() {
+     modal.style.top = '';
+ }

既存関数showModal, hideModalに修正を入れます。

/**
 * モーダルを開く
 */
function showModal() {
+     // モーダルウィンドウのtop値をセット
+     setModalTop();
    // モーダルベースレイヤを表示する
    baseLayer.style.visibility = 'visible';
}

/**
 * モーダルを閉じる
 */
function hideModal() {
    // モーダルベースレイヤを非表示にする
    baseLayer.style.visibility = 'hidden';
+     // モーダルウィンドウのtop値をクリア
+     clearModalTop();
}

これで、モーダルウィンドウを開く時に、画面内に表示がされるようになったかと思います。

問題点

・・・ただ、これだけの実装だと、こんなことが起こります。

  1. モーダルウィンドウの長さによっては、画面からはみ出して閲覧できない状態になる。
  2. モーダルウィンドウが複数ある場合はどうしたらいいの?ついでに、そのモーダルウィンドウをトリガリンクから指定して呼び出したいんだけど?

1は、以下のような状態のことですね。

モーダルウィンドウ説明画像4

次回は、上記問題点を解決する実装をしていきます。
※・・・と言いつつも、実は実装は完了していて、GitHubにあがっているので、興味がある方はソース覗いてみてください。

ではでは~~

  • このエントリーをはてなブックマークに追加

記事作成者の紹介

kokoe(フロントエンドエンジニア)

ソーシャルゲームのコーディングやってます。三度の飯よりコーディングが好きと言って入社させてもらった エンジニアのココエです。四度目は飯の方がいいです。

関連するSONICMOOVのサービス

フロントエンドエンジニア募集中!

×

SNSでも情報配信中!ぜひご登録ください。

×

SNSでも
情報配信中!
SONICMOOV Facebookページ SONICMOOV Twitter
フロントエンドエンジニア募集中!

新着の記事

mautic is open source marketing automation