L'/> L'/> 如何在不使用jQuery的情况下围绕文本部分包装跨度 | 所有编程讨论 | zhouni.net

问题 如何在不使用jQuery的情况下围绕文本部分包装跨度


<p>Lorem Ipsum <a href="#">Link</a> <div ... </div> </p>

我想围绕'Lorem Ipsum'  使用jQuery,结果如下:

<p><span>Lorem Ipsum </span><a href="#">Link</a> <div ... </div> </p>

有任何想法吗?谢谢


10182
2017-12-02 21:19


起源



答案:


首先,您需要某种方式来访问该段落。你可能想给它一个 id 属性,例如“foo”:

<p id="foo">Lorem Ipsum <a href="#">Link</a> <div ... </div> </p>

然后,你可以使用 document.getElementById 访问该元素并根据需要替换其子元素:

var p = document.getElementById('foo'),
    firstTextNode = p.firstChild,
    newSpan = document.createElement('span');

// Append "Lorem Ipsum" text to new span:
newSpan.appendChild( document.createTextNode(firstTextNode.nodeValue) );

// Replace old text node with new span:
p.replaceChild( newSpan, firstTextNode );

为了使其更可靠,您可能想要打电话 p.normalize() 在访问第一个子节点之前,确保将锚点之前的所有文本节点合并为一个。


Oook,所以你想用一个元素替换一个文本节点的一部分。我是这样做的:

function giveMeDOM(html) {

    var div = document.createElement('div'),
        frag = document.createDocumentFragment();

    div.innerHTML = html;

    while (div.firstChild) {
        frag.appendChild( div.firstChild );
    }

    return frag;
}

var p = document.getElementById('foo'),
    firstChild = p.firstChild;

// Merge adjacent text nodes:
p.normalize();

// Get new DOM structure:
var newStructure = giveMeDOM( firstChild.nodeValue.replace(/Lorem Ipsum/i, '<span>$&</span>') );

// Replace first child with new DOM structure:
p.replaceChild( newStructure, firstChild );

使用低级别的节点是一个令人讨厌的情况;特别是没有任何抽象来帮助你。我试图通过从替换的“Lorem Ipsum”短语生成的HTML字符串中创建DOM节点来保持正常感。纯粹主义者可能不喜欢这种解决方案,但我发现它非常合适。


编辑:现在使用文档片段!谢谢 新月新鲜


15
2017-12-02 21:41



但是,但......在哪里 搜索 (并转移到内部的匹配点 firstTextNode)为“Lorem Ipsum”? - Crescent Fresh
啊,忽略了,现在正在努力。 - James
@ J-P:我的upvote等待你的编辑!! - Crescent Fresh
编辑,匆忙但是:P - James
@ J-P:该死的,我希望能看到一点 DocumentFragment 行动!制作怎么样? giveMeDOM 返回一个文档片段,此时单个 p.replaceChild(p.firstChild, documentFragment) 真有魅力! - Crescent Fresh


答案:


首先,您需要某种方式来访问该段落。你可能想给它一个 id 属性,例如“foo”:

<p id="foo">Lorem Ipsum <a href="#">Link</a> <div ... </div> </p>

然后,你可以使用 document.getElementById 访问该元素并根据需要替换其子元素:

var p = document.getElementById('foo'),
    firstTextNode = p.firstChild,
    newSpan = document.createElement('span');

// Append "Lorem Ipsum" text to new span:
newSpan.appendChild( document.createTextNode(firstTextNode.nodeValue) );

// Replace old text node with new span:
p.replaceChild( newSpan, firstTextNode );

为了使其更可靠,您可能想要打电话 p.normalize() 在访问第一个子节点之前,确保将锚点之前的所有文本节点合并为一个。


Oook,所以你想用一个元素替换一个文本节点的一部分。我是这样做的:

function giveMeDOM(html) {

    var div = document.createElement('div'),
        frag = document.createDocumentFragment();

    div.innerHTML = html;

    while (div.firstChild) {
        frag.appendChild( div.firstChild );
    }

    return frag;
}

var p = document.getElementById('foo'),
    firstChild = p.firstChild;

// Merge adjacent text nodes:
p.normalize();

// Get new DOM structure:
var newStructure = giveMeDOM( firstChild.nodeValue.replace(/Lorem Ipsum/i, '<span>$&</span>') );

// Replace first child with new DOM structure:
p.replaceChild( newStructure, firstChild );

使用低级别的节点是一个令人讨厌的情况;特别是没有任何抽象来帮助你。我试图通过从替换的“Lorem Ipsum”短语生成的HTML字符串中创建DOM节点来保持正常感。纯粹主义者可能不喜欢这种解决方案,但我发现它非常合适。


