जब jQuery के बिना मूल निरपेक्ष div के बच्चे तत्व मँडरा जब onmouseout रोकें


169

मैं onmouseoutएक पूर्ण सकारात्मक div में समारोह के साथ परेशानी हो रही है । जब माउस div में एक बच्चे के तत्व को हिट करता है, तो माउसआउट घटना आग हो जाती है, लेकिन मैं इसे तब तक फायर नहीं करना चाहता जब तक कि माउस माता-पिता से बाहर न हो, पूर्ण div।

mouseoutजब मैं एक बच्चे के तत्व को jquery के बिना हिट करता है तो मैं इस घटना को गोलीबारी से कैसे रोक सकता हूं ।

मुझे पता है कि ईवेंट बुदबुदाहट के साथ कुछ करना है, लेकिन मुझे यह पता लगाने में कोई भाग्य नहीं है कि यह कैसे काम करना है।

मुझे यहां एक समान पोस्ट मिली: बाल तत्वों द्वारा ट्रिगर की गई माउसआउट घटनाओं को कैसे अक्षम करें?

हालाँकि वह समाधान jQuery का उपयोग करता है।


मैंने समयसीमा का उपयोग करके समस्या को सुलझाया और इसे बाल तत्वों के मंडराने पर समाप्त कर दिया
जॉन

नमस्ते, मैंने आपके डेमो को देखा है, लेकिन जब मैं नीचे दायें पैनल में तत्वों पर जाता हूं तो कुछ नहीं होता है?
जॉन

1
यह उत्तर मिला यदि आप मूल तत्व पर एक माउसआउट को रोकने के लिए देख रहे हैं जब आप एक बच्चे के तत्व का चयन करते हैं: जावास्क्रिप्ट माउसओवर / माउसआउट
23:82 पर user823527

जवाबों:


94
function onMouseOut(event) {
        //this is the original element the event handler was assigned to
        var e = event.toElement || event.relatedTarget;
        if (e.parentNode == this || e == this) {
           return;
        }
    alert('MouseOut');
    // handle mouse event here!
}



document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);

मैं एक त्वरित JsFiddle डेमो, सभी सीएसएस और HTML की जरूरत के साथ, इसे बाहर की जाँच करें ...

क्रॉस-ब्राउज़र समर्थन के लिए EDIT FIXED लिंक http://jsfiddle.net/RH3tA/9/

ध्यान दें कि यह केवल तत्काल माता-पिता की जांच करता है, अगर माता-पिता ने बच्चों को नेस्टेड किया था, तो आपको किसी तरह तत्वों के माध्यम से पार करना होगा जो माता-पिता "ऑर्गिनल तत्व" की तलाश में हैं।

नेस्टेड बच्चों के लिए EDIT उदाहरण

EDIT उम्मीद पार ब्राउज़र के लिए फिक्स्ड

function makeMouseOutFn(elem){
    var list = traverseChildren(elem);
    return function onMouseOut(event) {
        var e = event.toElement || event.relatedTarget;
        if (!!~list.indexOf(e)) {
            return;
        }
        alert('MouseOut');
        // handle mouse event here!
    };
}

//using closure to cache all child elements
var parent = document.getElementById("parent");
parent.addEventListener('mouseout',makeMouseOutFn(parent),true);

//quick and dirty DFS children traversal, 
function traverseChildren(elem){
    var children = [];
    var q = [];
    q.push(elem);
    while (q.length > 0) {
      var elem = q.pop();
      children.push(elem);
      pushAll(elem.children);
    }
    function pushAll(elemArray){
      for(var i=0; i < elemArray.length; i++) {
        q.push(elemArray[i]);
      }
    }
    return children;
}

और एक नया JSFiddle , EDIT अद्यतन लिंक


1
आपको फिडल में एक माउसआउट इवेंट जोड़ना चाहिए ताकि इसे टेस्ट किया जा सके। एक अलर्ट या कुछ करना चाहिए।
जॉन

