source

요소 외부의 클릭을 감지하려면 어떻게 해야 합니까?

nicesource 2023. 1. 8. 14:35
반응형

요소 외부의 클릭을 감지하려면 어떻게 해야 합니까?

HTML 메뉴가 몇 개 있는데, 사용자가 이 메뉴들의 머리 부분을 클릭하면 완전히 표시됩니다.사용자가 메뉴 영역 밖을 클릭할 때 이러한 요소를 숨기고 싶습니다.

jQuery에서 이런 일이 가능합니까?

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

사용방법: " " "stopPropagationDOM 내의 정상적인 이벤트플로우를 깨뜨리기 때문에 피해야 합니다.상세한 것에 대하여는, 이 CSS Tricks 기사를 참조해 주세요.대신 이 방법을 사용하는 것이 좋습니다.

창을 닫는 문서 본문에 클릭 이벤트를 첨부합니다.별도의 클릭 이벤트를 컨테이너에 첨부하여 문서 본문에 전파를 중지합니다.

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

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

클릭 이벤트는 다음에서 들을 수 있습니다.document 에 꼭 해 주세요.#menucontainer를 사용하여 클릭한 요소의 상위 또는 대상이 아닙니다.

않은 는 이 항목 밖에 .#menucontainer이치노

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

편집 – 2017-06-23

메뉴를 해제하고 이벤트 수신을 중지하려는 경우 이벤트 수신기를 정리할 수도 있습니다.는 새로 하고 다른 는 모두 합니다.documentES2015:

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

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

  document.addEventListener('click', outsideClickListener);
}

편집 – 2018-03-11

jQuery를 사용하지 않으시는 분들을 위해.위의 코드는 플레인 바닐라 JS(ECMAScript6)로 되어 있습니다.

