मैं jQuery के साथ टेक्स्ट नोड्स का चयन कैसे करूं?


388

मैं एक jQuery संग्रह के रूप में एक तत्व के सभी वंशज पाठ नोड्स प्राप्त करना चाहता हूं। उसे करने का सबसे अच्छा तरीका कौन सा है?

जवाबों:


261

jQuery के पास इसके लिए सुविधाजनक कार्य नहीं है। आपको गठबंधन करने की आवश्यकता है contents(), जो सिर्फ बच्चे को नोड्स देगा, लेकिन इसमें टेक्स्ट नोड्स भी शामिल हैं find(), जिसके साथ सभी वंशज तत्व हैं लेकिन कोई टेक्स्ट नोड्स नहीं है। यहाँ मैं क्या लेकर आया हूँ:

var getTextNodesIn = function(el) {
    return $(el).find(":not(iframe)").addBack().contents().filter(function() {
        return this.nodeType == 3;
    });
};

getTextNodesIn(el);

नोट: यदि आप jQuery 1.7 या पहले का उपयोग कर रहे हैं, तो ऊपर दिया गया कोड काम नहीं करेगा। इसे ठीक करने के लिए, के addBack()साथ बदलें andSelf()। 1.8 से आगे के andSelf()पक्ष में पदावनत किया जाता है addBack()

यह शुद्ध DOM तरीकों की तुलना में कुछ अक्षम है और इसमें jQuery के अपने contents()फ़ंक्शन के ओवरलोडिंग के लिए एक बदसूरत वर्कअराउंड को शामिल करना है (यह इंगित करने के लिए टिप्पणियों में @rabidsnail के लिए धन्यवाद), इसलिए यहां एक साधारण पुनरावर्ती फ़ंक्शन का उपयोग करके गैर-jQuery समाधान है। includeWhitespaceNodesपैरामीटर नियंत्रण किया जाए या नहीं खाली स्थान के पाठ नोड्स उत्पादन में शामिल हैं (jQuery में वे स्वचालित रूप से फ़िल्टर किए जाते हैं)।

अद्यतन: फिक्स्ड बग जब शामिल हैंवॉटस्पेसनोड्स मिथ्या है।

function getTextNodesIn(node, includeWhitespaceNodes) {
    var textNodes = [], nonWhitespaceMatcher = /\S/;

    function getTextNodes(node) {
        if (node.nodeType == 3) {
            if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
                textNodes.push(node);
            }
        } else {
            for (var i = 0, len = node.childNodes.length; i < len; ++i) {
                getTextNodes(node.childNodes[i]);
            }
        }
    }

    getTextNodes(node);
    return textNodes;
}

getTextNodesIn(el);

क्या तत्व में पारित हो सकता है, एक div का नाम हो सकता है?
क्रोसेनब्लम

@ क्रोसनब्लम: document.getElementById()यदि आप जो चाहते हैं, तो आप सबसे पहले कॉल कर सकते हैं :var div = document.getElementById("foo"); var textNodes = getTextNodesIn(div);
टिम डाउन

JQuery में बग की वजह से यदि आपके पास कोई iframes है, तो आपको .find ('* *') के बजाय .find (': not (iframe)') का उपयोग करना होगा।
bobpoekert

@rabidsnail: मुझे लगता है, .contents()वैसे भी इसका उपयोग iframe के माध्यम से खोज करेगा। मैं नहीं देखता कि यह बग कैसे हो सकता है।
रॉबिन माबेन

Bugs.jquery.com/ticket/11275 क्या यह वास्तव में एक बग बहस के लिए प्रतीत होता है, लेकिन बग या नहीं अगर आप कॉल पाते हैं ('*') सामग्री () नोड पर एक iframe है जो नहीं है। डोम में जोड़ा गया है आपको एक अपरिभाषित बिंदु पर एक अपवाद मिलेगा।
बोबपोकेर्ट

209

Jauco ने एक टिप्पणी में एक अच्छा समाधान पोस्ट किया है, इसलिए मैं इसे यहां कॉपी कर रहा हूं:

$(elem)
  .contents()
  .filter(function() {
    return this.nodeType === 3; //Node.TEXT_NODE
  });

