निकटतम पूर्वज तत्व का पता लगाएं जिसमें एक विशिष्ट वर्ग है


225

मैं एक तत्व के पूर्वज को कैसे खोज सकता हूं जो शुद्ध जावास्क्रिप्ट में पेड़ के सबसे करीब है ? उदाहरण के लिए, एक पेड़ में जैसे:

<div class="far ancestor">
    <div class="near ancestor">
        <p>Where am I?</p>
    </div>
</div>

फिर मैं चाहता हूं कि div.near.ancestorअगर मैं इस पर कोशिश करूं pऔर खोज करूं ancestor


1
कृपया ध्यान दें कि बाहरी div माता-पिता नहीं है, यह तत्व का पूर्वज है p। यदि आप वास्तव में केवल मूल नोड प्राप्त करना चाहते हैं, तो आप कर सकते हैं ele.parentNode
फेलिक्स क्लिंग

@FelixKling: उस शब्दावली को नहीं जानता था; मै इसे बदलूंगा।
आरविन्ह

3
यह वास्तव में वैसा ही है जैसा हम इंसान इस्तेमाल करते हैं :) आपके पिता (माता-पिता) के पिता (माता-पिता) आपके पिता (माता-पिता) नहीं हैं, यह आपके दादा (दादा-दादी), या आमतौर पर बोलने वाले, आपके पूर्वज हैं।
फेलिक्स क्लिंग

जवाबों:


346

अद्यतन: अब अधिकांश प्रमुख ब्राउज़रों में समर्थित है

document.querySelector("p").closest(".near.ancestor")

ध्यान दें कि यह चयनकर्ताओं से मेल खा सकता है, न कि केवल कक्षाओं में

https://developer.mozilla.org/en-US/docs/Web/API/Element.closest


विरासत ब्राउज़रों के लिए जो समर्थन नहीं करते हैं, closest()लेकिन matches()एक चयनकर्ता मिलान @ rvighne के वर्ग मिलान के समान बना सकते हैं:

function findAncestor (el, sel) {
    while ((el = el.parentElement) && !((el.matches || el.matchesSelector).call(el,sel)));
    return el;
}

1
अभी भी इंटरनेट एक्सप्लोरर, एज और ओपेरा मिनी के वर्तमान संस्करणों में समर्थित नहीं है।
क्लेइनफ्रेन्ड

1
@kleinfreund - अभी भी IE, एज, या ओपेरा मिनी में समर्थित नहीं है। caniuse.com/#search=closest
evolutionxbox

8
जून 2016: ऐसा लगता है कि सभी ब्राउज़र अभी भी पकड़े नहीं गए हैं
कुणाल

3
एक DOM लेवल 4 पॉलीफ़िल है जिसमें closestकई और अधिक उन्नत DOM ट्रैवर्सल सुविधाएँ हैं। आप उस कार्यान्वयन को अपने आप खींच सकते हैं या अपने कोड में बहुत सी नई सुविधाएँ प्राप्त करने के लिए पूरे बंडल को शामिल कर सकते हैं।
गरबी

2
एज 15 का समर्थन है, जिसमें सभी प्रमुख ब्राउज़रों को शामिल किया जाना चाहिए। जब तक आप IE11 की गिनती नहीं करते हैं, लेकिन यह किसी भी अपडेट को प्राप्त नहीं करता है
the8472

195

यह चाल है:

function findAncestor (el, cls) {
    while ((el = el.parentElement) && !el.classList.contains(cls));
    return el;
}

जब तक elवांछित वर्ग है, तब तक लूप इंतजार करता है , और यह elकरने के लिए सेट करता हैel अंत में माता-पिता के लिए हर पुनरावृत्ति , तो आपके पास उस वर्ग के साथ पूर्वज हैं या null

यहाँ एक बेला है , अगर कोई इसे सुधारना चाहता है। यह पुराने ब्राउज़रों (यानी IE) पर काम नहीं करेगा; क्लासिस्ट के लिए यह संगतता तालिका देखें । parentElementयहाँ उपयोग किया जाता है क्योंकि parentNodeयह सुनिश्चित करने के लिए अधिक कार्य शामिल होगा कि नोड एक तत्व है।


1
विकल्प के लिए .classList, stackoverflow.com/q/5898656/218196 देखें ।
फेलिक्स क्लिंग

1
मैंने कोड तय कर दिया है, लेकिन यह तब भी एक त्रुटि होगी, यदि इस तरह के वर्ग के नाम के साथ कोई पूर्वज नहीं है।
फेलिक्स क्लिंग

