如何单独检索's在父元素内部的子元素之前和之后

How can I separately retrieve the HTML that's before and after a child element inside a parent element?

本文关键字:元素 内部 之后 检索 何单独      更新时间:2023-09-26

我们正在编写一个依赖Javascript/jQuery的web应用程序。它涉及到用户在一大块文本中填写单个单词,有点像Mad Libs。我们创建了一种HTML格式,用于编写大块文本,然后在用户填写时使用jQuery对其进行操作。

文本块的一部分可能看起来像这样:

<span class="fillmeout">This is a test of the <span>NOUN</span> Broadcast System.</span>

给定该标记,我需要分别检索和操作内部<span>之前和之后的文本;我们称之为"前缀"answers"后缀"。

我知道你不能用简单的字符串操作来解析HTML,但我还是试过了;我尝试在<span></span>标签上使用split()。这似乎很简单。不幸的是,InternetExplorer将所有HTML标记强制转换为大写,因此该技术失败了。我可以写一个特例,但这个错误教会了我正确的方法。

我知道我可以简单地使用额外的HTML标记来手动表示前缀和后缀,但这看起来很难看,也很多余;我希望我们的标记格式尽可能精简、可读写。

我浏览了jQuery文档,找不到一个能满足我需要的函数。有各种各样的函数可以在元素之前、之后、周围和内部添加内容,但我找不到任何函数来检索已经存在的内容。我可以删除内部<span>,但我不知道如何区分删除元素之前的内容和之后的内容。

有没有一种"正确"的方式来做我想做的事情?

通过简单的字符串操作,您也可以使用Regex。这应该能解决你的问题。

var array = $('.fillmeout').html().split(/<'/?span>/i);

使用jQuery API!$('.fillmeout').children(),然后您可以根据需要操作该元素。

http://api.jquery.com/children/

为了完整性,我想我应该指出,最干净的答案是像这样将前缀和后缀文本放在它自己的<span>中,然后你可以使用jQuery选择器和方法直接访问所需的文本:

<span class="fillmeout">
    <span class="prefix">This is a test of the </span>
    <span>NOUN</span>
    <span class="suffix"> Broadcast System.</span>
</span>

然后,代码将简单到:

var fillme = $(".fillmeout").eq(0);
var prefix = fillme.find(".prefix").text();
var suffix = fillme.find(".suffix").text();

仅供参考,我不会像你所说的那样,把这种简单程度称为"丑陋和多余"。您使用HTML标记将文本划分为要单独访问的单独元素。这很聪明,不是多余的。

通过类比的方式,想象你有三种不同颜色的玩具(红色、白色和蓝色),它们最初是按颜色组织的,你知道在未来的某个时候,你需要再次按颜色将它们分开。你还有三个盒子可以存放它们。你可以现在把它们都放在一个盒子里,以后再手动按颜色分类,也可以把已经分离的颜色分别放在自己的盒子里,这样以后就没有分离的工作了。哪个更容易?哪个更聪明?

HTML元素就像盒子一样。它们是文本的容器。如果你想在未来将文本分离出来,你不妨将每一段文本放入它自己的命名容器中,这样以后就可以很容易地访问这段文本。

其中的几个答案几乎满足了我的需求,但最终我找到了一个这里没有提到的函数:.contents()。它返回一个包含所有子节点(包括文本节点)的数组,然后我可以对这些子节点进行迭代(如果需要,可以递归)以找到我需要的内容。

我也不确定这是否是"正确"的方式,但你可以用一个可以一致分割字符串的元素来替换SPAN:

jQuery('.fillmeout span').replaceWith('|');

http://api.jquery.com/replaceWith/

http://jsfiddle.net/mdarnell/P24se/

您可以使用

$('.fillmeout span').get(0).previousSibling.textContent
$('.fillmeout span').get(0).nextSibling.textContent

这在IE9中有效,但遗憾的是,在小于9的IE版本中无效。

根据您的示例,您可以使用目标作为分隔符来分隔句子。

var str = $('.fillmeout').html();
str = str.split('<span>NOUN</span>');

这将返回一个["This is a test of the ", " Broadcast System."]的数组。下面是一个jsFiddle示例

您只需使用nextSiblingpreviousSibling本机JavaScript(与jQuery选择器结合使用):

$('.fillmeout span').each(
    function(){
        var prefix = this.previousSibling.nodeValue,
            suffix = this.nextSibling.nodeValue;
    });

JS Fiddle概念证明。

参考文献:

  • each()
  • node.nextSibling
  • node.previousSibling

如果您想使用DOM而不是自己解析HTML,并且无法将所需的文本放在它自己的元素中,那么您需要在DOM中查找文本节点,并找到span标记前后的文本节点。

jQuery在处理文本节点而不是元素节点时并没有太多帮助,所以工作主要是用简单的javascript完成的,比如:

$(".fillmeout").each(function() {
    var node = this.firstChild, prefix = "", suffix = "", foundSpan = false;
    while (node) {
        if (node.nodeType == 3) {
            // if text node
            if (!foundSpan) {
                prefix += node.nodeValue;
            } else  {
                suffix += node.nodeValue;
            }
        } else if (node.nodeType == 1 && node.tagName == "SPAN") {
            // if element and span tag
            foundSpan = true;
        }
        node = node.nextSibling;
    }
    // here prefix and suffix are the text before and after the first
    // <span> tag in the HTML
    // You can do with them what you want here
});

注意:此代码并不假设跨度之前的所有文本都位于一个文本节点中,并且仅位于一个文字节点中。它可能是,但也可能不是,因此它将span标记前后的所有文本节点整理在一起。如果只在每一侧引用一个文本节点,代码会更简单,但不能100%确定这是一个安全的假设。

此代码还处理跨度前后没有文本的情况。

你可以在这里看到它的工作原理:http://jsfiddle.net/jfriend00/P9YQ6/