क्षमा करें, ऐसा लगता है कि आपके पास अलर्ट ('माउसओट') है, हालांकि यह मेरे लिए काम नहीं करता है? मैंने कोई जेएस लाइब्रेरी विकल्प नहीं चलाया है
जॉन

सफारी और क्रोम पर परीक्षण किया गया है, लेकिन हर चीज पर काम करना चाहिए! आपका ब्राउज़र क्या है?
अमजद मसा

2
यदि आपके पास भव्य बच्चे हैं तो क्या होगा? या महान भव्य बच्चे? यानी आपके पास सिर्फ बच्चों को पालने के बजाय एक पुनरावर्ती समाधान हो सकता है?
Roozbeh15

20
यह काम नहीं करता है। mouseleaveसही उत्तर है
कोड व्हिस्परर

126

का उपयोग करें onmouseleave

या, jQuery में, का उपयोग करें mouseleave()

यह आप के लिए देख रहे हैं सटीक बात है। उदाहरण:

<div class="outer" onmouseleave="yourFunction()">
    <div class="inner">
    </div>
</div>

या, jQuery में:

$(".outer").mouseleave(function(){
    //your code here
});

एक उदाहरण यहाँ है


3
onMouseLeaveयह है कि मैं भी का उपयोग कर समाप्त हो गया क्योंकि यह बुलबुला नहीं है।
एलेकज

मुझे बहुत समय बचाया। thnx
npo

mouseleaveरद्द नहीं किया जा सकता।
grecdev

@grecdev, और कहिए!
बेन व्हीलर

97

कुछ मामलों ( IE11 या नए ) में काम करने वाले एक सरल शुद्ध सीएसएस समाधान के लिए , कोई भी pointer-eventsउन्हें सेट करके बच्चों को निकाल सकता हैnone

.parent * {
     pointer-events: none;
}

4
प्रतिभाशाली! पूरी तरह से सिर्फ मेरा मुद्दा तय किया!
21_15 बजे अन्ना_मीडियाग्लाल

4
यह पहला या कम से कम दूसरा उत्तर होना चाहिए, मैं इवेंट श्रोताओं की परेशानी के साथ जाने के लिए तैयार था और यह पूरी तरह से मेरे मुद्दे को भी तय करता था। बहुत आसन !
मिकेल वी।

9
यह माउसआउट को गोलीबारी से रोकता है, लेकिन मेरे लिए यह वास्तविक बच्चे को मेनू में चयन के रूप में क्लिक करने से रोकता है, जो कि मेनू का बिंदु है।
जॉन्बेकर्स

@hellofunk यही कारण है कि आप क्लिक इवेंट को पैरेंट पर लागू करेंगे। कार्यान्वयन के आधार पर सटीक कोड की आवश्यकता होती है, यह उत्तर केवल pointer-eventsसंपत्ति का उपयोग करने का सुझाव देता है
Zach Saucier

1
यह तभी काम करता है जब आपके पास क्षेत्र के अन्य नियंत्रक तत्व (संपादित करें, हटाएं) न हों, क्योंकि यह समाधान उन्हें भी अवरुद्ध करता है ..
Zoltán Süle

28

यहां नीचे दिए गए बातों के आधार पर अधिक सुरुचिपूर्ण समाधान दिया गया है। यह बच्चों के एक से अधिक स्तरों से होने वाली घटना के लिए जिम्मेदार है। यह क्रॉस-ब्राउज़र समस्याओं के लिए भी खाता है।

function onMouseOut(this, event) {
//this is the original element the event handler was assigned to
   var e = event.toElement || event.relatedTarget;

//check for all children levels (checking from bottom up)
while(e && e.parentNode && e.parentNode != window) {
    if (e.parentNode == this||  e == this) {
        if(e.preventDefault) e.preventDefault();
        return false;
    }
    e = e.parentNode;
}

//Do something u need here
}

document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);

सैम एली, यह IE, सफारी या ओपेरा पर काम नहीं कर रहा है। क्या आपके पास इस स्क्रिप्ट का क्रॉस-ब्राउज़र संस्करण है? यह फ़ायरफ़ॉक्स और क्रोम में एक आकर्षण की तरह काम करता है। धन्यवाद।

