Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select element without a child

I have a page that might one of the following:

<span id='size'>33</span>

Or

<span id='size'>
    <b>33</b>
    <strike>32</strike>
</span>

I would like to grab the value '33' on both cases, is there a CSS selector I can use? I tried to use the following, #size with no b sibling or b which is a #size sibling:

document.querySelector('#size:not(>b), #size>b').innerText

But I keep getting an error- "Error: SYNTAX_ERR: DOM Exception 12"

According to w3 Spec only Simple Selectors are supported, the thing is that "greater-than sign" (U+003E, >)" is considered as part of the Simple Selectors definition.

like image 563
Guy Korland Avatar asked Feb 19 '13 20:02

Guy Korland


People also ask

How do you select an element without a class?

The :not CSS pseudo-class can be used to select elements that do not contain a specific class, id, attribute etc.

Which is used to select that element which does not contain any children?

children('. example'). length; }); This filters out any elements that have any child that matches .

How do you check if an element has a child?

Use one of the firstChild, childNodes. length, children. length property to find whether element has child or not. hasChildNodes() method can also be used to find the child of the parent node.

What is element childNodes?

Definition and Usage The childNodes property returns a collection (list) of an elements's child nodes. The childNodes property returns a NodeList object. The childNodes property is read-only. childNodes[0] is the same as firstChild .


1 Answers

So really you want significant text (ie other than whitespace, because in your second example there's probably tabs and returns between the span start tag and the b) of #size, or, if that doesn't exist, the significant text of its first element:

// Is text just whitespace?
function isWhitespace(text){
    return text.replace(/\s+/,'').length === 0;
}

// Get the immediate text (ie not that of children) of element
function getImmediateText(element){
    var text = '';

    // Text and elements are all DOM nodes. We can grab the lot of immediate descendants and cycle through them.
    for(var i = 0, l = element.childNodes.length, node; i < l, node = element.childNodes[i]; ++i){
    // nodeType 3 is text
        if(node.nodeType === 3){
            text += node.nodeValue;
        }
    }

    return text;
}

function getFirstTextNode(element){
    var text = getImmediateText(element);

    // If the text is empty, and there are children, try to get the first child's text (recursively)
    if(isWhitespace(text) && element.children.length){
        return getFirstTextNode(element.children[0])
    }
    // ...But if we've got no children at all, then we'll just return whatever we have.
    else {
        return text;
    }
}
like image 158
Barney Avatar answered Oct 05 '22 21:10

Barney