javascript - 除外 - メニュー 等 の 領域 外 を クリック した 時に 閉じる よう に する




要素の外側にあるクリックを検出するにはどうすればよいですか? (20)

私はいくつかのHTMLメニューを持っていますが、ユーザーがこれらのメニューの頭をクリックすると完全に表示されます。 ユーザーがメニューの領域外をクリックすると、これらの要素を非表示にしたいと思います。

これはjQueryで可能ですか?

$("#menuscontainer").clickOutsideThisElement(function() {
    // Hide the menus
});

注意: stopEventPropagation()使用は、DOMの通常のイベントフローを壊すので避けてください。 詳細については、 この記事参照してください。 この方法を代わりに使用することを検討してください。

ウィンドウを閉じるドキュメントボディにクリックイベントをアタッチします。 別のクリックイベントをコンテナにアタッチすると、ドキュメント本文への伝播が停止します。

$(window).click(function() {
//Hide the menus if visible
});

$('#menucontainer').click(function(event){
    event.stopPropagation();
});

要素の外側でクリックを検出するにはどうすればよいですか?

この質問がとても人気があり、答えが非常に多い理由は、それが信じられないほど複雑なことです。 ほぼ8年と数十回の答えの後、私はアクセシビリティにどのような配慮が与えられたかを知るために本当に驚いています。

ユーザーがメニューの領域外をクリックすると、これらの要素を非表示にしたいと思います。

これは貴重な原因であり、 実際の問題です。 ほとんどの回答が解決しようとしているような質問のタイトルには、不幸な赤ちゃんが含まれています。

ヒント: 「クリック」という言葉です!

実際にクリックハンドラーをバインドする必要はありません。

クリックハンドラーをバインドしてダイアログを閉じる場合は、既に失敗しています。 あなたが失敗した理由は、誰もがclickイベントを誘発するわけではないからです。 マウスを使用していないユーザーは、 Tabキーを押してダイアログをエスケープできます(また、ポップアップメニューはおそらくダイアログの一種です)。その後、 clickトリガーすることなくダイアログの後ろのコンテンツを読むことができなくなりclickイベント。

だから、質問を言い換えましょう。

ユーザーが終了したらダイアログを閉じる方法は?

これが目標です。 残念ながら、今度は、 userisfinishedwiththedialogイベントをuserisfinishedwiththedialogする必要があります。そのバインドはあまり簡単ではありません。

では、ユーザーがダイアログを使用し終わったことをどのように検出できますか?

focusoutイベント

まず、フォーカスがダイアログを離れたかどうかを判断することをお勧めします。

ヒント: blurイベントには注意してください。イベントがバブリングフェーズにバインドされていれば、 blurは伝播しません!

jQueryのfocusoutfocusoutいくでしょう。 jQueryを使用できない場合は、キャプチャフェーズでblurを使用できます。

element.addEventListener('blur', ..., true);
//                       use capture: ^^^^

また、多くのダイアログでは、コンテナのフォーカスを取得する必要があります。 tabindex="-1"を追加すると、ダイアログがタブフローを中断することなく動的にフォーカスを受け取ることができます。

$('a').on('click', function () {
  $(this.hash).toggleClass('active').focus();
});