1
जब मैं उपरोक्त फ़ंक्शन को अपनी स्क्रिप्ट में पेस्ट करता हूं, तो Dreamweaver और FF पहली पंक्ति में एक त्रुटि फेंकते हैं, "फ़ंक्शन onMouseOut (यह, घटना) {"। ऐसा लगता है कि आपको पैरामीटर के रूप में "यह" डालने की अनुमति नहीं है। मुझे लगता है कि यह काम करता है जब मैं इनपुट पार्म्स से "यह" छोड़ देता हूं, लेकिन मुझे यकीन नहीं है, क्योंकि "मुझे नहीं पता कि मुझे क्या पता है"।
तारक

1
मेरे पास Chrome में समान समस्या पॉप अप भी थी, thisफ़ंक्शन परिभाषा लाइन @GregoryLewis को छोड़कर समस्या का उल्लेख किया गया था। इसके अलावा अधिक क्रॉस ब्राउज़र समर्थन के लिए, यह कोशिश करें: यदि (window.addEventListener) {document.getElementById ('जनक')। addEventListener ('mouseout', onMouseOut, true); } और यदि (window.attachEvent) {document.getElementById ('पैरेंट')। संलग्नक ("ऑनमाउट", ऑनमाउट); }
डीडिल्स

बहुत सुंदर! सबसे अच्छा जवाब अगर पुराने ब्राउज़रों के लिए समर्थन की आवश्यकता है।
बर्निनलियो

13

अमजद मसाद का शुक्रिया जिसने मुझे प्रेरित किया।

मेरे पास निम्न समाधान है जो IE9, FF और Chrome में काम करता है और कोड काफी छोटा है (जटिल क्लोजर और अनुप्रस्थ चाइल्ड चीजों के बिना):

    DIV.onmouseout=function(e){
        // check and loop relatedTarget.parentNode
        // ignore event triggered mouse overing any child element or leaving itself
        var obj=e.relatedTarget;
        while(obj!=null){
            if(obj==this){
                return;
            }
            obj=obj.parentNode;
        }
        // now perform the actual action you want to do only when mouse is leaving the DIV
    }

13

ऑनमाउज़ाउट के बजाय ऑनमसेलवेव का उपयोग करें।

आपने हमें अपना विशिष्ट कोड नहीं दिखाया है, इसलिए मैं आपको अपने विशिष्ट उदाहरण पर नहीं दिखा सकता कि यह कैसे करना है।

लेकिन यह बहुत सरल है: बस ऑनमौसाउट को ऑनमौसलेव के साथ बदलें।

वह सब :) तो, सरल :)

यदि यह सुनिश्चित नहीं है कि यह कैसे करना है, तो स्पष्टीकरण देखें:

https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmousemove_leave_out

केक की शांति :) इसका आनंद लें :)


यह एक महान चिल्लाहट है, अच्छी तरह से जांचने योग्य है कि क्या आपके पास समान स्थिति है
क्रिस

12

यदि आप jQuery का उपयोग कर रहे हैं, तो आप "mouseleave" फ़ंक्शन का भी उपयोग कर सकते हैं, जो आपके लिए इस सब से संबंधित है।

$('#thetargetdiv').mouseenter(do_something);
$('#thetargetdiv').mouseleave(do_something_else);

do_something में आग लग जाएगी जब माउस intargetdiv या उसके किसी भी बच्चे में प्रवेश करता है, do_something_else केवल तभी फायर करेगा जब माउस thetargetdiv और उसके किसी भी बच्चे को छोड़ देता है।


8

मुझे लगता है कि Quirksmode सब अपनी आवश्यकता के उत्तर (विभिन्न ब्राउज़रों बुदबुदाती व्यवहार और है mouseenter / mouseleave घटनाओं), लेकिन मुझे लगता है कि घटना बुदबुदाती गड़बड़ करने के लिए सबसे आम निष्कर्ष है JQuery या Mootools (जो है की तरह एक रूपरेखा के उपयोग mouseenter और Mouseleave घटनाओं, जो वास्तव में आप अंतर्ज्ञान क्या होता है)।

