तत्व का पता लगाएं (वेनिला जावास्क्रिप्ट)


84

मैंने हर जगह एक अच्छे समाधान की तलाश की है, फिर भी मुझे वह नहीं मिल रहा है जो jQuery का उपयोग नहीं करता है ।

क्या एक क्रॉस-ब्राउज़र, सामान्य तरीका (अजीब हैक के बिना या कोड को तोड़ने में आसान है), एक तत्व के बाहर एक क्लिक का पता लगाने के लिए (जिसमें बच्चे हो सकते हैं या नहीं हो सकते हैं)?


क्या बॉडी टैग पर ऑनक्लिक ईवेंट हैंडलर सेट करना काम करेगा?
— बेंजामिन तूएग

जवाबों:


192

किसी ईवेंट श्रोता को इसमें जोड़ें documentऔर Node.contains()यह पता लगाने के लिए उपयोग करें कि क्या ईवेंट का लक्ष्य (जो सबसे आंतरिक क्लिक किया गया तत्व है) आपके निर्दिष्ट तत्व के अंदर है या नहीं। यह IE5 में भी काम करता है

var specifiedElement = document.getElementById('a');

//I'm using "click" but it works with any event
document.addEventListener('click', function(event) {
  var isClickInside = specifiedElement.contains(event.target);

  if (!isClickInside) {
    //the click was outside the specifiedElement, do something
  }
});


14
मुझे सबसे सुंदर समाधान लगता है।
— मैरिअन

3
यह मैंने कभी देखा है सबसे अच्छा समाधान है।
— हेलोवर्ल्ड

25

आपको दस्तावेज़ स्तर पर क्लिक ईवेंट को संभालने की आवश्यकता है। ईवेंट ऑब्जेक्ट में, आपके पास एक targetगुण है, आंतरिक-सबसे DOM तत्व जिसे क्लिक किया गया था। इसके साथ आप स्वयं जाँच करें और दस्तावेज़ तत्व तक उसके माता-पिता को चलाएं, यदि उनमें से एक आपका देखा गया तत्व है।

JsFiddle पर उदाहरण देखें

document.addEventListener("click", function (e) {
  var level = 0;
  for (var element = e.target; element; element = element.parentNode) {
    if (element.id === 'x') {
      document.getElementById("out").innerHTML = (level ? "inner " : "") + "x clicked";
      return;
    }
    level++;
  }
  document.getElementById("out").innerHTML = "not x clicked";
});

हमेशा की तरह, यह addEventListener / संलग्नक की वजह से क्रॉस-बैड-ब्राउज़र संगत नहीं है, लेकिन यह इस तरह काम करता है।

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

क्रॉस-ब्राउज़र संगतता को जोड़ना, मैं आमतौर पर इसे इस तरह से कर रहा हूं:

var addEvent = function (element, eventName, fn, useCapture) {
  if (element.addEventListener) {
    element.addEventListener(eventName, fn, useCapture);
  }
  else if (element.attachEvent) {
    element.attachEvent(eventName, function (e) {
      fn.apply(element, arguments);
    }, useCapture);
  }
};

यह एक ईवेंट श्रोता / हैंडलर संलग्न करने के लिए क्रॉस-ब्राउज़र संगत कोड है, thisIE में समावेशी पुनर्लेखन , तत्व होने के लिए, जैसे कि jQuery अपने इवेंट हैंडलर के लिए करता है। मन में jQuery के कुछ बिट्स होने के लिए बहुत सारे तर्क हैं;)


4
यदि उपयोगकर्ता तत्व का एक बच्चा क्लिक करता है तो क्या होगा?
— तिबरियू-आयनू स्टेन

3
इस समाधान का उपयोग करते हुए, आप targetसंपत्ति की जांच करते हैं (जो, जैसा कि मेटाडेट्स कहते हैं, सबसे भीतरी डोम तत्व होगा) - और इसके सभी मूल तत्व। या तो आप अपने देखे गए तत्व तक पहुँचते हैं, जिसका अर्थ है कि उपयोगकर्ता ने उसके अंदर क्लिक किया है, या आप दस्तावेज़ तत्व तक पहुँचते हैं, जिस स्थिति में वह बाहर क्लिक करता है। वैकल्पिक रूप से, आप दो क्लिक श्रोताओं को जोड़ सकते हैं - एक दस्तावेज़ तत्व पर, और दूसरा देखे गए तत्व पर, जो उपयोग करता है event.stopPropagation()/ cancelBubbleताकि दस्तावेज़ तत्व पर श्रोता केवल देखे गए तत्व के बाहर एक क्लिक से ट्रिगर हो।
— जिम्मी त्ह

2
इसका कुछ चतुर उपयोग है for। जिज्ञासा से बाहर, किसी भी कारण से एक तत्व की तुलना एक चर से लक्ष्य पर घटना से नहीं की जाएगी (सख्त तुलना का उपयोग करके)?
— तिबरियू-आयनू स्टेन

@ Tiberiu-IonuțStan हाँ, यदि आप आईडी 'x' के बजाय एक संदर्भ का उपयोग करके इस 'वॉच' को बनाते हैं, तो मेरा सुझाव है कि आप ट्रिपल इक्वल्स का उपयोग करके तत्व === watchedElement का उपयोग करें।
— मेटाडेट्स

