Replace a textNode with mixed-content HTML string
up vote
2
down vote
favorite
For this HTML node:
<div><i>foo</i> and <i>bar</i> go ### with <b>baz</b></div>
I would like to replace the string ###
with another node (<u>well</u>
), without replacing the entire innerHTML
of the wrapper div
.
Expected result:
<div><i>foo</i> and <i>bar</i> go <u>well</u> with <b>baz</b></div>
My approach was to iterate the childNodes, filter only the TEXT_NODE
elements with the string i would like to replace and replace those textNodes with replaceChild
using a DOM Fragment to hold the replaced content:
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>
As you can see, replacing a textNode
in this manner doesn't work as expected.
While I can manually extract each part of the replacedString and break it into:
`before textNode` / New element / `after textNode`
and piece them all in, that would create a lot of code (this is actually the way i'm currently doing it, and am trying to think of a smarter way, but the fragment didn't help with the parsing & insertion as you can see)
javascript html dom
add a comment |
up vote
2
down vote
favorite
For this HTML node:
<div><i>foo</i> and <i>bar</i> go ### with <b>baz</b></div>
I would like to replace the string ###
with another node (<u>well</u>
), without replacing the entire innerHTML
of the wrapper div
.
Expected result:
<div><i>foo</i> and <i>bar</i> go <u>well</u> with <b>baz</b></div>
My approach was to iterate the childNodes, filter only the TEXT_NODE
elements with the string i would like to replace and replace those textNodes with replaceChild
using a DOM Fragment to hold the replaced content:
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>
As you can see, replacing a textNode
in this manner doesn't work as expected.
While I can manually extract each part of the replacedString and break it into:
`before textNode` / New element / `after textNode`
and piece them all in, that would create a lot of code (this is actually the way i'm currently doing it, and am trying to think of a smarter way, but the fragment didn't help with the parsing & insertion as you can see)
javascript html dom
For anyone wondering, it's for my script Tagify
– vsync
Nov 10 at 20:12
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
For this HTML node:
<div><i>foo</i> and <i>bar</i> go ### with <b>baz</b></div>
I would like to replace the string ###
with another node (<u>well</u>
), without replacing the entire innerHTML
of the wrapper div
.
Expected result:
<div><i>foo</i> and <i>bar</i> go <u>well</u> with <b>baz</b></div>
My approach was to iterate the childNodes, filter only the TEXT_NODE
elements with the string i would like to replace and replace those textNodes with replaceChild
using a DOM Fragment to hold the replaced content:
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>
As you can see, replacing a textNode
in this manner doesn't work as expected.
While I can manually extract each part of the replacedString and break it into:
`before textNode` / New element / `after textNode`
and piece them all in, that would create a lot of code (this is actually the way i'm currently doing it, and am trying to think of a smarter way, but the fragment didn't help with the parsing & insertion as you can see)
javascript html dom
For this HTML node:
<div><i>foo</i> and <i>bar</i> go ### with <b>baz</b></div>
I would like to replace the string ###
with another node (<u>well</u>
), without replacing the entire innerHTML
of the wrapper div
.
Expected result:
<div><i>foo</i> and <i>bar</i> go <u>well</u> with <b>baz</b></div>
My approach was to iterate the childNodes, filter only the TEXT_NODE
elements with the string i would like to replace and replace those textNodes with replaceChild
using a DOM Fragment to hold the replaced content:
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>
As you can see, replacing a textNode
in this manner doesn't work as expected.
While I can manually extract each part of the replacedString and break it into:
`before textNode` / New element / `after textNode`
and piece them all in, that would create a lot of code (this is actually the way i'm currently doing it, and am trying to think of a smarter way, but the fragment didn't help with the parsing & insertion as you can see)
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>
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>
javascript html dom
javascript html dom
edited Nov 10 at 19:02
asked Nov 10 at 18:30
vsync
44.4k35154215
44.4k35154215
For anyone wondering, it's for my script Tagify
– vsync
Nov 10 at 20:12
add a comment |
For anyone wondering, it's for my script Tagify
– vsync
Nov 10 at 20:12
For anyone wondering, it's for my script Tagify
– vsync
Nov 10 at 20:12
For anyone wondering, it's for my script Tagify
– vsync
Nov 10 at 20:12
add a comment |
2 Answers
2
active
oldest
votes
up vote
1
down vote
Instead of this:
replacedString = inputChildren[i].nodeValue.replace('###', tag);
You can use
var offset = ...indexOf('###');
replacementNode = textnode.splitText(offset);
And then by adding
textnode.parent.insertBefore(wrapper, replacementNode);
you can achieve what you want.
Thanks. Split helped, I've managed to piece a working example (posted as an answer) but I still had to replace the###
string inreplacementNode
since it was still present
– vsync
Nov 10 at 19:21
add a comment |
up vote
0
down vote
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>
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
Instead of this:
replacedString = inputChildren[i].nodeValue.replace('###', tag);
You can use
var offset = ...indexOf('###');
replacementNode = textnode.splitText(offset);
And then by adding
textnode.parent.insertBefore(wrapper, replacementNode);
you can achieve what you want.
Thanks. Split helped, I've managed to piece a working example (posted as an answer) but I still had to replace the###
string inreplacementNode
since it was still present
– vsync
Nov 10 at 19:21
add a comment |
up vote
1
down vote
Instead of this:
replacedString = inputChildren[i].nodeValue.replace('###', tag);
You can use
var offset = ...indexOf('###');
replacementNode = textnode.splitText(offset);
And then by adding
textnode.parent.insertBefore(wrapper, replacementNode);
you can achieve what you want.
Thanks. Split helped, I've managed to piece a working example (posted as an answer) but I still had to replace the###
string inreplacementNode
since it was still present
– vsync
Nov 10 at 19:21
add a comment |
up vote
1
down vote
up vote
1
down vote
Instead of this:
replacedString = inputChildren[i].nodeValue.replace('###', tag);
You can use
var offset = ...indexOf('###');
replacementNode = textnode.splitText(offset);
And then by adding
textnode.parent.insertBefore(wrapper, replacementNode);
you can achieve what you want.
Instead of this:
replacedString = inputChildren[i].nodeValue.replace('###', tag);
You can use
var offset = ...indexOf('###');
replacementNode = textnode.splitText(offset);
And then by adding
textnode.parent.insertBefore(wrapper, replacementNode);
you can achieve what you want.
answered Nov 10 at 18:40
c-smile
20.1k44166
20.1k44166
Thanks. Split helped, I've managed to piece a working example (posted as an answer) but I still had to replace the###
string inreplacementNode
since it was still present
– vsync
Nov 10 at 19:21
add a comment |
Thanks. Split helped, I've managed to piece a working example (posted as an answer) but I still had to replace the###
string inreplacementNode
since it was still present
– vsync
Nov 10 at 19:21
Thanks. Split helped, I've managed to piece a working example (posted as an answer) but I still had to replace the
###
string in replacementNode
since it was still present– vsync
Nov 10 at 19:21
Thanks. Split helped, I've managed to piece a working example (posted as an answer) but I still had to replace the
###
string in replacementNode
since it was still present– vsync
Nov 10 at 19:21
add a comment |
up vote
0
down vote
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>
add a comment |
up vote
0
down vote
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>
add a comment |
up vote
0
down vote
up vote
0
down vote
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>
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>
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>
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>
answered Nov 10 at 19:20
vsync
44.4k35154215
44.4k35154215
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242142%2freplace-a-textnode-with-mixed-content-html-string%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
For anyone wondering, it's for my script Tagify
– vsync
Nov 10 at 20:12