사용자가 이러한 메뉴의 헤드를 클릭할 때 완전히 표시되는 일부 HTML 메뉴가 있습니다. 사용자가 메뉴 영역 외부를 클릭할 때 이러한 요소를 숨기고 싶습니다.
jQuery로 이와 같은 것이 가능합니까?
$("#menuscontainer").clickOutsideThisElement(function() { // Hide the menus });
질문자 :Community Wiki
사용자가 이러한 메뉴의 헤드를 클릭할 때 완전히 표시되는 일부 HTML 메뉴가 있습니다. 사용자가 메뉴 영역 외부를 클릭할 때 이러한 요소를 숨기고 싶습니다.
jQuery로 이와 같은 것이 가능합니까?
$("#menuscontainer").clickOutsideThisElement(function() { // Hide the menus });
참고:
stopPropagation
사용하면 DOM의 정상적인 이벤트 흐름이 중단되므로 피해야 합니다. 자세한 내용은 이 CSS 트릭 문서 를 참조하세요. 대신 이 방법을 사용하는 것이 좋습니다.
창을 닫는 문서 본문에 클릭 이벤트를 첨부합니다. 문서 본문에 대한 전파를 중지하는 별도의 클릭 이벤트를 컨테이너에 첨부합니다.
$(window).click(function() { //Hide the menus if visible }); $('#menucontainer').click(function(event){ event.stopPropagation(); });
document
에서 클릭 이벤트를 수신한 다음 .closest()
#menucontainer
가 클릭된 요소의 조상 또는 대상이 아닌지 확인할 수 있습니다.
그렇지 않은 경우 클릭된 요소는 #menucontainer
외부에 있으므로 안전하게 숨길 수 있습니다.
$(document).click(function(event) { var $target = $(event.target); if(!$target.closest('#menucontainer').length && $('#menucontainer').is(":visible")) { $('#menucontainer').hide(); } });
메뉴를 닫고 이벤트 수신을 중지하려는 경우 이벤트 리스너 이후를 정리할 수도 있습니다. 이 함수는 새로 생성된 리스너만 정리하고 document
다른 클릭 리스너는 보존합니다. ES2015 구문 사용:
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) }
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
참고: 이것은 jQuery 부분 대신 !element.contains(event.target)
를 사용하기 위한 Alex 주석을 기반으로 합니다.
그러나 element.closest()
는 이제 모든 주요 브라우저에서도 사용할 수 있습니다(W3C 버전은 jQuery 버전과 약간 다름). 폴리필은 여기에서 찾을 수 있습니다: Element.closest()
사용자가 요소 내부를 클릭하고 드래그할 수 있게 하려면 요소를 닫지 않고 요소 외부에서 마우스를 놓으십시오.
... 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
이벤트를 트리거하는 것은 아니기 때문입니다. 마우스를 사용하지 않는 사용자는 Tab 키 를 눌러 대화 상자(그리고 팝업 메뉴는 틀림없이 대화 상자 유형임)를 벗어날 수 click
트리거하지 않고는 대화 상자 뒤에 있는 내용을 읽을 수 없습니다. 이벤트.
그럼 질문을 바꿔보겠습니다.
사용자가 대화를 마쳤을 때 대화 상자를 어떻게 닫습니까?
이것이 목표입니다. 불행히도 이제 우리는 userisfinishedwiththedialog
를 바인딩해야 하며 그 바인딩은 그렇게 간단하지 않습니다.
그러면 사용자가 대화 상자 사용을 완료했음을 어떻게 감지할 수 있습니까?
focusout
이벤트포커스가 대화 상자를 벗어났는지 확인하는 것이 좋습니다.
힌트: blur
이벤트에 주의하십시오. 이벤트가 버블링 단계에 바인딩된 경우 blur
jQuery의 focusout
은 잘 될 것입니다. 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분 이상 플레이하면 문제가 빨리 보이기 시작해야 합니다.
첫 번째는 대화 상자의 링크를 클릭할 수 없다는 것입니다. 그것을 클릭하거나 탭을 시도하면 상호 작용이 일어나기 전에 대화 상자가 닫힙니다. 내부 요소에 초점을 focusin
이벤트가 다시 focusout
이벤트가 발생하기 때문입니다.
수정 사항은 이벤트 루프에서 상태 변경을 대기열에 넣는 것입니다. setImmediate(...)
를 사용하거나 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>
두 번째 문제는 링크를 다시 눌러도 대화 상자가 닫히지 않는다는 것입니다. 이는 대화 상자가 포커스를 잃고 닫기 동작을 트리거한 후 링크 클릭이 대화 상자를 다시 열도록 트리거하기 때문입니다.
이전 문제와 마찬가지로 포커스 상태를 관리해야 합니다. 상태 변경이 이미 대기 중이라는 점을 감안할 때 대화 상자 트리거에서 포커스 이벤트를 처리하기만 하면 됩니다.
이것은 친숙하게 보일 것입니다. $('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 역할과 특성을 하지만 내가보기 엔 구현 세부 사항에 대한 사양을 참조하는 것이 좋습니다, 그들이 사용해야 하는 역할과 기타 적절한 속성.
여기에 있는 다른 솔루션은 저에게 효과가 없었으므로 다음을 사용해야 했습니다.
if(!$(event.target).is('#foo')) { // hide menu }
이 방법을 사용하여 외부를 클릭할 때 드롭다운 메뉴 닫기를 처리했습니다.
먼저 구성 요소의 모든 요소에 대한 사용자 정의 클래스 이름을 만들었습니다. 이 클래스 이름은 메뉴 위젯을 구성하는 모든 요소에 추가됩니다.
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의 one()
함수 에 대한 추가 정보
event.composedPath()
사용할 수 있습니다.발신: https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath
Event 인터페이스의 configuredPath() 메서드는 이벤트의 경로를 반환합니다. 이 경로는 리스너가 호출될 객체의 배열입니다.
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>
연구 후 세 가지 작업 솔루션을 찾았습니다(참조용 페이지 링크를 잊었습니다).
<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(); });
나를 위해 잘 작동합니다.
이제 이를 위한 플러그인이 있습니다. 외부 이벤트 ( 블로그 게시물 )
다음은 WLOG(clickoutside 핸들러)가 요소에 바인딩될 때 발생합니다.
따라서 전파에서 이벤트가 중지되지 않으며 외부 처리기가 있는 요소 "위에서" 추가 클릭 처리기를 사용할 수 있습니다.
이것은 나를 위해 완벽하게 일했습니다 !!
$('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/
사용자가 외부를 클릭할 때 메뉴를 닫는 것이 정말로 필요한 것은 아니라고 생각합니다. 필요한 것은 사용자가 페이지의 아무 곳이나 클릭할 때 메뉴가 닫히는 것입니다. 메뉴를 클릭하거나 메뉴를 끄면 닫히겠죠?
위의 만족스러운 답변을 찾지 못해 요 전에 이 블로그 게시물 을 작성하게 되었습니다. 좀 더 현학적인 경우 주의해야 할 문제가 많이 있습니다.
body { margin-left:auto; margin-right: auto; width:960px;}
다른 포스터가 말했듯이 특히 표시하는 요소(이 경우 메뉴)에 대화형 요소가 있는 경우 문제가 많습니다. 다음 방법이 상당히 강력하다는 것을 알았습니다.
$('#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); } }) });
창 클릭 이벤트 대상을 확인하고(다른 곳에서 캡처되지 않는 한 창으로 전파되어야 함) 메뉴 요소가 아닌지 확인합니다. 그렇지 않으면 메뉴 밖에 있는 것입니다.
또는 클릭 위치를 확인하고 메뉴 영역에 포함되어 있는지 확인합니다.
부작용이 있을 수 있는 event.stopPropagation()을 사용하는 대신 간단한 플래그 변수를 정의하고 if
조건을 하나 추가하면 됩니다. 나는 이것을 테스트했고 stopPropagation의 부작용 없이 제대로 작동했습니다.
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"; } });
간단한 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
를 숨기는 본문에 클릭 핸들러를 바인딩합니다.
나는 아무도 실제로 focusout
이벤트를 인정하지 않았다는 것에 놀랐습니다.
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>
이벤트에는 "트리 순서의 모든 상위 항목의 정적 순서 목록"인 요소의 event.path라는 속성이 있습니다. 이벤트가 특정 DOM 요소 또는 그 자식 중 하나에서 발생했는지 확인하려면 해당 특정 DOM 요소의 경로를 확인하면 됩니다. some
함수에서 요소 검사를 OR
하여 여러 요소를 검사하는 데 사용할 수도 있습니다.
$("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);
다음은 미래의 시청자를 위한 바닐라 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>
동일한 페이지에 여러 토글을 사용하려는 경우 다음과 같이 사용할 수 있습니다.
hidden
클래스 이름을 추가합니다. (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>
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;}
흐름 중단, 흐림/초점 이벤트 또는 기타 까다로운 기술을 사용하는 대신 이벤트 흐름을 요소의 친족과 일치시키기만 하면 됩니다.
$(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(); });
여기에 궁금한 사람이 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'; }
});
다음은 순수한 자바 스크립트의 간단한 솔루션입니다. 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>
여기 에서 튜토리얼을 읽을 수 있습니다
네이티브 JS API 가장 가까운 방법을 사용하는 2020 솔루션.
document.addEventListener('click', ({ target }) => { if (!target.closest('.el1, .el2, #el3')) { alert('click outside') } })
$(document).click(function() { $(".overlay-window").hide(); }); $(".overlay-window").click(function() { return false; });
문서를 클릭하면 동일한 요소를 클릭하지 않는 한 주어진 요소를 숨깁니다.
문서에 클릭 이벤트 리스너를 연결합니다. 이벤트 리스너 내에서 이벤트 객체 , 특히 event.target 을 보고 어떤 요소가 클릭되었는지 확인할 수 있습니다.
$(document).click(function(e){ if ($(e.target).closest("#menuscontainer").length == 0) { // .closest can help you determine if the element // or one of its ancestors is #menuscontainer console.log("hide"); } });
출처 : http:www.stackoverflow.com/questions/152975/how-do-i-detect-a-click-outside-an-element
단일 비트를 어떻게 설정, 지우고 토글합니까? (0) | 2021.11.11 |
---|---|
JavaScript에서 쿼리 문자열 값을 얻으려면 어떻게 해야 합니까? (0) | 2021.11.11 |
JavaScript를 사용하여 JSON 예쁘게 인쇄하기 (0) | 2021.11.11 |
HTML5 localStorage에 객체 저장하기 (0) | 2021.11.11 |
__init__() 메서드로 Python super() 이해하기 [중복] (0) | 2021.11.11 |