Как сделать раунд вокруг раздела текста без использования jQuery

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

Я хочу поместить span вокруг "Lorem Ipsum" без использования jQuery, поэтому результат выглядит так:

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

Любые идеи? Благодаря

Ответ 1

Сначала вам нужен какой-то способ доступа к абзацу. Вы можете указать атрибут 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, поэтому вы хотите заменить часть текста node на элемент. Вот как я это сделаю:

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 );

Работа с узлами на низком уровне - это немного неприятная ситуация; особенно без какой-либо абстракции, чтобы помочь вам. Я попытался сохранить чувство нормальности, создав DOM node из строки HTML, созданной из замещенной фразы "Lorem Ipsum". Пуристам, вероятно, не нравится это решение, но я считаю его вполне подходящим.


EDIT: теперь используйте фрагмент документа! Спасибо Полумесяц свежий!

Ответ 2

Объедините эти 2 руководства:

PPK на JavaScript: DOM - часть 3

Добавление элементов в DOM

В принципе вам нужно получить доступ к значению node, удалить его и создать новый дочерний элемент, значение node - это значение родительского элемента node, а затем добавить этот элемент (span в этом случае) в родительский (абзац в этом случае)

Ответ 3

Как насчет использования регулярного выражения в javascript и замены "Lorem Ipsum" на "<span> Lorem Ipsum </span> " (просто помните, что вам нужно будет получить "innerHTML" элемента, а затем снова заменить всю партию, которая может быть немного медленной)

Ответ 4

UPDATE: Нижеприведенный метод будет искать в поддереве, возглавляемом container, и обернуть все экземпляры text в элементе span. Слова могут встречаться в любом месте текста node, а текст node может возникать в любой позиции в поддереве.

(ОК, поэтому потребовалось больше нескольких мелких настроек: 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 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 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;
  }
}