【问题标题】:How to determine if there exists text at the beginning or end of a parent element? HTML DOM & JavaScript如何确定父元素的开头或结尾是否存在文本? HTML DOM 和 JavaScript
【发布时间】:2014-10-14 22:34:23
【问题描述】:

假设我们有一个嵌套跨度:

<span><span></span></span>

我们想知道文本是否存在

<span> here <span> </span></span>

<span><span></span> here</span>

假设我们引用了父元素节点。

请注意

<span> text <span> text </span> text </span>

<span> text <span> text </span></span>

是两种完全可能的情况。

【问题讨论】:

  • 你知道那个空间也是一个文本节点吧?
  • 也可能是domnode.textContent()
  • 我没想到那个空间,不。如果在解决我的问题时使用了该功能,我不会感到惊讶,如果您能够自己在答案中使用它,请这样做来帮助我!
  • 这是一个属性顺便说一句不是方法developer.mozilla.org/en-US/docs/Web/API/Node.textContent

标签: javascript html dom textnode


【解决方案1】:

不确定这是不是最好的方法,但这是我的解决方案首先出现在我的脑海中:

HTML:

<span id="span1">
    thththt
    <span id="span2"></span>
</span>

JS:

var span = document.getElementById('span1');
var spanChilds = span.childNodes;
var textIndex = -1;

for(var i = 0; i < spanChilds.length; ++i){
    debugger;
    if(spanChilds[i].nodeType == 3){
        textIndex = i;
        break;
    }
}

var nestSpan = document.getElementById('span2');
var nestSpanIndex = Array.prototype.indexOf.call(span.childNodes, nestSpan);

if(nestSpanIndex > textIndex){
    alert('text first')
}else{
    alert('span first')
}

Example 上 jsFiddle

【讨论】:

  • 你能抓住文本而不是一开始就对其进行硬编码吗?我们不知道文本是什么,您可以使用它来查找文本的索引
  • 查看更新。我们可以通过nodeType 获取文本节点,它等于 3。
  • 拥有一个不依赖于特定元素 ID 的解决方案可能会很好。另外,这个方案没有处理文本节点是最后一个子节点的情况。
【解决方案2】:

因此,使用@weeklyTea 回答中的一些概念,我将三个函数组合在一起,为所提出的问题提供答案。

我认为要指出的重要一点是,我们总是有一个嵌套元素节点。而且我们“不确定”元素节点的两侧是否有文本节点。当它这样说时,我认为这些功能将相当简单:

function isNestedHighlightAtEnd(parent) {
    var childNodes = parent.childNodes;
    var childNodesLength = childNodes.length;

    if( childNodes[childNodesLength-1].nodeType != 3 ) {
        return true;
    }
    else {
        return false;
    }
}

function isNestedHighlightAtMiddle(parent) {

    if( !isNestedHighlightAtBeg( parent ) && !isNestedHighlightAtEnd( parent )) {
        return true;
    }
    else {
        return false;
    }                
}

function isNestedHighlightAtBeg(parent) {
    var childNodes = parent.childNodes;
    var childNodesLength = childNodes.length;

    if( childNodes[0].nodeType != 3) {
        return true;
    }
    else {
        return false;
    } 
}

【讨论】:

  • 只是好奇你为什么会说if (a != b) { return true; } else { return false; }而不是return a != b;
  • 这是一件小事,两者的工作方式相同,效率不高。
  • 当然可以,但抛开效率不谈,它更冗长、行数更多、拼写错误和错误的表面积更大,而且没有必要。
  • 我已经2年没有看到这个评论了,我仍然为自己的愚蠢感到畏缩。
【解决方案3】:

应该不会比

node.firstChild && node.firstChild.nodeType === Node.TEXT_NODE || 
  node.lastChild && node.lastChild.nodeType === Node.TEXT_NODE

为了可读性,最好使用Node.*_NODE 符号常量(尽管它们可能未在旧浏览器中定义)。

为避免出现空文本节点的问题,您可以在此之前添加

node.normalize()

哪个

将指定节点及其所有子树放入“规范化” 形式。在规范化子树中,子树中没有文本节点为空 并且没有相邻的文本节点。

https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize

省略注释节点和纯空格文本节点:

var children = Array.prototype.filter.call(node.childNodes || [], function(node) {
  return node.nodeType !== Node.COMMENT_NODE &&
    (node.nodeType !== Node.TEXT_NODE || /\S/.test(node.nodeValue));
}),
    firstChild = children[0],
    lastChild = children[children.length-1];

return firstChild && firstChild.nodeType === Node.TEXT_NODE ||
  lastChild && lastChild.nodeType === Node.TEXT_NODE;

如果由于某种原因检查是否有潜伏在其中的子元素很重要,那么添加检查就足够了

!!node.children.length

【讨论】:

  • 接受这个作为答案,因为它按字面意思回答了我的问题,并提供了很多有用/补充信息