Замените текстовый узел HTML-строкой со смешанным содержимым - PullRequest
0 голосов
/ 10 ноября 2018

Для этого узла HTML:

<div><i>foo</i> and <i>bar</i> go ### with <b>baz</b></div>

Я хотел бы заменить строку ### другим узлом (<u>well</u>), не заменяя всю innerHTML оболочки div.

Ожидаемый результат:

<div><i>foo</i> and <i>bar</i> go <u>well</u> with <b>baz</b></div>

Мой подход заключался в итерации childNodes , фильтрации только элементов TEXT_NODE со строкой, которую я хотел бы заменить, и замене этих textNodes на replaceChild, используя фрагмент DOM для хранения замененного содержимого:

var root = document.querySelector('div'),
    tag = "<u>well</u>",
    tempFrag = document.createDocumentFragment(),
    children = root.childNodes,
    replacedString;

 for( var i = children.length; i--; ){
      if( children[i].nodeType === Node.TEXT_NODE && 
          children[i].nodeValue.length > 1        && 
          children[i].nodeValue.indexOf('###') != -1 ){
       
            replacedString = children[i].nodeValue.replace('###', tag);

            console.log( replacedString );
            tempFrag.innerHTML = replacedString;
            children[i].parentNode.replaceChild(tempFrag, children[i])
      }    
}
<div><i>foo</i> and <i>bar</i> go ### with <b>baz</b></div>

Как видите, замена textNode таким образом не работает должным образом.

Хотя я могу вручную извлечь каждую часть replaceString и разбить ее на:

`before textNode` / New element / `after textNode` 

и объединить их воедино, это создаст много кода (именно так я сейчас и поступаю, и пытаюсь придумать более разумный способ, но фрагмент не помог при разборе & вставка как видите)

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

var root = document.querySelector('div'),
    tag = document.createElement('u'),
    children = root.childNodes,
    replacedNode,
    idx;

 tag.innerHTML = "well";
 
 for( var i = children.length; i--; ){
      if( children[i].nodeType === Node.TEXT_NODE && 
          children[i].nodeValue.length > 1 ){
            idx = children[i].nodeValue.indexOf('###');
            if( idx == -1 ) continue;
            
            replacedNode = children[i].splitText(idx);
            // remove '###' from the second split textNode ('### with')
            replacedNode.nodeValue = replacedNode.nodeValue.replace('###', '');
            // put the tag element before the second split textNode
            children[i].parentNode.insertBefore(tag, replacedNode);
      }    
}
<div><i>foo</i> and <i>bar</i> go ### with <b>baz</b></div>
0 голосов
/ 10 ноября 2018

Вместо этого:

replacedString = inputChildren[i].nodeValue.replace('###', tag);

Вы можете использовать

var offset = ...indexOf('###');
replacementNode = textnode.splitText(offset); 

А затем, добавив

textnode.parent.insertBefore(wrapper, replacementNode);

вы можете достичь того, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...