ใช้ jQuery เพื่อซ่อน DIV เมื่อผู้ใช้คลิกด้านนอก


967

ฉันใช้รหัสนี้:

$('body').click(function() {
   $('.form_wrapper').hide();
});

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

และHTMLนี้:

<div class="form_wrapper">
   <a class="agree" href="javascript:;">I Agree</a>
   <a class="disagree" href="javascript:;">Disagree</a>
</div>

ปัญหาคือฉันมีลิงค์ภายในdivและเมื่อพวกเขาไม่ทำงานเมื่อคลิก


6
การใช้จาวาสคริปต์แบบธรรมดาคุณสามารถลองสิ่งนี้: jsfiddle.net/aamir/y7mEY
Aamir Afridi

ใช้$('html')หรือ$(document)ดีกว่า$('body')
Adrien ใช้

คำตอบ:


2484

มีปัญหาเดียวกันเกิดขึ้นกับวิธีแก้ปัญหาง่าย ๆ นี้ มันยังทำงานซ้ำได้:

$(document).mouseup(function(e) 
{
    var container = $("YOUR CONTAINER SELECTOR");

    // if the target of the click isn't the container nor a descendant of the container
    if (!container.is(e.target) && container.has(e.target).length === 0) 
    {
        container.hide();
    }
});

19
เพียงแค่ใส่ไว้ในโครงการของฉัน แต่มีการปรับเปลี่ยนเล็กน้อยโดยใช้องค์ประกอบต่างๆเพื่อวนรอบพวกเขาทั้งหมดในครั้งเดียว jsfiddle.net/LCB5W
Thomas

5
@mpelzsherman หลายคนแสดงความคิดเห็นว่าข้อมูลโค้ดทำงานบนอุปกรณ์ระบบสัมผัส แต่เนื่องจากโพสต์ได้รับการแก้ไขความคิดเห็นเหล่านี้จึงหายไปบ้าง TBH ฉันไม่รู้ว่าฉันใช้ "mouseup" ด้วยเหตุผลเฉพาะหรือไม่ แต่ถ้ามันใช้งานได้กับ "คลิก" ฉันไม่เห็นเหตุผลว่าทำไมคุณไม่ควรใช้ "คลิก"

6
ฉันต้องการให้คอนเทนเนอร์ถูกซ่อนหนึ่งครั้งกับเหตุการณ์นี้การติดต่อกลับนี้ควรถูกทำลายเมื่อใช้งาน ในการทำเช่นนั้นฉันใช้เนมสเปซในเหตุการณ์การคลิกที่มีการผูก ("click.namespace") และเมื่อเกิดเหตุการณ์ขึ้นฉันจะโทรยกเลิกการผูก ("click.namespace") และสุดท้ายฉันใช้ $ (e.target) .closest (". container") ความยาวเพื่อรับรู้คอนเทนเนอร์ ... ดังนั้นฉันไม่ได้ใช้เคล็ดลับใด ๆ จากคำตอบนี้: D
Loenix

80
ความทรงจำที่จะใช้เพียงข้าง$("YOUR CONTAINER SELECTOR").unbind( 'click', clickDocument ); .hide()ดังนั้นdocumentอย่าคอยฟังเสียงคลิก
brasofilo

12
สำหรับแนวทางปฏิบัติที่ดีที่สุดฉันได้เขียนไว้$(document).on("mouseup.hideDocClick", function () { ... });ในฟังก์ชันที่เปิดคอนเทนเนอร์และ$(document).off('.hideDocClick');ในฟังก์ชั่นซ่อน การใช้เนมสเปซฉันไม่ได้ลบmouseupผู้ฟังที่เป็นไปได้อื่น ๆ ที่แนบมากับเอกสาร
campsjos

204

คุณควรไปกับสิ่งนี้:

var mouse_is_inside = false;

$(document).ready(function()
{
    $('.form_content').hover(function(){ 
        mouse_is_inside=true; 
    }, function(){ 
        mouse_is_inside=false; 
    });

    $("body").mouseup(function(){ 
        if(! mouse_is_inside) $('.form_wrapper').hide();
    });
});