34
वास्तव में $ (elem) .contents () .filter (फ़ंक्शन () {इसे वापस लौटाएँ। nodeType == Node.TEXT_NODE;}); पर्याप्त है
जाको

37
IE7 नोड वैश्विक को परिभाषित नहीं करता है, इसलिए आपको इसका उपयोग करना होगा। nodeType == 3, दुर्भाग्य से: stackoverflow.com/questions/1423599/node-textnode-and-ie7
ईसाई Oud 20

17
क्या यह न केवल उन पाठ नोड्स को वापस करता है जो तत्व के प्रत्यक्ष बच्चे हैं, बल्कि तत्व के वंशज के रूप में ओपी द्वारा अनुरोध किया गया है?
टिम डाउन

7
यह तब काम नहीं करेगा जब टेक्स्ट नोड अन्य तत्वों के अंदर गहरे नेस्टेड हो, क्योंकि सामग्री () विधि केवल तत्काल बच्चों के नोड्स वापस करती है, api.jquery.com/contents
minhajul

1
@ जूको, नहीं, बहुत नहीं! as .contents () केवल तत्काल बच्चों के नोड्स देता है
मिन्हाजुल


6

jQuery.contents()jQuery.filterसभी बाल पाठ नोड्स को खोजने के लिए इस्तेमाल किया जा सकता है । थोड़े से मोड़ के साथ, आप पोते-पोतियों को भी पा सकते हैं। कोई पुनरावृत्ति आवश्यक नहीं:

$(function() {
  var $textNodes = $("#test, #test *").contents().filter(function() {
    return this.nodeType === Node.TEXT_NODE;
  });
  /*
   * for testing
   */
  $textNodes.each(function() {
    console.log(this);
  });
});
div { margin-left: 1em; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="test">
  child text 1<br>
  child text 2
  <div>
    grandchild text 1
    <div>grand-grandchild text 1</div>
    grandchild text 2
  </div>
  child text 3<br>
  child text 4
</div>

jsFiddle


4

मुझे स्वीकृत फ़िल्टर फ़ंक्शन के साथ बहुत सारे खाली पाठ नोड्स मिल रहे थे। यदि आप केवल ऐसे टेक्स्ट नोड्स का चयन करने में रुचि रखते हैं, जिनमें गैर-व्हाट्सएप हो, तो nodeValueअपने filterफ़ंक्शन को एक साधारण की तरह सशर्त जोड़ने का प्रयास करें $.trim(this.nodevalue) !== '':

$('element')
    .contents()
    .filter(function(){
        return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
    });

http://jsfiddle.net/ptp6m97v/

या अजीब स्थितियों से बचने के लिए जहां सामग्री व्हाट्सएप की तरह दिखती है, लेकिन ऐसा नहीं है (जैसे कि नरम हाइफ़न &shy;चरित्र, नए अंक \n, टैब, आदि), आप एक नियमित अभिव्यक्ति का उपयोग करने का प्रयास कर सकते हैं। उदाहरण के लिए, \Sकिसी भी गैर-व्हाट्सएप पात्रों से मेल खाएगा:

$('element')
        .contents()
        .filter(function(){
            return this.nodeType === 3 && /\S/.test(this.nodeValue);
        });

3

यदि आप यह अनुमान लगा सकते हैं कि सभी बच्चे या तो तत्व नोड्स या टेक्स्ट नोड्स हैं, तो यह एक समाधान है।

एक संग्रह के रूप में सभी बाल पाठ नोड्स प्राप्त करने के लिए:

$('selector').clone().children().remove().end().contents();

हटाए गए गैर-पाठ बच्चों के साथ मूल तत्व की एक प्रति प्राप्त करने के लिए:

$('selector').clone().children().remove().end();

1
बस एक और जवाब पर टिम डाउन की टिप्पणी पर ध्यान दिया। यह समाधान केवल सीधे बच्चों को मिलता है, सभी वंशजों को नहीं।
14

2

किसी कारण से contents()मेरे लिए काम नहीं किया, इसलिए अगर यह आपके लिए काम नहीं करता है, तो यहां एक समाधान मैंने बनाया है, मैंने jQuery.fn.descendantsटेक्स्ट नोड्स शामिल करने के विकल्प के साथ बनाया या नहीं

प्रयोग


पाठ नोड्स और तत्व नोड्स सहित सभी वंशज प्राप्त करें

jQuery('body').descendants('all');

केवल पाठ नोड्स लौटने वाले सभी वंशज प्राप्त करें

jQuery('body').descendants(true);

केवल तत्व नोड्स लौटने वाले सभी वंशज प्राप्त करें

jQuery('body').descendants();

कॉफ़ीस्क्रिप्ट मूल :

jQuery.fn.descendants = ( textNodes ) ->

    # if textNodes is 'all' then textNodes and elementNodes are allowed
    # if textNodes if true then only textNodes will be returned
    # if textNodes is not provided as an argument then only element nodes
    # will be returned

    allowedTypes = if textNodes is 'all' then [1,3] else if textNodes then [3] else [1]

    # nodes we find
    nodes = []


    dig = (node) ->

        # loop through children
        for child in node.childNodes

            # push child to collection if has allowed type
            nodes.push(child) if child.nodeType in allowedTypes

            # dig through child if has children
            dig child if child.childNodes.length


    # loop and dig through nodes in the current
    # jQuery object
    dig node for node in this


    # wrap with jQuery
    return jQuery(nodes)

जावास्क्रिप्ट संस्करण में छोड़ें

var __indexOf=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++){if(t in this&&this[t]===e)return t}return-1}; /* indexOf polyfill ends here*/ jQuery.fn.descendants=function(e){var t,n,r,i,s,o;t=e==="all"?[1,3]:e?[3]:[1];i=[];n=function(e){var r,s,o,u,a,f;u=e.childNodes;f=[];for(s=0,o=u.length;s<o;s++){r=u[s];if(a=r.nodeType,__indexOf.call(t,a)>=0){i.push(r)}if(r.childNodes.length){f.push(n(r))}else{f.push(void 0)}}return f};for(s=0,o=this.length;s<o;s++){r=this[s];n(r)}return jQuery(i)}