function hideOnClickOutside(element) {
    const outsideClickListener = event => {
        if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
          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 

메모: 이것은 Alex의 코멘트에 근거한 것입니다.!element.contains(event.target) 대신j.쿼리 " " " " 입니다.

★★★★★★★★★★★★★★★★★.element.closest()는 모든 주요 브라우저에서도 사용할 수 있게 되었습니다(W3C 버전은 jQuery 버전과 조금 다릅니다).폴리필은 Element.closest()에서 찾을 수 있습니다.

편집 – 2020-05-21

사용자가 요소 내부를 클릭하여 드래그한 후 요소를 닫지 않고 요소 외부에 마우스를 놓을 수 있도록 하려면 다음 절차를 따릅니다.

      ...
      let lastMouseDownX = 0;
      let lastMouseDownY = 0;
      let lastMouseDownWasOutside = false;

      const mouseDownListener = (event: MouseEvent) => {
        lastMouseDownX = event.offsetX;
        lastMouseDownY = event.offsetY;
        lastMouseDownWasOutside = !$(event.target).closest(element).length;
      }
      document.addEventListener('mousedown', mouseDownListener);

★★★★★★★★★★★★★★★.outsideClickListener:

const outsideClickListener = event => {
        const deltaX = event.offsetX - lastMouseDownX;
        const deltaY = event.offsetY - lastMouseDownY;
        const distSq = (deltaX * deltaX) + (deltaY * deltaY);
        const isDrag = distSq > 3;
        const isDragException = isDrag && !lastMouseDownWasOutside;

        if (!element.contains(event.target) && isVisible(element) && !isDragException) { // or use: event.target.closest(selector) === null
          element.style.display = 'none';
          removeClickListener();
          document.removeEventListener('mousedown', mouseDownListener); // Or add this line to removeClickListener()
        }
    }

요소 외부의 클릭을 감지하는 방법

이 질문이 인기가 많고 답이 많은 이유는 그것이 기만적으로 복잡하기 때문이다.거의 8년 동안 수십 개의 답변을 받은 후, 접근성에 대한 관심이 얼마나 적은지 보고 정말 놀랐습니다.

사용자가 메뉴 영역 밖을 클릭할 때 이러한 요소를 숨기고 싶습니다.

이것은 숭고한 명분이고 실제 문제이다.질문의 제목(대부분의 답변에서 다루려고 하는 것처럼 보이는 것)에는 유감스러운 문제가 포함되어 있습니다.

힌트: 클릭!

클릭 핸들러를 실제로 바인드하고 싶지 않습니다.

대화 상자를 닫으려면 핸들러를 클릭하십시오.한 모든 이 트리거하는 것은 입니다.click이벤트입니다.마우스를 사용하지 않는 사용자는 를 눌러 대화 상자를 벗어날 수 있습니다(팝업 메뉴는 거의 틀림없이 대화상자의 일종입니다). 그 후 대화 상자 뒤에 있는 내용을 읽을 때는 나중에 를 트리거해야 합니다.click

그럼 질문을 바꿔서 해 봅시다.

사용자가 대화상자를 종료했을 때 어떻게 닫습니까?

그런데이렇게 묶어야 .userisfinishedwiththedialog그 결속은 그리 간단하지 않아요

그러면 사용자가 대화상자를 사용한 것을 어떻게 검출할 수 있을까요?

focusout

대화 상자에서 포커스가 사라졌는지 확인하는 것이 좋습니다.

: 주의:blur 「」,blur이벤트가 버블링 단계에 바인딩되어 있으면 전파되지 않습니다.

jQuery's는 괜찮을거야.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분 이상 재생하면 문제가 바로 표시됩니다.

첫 번째는 대화상자의 링크를 클릭할 수 없다는 것입니다.대화 상자를 클릭하거나 탭을 클릭하면 대화 상자가 닫히기 전에 대화 상자가 닫힙니다. 이유는 의 포커싱이 '내부 요소'를 입니다.focusoutfocusin츠키다

수정은 이벤트 루프에서 상태 변경을 큐잉하는 것입니다. 할 수 .setImmediate(...) , 「」setTimeout(..., 0)하지 않는 setImmediate 큐잉으로 할 수 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>

두 번째 문제는 링크를 다시 눌러도 대화 상자가 닫히지 않는다는 것입니다.이는 대화상자가 포커스를 잃고 닫힘 동작을 트리거하기 때문입니다.그 후 링크 클릭을 하면 대화상자가 다시 열립니다.

이전 호와 마찬가지로 포커스 상태 관리가 필요합니다.상태 변경은 이미 큐잉되어 있기 때문에 대화상자 트리거의 포커스이벤트 처리만 하면 됩니다

어디서 많이 본 것 같은데
$('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

포커스 스테이트를 처리함으로써 완료되었다고 생각되는 경우는, 유저 익스피리언스를 심플화하기 위해서 할 수 있는 일이 더 있습니다.

이것은 많은 경우 "갖기 좋은" 기능이지만, 일반적으로 모달이나 팝업이 있을 때 키가 닫힙니다.

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의 역할과 속성에 대해서는 설명하지 않겠습니다.다만, 실장자가 사용하는 역할과 그 외의 적절한 속성에 대해서는, 사양을 참조하는 것을 강하게 추천합니다.

여기 있는 다른 솔루션들은 나에게 효과가 없었기 때문에 나는 다음 방법을 사용해야만 했다.

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

편집 : 플레인 Javascript 버전(2021-03-31)

이 방법을 사용하여 드롭다운 메뉴를 닫을 때 해당 메뉴를 닫았습니다.

먼저 컴포넌트의 모든 요소에 대해 커스텀클래스 이름을 만들었습니다.이 클래스 이름은 메뉴 위젯을 구성하는 모든 요소에 추가됩니다.

const className = `dropdown-${Date.now()}-${Math.random() * 100}`;

클릭 여부 및 클릭된 요소의 클래스 이름을 확인하는 기능을 만듭니다.위에서 되지 않은 " " " 를 해야 합니다.show을 들다false그러면 메뉴가 닫힙니다.

const onClickOutside = (e) => {
  if (!e.target.className.includes(className)) {
    show = false;
  }
};

그런 다음 클릭 핸들러를 창 개체에 부착했습니다.

// add when widget loads
window.addEventListener("click", onClickOutside);

그리고 마지막으로 집안일을 좀 하고 있다.

// remove listener when destroying the widget
window.removeEventListener("click", onClickOutside);

메뉴를 열 때 클릭 이벤트를 본문에 첨부하는 것 이외에는 Eran의 예와 같은 기능을 하는 어플리케이션이 있습니다.이런 느낌이에요.

$('#menucontainer').click(function(event) {
  $('html').one('click',function() {
    // Hide the menus
  });

  event.stopPropagation();
});

jQuery 함수에 대한 자세한 정보

이고 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★」event.composedPath()

송신원: https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath

이벤트 인터페이스의 composedPath() 메서드는 수신자가 호출되는 객체의 배열인 이벤트 경로를 반환합니다.

const target = document.querySelector('#myTarget')

document.addEventListener('click', (event) => {
  const withinBoundaries = event.composedPath().includes(target)

  if (withinBoundaries) {
    target.innerText = 'Click happened inside element'
  } else {
    target.innerText = 'Click happened **OUTSIDE** element'
  } 
})
/* just to make it good looking. you don't need this */
#myTarget {
  margin: 50px auto;
  width: 500px;
  height: 500px;
  background: gray;
  border: 10px solid black;
}
<div id="myTarget">
  click me (or not!)
</div>

조사 결과, 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>

두 번째 솔루션

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

세 번째 솔루션

<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>
$("#menuscontainer").click(function() {
    $(this).focus();
});
$("#menuscontainer").blur(function(){
    $(this).hide();
});

난 괜찮아.

외부 이벤트(블로그 투고)를 위한 플러그인이 있습니다.

Clickoutside Handler(WLOG; 클릭아웃사이드 핸들러)가 요소에 바인드 되어 있는 경우는, 다음과 같이 됩니다.

  • 요소는 클릭 아웃사이드 핸들러가 있는 모든 요소를 유지하는 배열에 추가됩니다.
  • (이름 앞) 클릭 핸들러가 문서에 바인딩되어 있습니다(아직 존재하지 않는 경우).
  • 문서를 클릭할 때마다 클릭아웃사이드 이벤트가 해당 배열의 요소 중 클릭아웃 타깃과 동일하지 않거나 상위 요소에 대해 트리거됩니다.
  • 또한 클릭아웃사이드 이벤트의 event.target은 사용자가 클릭한 요소로 설정됩니다(따라서 사용자가 Outside를 클릭했을 뿐만 아니라 무엇을 클릭했는지도 알 수 있습니다).

따라서 이벤트는 전파에서 정지되지 않으며 외부 핸들러와 함께 요소 위에서 클릭 핸들러를 추가로 사용할 수 있습니다.

나한텐 완벽하게 먹혔어!!

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

이 상황에 대한 간단한 해결책은 다음과 같습니다.

$(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의 경우div이치노

상세한 것에 대하여는, 다음의 블로그를 참조해 주세요.http://www.codecanal.com/detect-click-outside-div-using-javascript/

사용자가 바깥쪽을 클릭했을 때 메뉴를 닫는 것이 아니라 사용자가 페이지에서 아무 곳이나 클릭했을 때 메뉴를 닫는 것이 필요하다고 생각합니다.메뉴를 클릭하거나 메뉴를 해제하면 닫히겠죠?

위의 답변이 만족스럽지 않아서 얼마 전 이 블로그 투고를 쓰게 되었습니다.좀 더 현학적이라면 주의해야 할 몇 가지 사항이 있습니다.

  1. 클릭 시 클릭 이벤트 핸들러를 본문 요소에 부착하는 경우 메뉴를 닫고 이벤트를 바인딩 해제하기 전에 두 번째 클릭을 기다려야 합니다.그렇지 않으면 메뉴를 열었던 클릭 이벤트가 메뉴를 닫아야 하는 청취자에게 버블됩니다.
  2. 클릭 이벤트에서 event.stopPropogation()을 사용하는 경우 페이지 내의 다른 요소는 클릭 시 아무 곳이나 닫을 수 없습니다.
  3. 클릭 이벤트 핸들러를 본문 요소에 무기한 접속하는 것은 퍼포먼스 솔루션이 아닙니다.
  4. 이벤트의 대상과 상위 이벤트를 핸들러의 작성자와 비교하는 것은 메뉴를 클릭했을 때 메뉴를 닫는 것을 전제로 하며, 페이지 상의 아무 곳이나 클릭했을 때 메뉴를 닫는 것을 전제로 합니다.
  5. 본문 요소에 대한 이벤트를 듣는 것은 코드를 더 취약하게 만듭니다.한 스타일링을 .body { margin-left:auto; margin-right: auto; width:960px;}

다른 포스터에서 알 수 있듯이, 특히 표시하는 요소(이 경우 메뉴)에 인터랙티브 요소가 있는 경우, 많은 겟차들이 있습니다.cha)가 있습니다.다음 방법이 상당히 강력하다는 것을 알게 되었습니다.

$('#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 button = document.getElementById('button');
button.addEventListener('click', function(e){
  e.target.style.backgroundColor = 'green';
});
button.addEventListener('focusout', function(e){
  e.target.style.backgroundColor = '';
});
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <button id="button">Click</button>
</body>
</html>

해결책 1

.stopPropagation()을 추가합니다.if i. 이것을 하고, 의 부작용 없이 동작했습니다전파를 정지하다

var flag = "1";
$('#menucontainer').click(function(event){
    flag = "0"; // flag 0 means click happened in the area where we should not do any action
});

$('html').click(function() {
    if(flag != "0"){
        // Hide the menus if visible
    }
    else {
        flag = "1";
    }
});

해결책 2

한 ★★★★★★if★★★★

$(document).on('click', function(event){
    var container = $("#menucontainer");
    if (!container.is(event.target) &&            // If the target of the click isn't the container...
        container.has(event.target).length === 0) // ... nor a descendant of the container
    {
        // Do whatever you want to do when click is outside the element
    }
});

저는 다음과 같은 방법으로 성공을 거뒀습니다.

var $menuscontainer = ...;

$('#trigger').click(function() {
  $menuscontainer.show();

  $('body').click(function(event) {
    var $target = $(event.target);

    if ($target.parents('#menuscontainer').length == 0) {
      $menuscontainer.hide();
    }
  });
});

는 '언제인가' 입니다#menuscontainer를, 「 핸들러」를 숨기는 합니다.#menuscontainer그 가 아닌

이 이벤트에는 요소의 event.path라는 속성이 있습니다. 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;
  background:yellow;
}
<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
  }
});