编辑:现在使用文档片段!谢谢 新月新鲜


15
2017-12-02 21:41



但是,但......在哪里 搜索 (并转移到内部的匹配点 firstTextNode)为“Lorem Ipsum”? - Crescent Fresh
啊,忽略了,现在正在努力。 - James
@ J-P:我的upvote等待你的编辑!! - Crescent Fresh
编辑,匆忙但是:P - James
@ J-P:该死的,我希望能看到一点 DocumentFragment 行动!制作怎么样? giveMeDOM 返回一个文档片段,此时单个 p.replaceChild(p.firstChild, documentFragment) 真有魅力! - Crescent Fresh


结合这两个教程:

JavaScript上的PPK:DOM - 第3部分

向DOM添加元素

基本上,您需要访问节点值,删除它,并创建一个新的子元素,其节点值是父项的节点的值,然后将该元素(在本例中为span)附加到父元素(在本例中为段落)


0
2017-12-02 21:29





如何在javascript中使用正则表达式并将“Lorem Ipsum”替换为“<span> Lorem Ipsum </ span>”(请记住,您必须获取元素的“innerHTML”,然后再次替换整个批次可能有点慢)


0
2017-12-02 21:34



并且会破坏所有绑定的事件处理程序(如果有的话)。 - Crescent Fresh
问题是文本不是两个单词,而是一个较长的文本。此外,文本将出现在具有不同文本内容的不同位置。所以搜索特定的文本节点在这里不起作用: - / - patad


更新: 下面的方法将搜索以下为的子树 container 并包装所有的实例 text在span元素中。单词可以出现在文本节点内的任何位置,文本节点可以出现在子树中的任何位置。

(好的,所以只需要一些小的调整。:P)

function wrapText(container, text) {
  // Construct a regular expression that matches text at the start or end of a string or surrounded by non-word characters.
  // Escape any special regex characters in text.
  var textRE = new RegExp('(^|\\W)' + text.replace(/[\\^$*+.?[\]{}()|]/, '\\$&') + '($|\\W)', 'm');
  var nodeText;
  var nodeStack = [];

  // Remove empty text nodes and combine adjacent text nodes.
  container.normalize();

  // Iterate through the container's child elements, looking for text nodes.
  var curNode = container.firstChild;

  while (curNode != null) {
    if (curNode.nodeType == Node.TEXT_NODE) {
      // Get node text in a cross-browser compatible fashion.
      if (typeof curNode.textContent == 'string')
        nodeText = curNode.textContent;
      else
        nodeText = curNode.innerText;

      // Use a regular expression to check if this text node contains the target text.
      var match = textRE.exec(nodeText);
      if (match != null) {
        // Create a document fragment to hold the new nodes.
        var fragment = document.createDocumentFragment();

        // Create a new text node for any preceding text.
        if (match.index > 0)
          fragment.appendChild(document.createTextNode(match.input.substr(0, match.index)));

        // Create the wrapper span and add the matched text to it.
        var spanNode = document.createElement('span');
        spanNode.appendChild(document.createTextNode(match[0]));
        fragment.appendChild(spanNode);

        // Create a new text node for any following text.
        if (match.index + match[0].length < match.input.length)
          fragment.appendChild(document.createTextNode(match.input.substr(match.index + match[0].length)));

        // Replace the existing text node with the fragment.
        curNode.parentNode.replaceChild(fragment, curNode);

        curNode = spanNode;
      }
    } else if (curNode.nodeType == Node.ELEMENT_NODE && curNode.firstChild != null) {
      nodeStack.push(curNode);
      curNode = curNode.firstChild;
      // Skip the normal node advancement code.
      continue;
    }

    // If there's no more siblings at this level, pop back up the stack until we find one.
    while (curNode != null && curNode.nextSibling == null)
      curNode = nodeStack.pop();

    // If curNode is null, that means we've completed our scan of the DOM tree.
    // If not, we need to advance to the next sibling.
    if (curNode != null)
      curNode = curNode.nextSibling;
  }
}

0
2017-12-02 22:56



感谢那。问题是文本不是lorem ipsum,它是一个很长的文本。文本也可以出现在具有不同内容的不同地方。所以搜索特定的文本节点在这里不起作用: - / - patad
所以你需要它来遍历DOM树的一部分(或全部?)并用span来包装一些文本字符串的每个实例?通过一些重新设计,这应该是可能的。我将编辑我的功能来执行此操作。 - Annabelle
我更新了我的回复。它现在遍历DOM子树,检查它为指定文本找到的任何文本节点。 - Annabelle