एक नज़र डालें कि वे कैसे करते हैं, यदि आप चाहते हैं, तो इसे स्वयं करें
या आप अपने ईवेंट "और उसके आश्रितों" के साथ अपने कस्टम "म्यूटूल" संस्करण बना सकते हैं



5

मुझे एक बहुत ही सरल उपाय मिला है,

बस onmouseleave = "myfunc ()" घटना का उपयोग onmousout = "myfunc ()" ईवेंट से करें

मेरे कोड में यह काम किया !!

उदाहरण:

<html>
<head>
<script type="text/javascript">
   function myFunc(){
      document.getElementById('hide_div').style.display = 'none';
   }
   function ShowFunc(){
      document.getElementById('hide_div').style.display = 'block';
   }
</script>
</head>
<body>
<div onmouseleave="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
   Hover mouse here
   <div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
      CHILD <br/> It doesn't fires if you hover mouse over this child_div
   </div>
</div>
<div id="hide_div" >TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>

माउसआउट फ़ंक्शन के साथ एक ही उदाहरण:

<html>
<head>
<script type="text/javascript">
   function myFunc(){
      document.getElementById('hide_div').style.display = 'none';
   }
   function ShowFunc(){
      document.getElementById('hide_div').style.display = 'block';
   }
</script>
</head>
<body>
<div onmouseout="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
   Hover mouse here
   <div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
      CHILD <br/> It fires if you hover mouse over this child_div
   </div>
</div>
<div id="hide_div">TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>

आशा करता हूँ की ये काम करेगा :)



2

इसे संभालने के दो तरीके हैं।

1) अपने कॉलबैक में event.target परिणाम की जाँच करें कि क्या यह आपके अभिभावक div से मेल खाता है

var g_ParentDiv;

function OnMouseOut(event) {
    if (event.target != g_ParentDiv) {
        return;
    }
    // handle mouse event here!
};


window.onload = function() {
    g_ParentDiv = document.getElementById("parentdiv");
    g_ParentDiv.onmouseout = OnMouseOut;
};

<div id="parentdiv">
    <img src="childimage.jpg" id="childimg" />
</div>

2) या कॉलबैक फ़ंक्शन में ईवेंट कैप्चरिंग और ईवेंट कैप्चर ।stopPropagation का उपयोग करें

var g_ParentDiv;

function OnMouseOut(event) {

    event.stopPropagation(); // don't let the event recurse into children

    // handle mouse event here!
};


window.onload = function() {
    g_ParentDiv = document.getElementById("parentdiv");
    g_ParentDiv.addEventListener("mouseout", OnMouseOut, true); // pass true to enable event capturing so parent gets event callback before children
};

<div id="parentdiv">
    <img src="childimage.jpg" id="childimg" />
</div>

मैं इस कार्य को onmouseover के बजाय onmouseout के लिए कैसे कर सकता हूं?
जॉन

उफ़। मेरी गलती। मैं उपरोक्त कोड में "माउसआउट" के सभी "माउसओवर" संदर्भों को बदल देता हूं। यह आपके लिए करना चाहिए।
सेलेबी

पहली विधि के लिए, event.target हमेशा मूल तत्व से मेल खाता है जब माउस बाल तत्व के ऊपर जाता है, तो यह काम नहीं करता है
जॉन

दूसरी विधि के लिए एक ही बात होती है। जब माउस एक बाल तत्व में प्रवेश करता है तब भी यह घटना को ट्रिगर करता है
जॉन

1

मैं इसके साथ एक आकर्षण की तरह काम करता हूं:

function HideLayer(theEvent){
 var MyDiv=document.getElementById('MyDiv');
 if(MyDiv==(!theEvent?window.event:theEvent.target)){
  MyDiv.style.display='none';
 }
}

आह, और MyDivटैग इस तरह है:

<div id="MyDiv" onmouseout="JavaScript: HideLayer(event);">
 <!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>

