วิธีปิดการใช้งาน mouseout เหตุการณ์ที่เรียกโดยองค์ประกอบลูก?


107

ให้ฉันอธิบายปัญหาโดยละเอียด:

ฉันต้องการแสดง div ที่อยู่ในตำแหน่งที่แน่นอนเมื่อวางเมาส์เหนือองค์ประกอบ มันง่ายมากกับ jQuery และใช้งานได้ดี แต่เมื่อเมาส์ไปที่องค์ประกอบลูกรายการหนึ่งมันจะทริกเกอร์เหตุการณ์ mouseout ของ div ที่มีอยู่ ฉันจะป้องกันไม่ให้ javascript ทริกเกอร์เหตุการณ์ mouseout ขององค์ประกอบที่มีเมื่อวางเมาส์เหนือองค์ประกอบลูกได้อย่างไร

วิธีที่ดีที่สุดและสั้นที่สุดในการทำ jQuery คืออะไร?

นี่คือตัวอย่างที่เรียบง่ายเพื่อแสดงสิ่งที่ฉันหมายถึง:

Html:

<a>Hover Me</a>
<div>
  <input>Test</input>
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
  </select>
</div>

Javascript / jQuery:

$('a').hover( function() { $(this).next().show() }
              function() { $(this).next().hide() } );

คำตอบ:


209

คำถามเก่าไปหน่อย แต่เมื่อวันก่อนฉันเจอเรื่องนี้

วิธีที่ง่ายที่สุดในการทำสิ่งนี้กับ jQuery เวอร์ชันล่าสุดคือการใช้mouseenterและmouseleaveเหตุการณ์แทนmouseovermouseoutและ

คุณสามารถทดสอบพฤติกรรมได้อย่างรวดเร็วด้วย:

$(".myClass").on( {
   'mouseenter':function() { console.log("enter"); },
   'mouseleave':function() { console.log("leave"); }
});

4
ช่วยปัญหาที่เกี่ยวข้องกับจาวาสคริปต์ที่ไม่ใช่ jquery ของฉัน ฉันใช้ mouseenter / mouseout แทน mouseleave กับผู้ฟังเหตุการณ์ของฉัน!
โจอี

1
เพื่อประโยชน์ในการค้นหาพฤติกรรมเหตุการณ์ของเมาส์เหล่านี้จะเทียบเท่าROLL_OVERและROLL_OUTใน AS3
Jeff Ward

2
ช่วยให้ฉันปวดหัว มันแปลกที่การวางเมาส์บนองค์ประกอบลูกทำให้เกิดmouseoutเหตุการณ์ของผู้ปกครองเมื่อในความเป็นจริงมันยังอยู่ในองค์ประกอบหลัก
javiniar.leonard

18

เพื่อความเรียบง่ายฉันจะจัดระเบียบ html ใหม่เล็กน้อยเพื่อใส่เนื้อหาที่แสดงใหม่ภายในองค์ประกอบที่เหตุการณ์เมาส์โอเวอร์ถูกผูกไว้:

<div id="hoverable">
  <a>Hover Me</a>
  <div style="display:none;">
    <input>Test</input>
    <select>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  </div>
</div>

จากนั้นคุณสามารถทำสิ่งนี้:

$('#hoverable').hover( function() { $(this).find("div").show(); },
                       function() { $(this).find("div").hide(); } );

หมายเหตุ: ฉันไม่แนะนำ inline css แต่ทำเพื่อให้ตัวอย่างง่ายต่อการย่อย


นี่เป็นวิธีที่ง่ายและสะอาดมาก ขอบคุณที่เตือนฉัน. แต่ในสถานการณ์เฉพาะของฉันซึ่งไม่ตรงกับคำถามนี่ไม่ใช่ตัวเลือก ขอบคุณมาก!
Sander Versluys

หลังจากลองใช้วิธีต่างๆตามที่ผู้อื่นอธิบายไว้ที่ SO ฉันกลับมาที่วิธีการของคุณและทำให้มันได้ผลในกรณีของฉัน เย้! :-)
Sander Versluys

11

ใช่พวกใช้.mouseleaveแทน.mouseout:

$('div.sort-selector').mouseleave(function() {
    $(this).hide();
});

หรือแม้แต่ใช้ร่วมกับlive:

$('div.sort-selector').live('mouseleave', function() {
    $(this).hide();
});

8

คุณกำลังมองหา jQuery ที่เทียบเท่ากับการป้องกันไม่ให้เหตุการณ์เป็นฟองของจาวาสคริปต์

ลองดู:

http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29

โดยพื้นฐานแล้วคุณต้องจับเหตุการณ์ในโหนด DOM ลูกและหยุดการขยายพันธุ์ของพวกเขาในทรี DOM อีกวิธีหนึ่งแม้ว่าจะไม่ได้รับการแนะนำจริงๆ (เนื่องจากอาจทำให้เกิดความยุ่งเหยิงกับเหตุการณ์ที่มีอยู่ในเพจของคุณได้) คือการตั้งค่าการบันทึกเหตุการณ์เป็นองค์ประกอบเฉพาะบนหน้าเว็บและจะได้รับเหตุการณ์ทั้งหมด สิ่งนี้มีประโยชน์สำหรับพฤติกรรม DnD และเช่นนั้น แต่ไม่แน่นอนสำหรับกรณีของคุณ