अनवांटेड जावास्क्रिप्ट संस्करण: http://pastebin.com/cX3jMfuD

यह क्रॉस ब्राउज़र है, एक छोटा Array.indexOfपॉलीफ़िल कोड में शामिल है।


1

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

var textContents = $(document.getElementById("ElementId").childNodes).filter(function(){
        return this.nodeType == 3;
});

उपरोक्त कोड दिए गए तत्व के सीधे बच्चे चाइल्ड नोड्स से टेक्स्टनोड्स को फ़िल्टर करता है।


1
... लेकिन सभी वंशज बच्चे नोड्स नहीं हैं (उदाहरण के लिए एक पाठ नोड जो मूल तत्व का बच्चा है)।
टिम डाउन

0

यदि आप सभी टैग को हटाना चाहते हैं, तो यह प्रयास करें

समारोह:

String.prototype.stripTags=function(){
var rtag=/<.*?[^>]>/g;
return this.replace(rtag,'');
}

उपयोग:

var newText=$('selector').html().stripTags();

0

मेरे लिए, सादे पुराने .contents() पाठ नोड्स को वापस करने के लिए काम करते दिखाई दिए, बस आपको अपने चयनकर्ताओं से सावधान रहना होगा ताकि आपको पता चले कि वे पाठ नोड्स होंगे।

उदाहरण के लिए, इसने टीडी के सभी पाठ सामग्री को preटैग के साथ मेरी तालिका में लपेटा और कोई समस्या नहीं थी।

jQuery("#resultTable td").content().wrap("<pre/>")

0

मेरे पास एक ही समस्या थी और इसे हल किया:

कोड:

$.fn.nextNode = function(){
  var contents = $(this).parent().contents();
  return contents.get(contents.index(this)+1);
}

उपयोग:

$('#my_id').nextNode();

की तरह है, next()लेकिन पाठ नोड्स भी लौटाता है।


.nextSibling डोम स्पेसिफिकेशन से है: developer.mozilla.org/en/Document_Object_Model_(DOM)/…
Guillermo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.