변종으로서:

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();
    }
});

이벤트 전파를 정지하는 데 문제가 없으며 첫 번째 메뉴가 열려 있을 때 두 번째 메뉴를 클릭하면 첫 번째 메뉴가 stopPropagation 솔루션에서 열린 상태로 유지되는 동일한 페이지에서 여러 메뉴를 더 잘 지원합니다.

이 메서드는 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);

focusout을 위해

에서는 '하다'에 초점을 있어요click이벤트는 키보드 사용자를 위한 접근성 문제입니다.focusout여기서 event를 사용하는 것은 올바르지만, 다른 답변보다 훨씬 간단하게 실행할 수 있습니다(순수한 javascript에서도 마찬가지입니다.

보다 심플한 방법:

'focusout대화 상자/모달/메뉴 내의 요소가 포커스를 잃었을 경우, 다른 요소에 대해서도 이벤트가 발생한다는 것입니다. 않다는 알 수 있어요.event.relatedTarget(어떤 요소가 초점을 맞췄는지 알 수 있습니다).

dialog = document.getElementById("dialogElement")

dialog.addEventListener("focusout", function (event) {
    if (
        // we are still inside the dialog so don't close
        dialog.contains(event.relatedTarget) ||
        // we have switched to another tab so probably don't want to close 
        !document.hasFocus()  
    ) {
        return;
    }
    dialog.close();  // or whatever logic you want to use to close
});

살짝 있는 게 , 은 바로 에에 、 there there 、 것 there 、 것 there to there there there there there there there there there there there there there there there there there there there there 。relatedTargetnull사용자가 대화상자 밖을 클릭하는 경우에는 문제가 없지만 사용자가 대화상자 내부를 클릭하지 않으면 대화 상자가 포커스를 맞출 수 없는 경우에는 문제가 됩니다. , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,tabIndex=0대화에 집중할 수 있습니다.

이것은 미래의 시청자를 위한 바닐라 자바스크립트 솔루션입니다.

문서 내에서 요소를 누를 때, 누른 요소의 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>

네이티브 JS API 가장 가까운 방법을 사용한 2020 솔루션.

document.addEventListener('click', ({ target }) => {
  if (!target.closest('#menupop')) {
    document.querySelector('#menupop').style.display = 'none'
  }
})
#menupop {
    width: 300px;
    height: 300px;
    background-color: red;
}
<div id="menupop">
clicking outside will close this
</div>

