【问题标题】:Select element without a child选择没有子元素的元素
【发布时间】:2013-02-04 16:28:17
【问题描述】:

我的页面可能是以下之一:

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

或者

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

我想在这两种情况下都获取值“33”,有没有我可以使用的 CSS 选择器? 我尝试使用以下,没有 b 兄弟的 #size 或 #size 兄弟的 b:

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

但我不断收到错误消息-“错误:SYNTAX_ERR:DOM Exception 12”

根据w3 Spec,仅支持Simple Selectors,问题是“大于号”(U+003E,>)”被视为Simple Selectors定义的一部分。

【问题讨论】:

  • 你得到什么样的错误?
  • 第一个标签示例没有正确关闭:它以&lt;span&gt; 开头并以&lt;/a&gt; 结束。
  • 在CSS级别4和父选择器之前恐怕没有纯CSS的解决方案...
  • 对于那些可以使用 jQuery 的人,$('#size:not(:has(b)), #size:has(b)') 应该按照this question 工作。
  • @Blender 这也将选择第二个示例的整个 span 元素,这(我猜)不是 OP 想要的。不过不确定。

标签: css css-selectors


【解决方案1】:

我们将拥有 CSS Level 4 选择器和父选择器的那一天,您将能够使用简单的选择器,但现在您不能直接使用。

您可以迭代找到第一个文本节点,但这是一个 hacky 解决方案:

var text = document.getElementById('size').innerHTML.split(/<.*?>/)[0];

仅在您对#size 元素的内容有所了解时使用。

【讨论】:

  • 不会在第二种情况下返回“b>33”吗?
  • 1) 它不是父选择器 2) 主题选择器在这里没有帮助,所以在第 4 级也不行。
【解决方案2】:

所以你真的想要重要的文本(即除了空格,因为在你的第二个例子中,#sizespan 开始标记和b 之间可能有制表符和返回),或者,如果不是这样存在,其第一个元素的重要文本:

// 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;
    }
}

【讨论】:

  • 我修复了问题并从第一个示例中删除了空格
【解决方案3】:

你不能用常规的 CSS 选择器来做,但是你可以用几行 JS 来做:

var element = document.querySelector('#size');
var b = element.querySelector('b');
var text = b ? b.innerText : element.childNodes[0].nodeValue;

console.log(text);

【讨论】:

  • 查看我对规范的最后一次编辑,如果我没记错的话,规范说它应该可以工作。
  • @GuyKorland: :not() 需要一组 #size 不应该包含的元素。 &gt; b 本身不是一个有效的选择器,这就是你得到错误的原因。
猜你喜欢
  • 2010-10-24
  • 2013-07-17
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 2014-07-06
  • 1970-01-01
相关资源
最近更新 更多