.index( )と.eq( )を使った効率的なモーダル表示

今回やりたいこと

例えば、何十個のリンク付きコンテンツがあり、それぞれをクリックした時に違う内容のモーダルウィンドウを表示させたいとします。
そんな時、それぞれクラスを付与してjsを動かすのは非効率です。

こういった場合に使えるjQueryの記述を紹介します。

HTML(Pug)

まず、HTMLの記述です。今回はPug記法を使用しています。


ul.list_contents
  li.js-modal
    a
      img(src="https://placehold.jp/120x160.png")
  li.js-modal
    a
      img(src="https://placehold.jp/120x160.png")
  li.js-modal
    a
      img(src="https://placehold.jp/120x160.png")
  li.js-modal
    a
      img(src="https://placehold.jp/120x160.png")
  li.js-modal
    a
      img(src="https://placehold.jp/120x160.png")

.modal_area
  .modal_box
    .modal_bg
    .modal_inner
      .modal_close ×
      .list_contents_more
        img(src="https://placehold.jp/300x400.png")
        dl
          dt テキストテキスト
          dd
            a(href="#").btn ボタンボタン
  .modal_box
    .modal_bg
    .modal_inner
      .modal_close ×
      .list_contents_more
        img(src="https://placehold.jp/300x400.png")
        dl
          dt テキストテキスト
          dd
            a(href="#").btn ボタンボタン
  .modal_box
    .modal_bg
    .modal_inner
      .modal_close ×
      .list_contents_more
        img(src="https://placehold.jp/300x400.png")
        dl
          dt テキストテキスト
          dd
            a(href="#").btn ボタンボタン
  .modal_box
    .modal_bg
    .modal_inner
      .modal_close ×
      .list_contents_more
        img(src="https://placehold.jp/300x400.png")
        dl
          dt テキストテキスト
          dd
            a(href="#").btn ボタンボタン
  .modal_box
    .modal_bg
    .modal_inner
      .modal_close ×
      .list_contents_more
        img(src="https://placehold.jp/300x400.png")
        dl
          dt テキストテキスト
          dd
            a(href="#").btn ボタンボタン

一覧に表示される部分がul要素(.list_contents)です。
それと同階層に並んでいるdiv要素(.modal_area .modalbox)が、一覧の中のどれかをクリックした時に開かれる各モーダルになります。

「.modal_box」要素の配下にある「.modal_bg」はモーダルウィンドウを表示した時に、モーダルエリア以外の部分を黒の透過で表現するために必要な要素です。「.modal_inner」が実際に表示されるモーダルのコンテンツ部分になります。

さらに「.modal_inner」の配下に「.modal_close ×」を配置されているのはモーダルの閉じるボタンです。

CSS(Scss)

CSSは一部省略しますが、モーダルエリアのCSSは以下のようになります。


// モーダル部分
.modal_area{
  .modal_box{
    display: none; // 初期表示は非表示
    position:fixed;
    width: 100%;
    height:100%;
    top:0;
    left:0;
    z-index:999;
  }
  .modal_bg{
    background-color: rgba(30, 30, 30, 0.5);
    height: 100%;
    width: 100%;
  }
  .modal_inner{
    background-color: #000;
    padding:8px;
    position: absolute;
    left: 50%;
    top: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
    width: 80%;
    max-width: 400px;
    @include l-pc{
      width: auto;
      max-width: calc(100% - 20px);
    }
  }
  .modal_close{
    background-color: #000;
    color:#fff;
    font-size: 1.6rem;
    display: flex;
    justify-content: center;
    align-items: center;
    position:absolute;
    right:0;
    top:0;
    width: 30px;
    height:30px;
    @include l-pc{
      width: 38px;
      height:38px;
    }
  }
}

クラス名や階層が同じであればコピペで使用できると思います。

jQuery

最後にjQueryの記述です。ライブラリなどは特に使用しません。


var target = $(".js-modal");
target.on("click", function () {
  var btnIndex = $(this).index(); // .js-modalが何番目の要素かを取得(数字を取得)
  $('.modal_area .modal_box').eq(btnIndex).fadeIn(); // .modal_area内の'btnIndex'番目の要素をフェードインで表示
});
// ×ボタンまたはモーダルの背景エリアをクリックした時
$('.modal_close , .modal_bg').click(function () {
  $('.modal_box').fadeOut(); // モーダルを非表示にする
});

たったこれだけでOKです。

Point!

ポイントとなるのは「.index()」と「.eq()」です。

「.index()」で、リスト一覧のどれかをクリックした時に、クリックされた要素(.js-modal)が何番目のものかを調べ、その数字を取得することができます。

「.eq()」で、取得した数字を指定することで、〇番目の「.modal_box」という指定ができます。

モーダルではなくても、同じコンテンツが並んでいて同じ挙動をする場合などは、使える機会があると思うので、是非使ってみてください。

related article

2019/11/08 JavaScript

1個開けると他は閉じるアコーディオンメニュー

2019/11/15 JavaScript

Youtubeをポップアップで再生させる方法

2019/11/12 JavaScript

jQueryで作るテキストモーダルウィンドウ

2019/10/10 JavaScript

HTML内に書いたjQueryが動かない