javascript 솔루션(es6)에 대해 궁금한 사람이 있다면:

window.addEventListener('mouseup', e => {
        if (e.target != yourDiv && e.target.parentNode != yourDiv) {
            yourDiv.classList.remove('show-menu');
            //or yourDiv.style.display = 'none';
        }
    })

및 es5(만일의 경우):

window.addEventListener('mouseup', function (e) {
if (e.target != yourDiv && e.target.parentNode != yourDiv) {
    yourDiv.classList.remove('show-menu'); 
    //or yourDiv.style.display = 'none';
}

});

흐름 중단, 흐림/초점 이벤트 또는 기타 까다로운 기술을 사용하는 대신 이벤트 흐름을 요소의 친족 관계와 연결하기만 하면 됩니다.

$(document).on("click.menu-outside", function(event){
    // Test if target and it's parent aren't #menuscontainer
    // That means the click event occur on other branch of document tree
    if(!$(event.target).parents().andSelf().is("#menuscontainer")){
        // Click outisde #menuscontainer
        // Hide the menus (but test if menus aren't already hidden)
    }
});

외부 이벤트 리스너를 삭제하려면 다음 절차를 따릅니다.

$(document).off("click.menu-outside");

용도:

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();
});

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;
}

여기 순수한 자바스크립트에 의한 간단한 해결책이 있습니다.ES6에서는 최신 버전입니다.

var isMenuClick = false;
var menu = document.getElementById('menuscontainer');
document.addEventListener('click',()=>{
    if(!isMenuClick){
       //Hide the menu here
    }
    //Reset isMenuClick 
    isMenuClick = false;
})
menu.addEventListener('click',()=>{
    isMenuClick = true;
})

아래 스크립트를 사용하여 jQuery를 완료했습니다.

jQuery(document).click(function(e) {
    var target = e.target; //target div recorded
    if (!jQuery(target).is('#tobehide') ) {
        jQuery(this).fadeOut(); //if the click element is not the above id will hide
    }
})

아래에서 HTML 코드를 찾습니다.

<div class="main-container">
<div> Hello I am the title</div>
<div class="tobehide">I will hide when you click outside of me</div>
</div>

튜토리얼은 이쪽에서 보실 수 있습니다.

$(document).click(function() {
    $(".overlay-window").hide();
});
$(".overlay-window").click(function() {
    return false;
});

문서를 클릭할 경우 동일한 요소를 클릭하지 않는 한 해당 요소를 숨깁니다.

언급URL : https://stackoverflow.com/questions/152975/how-do-i-detect-a-click-outside-an-element

반응형