इस तरह, जब ऑनमाउट एक बच्चे, भव्य-बच्चे, आदि के पास जाता है ... तो style.display='none'निष्पादित नहीं किया जाता है; लेकिन जब ऑनमाउट MyDiv से बाहर चला जाता है तो यह चलता है।

इसलिए प्रचार बंद करने, टाइमर आदि का इस्तेमाल करने की जरूरत नहीं ...

उदाहरण के लिए धन्यवाद, मैं उनसे यह कोड बना सकता हूं।

आशा है कि यह किसी की मदद करता है।

इस तरह भी सुधार किया जा सकता है:

function HideLayer(theLayer,theEvent){
 if(theLayer==(!theEvent?window.event:theEvent.target)){
  theLayer.style.display='none';
 }
}

और फिर इस तरह DIV टैग:

<div onmouseout="JavaScript: HideLayer(this,event);">
 <!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>

इतना सामान्य है, न केवल एक div के लिए और id="..."प्रत्येक परत पर जोड़ने की जरूरत नहीं है ।


1

यदि आपके पास उस तत्व तक पहुंच है, जो घटना mouseoutविधि के अंदर संलग्न है , तो आप यह contains()देखने के लिए उपयोग कर सकते हैं कि क्या event.relatedTargetबाल तत्व है या नहीं।

जैसा event.relatedTargetकि वह तत्व है जिसमें माउस पास हो गया है, यदि यह एक बाल तत्व नहीं है, तो आप तत्व से बाहर निकल गए हैं।

div.onmouseout = function (event) {
    if (!div.contains(event.relatedTarget)) {
        // moused out of div
    }
}

1

कोणीय 5, 6 और 7 पर

<div (mouseout)="onMouseOut($event)"
     (mouseenter)="onMouseEnter($event)"></div>

तब से