$('div').on('focusout', function () {
  $(this).removeClass('active');
});
div {
  display: none;
}
.active {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
  Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>

そのデモを1分以上プレイすると、すばやく問題が発生するはずです。

1つは、ダイアログ内のリンクがクリック可能でないことです。 それをクリックするか、またはタブをクリックすると、対話が行われる前にダイアログが閉じられます。 これは、内側の要素にフォーカスを合わせるとfocusoutイベントがトリガされる前にトリガされるためfocusin

この問題を解決するには、イベントループにステート変更をキューイングする必要があります。 これは、 setImmediate(...)を使用するかsetTimeout(..., 0) setImmediateサポートしないブラウザーに対してsetTimeout(..., 0)を使用して行うことができます。 一旦キューに入れられると、それは後続のfocusinによって取り消すことができます:

$('.submenu').on({
  focusout: function (e) {
    $(this).data('submenuTimer', setTimeout(function () {
      $(this).removeClass('submenu--active');
    }.bind(this), 0));
  },
  focusin: function (e) {
    clearTimeout($(this).data('submenuTimer'));
  }
});

$('a').on('click', function () {
  $(this.hash).toggleClass('active').focus();
});

$('div').on({
  focusout: function () {
    $(this).data('timer', setTimeout(function () {
      $(this).removeClass('active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this).data('timer'));
  }
});
div {
  display: none;
}
.active {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
  Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>

2番目の問題は、リンクを再度押すとダイアログが閉じないということです。 これは、ダイアログがフォーカスを失ってクローズドビヘイビアがトリガされた後で、リンクをクリックするとダイアログが再オープンされます。

以前の問題と同様に、フォーカス状態を管理する必要があります。 状態の変更が既にキューに入れられていることを考えると、ダイアログのトリガーでフォーカスイベントを処理するだけです。

これはよく知られているはずです
$('a').on({
  focusout: function () {
    $(this.hash).data('timer', setTimeout(function () {
      $(this.hash).removeClass('active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this.hash).data('timer'));  
  }
});

$('a').on('click', function () {
  $(this.hash).toggleClass('active').focus();
});

$('div').on({
  focusout: function () {
    $(this).data('timer', setTimeout(function () {
      $(this).removeClass('active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this).data('timer'));
  }
});

$('a').on({
  focusout: function () {
    $(this.hash).data('timer', setTimeout(function () {
      $(this.hash).removeClass('active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this.hash).data('timer'));  
  }
});
div {
  display: none;
}
.active {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
  Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>

Escキー

あなたがフォーカス状態を処理することで完了したと思ったら、ユーザーエクスペリエンスを簡素化するためにもっと多くのことができます。

これはしばしば「持っているのがいい」機能ですが、 Escキーが閉じられるようなモーダルやポップアップがあればよくあります

keydown: function (e) {
  if (e.which === 27) {
    $(this).removeClass('active');
    e.preventDefault();
  }
}

$('a').on('click', function () {
  $(this.hash).toggleClass('active').focus();
});

$('div').on({
  focusout: function () {
    $(this).data('timer', setTimeout(function () {
      $(this).removeClass('active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this).data('timer'));
  },
  keydown: function (e) {
    if (e.which === 27) {
      $(this).removeClass('active');
      e.preventDefault();
    }
  }
});

$('a').on({
  focusout: function () {
    $(this.hash).data('timer', setTimeout(function () {
      $(this.hash).removeClass('active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this.hash).data('timer'));  
  }
});
div {
  display: none;
}
.active {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
  Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>

ダイアログ内にフォーカス可能な要素があることがわかっている場合は、ダイアログに直接フォーカスする必要はありません。 メニューを作成している場合は、代わりに最初のメニュー項目をフォーカスすることができます。

click: function (e) {
  $(this.hash)
    .toggleClass('submenu--active')
    .find('a:first')
    .focus();
  e.preventDefault();
}

$('.menu__link').on({
  click: function (e) {
    $(this.hash)
      .toggleClass('submenu--active')
      .find('a:first')
      .focus();
    e.preventDefault();
  },
  focusout: function () {
    $(this.hash).data('submenuTimer', setTimeout(function () {
      $(this.hash).removeClass('submenu--active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this.hash).data('submenuTimer'));  
  }
});

$('.submenu').on({
  focusout: function () {
    $(this).data('submenuTimer', setTimeout(function () {
      $(this).removeClass('submenu--active');
    }.bind(this), 0));
  },
  focusin: function () {
    clearTimeout($(this).data('submenuTimer'));
  },
  keydown: function (e) {
    if (e.which === 27) {
      $(this).removeClass('submenu--active');
      e.preventDefault();
    }
  }
});
.menu {
  list-style: none;
  margin: 0;
  padding: 0;
}
.menu:after {
  clear: both;
  content: '';
  display: table;
}
.menu__item {
  float: left;
  position: relative;
}

.menu__link {
  background-color: lightblue;
  color: black;
  display: block;
  padding: 0.5em 1em;
  text-decoration: none;
}
.menu__link:hover,
.menu__link:focus {
  background-color: black;
  color: lightblue;
}

.submenu {
  border: 1px solid black;
  display: none;
  left: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  position: absolute;
  top: 100%;
}
.submenu--active {
  display: block;
}

.submenu__item {
  width: 150px;
}

.submenu__link {
  background-color: lightblue;
  color: black;
  display: block;
  padding: 0.5em 1em;
  text-decoration: none;
}

.submenu__link:hover,
.submenu__link:focus {
  background-color: black;
  color: lightblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
  <li class="menu__item">
    <a class="menu__link" href="#menu-1">Menu 1</a>
    <ul class="submenu" id="menu-1" tabindex="-1">
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#1">Example 1</a></li>
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#2">Example 2</a></li>
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#3">Example 3</a></li>
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#4">Example 4</a></li>
    </ul>
  </li>
  <li class="menu__item">
    <a  class="menu__link" href="#menu-2">Menu 2</a>
    <ul class="submenu" id="menu-2" tabindex="-1">
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#1">Example 1</a></li>
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#2">Example 2</a></li>
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#3">Example 3</a></li>
      <li class="submenu__item"><a class="submenu__link" href="http://example.com/#4">Example 4</a></li>
    </ul>
  </li>
</ul>
lorem ipsum <a href="http://example.com/">dolor</a> sit amet.

WAI-ARIAの役割とその他のアクセシビリティサポート

この回答は、この機能のキーボードとマウスのアクセシビリティの基礎についてはうまくいきたいと思っていますが、すでにかなり大きかったので、 WAI-ARIAの役割と属性の議論を避けるつもりですが、詳細については実装者が仕様を参照することを強くお勧めしますどの役割を使用すべきか、およびその他の適切な属性について説明します。


document上でクリックイベントをリッスンし、 #menucontainer.closest()を使用してクリックされた要素の祖先またはターゲットでないことを確認#menucontainerます。

そうでない場合、クリックされた要素は#menucontainer外にあり、安全に非表示にできます。

$(document).click(function(event) { 
    if(!$(event.target).closest('#menucontainer').length) {
        if($('#menucontainer').is(":visible")) {
            $('#menucontainer').hide();
        }
    }        
});

編集 - 2017-06-23

メニューを終了し、イベントの受信を停止したい場合は、イベントリスナーの後にクリーンアップすることもできます。 この関数は、新しく作成されたリスナーのみをクリーンアップし、 document上の他のクリックリスナーを保持しdocument 。 ES2015の構文:

export function hideOnClickOutside(selector) {
  const outsideClickListener = (event) => {
    if (!$(event.target).closest(selector).length) {
      if ($(selector).is(':visible')) {
        $(selector).hide()
        removeClickListener()
      }
    }
  }

  const removeClickListener = () => {
    document.removeEventListener('click', outsideClickListener)
  }

  document.addEventListener('click', outsideClickListener)
}

編集 - 2018-03-11

jQueryを使いたくない人のために。 上記のコードはプレーンなvanillaJS(ECMAScript6)です。

function hideOnClickOutside(element) {
    const outsideClickListener = event => {
        if (!element.contains(event.target)) { // or use: event.target.closest(selector) === null
            if (isVisible(element)) {
                element.style.display = 'none'
                removeClickListener()
            }
        }
    }

    const removeClickListener = () => {
        document.removeEventListener('click', outsideClickListener)
    }

    document.addEventListener('click', outsideClickListener)
}

const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ) // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js 

注:これは、jQueryパートの代わりに!element.contains(event.target)使用するAlexのコメントに基づいています。

しかし、 element.closest()はすべての主要なブラウザで利用できるようになりました(W3CのバージョンはjQueryのバージョンと少し異なります)。 ポリフィルはhttps://developer.mozilla.org/en-US/docs/Web/API/Element/closest


IEとFF 3. *用にスクリプトを作成していて、特定のボックス領域内でクリックが発生したかどうかを知りたければ、次のようなものを使用することもできます:

this.outsideElementClick = function(objEvent, objElement){   
var objCurrentElement = objEvent.target || objEvent.srcElement;
var blnInsideX = false;
var blnInsideY = false;

if (objCurrentElement.getBoundingClientRect().left >= objElement.getBoundingClientRect().left && objCurrentElement.getBoundingClientRect().right <= objElement.getBoundingClientRect().right)
    blnInsideX = true;

if (objCurrentElement.getBoundingClientRect().top >= objElement.getBoundingClientRect().top && objCurrentElement.getBoundingClientRect().bottom <= objElement.getBoundingClientRect().bottom)
    blnInsideY = true;

if (blnInsideX && blnInsideY)
    return false;
else
    return true;}

これは完全に私のために働いた!

$('html').click(function (e) {
    if (e.target.id == 'YOUR-DIV-ID') {
        //do something
    } else {
        //do something
    }
});

これは私のこの問題に対する解決策です:

$(document).ready(function() {
  $('#user-toggle').click(function(e) {
    $('#user-nav').toggle();
    e.stopPropagation();
  });

  $('body').click(function() {
    $('#user-nav').hide(); 
  });

  $('#user-nav').click(function(e){
    e.stopPropagation();
  });
});

つかいます:

var go = false;
$(document).click(function(){
    if(go){
        $('#divID').hide();
        go = false;
    }
})

$("#divID").mouseover(function(){
    go = false;
});

$("#divID").mouseout(function (){
    go = true;
});

$("btnID").click( function(){
    if($("#divID:visible").length==1)
        $("#divID").hide(); // Toggle
    $("#divID").show();
});

より使いやすく、より表現力豊かなコードのために、私はこれのためにjQueryプラグインを作成しました:

$('div.my-element').clickOut(function(target) { 
    //do something here... 
});

注:targetは、ユーザーが実際にクリックした要素です。しかし、コールバックは、まだ元の要素のコンテキストで実行されるので、あなたが利用することができ、これを使用すると、jQueryのコールバックで期待通り。

プラグイン:

$.fn.clickOut = function (parent, fn) {
    var context = this;
    fn = (typeof parent === 'function') ? parent : fn;
    parent = (parent instanceof jQuery) ? parent : $(document);

    context.each(function () {
        var that = this;
        parent.on('click', function (e) {
            var clicked = $(e.target);
            if (!clicked.is(that) && !clicked.parents().is(that)) {
                if (typeof fn === 'function') {
                    fn.call(that, clicked);
                }
            }
        });

    });
    return context;
};

デフォルトでは、クリックイベントリスナーがドキュメントに配置されます。ただし、イベントリスナーのスコープを制限したい場合は、クリックが聴取される最上位の親となる親レベル要素を表すjQueryオブジェクトを渡すことができます。これにより、不必要なドキュメントレベルのイベントリスナーを防止します。明らかに、与えられた親要素があなたの最初の要素の親でない限り動作しません。

そう使います:

$('div.my-element').clickOut($('div.my-parent'), function(target) { 
    //do something here...
});

今後の視聴者のためのバニラJavaScriptソリューションです

ドキュメント内の任意の要素をクリックすると、クリックされた要素のIDがトグルされた場合、または隠れ要素が隠されていない場合、隠された要素にクリックされた要素が含まれていない場合、要素を切り替えます。

(function () {
    "use strict";
    var hidden = document.getElementById('hidden');
    document.addEventListener('click', function (e) {
        if (e.target.id == 'toggle' || (hidden.style.display != 'none' && !hidden.contains(e.target))) hidden.style.display = hidden.style.display == 'none' ? 'block' : 'none';
    }, false);
})();

(function () {
    "use strict";
    var hidden = document.getElementById('hidden');
    document.addEventListener('click', function (e) {
        if (e.target.id == 'toggle' || (hidden.style.display != 'none' && !hidden.contains(e.target))) hidden.style.display = hidden.style.display == 'none' ? 'block' : 'none';
    }, false);
})();
<a href="javascript:void(0)" id="toggle">Toggle Hidden Div</a>
<div id="hidden" style="display: none;">This content is normally hidden. click anywhere other than this content to make me disappear</div>

同じページに複数のトグルを設定する場合は、次のようなものを使用できます。

  1. 折りたたみ可能なアイテムにhiddenのクラス名を追加します。
  2. ドキュメントをクリックすると、クリックされた要素を含まず、隠されていない隠し要素をすべて閉じます
  3. クリックされた要素がトグルの場合、指定された要素を切り替えます。

(function () {
    "use strict";
    var hiddenItems = document.getElementsByClassName('hidden'), hidden;
    document.addEventListener('click', function (e) {
        for (var i = 0; hidden = hiddenItems[i]; i++) {
            if (!hidden.contains(e.target) && hidden.style.display != 'none')
                hidden.style.display = 'none';
        }
        if (e.target.getAttribute('data-toggle')) {
            var toggle = document.querySelector(e.target.getAttribute('data-toggle'));
            toggle.style.display = toggle.style.display == 'none' ? 'block' : 'none';
        }
    }, false);
})();
<a href="javascript:void(0)" data-toggle="#hidden1">Toggle Hidden Div</a>
<div class="hidden" id="hidden1" style="display: none;" data-hidden="true">This content is normally hidden</div>
<a href="javascript:void(0)" data-toggle="#hidden2">Toggle Hidden Div</a>
<div class="hidden" id="hidden2" style="display: none;" data-hidden="true">This content is normally hidden</div>
<a href="javascript:void(0)" data-toggle="#hidden3">Toggle Hidden Div</a>
<div class="hidden" id="hidden3" style="display: none;" data-hidden="true">This content is normally hidden</div>


他のソリューションは私のためには機能しませんでしたので、

if(!$(event.target).is('#foo'))
{
    // hide menu
}

別のポスターが言ったように、特にあなたが表示している要素(この場合はメニュー)にインタラクティブな要素がある場合は、多くの問題があります。 私は非常に堅牢であるために次の方法を見つけました:

$('#menuscontainer').click(function(event) {
    //your code that shows the menus fully

    //now set up an event listener so that clicking anywhere outside will close the menu
    $('html').click(function(event) {
        //check up the tree of the click target to check whether user has clicked outside of menu
        if ($(event.target).parents('#menuscontainer').length==0) {
            // your code to hide menu

            //this event listener has done its job so we can unbind it.
            $(this).unbind(event);
        }

    })
});

変種として:

var $menu = $('#menucontainer');
$(document).on('click', function (e) {

    // If element is opened and click target is outside it, hide it
    if ($menu.is(':visible') && !$menu.is(e.target) && !$menu.has(e.target).length) {
        $menu.hide();
    }
});

css-tricks.com/dangers-stopping-event-propagationcss-tricks.com/dangers-stopping-event-propagationことは問題ありません。同じページ上の複数のメニューをサポートしています。最初のメニューが開いている間に2番目のメニューをクリックすると、stopPropagationソリューションの最初のメニューが開きます。


状況の簡単な解決策は次のとおりです。

$(document).mouseup(function (e)
{
    var container = $("YOUR SELECTOR"); // Give you class or ID

    if (!container.is(e.target) &&            // If the target of the click is not the desired div or section
        container.has(e.target).length === 0) // ... nor a descendant-child of the container
    {
        container.hide();
    }
});

上記のスクリプトは、 div clickイベントの外側がトリガーされた場合にdivを非表示にします。

詳細については、次のブログを参照してhttp://www.codecanal.com/detect-click-outside-div-using-javascript/ : http://www.codecanal.com/detect-click-outside-div-using-javascript/


研究の後、私は3つの実用的な解決策を見つけました(私は参照のためにページリンクを忘れました)

最初の解決策

<script>
    //The good thing about this solution is it doesn't stop event propagation.

    var clickFlag = 0;
    $('body').on('click', function () {
        if(clickFlag == 0) {
            console.log('hide element here');
            /* Hide element here */
        }
        else {
            clickFlag=0;
        }
    });
    $('body').on('click','#testDiv', function (event) {
        clickFlag = 1;
        console.log('showed the element');
        /* Show the element */
    });
</script>

第2の解決策

<script>
    $('body').on('click', function(e) {
        if($(e.target).closest('#testDiv').length == 0) {
           /* Hide dropdown here */
        }
    });
</script>

第3の解決策

<script>
    var specifiedElement = document.getElementById('testDiv');
    document.addEventListener('click', function(event) {
        var isClickInside = specifiedElement.contains(event.target);
        if (isClickInside) {
          console.log('You clicked inside')
        }
        else {
          console.log('You clicked outside')
        }
    });
</script>

私はいくつかのjQueryカレンダープラグインでこのメソッドを見つけました。

function ClickOutsideCheck(e)
{
  var el = e.target;
  var popup = $('.popup:visible')[0];
  if (popup==undefined)
    return true;

  while (true){
    if (el == popup ) {
      return true;
    } else if (el == document) {
      $(".popup").hide();
      return false;
    } else {
      el = $(el).parent()[0];
    }
  }
};

$(document).bind('mousedown.popup', ClickOutsideCheck);

私はこのようなことをした:

$(document).on('click', 'body, #msg_count_results .close',function() {
    $(document).find('#msg_count_results').remove();
});
$(document).on('click','#msg_count_results',function(e) {
    e.preventDefault();
    return false;
});

私はエンドユーザーフレンドリーなUIの目的のために、新しいコンテナ内にクローズボタンを持っています。私は通過しないためにfalseを返さなければならなかった。もちろん、そこにA HREFを置くことで、あなたをどこかに連れて行くことができます。あるいは、代わりにいくつかのAjaxを呼び出すこともできます。いずれにせよ、それは私のために大丈夫動作します。ちょうど私が欲しいもの。


関数:

$(function() {
    $.fn.click_inout = function(clickin_handler, clickout_handler) {
        var item = this;
        var is_me = false;
        item.click(function(event) {
            clickin_handler(event);
            is_me = true;
        });
        $(document).click(function(event) {
            if (is_me) {
                is_me = false;
            } else {
                clickout_handler(event);
            }
        });
        return this;
    }
});

使用法:

this.input = $('<input>')
    .click_inout(
        function(event) { me.ShowTree(event); },
        function() { me.Hide(); }
    )
    .appendTo(this.node);

機能は非常にシンプルです。

ShowTree: function(event) {
    this.data_span.show();
}
Hide: function() {
    this.data_span.hide();
}

このイベントには、要素のevent.pathというプロパティがあります。この要素は、「すべての祖先をツリー順に静的に並べ替えたリスト」です。イベントが特定のDOM要素またはその子要素から発生したかどうかを確認するには、その特定のDOM要素のパスを確認してください。関数OR内で要素チェックを論理的に行うことにより、複数の要素をチェックするためにも使用できsomeます。

$("body").click(function() {
  target = document.getElementById("main");
  flag = event.path.some(function(el, i, arr) {
    return (el == target)
  })
  if (flag) {
    console.log("Inside")
  } else {
    console.log("Outside")
  }
});
#main {
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
  <ul>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
  </ul>
</div>
<div id="main2">
  Outside Main
</div>

あなたのためにそれはすべきです

$("body").click(function() {
  target = $("#menuscontainer")[0];
  flag = event.path.some(function(el, i, arr) {
    return (el == target)
  });
  if (!flag) {
    // Hide the menus
  }
});

上記のユーザーからのコメントに部分的に基づいた解決策を実装しましたが、これは完璧に機能します。元の要素を除いて、これらの要素の外側をクリックすると、検索ボックス/結果が非表示になります。

// HIDE SEARCH BOX IF CLICKING OUTSIDE
$(document).click(function(event){ 
    // IF NOT CLICKING THE SEARCH BOX OR ITS CONTENTS OR SEARCH ICON 
    if ($("#search-holder").is(":visible") && !$(event.target).is("#search-holder *, #search")) {
        $("#search-holder").fadeOut('fast');
        $("#search").removeClass('active');
    }
});

検索ボックスがすでに最初に表示されているかどうかをチェックし、この場合は、非表示/検索検索ボタンでアクティブなクラスも削除します。


$("#menuscontainer").click(function() {
    $(this).focus();
});
$("#menuscontainer").blur(function(){
    $(this).hide();
});

私のためにうまく動作します。





jquery