आपका समाधान महान काम करता है। यह एक व्यक्तिगत मुद्दा हो सकता है, लेकिन मैं इसे साझा करना चाहूंगा। मुझे एक ही आवश्यकता है, लेकिन एक बटन पर क्लिक करने से एक div दिखाता है, जब उपयोगकर्ता क्लिक करता है, तो उसे छिपाया जाना चाहिए। इस समाधान के साथ समस्या यह है कि div को फिर कभी नहीं दिखाया गया है। मैंने आपके कोड को एक उदाहरण के लिए यहां दिया था: jsfiddle.net/bx5hnL2h
— अलेक्जेंड्रे श्मिट

7

इस बारे में कैसा है:

jsBin डेमो

document.onclick = function(event){
  var hasParent = false;
    for(var node = event.target; node != document.body; node = node.parentNode)
    {
      if(node.id == 'div1'){
        hasParent = true;
        break;
      }
    }
  if(hasParent)
    alert('inside');
  else
    alert('outside');
} 

0

इसके बाहर क्लिक करके एलिमेंट छिपाने के लिए मैं आमतौर पर इस तरह के सरल कोड लागू करता हूं:

var bodyTag = document.getElementsByTagName('body');
var element = document.getElementById('element'); 
function clickedOrNot(e) {
	if (e.target !== element) {
		// action in the case of click outside 
		bodyTag[0].removeEventListener('click', clickedOrNot, true);
	}	
}
bodyTag[0].addEventListener('click', clickedOrNot, true);


0

इस समस्या के लिए एक और बहुत ही सरल और त्वरित दृष्टिकोण pathश्रोता द्वारा लौटाए गए ईवेंट ऑब्जेक्ट में सरणी को मैप करना है। यदि idयाclass अपने तत्व के नाम सरणी में उन में से एक से मेल खाता है, क्लिक करें अपने तत्व के अंदर है।

(यह समाधान उपयोगी हो सकता है यदि आप सीधे तत्व प्राप्त नहीं करना चाहते हैं (उदाहरण के लिए: document.getElementById('...') एक प्रतिक्रिया में / उदाहरण के लिए, एप्लिकेशन में ssr में)।

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

   document.addEventListener('click', e => {
      let clickedOutside = true;

      e.path.forEach(item => {
        if (!clickedOutside)
          return;

        if (item.className === 'your-element-class')
          clickedOutside = false;
      });

      if (clickedOutside)
        // Make an action if it's clicked outside..
    });

मुझे उम्मीद है कि यह उत्तर आपकी मदद करेगा! (मुझे बताएं कि क्या मेरा समाधान एक अच्छा समाधान नहीं है या यदि आप कुछ सुधार करने के लिए देखते हैं।)


नेस्टेड तत्वों के बारे में क्या?
— टिबेरिउ-आयनो स्टेन

@ Tiberiu-IonuțStan आपके पास माता-पिता से लेकर बच्चों तक की पूरी नोड सूची तक पहुंच है, इसलिए आप उन्हें आसानी से हेरफेर कर सकते हैं।
— hpapier

अचानक आपका समाधान सरल नहीं है।
— तिबेरिउ-आयनो स्टेन

@ Tiberiu-IonuțStan क्यों? व्यक्तिगत रूप से मुझे लगता है कि यह समाधान रिएक्ट या जटिल जेएस वातावरण में सबसे सरल है। किसी भी रेफरी की जरूरत नहीं है, एक समाधान लागू करने की जरूरत नहीं है अगर डोम लोड करने के लिए समय बनाते हैं, तो आपके पास अधिक नियंत्रण है।
— hpapier

0

मैंने एक बेहतर तरीका खोजने के लिए इस पर काफी शोध किया। JavaScript विधि .contains DOM में पुनरावर्ती रूप से यह जाँचने के लिए जाती है कि उसमें लक्ष्य है या नहीं। मैंने इसे एक प्रतिक्रिया परियोजना में इस्तेमाल किया, लेकिन जब प्रतिक्रिया DOM सेट स्थिति पर बदल जाती है, तो .contains विधि काम नहीं करती है। तो मैं इस समाधान के साथ आया था

//Basic Html snippet
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
<div id="mydiv">
  <h2>
    click outside this div to test
  </h2>
  Check click outside 
</div>
</body>
</html>


//Implementation in Vanilla javaScript
const node = document.getElementById('mydiv')
//minor css to make div more obvious
node.style.width = '300px'
node.style.height = '100px'
node.style.background = 'red'

let isCursorInside = false

//Attach mouseover event listener and update in variable
node.addEventListener('mouseover', function() {
  isCursorInside = true
  console.log('cursor inside')
})

/Attach mouseout event listener and update in variable
node.addEventListener('mouseout', function() {
    isCursorInside = false
  console.log('cursor outside')
})


document.addEventListener('click', function() {
  //And if isCursorInside = false it means cursor is outside 
    if(!isCursorInside) {
    alert('Outside div click detected')
  }
})

काम कर रहा है डेमो jsfiddle

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