ฉลาดแค่ไหน! เป็นเทคนิคมาตรฐานหรือไม่
advait

@advait ฉันไม่เคยเห็นมาก่อน มันคือทั้งหมดที่เกี่ยวกับhoverตัวจัดการเหตุการณ์ซึ่งเปิดโอกาสมากมาย
Makram Saleh

5
ฉันไม่คิดว่านี่จะเป็นวิธีแก้ปัญหาที่ดีเพราะมันทำให้คนคิดว่ามันเป็นเรื่องปกติที่จะเติมวัตถุหน้าต่าง (= โดยใช้ตัวแปรทั่วโลก)

1
เพียงเพิ่มบางสิ่งที่ @ prc322 พูดคุณสามารถใส่โค้ดของคุณด้วยฟังก์ชั่นนิรนามและเรียกมันทันที (function() { // ... code })(); ฉันจำชื่อโอแบบนี้ไม่ได้ แต่มันมีประโยชน์มาก! ตัวแปรที่ประกาศทั้งหมดของคุณจะอยู่ภายในฟังก์ชันและจะไม่ทำให้เกิดเนมสเปซส่วนกลาง
pedromanoel

3
@ prc322 หากคุณไม่รู้วิธีเปลี่ยนขอบเขตของตัวแปรคุณก็ถูกต้องทางออกนี้ไม่ดีสำหรับคุณ ... และไม่ใช่ JavaScript หากคุณเพียงแค่คัดลอกและวางรหัสจาก Stack Overflow คุณจะมีปัญหามากกว่าการเขียนทับบางอย่างในวัตถุหน้าต่าง
กาวิน

87

รหัสนี้จะตรวจจับเหตุการณ์การคลิกใด ๆ บนหน้าแล้วซ่อน#CONTAINERองค์ประกอบถ้าและเมื่อองค์ประกอบที่คลิกนั้นไม่ใช่#CONTAINERองค์ประกอบหรือหนึ่งในลูกหลานของมัน

$(document).on('click', function (e) {
    if ($(e.target).closest("#CONTAINER").length === 0) {
        $("#CONTAINER").hide();
    }
});

มันสมบูรณ์แบบ !!
Mohd Abdul Mujib

@ 9KSoft ฉันดีใจที่สามารถช่วยคุณได้ ขอบคุณสำหรับคำติชมและขอให้โชคดี
คดี

วิธีการแก้ปัญหานี้ทำงานอย่างสมบูรณ์แบบสำหรับฉันโดยใช้ div เป็นที่เก็บ!
JCO9

76

คุณอาจต้องการตรวจสอบเป้าหมายของเหตุการณ์คลิกที่ยิงร่างกายแทนการพึ่งพา stopPropagation

สิ่งที่ต้องการ:

$("body").click
(
  function(e)
  {
    if(e.target.className !== "form_wrapper")
    {
      $(".form_wrapper").hide();
    }
  }
);

นอกจากนี้องค์ประกอบของร่างกายอาจไม่รวมพื้นที่ภาพทั้งหมดที่แสดงในเบราว์เซอร์ หากคุณสังเกตเห็นว่าการคลิกของคุณไม่ได้ลงทะเบียนคุณอาจต้องเพิ่มตัวจัดการการคลิกสำหรับองค์ประกอบ HTML แทน


ใช่ตอนนี้ลิงก์ใช้งานได้! แต่ด้วยเหตุผลบางอย่างเมื่อฉันคลิกลิงก์มันจะยิงสองครั้ง
Scott Yu - สร้างสิ่งต่าง ๆ

ฉันลงเอยด้วยรูปแบบของสิ่งนี้ ฉันก่อนตรวจสอบว่าองค์ประกอบสามารถมองเห็นได้แล้วถ้า target.hasClass ฉันซ่อน
Hawkee

และอย่าลืมe.stopPropagation();ว่าคุณมีคนฟังคลิกคนอื่น ๆ
ดารินโคเลฟ

2
-1 สิ่งนี้จะซ่อนform_wrapperเมื่อคุณคลิกลูก ๆ ของมันซึ่งไม่ใช่พฤติกรรมที่ต้องการ ใช้คำตอบของ prc322 แทน
Mark Amery

38

สาธิตสด

ตรวจสอบพื้นที่การคลิกไม่ได้อยู่ในองค์ประกอบเป้าหมายหรืออยู่ในระดับย่อย

$(document).click(function (e) {
    if ($(e.target).parents(".dropdown").length === 0) {
        $(".dropdown").hide();
    }
});

UPDATE:

การแพร่กระจายหยุด jQuery เป็นทางออกที่ดีที่สุด

สาธิตสด

$(".button").click(function(e){
    $(".dropdown").show();
     e.stopPropagation();
});

$(".dropdown").click(function(e){
    e.stopPropagation();
});

$(document).click(function(){
    $(".dropdown").hide();
});

ขอบคุณสำหรับการอัพเดทสมบูรณ์แบบ! ใช้งานได้กับอุปกรณ์ระบบสัมผัสหรือไม่?
FFish

1
ในกรณีที่คุณมีหลายรายการในหน้า ฉันคิดว่าคุณจะต้องปิดเมนูแบบเลื่อนลงทั้งหมดก่อนที่จะเปิดclickedอย่างใดอย่างหนึ่ง มิฉะนั้นstopPropagationจะทำให้เป็นไปได้ว่ามีการเปิดหลายรายการพร้อมกัน
T04435

19
$(document).click(function(event) {
    if ( !$(event.target).hasClass('form_wrapper')) {
         $(".form_wrapper").hide();
    }
});

2
อืมถ้าฉันคลิกที่สิ่งที่อยู่ภายในกอง div ทั้งหมดจะหายไปด้วยเหตุผลบางอย่าง
Scott Yu - สร้างสิ่งต่าง ๆ

11
แทนที่จะตรวจสอบว่าเป้าหมายมีคลาสหรือไม่ให้ลอง: if ($ (event.target) .closest ('. form_wrapper) .get (0) == null) {$ (". form_wrapper"). hide (); } สิ่งนี้จะประกันว่าการคลิกสิ่งต่าง ๆ ภายใน div จะไม่ซ่อน div
John Haager

17

อัปเดตโซลูชันเป็น:

  • ใช้ mouseenter และ mouseleave แทน
  • ของโฮเวอร์ใช้การเชื่อมเหตุการณ์สด

var mouseOverActiveElement = false;

$('.active').live('mouseenter', function(){
    mouseOverActiveElement = true; 
}).live('mouseleave', function(){ 
    mouseOverActiveElement = false; 
});
$("html").click(function(){ 
    if (!mouseOverActiveElement) {
        console.log('clicked outside active element');
    }
});

1
.liveคือตอนนี้เลิก ; ใช้.onแทน
เบร็ท

15

วิธีการแก้ปัญหาที่ไม่มี jQuery สำหรับคำตอบยอดนิยม :

document.addEventListener('mouseup', function (e) {
    var container = document.getElementById('your container ID');

    if (!container.contains(e.target)) {
        container.style.display = 'none';
    }
}.bind(this));

MDN: https://developer.mozilla.org/en/docs/Web/API/Node/contain


bindไม่ทำงาน คุณสามารถแก้ไขฟังก์ชั่นเพื่อให้ทำงานได้หรือไม่?
Memmo

9

การสาธิตสดพร้อมESCฟังก์ชั่น

ใช้งานได้ทั้งบนเดสก์ท็อปและมือถือ

var notH = 1,
    $pop = $('.form_wrapper').hover(function(){ notH^=1; });

$(document).on('mousedown keydown', function( e ){
  if(notH||e.which==27) $pop.hide();
});

หากในบางกรณีคุณต้องแน่ใจว่าองค์ประกอบของคุณจะปรากฏให้เห็นจริง ๆ เมื่อคุณคลิกที่เอกสาร: if($pop.is(':visible') && (notH||e.which==27)) $pop.hide();


8

จะไม่ชอบงานนี้หรือไม่

$("body *").not(".form_wrapper").click(function() {

});

หรือ

$("body *:not(.form_wrapper)").click(function() {

});

4
คำตอบนี้ไม่ถูกต้อง เช่นเดียวกับคำตอบมากมายที่นี่สิ่งนี้จะซ่อน.form_wrapperเมื่อคุณคลิกลูก ๆ ของมัน (ท่ามกลางปัญหาอื่น ๆ )
Mark Amery

6

แม้แต่คนเฉื่อยชา:

$("html").click(function(){ 
    $(".wrapper:visible").hide();
});

4
คำตอบนี้ไม่ถูกต้อง การดำเนินการนี้จะซ่อน.wrapperไม่ว่าคุณจะคลิกที่หน้าใดซึ่งไม่ใช่สิ่งที่ขอ
Mark Amery

6

แทนที่จะฟังทุก ๆ คลิกที่ DOM เพื่อซ่อนองค์ประกอบเฉพาะคุณสามารถตั้งค่าtabindexให้ผู้ปกครอง<div>และฟังfocusoutเหตุการณ์ได้

การตั้งค่าtabindexจะทำให้แน่ใจว่าblurเหตุการณ์ถูกเปิดใช้งานบน<div>(โดยปกติจะไม่เกิดขึ้น)

ดังนั้น HTML ของคุณจะมีลักษณะดังนี้:

<div class="form_wrapper" tabindex="0">
    <a class="agree" href="javascript:;">I Agree</a>
    <a class="disagree" href="javascript:;">Disagree</a>
</div>

และ JS ของคุณ:

$('.form_wrapper').on('focusout', function(event){
    $('.form_wrapper').hide();
});

5

และสำหรับอุปกรณ์ Touch เช่น IPAD และ IPHONE เราสามารถใช้รหัสต่อไปนี้

$(document).on('touchstart', function (event) {
var container = $("YOUR CONTAINER SELECTOR");

if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
    {
        container.hide();
    }
});

5

นี่คือ jsfiddle ที่ฉันพบในเธรดอื่นทำงานกับคีย์ esc ด้วย: http://jsfiddle.net/S5ftb/404

    var button = $('#open')[0]
    var el     = $('#test')[0]

    $(button).on('click', function(e) {
      $(el).show()
      e.stopPropagation()
    })

    $(document).on('click', function(e) {
      if ($(e.target).closest(el).length === 0) {
        $(el).hide()
      }
    })

    $(document).on('keydown', function(e) {
      if (e.keyCode === 27) {
        $(el).hide()
      }
    })

ฉันเห็นมันตรวจพบว่าเหตุการณ์ 'คลิก' อยู่ในองค์ประกอบ #test .. ลองลิงก์ทดสอบเป็นjsfiddle.net/TA96A & ดูเหมือนว่าอาจใช้งานได้หรือไม่
โทมัส W

ใช่ดูเหมือนว่า jsfiddle จะบล็อกลิงก์ภายนอก ถ้าคุณใช้ http: // jsfiddle.net คุณจะเห็นหน้าผลการประมวลผลเชื่อมโยง :)
djv

5

สร้างขึ้นจากคำตอบที่ยอดเยี่ยมของ prc322

function hideContainerOnMouseClickOut(selector, callback) {
  var args = Array.prototype.slice.call(arguments); // Save/convert arguments to array since we won't be able to access these within .on()
  $(document).on("mouseup.clickOFF touchend.clickOFF", function (e) {
    var container = $(selector);

    if (!container.is(e.target) // if the target of the click isn't the container...
        && container.has(e.target).length === 0) // ... nor a descendant of the container
    {
      container.hide();
      $(document).off("mouseup.clickOFF touchend.clickOFF");
      if (callback) callback.apply(this, args);
    }
  });
}

สิ่งนี้เพิ่มสองสามสิ่ง ...

  1. วางไว้ภายในฟังก์ชันที่มีการโทรกลับด้วย args "unlimited"
  2. เพิ่มการเรียกไปยัง. off () ของ jquery ที่จับคู่กับเนมสเปซเหตุการณ์เพื่อยกเลิกการผูกเหตุการณ์จากเอกสารเมื่อมีการเรียกใช้
  3. touchend รวมถึงฟังก์ชั่นมือถือ

ฉันหวังว่านี่จะช่วยให้ใครบางคน!



4

(เพียงเพิ่มคำตอบของ prc322)

ในกรณีของฉันฉันใช้รหัสนี้เพื่อซ่อนเมนูนำทางที่ปรากฏขึ้นเมื่อผู้ใช้คลิกที่แท็บที่เหมาะสม ฉันพบว่ามันมีประโยชน์ในการเพิ่มเงื่อนไขพิเศษว่าเป้าหมายของการคลิกภายนอกคอนเทนเนอร์ไม่ใช่ลิงก์

$(document).mouseup(function (e)
{
    var container = $("YOUR CONTAINER SELECTOR");

    if (!$("a").is(e.target) // if the target of the click isn't a link ...
        && !container.is(e.target) // ... or the container ...
        && container.has(e.target).length === 0) // ... or a descendant of the container
    {
        container.hide();
    }
});

นี่เป็นเพราะบางลิงค์ในเว็บไซต์ของฉันเพิ่มเนื้อหาใหม่ลงในหน้า หากเนื้อหาใหม่นี้ถูกเพิ่มในเวลาเดียวกันว่าเมนูนำทางหายไปมันอาจจะสับสนสำหรับผู้ใช้


4

คำตอบมากมายต้องเป็นคำที่ถูกต้องในการเพิ่มคำตอบ ... ฉันไม่เห็นคำตอบปัจจุบัน (jQuery 3.1.1) - ดังนั้น:

$(function() {
    $('body').on('mouseup', function() {
        $('#your-selector').hide();
    });
});


3
 $('body').click(function(event) {
    if (!$(event.target).is('p'))
    {
        $("#e2ma-menu").hide();
    }
});

pเป็นชื่อองค์ประกอบ ที่หนึ่งสามารถส่ง ID หรือชั้นหรือชื่อองค์ประกอบด้วย


3

กลับเท็จถ้าคุณคลิกที่. form_wrapper:

$('body').click(function() {
  $('.form_wrapper').click(function(){
  return false
});
   $('.form_wrapper').hide();
});

//$('.form_wrapper').click(function(event){
//   event.stopPropagation();
//});

3

แนบเหตุการณ์การคลิกไปที่องค์ประกอบระดับบนสุดนอกตัวตัดแบบฟอร์มตัวอย่างเช่น:

$('#header, #content, #footer').click(function(){
    $('.form_wrapper').hide();
});

สิ่งนี้จะใช้งานได้บนอุปกรณ์แบบสัมผัสเพียงตรวจสอบให้แน่ใจว่าคุณไม่ได้รวมพาเรนต์ของ. form_wrapper ไว้ในรายการตัวเลือกของคุณ



3

$(document).ready(function() {
	$('.modal-container').on('click', function(e) {
	  if(e.target == $(this)[0]) {
		$(this).removeClass('active'); // or hide()
	  }
	});
});
.modal-container {
	display: none;
	justify-content: center;
	align-items: center;
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(0,0,0,0.5);
	z-index: 999;
}

.modal-container.active {
    display: flex;  
}

.modal {
	width: 50%;
	height: auto;
	margin: 20px;
	padding: 20px;
	background-color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="modal-container active">
	<div class="modal">
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ac varius purus. Ut consectetur viverra nibh nec maximus. Nam luctus ligula quis arcu accumsan euismod. Pellentesque imperdiet volutpat mi et cursus. Sed consectetur sed tellus ut finibus. Suspendisse porttitor laoreet lobortis. Nam ut blandit metus, ut interdum purus.</p>
	</div>
</div>


3

คัดลอกมาจากhttps://sdtuts.com/click-on-not-specified-element/

การสาธิตสดhttp://demos.sdtuts.com/click-on-specified-element

$(document).ready(function () {
    var is_specified_clicked;
    $(".specified_element").click(function () {
        is_specified_clicked = true;
        setTimeout(function () {
            is_specified_clicked = false;
        }, 200);
    })
    $("*").click(function () {
        if (is_specified_clicked == true) {
//WRITE CODE HERE FOR CLICKED ON OTHER ELEMENTS
            $(".event_result").text("you were clicked on specified element");
        } else {
//WRITE CODE HERE FOR SPECIFIED ELEMENT CLICKED
            $(".event_result").text("you were clicked not on specified element");
        }
    })
})

2

ฉันทำแบบนี้:

var close = true;

$(function () {

    $('body').click (function(){

        if(close){
            div.hide();
        }
        close = true;
    })


alleswasdenlayeronclicknichtschliessensoll.click( function () {   
        close = false;
    });

});

2
dojo.query(document.body).connect('mouseup',function (e)
{
    var obj = dojo.position(dojo.query('div#divselector')[0]);
    if (!((e.clientX > obj.x && e.clientX <(obj.x+obj.w)) && (e.clientY > obj.y && e.clientY <(obj.y+obj.h))) ){
        MyDive.Hide(id);
    }
});

2

โดยใช้รหัสนี้คุณสามารถซ่อนรายการได้มากเท่าที่คุณต้องการ

var boxArray = ["first element's id","second element's id","nth element's id"];
   window.addEventListener('mouseup', function(event){
   for(var i=0; i < boxArray.length; i++){
    var box = document.getElementById(boxArray[i]);
    if(event.target != box && event.target.parentNode != box){
        box.style.display = 'none';
    }
   }
})

1

สิ่งที่คุณสามารถทำได้คือผูกเหตุการณ์การคลิกไปที่เอกสารที่จะซ่อนรายการแบบเลื่อนลงหากมีการคลิกบางสิ่งที่อยู่ด้านนอกรายการแบบเลื่อนลง แต่จะไม่ซ่อนมันหากสิ่งใดก็ตามที่อยู่ภายในรายการแบบเลื่อนลงถูกคลิก แสดงรายการแบบเลื่อนลง)

    $('.form_wrapper').show(function(){

        $(document).bind('click', function (e) {
            var clicked = $(e.target);
            if (!clicked.parents().hasClass("class-of-dropdown-container")) {
                 $('.form_wrapper').hide();
            }
        });

    });

จากนั้นเมื่อซ่อนมันให้ยกเลิกการผูกเหตุการณ์การคลิก

$(document).unbind('click');

0

ตามเอกสาร , .blur()ทำงานให้มากขึ้นกว่า<input>แท็ก ตัวอย่างเช่น:

$('.form_wrapper').blur(function(){
   $(this).hide();
});

-1 ไม่ทำงาน แนวคิดที่น่าสนใจมาก แต่เอกสาร jQuery ผิด ดูdeveloper.mozilla.org/en-US/docs/Web/API/ …ตัวอย่างเช่น "ตรงกันข้ามกับ MSIE - องค์ประกอบเกือบทุกประเภทได้รับเหตุการณ์เบลอ - องค์ประกอบเกือบทุกชนิดในเบราว์เซอร์ Gecko ไม่ทำงานกับกิจกรรมนี้ " นอกจากนี้ยังได้รับการทดสอบใน Chrome และdivไม่เคยเบลอ - เหตุการณ์ที่เบลอไม่สามารถทำให้ลูก ๆ ในที่สุดแม้ว่าสิ่งที่กล่าวมาข้างต้นไม่เป็นความจริงสิ่งนี้จะใช้ได้ผลก็ต่อเมื่อคุณแน่ใจว่าสิ่ง.form_wrapperนั้นอยู่ในโฟกัสก่อนที่ผู้ใช้จะคลิกมัน
Mark Amery
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.