มันใช้งานได้ตามที่ควรไม่รู้ว่าทำไมคุณถึงใช้งานไม่ได้ .. แค่ข้อมูลลิงก์ไปยังเอกสารก็เปลี่ยนไปลิงค์ใหม่คือdocs.jquery.com/Events/jQuery.Event#event.stopPropagation 28.29
zappan

3

ฉันแค่ตรวจสอบว่าพิกัดของเมาส์อยู่นอกองค์ประกอบใน mouseout-event หรือไม่

มันใช้งานได้ แต่มีโค้ดมากมายสำหรับสิ่งง่ายๆเช่นนี้ :(

function mouseOut(e)
{
    var pos = GetMousePositionInElement(e, element);
    if (pos.x < 0 || pos.x >= element.size.X || pos.y < 0 || pos.y >= element.size.Y)
    {
        RealMouseOut();
    }
    else
    {
         //Hit a child-element
    }
}

โค้ดถูกตัดลงเพื่อให้อ่านง่ายไม่สามารถใช้งานได้นอกกรอบ


1

ฉันเห็นด้วยกับไรอัน

ปัญหาของคุณคือ div "ถัดไป" ไม่ใช่ "ลูก" ของ A ไม่มีทางที่ HTML หรือ jQuery จะรู้ว่าองค์ประกอบ "a" ของคุณเกี่ยวข้องกับ div ลูกใน DOM การห่อและวางโฮเวอร์บนกระดาษห่อหมายความว่ามีความเกี่ยวข้องกัน

โปรดทราบว่ารหัสของเขาไม่สอดคล้องกับแนวทางปฏิบัติที่ดีที่สุด อย่าตั้งค่าสไตล์ที่ซ่อนอยู่แบบอินไลน์บนองค์ประกอบ หากผู้ใช้มี CSS แต่ไม่มีจาวาสคริปต์องค์ประกอบจะซ่อนและไม่สามารถแสดงได้ แนวทางปฏิบัติที่ดีกว่าคือใส่คำประกาศนั้นไว้ในเหตุการณ์ document.ready


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

1

ฉันแก้ไขปัญหานี้โดยเพิ่มpointer-events: none;องค์ประกอบลูกของฉัน css


สิ่งนี้ช่วยได้มากเมื่อแก้ไขรหัสเดิมที่สร้างป๊อปโอเวอร์ของตัวเองด้วยเหตุการณ์ mouseover และ mouseleave
CM

0

วิธีที่ฉันมักจะเห็นการจัดการนี้คือมีความล่าช้าประมาณ 1/2 วินาทีระหว่างการเลื่อนเมาส์จากองค์ประกอบ HoverMe เมื่อเลื่อนเมาส์เข้าไปในองค์ประกอบที่วางเมาส์ไว้คุณจะต้องตั้งค่าตัวแปรบางอย่างที่ส่งสัญญาณว่าคุณกำลังวางเมาส์เหนือองค์ประกอบจากนั้นโดยทั่วไปจะหยุดส่วนที่ลอยอยู่ไม่ให้ซ่อนหากตั้งค่าตัวแปรนี้ไว้ จากนั้นคุณต้องเพิ่มฟังก์ชันซ่อนที่คล้ายกัน OnMouseOut จากองค์ประกอบที่วางเมาส์ไว้เพื่อให้มันหายไปเมื่อคุณเอาเมาส์ออก ขออภัยฉันไม่สามารถให้รหัสใด ๆ กับคุณหรือมีอะไรที่เป็นรูปธรรมมากกว่านี้ได้ แต่ฉันหวังว่านี่จะชี้ให้คุณไปในทิศทางที่ถูกต้อง


ใช่ฉันเพิ่งใช้วิธีแก้ปัญหาแบบนั้น มันเป็นปัญหาที่พบบ่อยจริงๆ ฉันอยากรู้จริงๆว่ามีวิธีแก้ปัญหาอะไรอีกบ้าง ... ขอบคุณสำหรับคำตอบ!
Sander Versluys

0

เป็นคำถามเก่า แต่ก็ไม่เคยล้าสมัย คำตอบที่ถูกต้องควรเป็นคำตอบที่ไบต์ไบรท์กำหนดให้ bytebrite

ฉันอยากจะชี้ให้เห็นความแตกต่างระหว่าง mouseover / mouseout และ mouseenter / mouseleave เท่านั้น คุณสามารถอ่านคำอธิบายที่ดีและเป็นประโยชน์ได้ที่นี่ (ไปที่ด้านล่างสุดของหน้าเพื่อดูการสาธิตที่ใช้งานได้) เมื่อคุณใช้mouseoutเหตุการณ์จะหยุดลงเมื่อเมาส์เข้าสู่องค์ประกอบอื่นแม้ว่าจะเป็นองค์ประกอบลูกก็ตาม ในอีกด้านหนึ่งเมื่อคุณใช้mouseleaveเหตุการณ์จะไม่ถูกทริกเกอร์เมื่อเมาส์เกินองค์ประกอบลูกและนี่คือพฤติกรรมที่ OP ต้องการให้บรรลุ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.