Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery selector for an element that directly contains text?

Tags:

I was able to get this partially working using the :contains selector, but my problem is if an element contains an element that contains the text it is still returned. For example:

$('div:contains("test")')

Will select both divs below:

<div>something else
   <div>test</div>
</div>

fiddle: http://jsfiddle.net/TT7dR/

How can I select only divs that "directly" contain the text? Meaning that in the above example only the child div would be selected.

UPDATE:

Just to clarify, if I were searching for the text "something else" instead of "test" then I would like to only find the parent div.

like image 235
Abe Miessler Avatar asked Oct 25 '11 22:10

Abe Miessler


People also ask

How do I check if a div contains a text?

To check if a div element contains specific text:Use the textContent property on the element to get the text content of the element and its descendants. Use the includes() method to check if the specific text is contained in the div . If it is, the includes() method returns true , otherwise false is returned.

How do I select a span containing a specific text value using jQuery?

To select a span containing a specific text value using jQuery, we can select all the spans and then use the filter method to find the one with the given text value. We call $(“span”) to get all the spans. Then we spread the spans into an array with the spread operator.

Which jQuery function is used to get the text content of an element?

jQuery text() Method The text() method sets or returns the text content of the selected elements. When this method is used to return content, it returns the text content of all matched elements (HTML markup will be removed).


Video Answer


4 Answers

$('div>:contains("test")') is not a general solution, it only works for your specific example. It still matches any element whose descendants contain the text test, as long as its parent is a div.

There is in fact currently no selector that will select only direct parents of text nodes containing your target text. To do it you would have to walk the DOM tree yourself checking each text node you find for the target text, or write a plugin to do the same. It'd be slow, but then not as slow as :contains already is (it's not a standard CSS selector so you don't get browser-native fast selector support).

Here's a plain DOM function you could use as a starting point. It might be improved to find text in adjacent (non-normalised) text nodes, or to hide it in a plugin/selector-extension.

function findElementsDirectlyContainingText(ancestor, text) {
    var elements= [];
    walk(ancestor);
    return elements;

    function walk(element) {
        var n= element.childNodes.length;
        for (var i= 0; i<n; i++) {
            var child= element.childNodes[i];
            if (child.nodeType===3 && child.data.indexOf(text)!==-1) {
                elements.push(element);
                break;
            }
        }
        for (var i= 0; i<n; i++) {
            var child= element.childNodes[i];
            if (child.nodeType===1)
                walk(child);
        }
    }
}
like image 127
bobince Avatar answered Sep 28 '22 09:09

bobince


Just to complete the knowledge base. If you need to get all DOM elements within the body (not only DIVs) that contain specific text or characters you can use:

function getNodesThatContain(text) {
    var textNodes = $(document).find(":not(iframe, script)")
      .contents().filter( 
          function() {
           return this.nodeType == 3 
             && this.textContent.indexOf(text) > -1;
    });
    return textNodes.parent();
};

console.log(getNodesThatContain("test"));

Hope that helps.

jsfiddle: http://jsfiddle.net/85qEh/2/

Credits: DMoses

like image 23
Avatar Avatar answered Sep 24 '22 09:09

Avatar


You might have to do an in-efficient query. Do not use this solution if someone finds a selector that manages to filter out child elements: http://viralpatel.net/blogs/2011/02/jquery-get-text-element-without-child-element.html

$("div:contains('test')")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .filter(":contains('test')")

edit: that snippet above is just to test the element, in implementation it would look more like this: http://jsfiddle.net/rkw79/TT7dR/6/

$("div:contains('test')").filter(function() {
    return (
    $(this).clone() //clone the element
    .children() //select all the children
    .remove() //remove all the children
    .end() //again go back to selected element
    .filter(":contains('test')").length > 0)
}).css('border', 'solid 1px black');
like image 6
rkw Avatar answered Sep 25 '22 09:09

rkw


try adding the greater than:

$('div>:contains("test")')
like image 3
Hussam Avatar answered Sep 24 '22 09:09

Hussam