2
उह, मैंने सोचा कि यह मौजूद नहीं था, लेकिन मैं गलत था । वैसे भी, parentElementएक नई संपत्ति (DOM स्तर 4) है और parentNodeतब से मौजूद है ... हमेशा के लिए। इसलिए parentNodeपुराने ब्राउज़रों में भी काम करता है, जबकि ऐसा parentElementनहीं हो सकता है। बेशक आप / के खिलाफ एक ही तर्क कर सकते हैं classList, लेकिन यह एक सरल विकल्प नहीं है, जैसे parentElementहै। मुझे वास्तव में आश्चर्य है कि parentElementयह सब क्यों मौजूद है, यह किसी भी मूल्य को जोड़ने के लिए प्रतीत नहीं होता है parentNode
फेलिक्स क्लिंग

1
@FelixKling: अभी संपादित किया गया है, यह अब इस मामले के लिए ठीक काम करता है जब कोई पूर्वज मौजूद नहीं है। मुझे शॉर्ट ओरिजिनल वर्जन के साथ ओवरएगर मिलना चाहिए था।
rvighne

3
यदि आप पैरामीटर तत्व में वर्ग नाम के लिए स्वयं जाँच करना चाहते हैं, तो इसके पूर्वजों को खोजने से पहले, आप केवल लूप में शर्तों के क्रम को बदल सकते हैं:while (!el.classList.contains(cls) && (el = el.parentElement));
निकोमक

34

एलीमेंट का उपयोग करें

https://developer.mozilla.org/en-US/docs/Web/API/Element/closest

इस उदाहरण को देखें DOM:

<article>
  <div id="div-01">Here is div-01
    <div id="div-02">Here is div-02
      <div id="div-03">Here is div-03</div>
    </div>
  </div>
</article>

इस तरह से आप element.closest का उपयोग करेंगे:

var el = document.getElementById('div-03');

var r1 = el.closest("#div-02");  
// returns the element with the id=div-02

var r2 = el.closest("div div");  
// returns the closest ancestor which is a div in div, here is div-03 itself

var r3 = el.closest("article > div");  
// returns the closest ancestor which is a div and has a parent article, here is div-01

var r4 = el.closest(":not(div)");
// returns the closest ancestor which is not a div, here is the outmost article

14

On४ on२ के उत्तर और https://developer.mozilla.org/en-US/docs/Web/API/Element/matches के आधार पर यहां क्रॉस-प्लेटफॉर्म २०१47 समाधान है:

if (!Element.prototype.matches) {
    Element.prototype.matches =
        Element.prototype.matchesSelector ||
        Element.prototype.mozMatchesSelector ||
        Element.prototype.msMatchesSelector ||
        Element.prototype.oMatchesSelector ||
        Element.prototype.webkitMatchesSelector ||
        function(s) {
            var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                i = matches.length;
            while (--i >= 0 && matches.item(i) !== this) {}
            return i > -1;
        };
}

function findAncestor(el, sel) {
    if (typeof el.closest === 'function') {
        return el.closest(sel) || null;
    }
    while (el) {
        if (el.matches(sel)) {
            return el;
        }
        el = el.parentElement;
    }
    return null;
}

11

@rvighne समाधान अच्छी तरह से काम करता है, लेकिन जैसा कि टिप्पणियों में पहचाना गया है ParentElementऔर ClassListदोनों में संगतता मुद्दे हैं। इसे और अधिक सुसंगत बनाने के लिए, मैंने उपयोग किया है:

function findAncestor (el, cls) {
    while ((el = el.parentNode) && el.className.indexOf(cls) < 0);
    return el;
}
  • parentNodeसंपत्ति के बदले parentElementसंपत्ति
  • indexOfclassNameसंपत्ति पर विधि के बजाय संपत्ति containsपर विधि classList

बेशक, इंडेक्सऑफ बस उस स्ट्रिंग की उपस्थिति की तलाश में है, यह परवाह नहीं करता है कि यह पूरी स्ट्रिंग है या नहीं। इसलिए यदि आपके पास कक्षा 'पूर्वज-प्रकार' के साथ एक और तत्व था, तो यह अभी भी 'पूर्वज' के रूप में पाया जाएगा, यदि यह आपके लिए एक समस्या है, तो शायद आप सटीक मिलान खोजने के लिए regexp का उपयोग कर सकते हैं।

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