34305

[code]

    // リストをクリックで背景色切り替え
    $('#list li').on('click', function() {
      $(this).toggleClass('active');
    });
    
    // モーダルを閉じる
    $(document).on('click', function() {
      $('#modal').removeClass('active');
    });
    // モーダルの中身をクリックしても閉じないように
    $('#modal').on('click', function(event) {
      event.stopPropagation();
    });
    
    // ボタンをクリックでモーダル表示/非表示
    $('#button').on('click', function(event) {
      event.stopPropagation();
      $('#modal').toggleClass('active');
    });
[/code]

[code]

    * {
      margin: 0;
      padding: 0;
    }
    #list li {
      display: block;
    }
    #list li:nth-child(even) {
      background: #ddd;
    }
    #list li.active {
      background: rgba(0, 0, 255, .4);
    }
    #modal {
      visibility: hidden;
      position: absolute;
      top: 50%;
      left: 50%;
      width: 300px;
      height: 100px;
      color: #fff;
      background: blue;
      transform: translate(-50%, -50%);
    }
    #modal.active {
      visibility: visible;
    }
[/code]

[code]

    <button id="button">モーダルを開く</button>
    <ul id="list">
      <li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li>
    </ul>
    <div id="modal">モーダル</div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
[/code]

スニペットを次の順番で実行してみてください。  
① モーダルを開くボタンをクリック  
② モーダルの領域外をクリック（モーダルが閉じる）  
③ モーダルは閉じるがその下のリストの背景色まで変わってしまう

領域外をクリックしてもリストの背景色は変えたくない場合、以下のようにJSのコードを一部修正し、例外処理するほかないのでしょうか？

[code]

    // リストをクリックで背景色切り替え
    $('#list li').on('click', function() {
      // 追加した例外処理
      if ($('#modal').hasClass('active')) return;
      
      $(this).toggleClass('active');
    });
    
    // モーダルを閉じる
    $(document).on('click', function() {
      $('#modal').removeClass('active');
    });
    // モーダルの中身をクリックしても閉じないように
    $('#modal').on('click', function(event) {
      event.stopPropagation();
    });
    
    // ボタンをクリックでモーダル表示/非表示
    $('#button').on('click', function(event) {
      event.stopPropagation();
      $('#modal').toggleClass('active');
    });
[/code]

[code]

    * {
      margin: 0;
      padding: 0;
    }
    #list li {
      display: block;
    }
    #list li:nth-child(even) {
      background: #ddd;
    }
    #list li.active {
      background: rgba(0, 0, 255, .4);
    }
    #modal {
      visibility: hidden;
      position: absolute;
      top: 50%;
      left: 50%;
      width: 300px;
      height: 100px;
      color: #fff;
      background: blue;
      transform: translate(-50%, -50%);
    }
    #modal.active {
      visibility: visible;
    }
[/code]

[code]

    <button id="button">モーダルを開く</button>
    <ul id="list">
      <li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li>
    </ul>
    <div id="modal">モーダル</div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
[/code]

今回はイベントを設定しているのがリスト部分だけなのですが、モーダルの領域外部分に他の要素などがある場合、その都度例外処理を追加しなければならなくて汎用性がありません。

何かスマートな方法があれば教えてください。よろしくお願いします。


CC BY-SA 3.0
2017-04-26T20:17:36.960
34303
2017-04-26T23:19:52.453
19687
question
javascript jquery
JS/jQueryでモーダルの領域外をクリックしたとき下にある要素のイベントが発火してしまう


Lightboxなどもそうですが、よくあるパターンは「ウィンドウ全体に背景を表示し、その背景がクリックされたら閉じる」というものだと思います。背景の存在によって、

  * そこをクリックすることでモーダルが閉じてくれる...かもしれない
  * そこをクリックしてもその下にあるボタン等には効果を及ぼさないこと

という予想も期待できるかもしれません。（あくまでこの手のUIに慣れている人の話です。閉じるボタンもあるとよりわかりやすいとは思います）

[code]

    // リストをクリックで背景色切り替え
    $('#list li').on('click', function() {
      $(this).toggleClass('active');
    });
    
    // モーダルを閉じる
    $('#modal_bg').on('click', function(e) {
      // 背景以外（フォーム）をクリックしたときは無視
      if (e.target !== e.delegateTarget) return;
      
      $('#modal_bg').removeClass('active');
    });
    
    // ボタンをクリックでモーダル表示/非表示
    $('#button').on('click', function(event) {
      $('#modal_bg').toggleClass('active');
    });
[/code]

[code]

    * {
      margin: 0;
      padding: 0;
    }
    #list li {
      display: block;
    }
    #list li:nth-child(even) {
      background: #ddd;
    }
    #list li.active {
      background: rgba(0, 0, 255, .4);
    }
    #modal {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 300px;
      height: 100px;
      color: #fff;
      background: blue;
      transform: translate(-50%, -50%);
    }
    
    #modal_bg {
      display: none;
      position: fixed;
      top: 0; bottom: 0;
      left: 0; right: 0;
      background: rgba(0, 0, 0, 0.2);
    }
    
    #modal_bg.active {
      display: block;
    }
[/code]

[code]

    <button id="button">モーダルを開く</button>
    <ul id="list">
      <li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li><li>リスト</li>
    </ul>
    <div id="modal_bg">
      <div id="modal">モーダル</div>
    </div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
[/code]

逆に背景を何も表示しないのであれば、（個人的には）クリックした先のイベントが発生すべきだと思います。「モーダルによってクリックイベントが阻害されている。これを消すにはクリックが必要だ」ということがユーザーに伝わっていなければ、「ユーザーはモーダルを無視してどこかをクリックしようとした」と考える方が自然ではないでしょうか。右クリックメニューとかもそうですよね。


CC BY-SA 3.0
2017-04-26T23:19:52.453
34305
2017-04-26T23:19:52.453
8000
34303
answer