import {Component,Renderer2} from '@angular/core';
...
@Component({
 selector: 'app-test',
 templateUrl: './test.component.html',
 styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit, OnDestroy {
...
 public targetElement: HTMLElement;

 constructor(private _renderer: Renderer2) {
 }

 ngOnInit(): void {
 }

 ngOnDestroy(): void {
  //Maybe reset the targetElement
 }

 public onMouseEnter(event): void {
  this.targetElement = event.target || event.srcElement;
  console.log('Mouse Enter', this.targetElement);
 }

 public onMouseOut(event): void {
  const elementRelated = event.toElement || event.relatedTarget;
  if (this.targetElement.contains(elementRelated)) {
    return;
  }
  console.log('Mouse Out');
 }
}

0

मैं तत्व की सीमा के पृष्ठ निर्देशांक प्राप्त करने के लिए मूल तत्व की ऑफसेट की जांच करता हूं, फिर सुनिश्चित करें कि जब माउसआउट उन सीमाओं से बाहर हो जाता है तो केवल माउसआउट कार्रवाई शुरू हो जाती है। गंदा लेकिन यह काम करता है।

$(el).live('mouseout', function(event){
    while(checkPosition(this, event)){
        console.log("mouseovering including children")
    }
    console.log("moused out of the whole")
})

var checkPosition = function(el, event){
    var position = $(el).offset()
    var height = $(el).height()
    var width = $(el).width()
    if (event.pageY > position.top 
|| event.pageY < (position.top + height) 
|| event.pageX > position.left 
|| event.pageX < (position.left + width)){
    return true
}
}


0

यदि आपने मूल तत्व में CSS क्लास या id जोड़ी है (या है), तो आप ऐसा कुछ कर सकते हैं:

<div id="parent">
  <div>
  </div>
</div>

JavaScript:
document.getElementById("parent").onmouseout = function(e) {
  e = e ? e : window.event //For IE
  if(e.target.id == "parent") {
    //Do your stuff
  }
}

तो सामान केवल तब निष्पादित होता है जब घटना पैरेंट डिव पर होती है।


0

मैं सिर्फ आपके साथ कुछ साझा करना चाहता था।
मुझे कुछ कठिन समय ng-mouseenterऔर ng-mouseleaveघटनाओं के साथ मिला ।

मामले का अध्ययन:

मैंने एक फ्लोटिंग नेविगेशन मेनू बनाया, जो कर्सर के आइकन पर होने पर टॉगल होता है।
यह मेनू प्रत्येक पृष्ठ के शीर्ष पर था।

  • मेनू पर दिखाने / छिपाने के लिए, मैं एक क्लास टॉगल करता हूं।
    ng-class="{down: vm.isHover}"
  • Vm.isHover टॉगल करने के लिए , मैं एनजी माउस घटनाओं का उपयोग करता हूं।
    ng-mouseenter="vm.isHover = true"
    ng-mouseleave="vm.isHover = false"

अभी के लिए, सब कुछ ठीक था और उम्मीद के मुताबिक काम किया।
समाधान साफ ​​और सरल है।

आने वाली समस्या:

एक विशिष्ट दृष्टिकोण में, मेरे पास तत्वों की एक सूची है।
जब कर्सर सूची के एक तत्व से अधिक हो तो मैंने एक एक्शन पैनल जोड़ा।
मैंने व्यवहार को संभालने के लिए ऊपर दिए गए समान कोड का उपयोग किया।

समस्या:

मुझे पता चला जब मेरा कर्सर फ्लोटिंग नेविगेशन मेनू पर है और एक तत्व के शीर्ष पर भी, एक दूसरे के बीच संघर्ष है।
एक्शन पैनल दिखाई दिया और फ्लोटिंग नेविगेशन छिपा हुआ था।

बात यह है कि भले ही कर्सर फ्लोटिंग नेविगेशन मेनू पर हो, सूची तत्व एनजी-माउसेंटर चालू हो जाता है।
इससे मुझे कोई मतलब नहीं है, क्योंकि मैं माउस के प्रसार की घटनाओं के स्वत: विराम की उम्मीद करूंगा।
मुझे कहना होगा कि मैं निराश था और मैंने उस समस्या का पता लगाने के लिए कुछ समय बिताया।

पहले विचार:

मैंने इन्हें इस्तेमाल करने की कोशिश की:

  • $event.stopPropagation()
  • $event.stopImmediatePropagation()

मैंने बहुत सारे एनजी पॉइंटर इवेंट्स (मूसमोव, म्यूओवर, ...) को जोड़ा, लेकिन किसी ने भी मेरी मदद नहीं की।

सीएसएस समाधान:

मुझे एक सरल सीएसएस संपत्ति के साथ समाधान मिला जिसे मैं अधिक से अधिक उपयोग करता हूं:

pointer-events: none;

मूल रूप से, मैं इसका उपयोग उस तरह करता हूं (मेरी सूची तत्वों पर):

ng-style="{'pointer-events': vm.isHover ? 'none' : ''}"

इस मुश्किल के साथ, एनजी-माउस की घटनाओं को अब ट्रिगर नहीं किया जाएगा और मेरा फ्लोटिंग नेविगेशन मेनू कर्सर के ऊपर और सूची से एक तत्व के ऊपर होने पर अब खुद को बंद नहीं करेगा।

आगे जाने के लिए:

जैसा कि आप उम्मीद कर सकते हैं, यह समाधान काम करता है लेकिन मुझे यह पसंद नहीं है।
हम अपनी घटनाओं को नियंत्रित नहीं करते हैं और यह खराब है।
इसके अलावा, आपके पास vm.isHoverइसे प्राप्त करने के लिए गुंजाइश होनी चाहिए और यह संभव या संभव नहीं हो सकता है लेकिन किसी तरह या किसी अन्य तरीके से गंदा हो सकता है।
अगर कोई दिखना चाहे तो मैं एक फील कर सकता था।

फिर भी, मेरे पास दूसरा उपाय नहीं है ...
यह एक लंबी कहानी है और मैं आपको एक आलू नहीं दे सकता, इसलिए कृपया मुझे मेरे दोस्त को माफ कर दें।
वैसे भी, pointer-events: noneजीवन है, इसलिए इसे याद रखें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.