CSS styling a single character within a word - javascript

My client has asked for the letter 4 to appear in red, wherever it is used in his website navigation.
For instance, where he has 'bikes4kids' as a menu item.
Unfortunately, I am using a 'mega menu' style plugin for his Magento site that only allows for plain text menu items - I cannot use HTML code in the menu item title box, which takes away the chance of me using <span>.
Is there a way of achieving this with JS? I assume not with CSS alone.
EDIT: The mega menu I am working with can be seen here: http://www.magentech.com/extensions/commercial-extensions/item/246-sm-mega-menu-responsive-magento-module

I did it.
Please have a look at this Link
<div class="title">menu1</div>
<div class="title">bike4kids</div>
<div class="title">menu2</div>
var avno = $(".title:nth-child(2)").text();
var avn = avno.split('4');
var item = avn[0]+"<span style='color:red'>4</span>"+avn[1];
$(".title:nth-child(2)").html(item);

No, within “plain text menu items” (as described in the question) you cannot style one character differently from others (except in a few very special cases, which do not apply here: styling the first letter, and setting the font of some characters different from others). JavaScript won’t help, because you would still need to make the character an element, and anything containing an element is by definition not plain text.
So you need to consider other approaches, like menus with items that allow some markup.

If you can process the document after it's finished loading, or sometime after magento has finished doing its thing, you can try the following. It will wrap a provided character in a span with a supplied class. A root element can be provided to limit the scope of the replace. If no root is provided, it searches the entire document.
// Simple function to convert NodeList to Array
// Not suitable for general application
function toArray(obj) {
var a = [];
for (var i=0, iLen=obj.length; i<iLen; i++) {
a[i] = obj[i];
}
return a;
}
// Highlight character c by wrapping in a span with class className
// starting with element root. If root not provided, document.body is used
function highlightChar(c, className, root) {
if (!root) root = document.body;
var frag, idx, t;
var re = new RegExp(c);
// Add tag names to ignore
var ignoreTags = {'script':'script'};
// Child nodes is a live NodeList, convert to array
// so don't have to deal with changing as nodes are added
var node, nodes = toArray(root.childNodes);
var span = document.createElement('span');
span.appendChild(document.createTextNode(c));
span.className = 'highlightChar';
for (var i=0, iLen=nodes.length; i<iLen; i++) {
node = nodes[i];
// If node is a text node and contains the chacter, highlight it
if (node.nodeType == 3 && re.test(node.data)) {
t = node.data.split(re);
frag = document.createDocumentFragment();
// Insert higlight spans after first but not after last
for (var j=0, jLen = t.length-1; j<jLen; j++) {
frag.appendChild(document.createTextNode(t[j]));
frag.appendChild(span.cloneNode(true));
}
// Append last text node
if (j > 0 && t[j]) {
frag.appendChild(document.createTextNode(t[j]));
}
// Replace the original text node with higlighted fragment
node.parentNode.replaceChild(frag, node);
// Otherwise, if node is an element, process it
} else if (node.nodeType == 1 && !(node.tagName.toLowerCase() in ignoreTags)) {
highlightChar(c, className, node);
}
}
}
It can be used to process the entire document using:
window.onload = function() {
highlightChar('4','highlightChar');
};

Edit:
Modified to find menu-items in 'mega menu'... I hope. In the demo site the "$" variable isn't jQuery so I modified the answer as well to use the jQuery function.
Testing in the demo site I found that the letter I modified did color yellow, but there was a bullet added to the left of it - apparently their css adds a bullet to the left (ie. :before) every span...
After the plugin completes its DOM modifications - simply run over the menu items and search-and-replace "4" with a colored span
eg.
// loop over all dom elements with class 'menu-item'
// - I assume here below them exist only text
jQuery('.sm-megamenu-child span').each(function() {
var $item = jQuery(this);
var text = $item.text();
var modified = text.replace(/4/g, "<span style='color:yellow'>4</span>");
$item.html(modified);
})

Related

Swapping Two Divs with Javascript [duplicate]

What is the easiest way to swap the order of child nodes?
For example I want childNode[3] to be childNode[4] and vice-versa.
There is no need for cloning. You can just move one node before the other. The .insertBefore() method will take it from its current location and insert it somewhere else (thus moving it):
childNode[4].parentNode.insertBefore(childNode[4], childNode[3]);
You get the parent of the node. You then call the insertBefore method on the parent and you pass it the childNode[4] node and tell it you want it inserted before childNode[3]. That will give you the result of swapping their order so 4 will be before 3 when it's done.
Reference documentation on insertBefore.
Any node that is inserted into the DOM that is already in the DOM is first removed automatically and then inserted back so there is no need to manually remove it first.
Use .before or .after!
This is vanilla JS!
childNode[3].before(childNode[4]);
or
childNode[4].after(childNode[3]);
For more durability swapping, try:
function swap(node1, node2) {
const afterNode2 = node2.nextElementSibling;
const parent = node2.parentNode;
node1.replaceWith(node2);
parent.insertBefore(node1, afterNode2);
}
This should work, even if the parents don't match
Can I Use - 95% Jul '21
Answer by jfriend00 does not really swap elements (it "swaps" only elements which are next to each other and only under the same parent node). This is ok, since this was the question.
This example swaps elements by cloning it but regardless of their position and DOM level:
// Note: Cloned copy of element1 will be returned to get a new reference back
function exchangeElements(element1, element2)
{
var clonedElement1 = element1.cloneNode(true);
var clonedElement2 = element2.cloneNode(true);
element2.parentNode.replaceChild(clonedElement1, element2);
element1.parentNode.replaceChild(clonedElement2, element1);
return clonedElement1;
}
Edit: Added return of new reference (if you want to keep the reference, e. g. to access attribute "parentNode" (otherwise it gets lost)). Example: e1 = exchangeElements(e1, e2);
I needed a function to swap two arbitrary nodes keeping the swapped elements in the same place in the dom. For example, if a was in position 2 relative to its parent and b was in position 0 relative to its parent, b should replace position 2 of a's former parent and a should replace child 0 of b's former parent.
This is my solution which allows the swap to be in completely different parts of the dom. Note that the swap cannot be a simple three step swap. Each of the two elements need to be removed from the dom first because they may have siblings that would need updating, etc.
Solution: I put in two holder div's to hold the place of each node to keep relative sibling order. I then reinsert each of the nodes in the other's placeholder, keeping the relative position that the swapped node had before the swap. (My solution is similar to Buck's).
function swapDom(a,b)
{
var aParent = a.parentNode;
var bParent = b.parentNode;
var aHolder = document.createElement("div");
var bHolder = document.createElement("div");
aParent.replaceChild(aHolder,a);
bParent.replaceChild(bHolder,b);
aParent.replaceChild(b,aHolder);
bParent.replaceChild(a,bHolder);
}
For a real Swap of any nodes without cloneNode:
<div id="d1">D1</div>
<div id="d2">D2</div>
<div id="d3">D3</div>
With SwapNode function (using PrototypeJS):
function SwapNode(N1, N2) {
N1 = $(N1);
N2 = $(N2);
if (N1 && N2) {
var P1 = N1.parentNode;
var T1 = document.createElement("span");
P1.insertBefore(T1, N1);
var P2 = N2.parentNode;
var T2 = document.createElement("span");
P2.insertBefore(T2, N2);
P1.insertBefore(N2, T1);
P2.insertBefore(N1, T2);
P1.removeChild(T1);
P2.removeChild(T2);
}
}
SwapNode('d1', 'd2');
SwapNode('d2', 'd3');
Will produce:
<div id="d3">D3</div>
<div id="d1">D1</div>
<div id="d2">D2</div>
Use a dummy sibling as a temporary position marker and then .before (or .after).
It works for any siblings (not only adjacent) and also maintains event handlers.
function swap(a, b) {
let dummy = document.createElement("span")
a.before(dummy)
b.before(a)
dummy.replaceWith(b)
}
<div id="div1">A</div>
<div id="div2">B</div>
<p> parent<div id="div3">C</div>
</p>
<button onclick="swap(div1, div3)">swap</button>
Just like temporary variables are used to swap variables, if more sophicated methods are missing.
Best way to do this is to create a temporary node
function swapNodes(node1, node2) {
const temp = document.createComment('')
node2.replaceWith(temp)
node1.replaceWith(node2)
temp.replaceWith(node1)
}
Try this method:
Get the parent element
Store the two elements you want to swap
Store the .nextSibling of the node that is last in order
eg: [1,2,3,4] => we want to swap 3 & 2 then store nextSibling of 3, '4'.
.insertBefore(3,2);
.insertBefore(2,nextSibling);
Code Explanation
val & val2 are the 2 nodes/elements to be swapped
equiv(index) gets the present node/element in DOM at index passed as the paramter
NOTE: It will count comment & text elements so take care xD
Hopes this helps :)
function equiv(index){
return Array.prototype.slice.call( document.querySelectorAll("*"))[index];
}
function swap (val,val2){
let _key = val.key;
let _key_ = val2.key;
_key_ = _key < _key_ ? _key_+1:_key_;
let _parent_ = val2.parentElement.valueOf();
if (val.parentElement.children.length ==1)
val.parentElement.appendChild(val2);
else
val.parentElement.insertBefore(val2,val);
if (_parent_.children.length ==0)
_parent_.appendChild(val);
else{
let _sibling_ = equiv(_key_);
_parent_.insertBefore(val,_sibling_);}
}
A solution that works without cloning, given the indices of the two elements to swap:
function swapChildren(parentElement, index1, index2) {
if (index1 === index2)
return
if (index1 > index2) {
const temp = index1
index1 = index2
index2 = temp
}
const { [index1]: element1, [index2]: element2 } = parentElement.childNodes
if (index2 === index1 + 1) {
parentElement.insertBefore(element2, element1)
} else {
const reference = element2.nextSibling
parentElement.replaceChild(element2, element1)
parentElement.insertBefore(element1, reference)
}
}
You can swap a DOM element with its next sibling like that:
el.parentNode.insertBefore(el, el.nextElementSibling)
Or with its previous sibling like this:
el.parentNode.insertBefore(el, el.previousElementSibling)
And if your content is dynamic, you might want to check that el.nextElementSibling or el.previousElementSibling is not null.

Remove Text from Element Without Removing Reference

I would like to replace all the text in some element (including text in children) with some other text. For example, the html
<div id="myText">
This is some text.
This is some other text.
<p id="toHide">
This is even more text.
Click this text to hide it.
</p>
</div>
should become
<div id="myText">
That is some text.
That is some other text.
<p id="toHide">
That is even more text.
Click That text to hide it.
</p>
</div>
Essentially, I've replaced all of /this/gi with "That". However, I cannot use the following:
$("#myText").innerHTML = $("#myText").innerHTML.replace(/this/gi, "");
This is because I keep a lot of references to the children of myText. This references will be erased. I realize that in simple cases, I can just update these references, but I have a fairly large file, and many references (and it would be troublesome and error prone to have to update every reference every time this function is called).
I also store some data not visible to innerHTML. For example, I use
$("#toHide").test = "test";
This is lost when writing to innerHTML.
How can I replace text in a div without innerHTML (preferably without jquery)?
Jsfiddle http://jsfiddle.net/prankol57/ZEfM7/
Here's a solution:
var n, walker = document.createTreeWalker(document.getElementById("myText"), NodeFilter.SHOW_TEXT);
while (n = walker.nextNode()) {
n.nodeValue = n.nodeValue.replace(/this/ig, "that");
}
Basically, walk all the text nodes, and substitute their values.
For better compatibility, here's some reusable code:
function visitTextNodes(el, callback) {
if (el.nodeType === 3) {
callback(el);
}
for (var i=0; i < el.childNodes.length; ++i) {
visitTextNodes(el.childNodes[i], callback);
}
}
Then you can do:
visitTextNodes(document.getElementById("myText"), function(el) {
el.nodeValue = el.nodeValue.replace(/this/ig, "that");
});
You can use DOM methods (a.k.a. the old and safe way)
function replaceText(el, pattern, txt) {
for(var i=0; i<el.childNodes.length; ++i) {
var node = el.childNodes[i];
switch(node.nodeType){
case 1: // Element
replaceText(node, pattern, txt); continue;
case 3: // Text node
node.nodeValue = node.nodeValue.replace(/this/gi, "that"); continue;
}
}
}
Demo
Here my version of replaceText:
function replaceText(elem) {
if(elem.nodeType === Node.TEXT_NODE) {
elem.nodeValue = elem.nodeValue.replace(/this/gi, 'that')
return
}
var children = elem.childNodes
for(var i = 0, len = children.length; i < len; ++i)
replaceText(children[i]);
}
NB this take an element as the first parameter and traverse all children, hence it works even with complex elements.
Here the updated fiddle: http://jsfiddle.net/ZEfM7/6/

How to swap DOM child nodes in JavaScript?

What is the easiest way to swap the order of child nodes?
For example I want childNode[3] to be childNode[4] and vice-versa.
There is no need for cloning. You can just move one node before the other. The .insertBefore() method will take it from its current location and insert it somewhere else (thus moving it):
childNode[4].parentNode.insertBefore(childNode[4], childNode[3]);
You get the parent of the node. You then call the insertBefore method on the parent and you pass it the childNode[4] node and tell it you want it inserted before childNode[3]. That will give you the result of swapping their order so 4 will be before 3 when it's done.
Reference documentation on insertBefore.
Any node that is inserted into the DOM that is already in the DOM is first removed automatically and then inserted back so there is no need to manually remove it first.
Use .before or .after!
This is vanilla JS!
childNode[3].before(childNode[4]);
or
childNode[4].after(childNode[3]);
For more durability swapping, try:
function swap(node1, node2) {
const afterNode2 = node2.nextElementSibling;
const parent = node2.parentNode;
node1.replaceWith(node2);
parent.insertBefore(node1, afterNode2);
}
This should work, even if the parents don't match
Can I Use - 95% Jul '21
Answer by jfriend00 does not really swap elements (it "swaps" only elements which are next to each other and only under the same parent node). This is ok, since this was the question.
This example swaps elements by cloning it but regardless of their position and DOM level:
// Note: Cloned copy of element1 will be returned to get a new reference back
function exchangeElements(element1, element2)
{
var clonedElement1 = element1.cloneNode(true);
var clonedElement2 = element2.cloneNode(true);
element2.parentNode.replaceChild(clonedElement1, element2);
element1.parentNode.replaceChild(clonedElement2, element1);
return clonedElement1;
}
Edit: Added return of new reference (if you want to keep the reference, e. g. to access attribute "parentNode" (otherwise it gets lost)). Example: e1 = exchangeElements(e1, e2);
I needed a function to swap two arbitrary nodes keeping the swapped elements in the same place in the dom. For example, if a was in position 2 relative to its parent and b was in position 0 relative to its parent, b should replace position 2 of a's former parent and a should replace child 0 of b's former parent.
This is my solution which allows the swap to be in completely different parts of the dom. Note that the swap cannot be a simple three step swap. Each of the two elements need to be removed from the dom first because they may have siblings that would need updating, etc.
Solution: I put in two holder div's to hold the place of each node to keep relative sibling order. I then reinsert each of the nodes in the other's placeholder, keeping the relative position that the swapped node had before the swap. (My solution is similar to Buck's).
function swapDom(a,b)
{
var aParent = a.parentNode;
var bParent = b.parentNode;
var aHolder = document.createElement("div");
var bHolder = document.createElement("div");
aParent.replaceChild(aHolder,a);
bParent.replaceChild(bHolder,b);
aParent.replaceChild(b,aHolder);
bParent.replaceChild(a,bHolder);
}
For a real Swap of any nodes without cloneNode:
<div id="d1">D1</div>
<div id="d2">D2</div>
<div id="d3">D3</div>
With SwapNode function (using PrototypeJS):
function SwapNode(N1, N2) {
N1 = $(N1);
N2 = $(N2);
if (N1 && N2) {
var P1 = N1.parentNode;
var T1 = document.createElement("span");
P1.insertBefore(T1, N1);
var P2 = N2.parentNode;
var T2 = document.createElement("span");
P2.insertBefore(T2, N2);
P1.insertBefore(N2, T1);
P2.insertBefore(N1, T2);
P1.removeChild(T1);
P2.removeChild(T2);
}
}
SwapNode('d1', 'd2');
SwapNode('d2', 'd3');
Will produce:
<div id="d3">D3</div>
<div id="d1">D1</div>
<div id="d2">D2</div>
Use a dummy sibling as a temporary position marker and then .before (or .after).
It works for any siblings (not only adjacent) and also maintains event handlers.
function swap(a, b) {
let dummy = document.createElement("span")
a.before(dummy)
b.before(a)
dummy.replaceWith(b)
}
<div id="div1">A</div>
<div id="div2">B</div>
<p> parent<div id="div3">C</div>
</p>
<button onclick="swap(div1, div3)">swap</button>
Just like temporary variables are used to swap variables, if more sophicated methods are missing.
Best way to do this is to create a temporary node
function swapNodes(node1, node2) {
const temp = document.createComment('')
node2.replaceWith(temp)
node1.replaceWith(node2)
temp.replaceWith(node1)
}
Try this method:
Get the parent element
Store the two elements you want to swap
Store the .nextSibling of the node that is last in order
eg: [1,2,3,4] => we want to swap 3 & 2 then store nextSibling of 3, '4'.
.insertBefore(3,2);
.insertBefore(2,nextSibling);
Code Explanation
val & val2 are the 2 nodes/elements to be swapped
equiv(index) gets the present node/element in DOM at index passed as the paramter
NOTE: It will count comment & text elements so take care xD
Hopes this helps :)
function equiv(index){
return Array.prototype.slice.call( document.querySelectorAll("*"))[index];
}
function swap (val,val2){
let _key = val.key;
let _key_ = val2.key;
_key_ = _key < _key_ ? _key_+1:_key_;
let _parent_ = val2.parentElement.valueOf();
if (val.parentElement.children.length ==1)
val.parentElement.appendChild(val2);
else
val.parentElement.insertBefore(val2,val);
if (_parent_.children.length ==0)
_parent_.appendChild(val);
else{
let _sibling_ = equiv(_key_);
_parent_.insertBefore(val,_sibling_);}
}
A solution that works without cloning, given the indices of the two elements to swap:
function swapChildren(parentElement, index1, index2) {
if (index1 === index2)
return
if (index1 > index2) {
const temp = index1
index1 = index2
index2 = temp
}
const { [index1]: element1, [index2]: element2 } = parentElement.childNodes
if (index2 === index1 + 1) {
parentElement.insertBefore(element2, element1)
} else {
const reference = element2.nextSibling
parentElement.replaceChild(element2, element1)
parentElement.insertBefore(element1, reference)
}
}
You can swap a DOM element with its next sibling like that:
el.parentNode.insertBefore(el, el.nextElementSibling)
Or with its previous sibling like this:
el.parentNode.insertBefore(el, el.previousElementSibling)
And if your content is dynamic, you might want to check that el.nextElementSibling or el.previousElementSibling is not null.

Javascript Regex to replace text NOT in html attributes [duplicate]

This question already has answers here:
Highlight search terms (select only leaf nodes)
(7 answers)
Closed 9 years ago.
I'd like a Javascript Regex to wrap a given list of of words in a given start (<span>) and end tag (i.e. </span>), but only if the word is actually "visible text" on the page, and not inside of an html attribute (such as a link's title tag, or inside of a <script></script> block.
I've created a JS Fiddle with the basics setup: http://jsfiddle.net/4YCR6/1/
HTML is too complex to reliably parse with a regular expression.
If you're looking to do this client-side, you can create a document fragment and/or disconnected DOM node (neither of which is displayed anywhere) and initialize it with your HTML string, then walk through the resulting DOM tree and process the text nodes. (Or use a library to help you do that, although it's actually quite simple.)
Here's a DOM walking example. This example is slightly simpler than your problem because it just updates the text, it doesn't add new elements to the structure (wrapping parts of the text in spans involves updating the structure), but it should get you going. Notes on what you'll need to change at the end.
var html =
"<p>This is a test.</p>" +
"<form><input type='text' value='test value'></form>" +
"<p class='testing test'>Testing here too</p>";
var frag = document.createDocumentFragment();
var body = document.createElement('body');
var node, next;
// Turn the HTML string into a DOM tree
body.innerHTML = html;
// Walk the dom looking for the given text in text nodes
walk(body);
// Insert the result into the current document via a fragment
node = body.firstChild;
while (node) {
next = node.nextSibling;
frag.appendChild(node);
node = next;
}
document.body.appendChild(frag);
// Our walker function
function walk(node) {
var child, next;
switch (node.nodeType) {
case 1: // Element
case 9: // Document
case 11: // Document fragment
child = node.firstChild;
while (child) {
next = child.nextSibling;
walk(child);
child = next;
}
break;
case 3: // Text node
handleText(node);
break;
}
}
function handleText(textNode) {
textNode.nodeValue = textNode.nodeValue.replace(/test/gi, "TEST");
}
Live example
The changes you'll need to make will be in handleText. Specifically, rather than updating nodeValue, you'll need to:
Find the index of the beginning of each word within the nodeValue string.
Use Node#splitText to split the text node into up to three text nodes (the part before your matching text, the part that is your matching text, and the part following your matching text).
Use document.createElement to create the new span (this is literally just span = document.createElement('span')).
Use Node#insertBefore to insert the new span in front of the third text node (the one containing the text following your matched text); it's okay if you didn't need to create a third node because your matched text was at the end of the text node, just pass in null as the refChild.
Use Node#appendChild to move the second text node (the one with the matching text) into the span. (No need to remove it from its parent first; appendChild does that for you.)
T.J. Crowder's answer is correct. I've gone a little further code-wise: here's a fully-formed example that works in all major browsers. I've posted variations of this code on Stack Overflow before (here and here, for example), and made it nice and generic so I (or anyone else) don't have to change it much to reuse it.
jsFiddle example: http://jsfiddle.net/7Vf5J/38/
Code:
// Reusable generic function
function surroundInElement(el, regex, surrounderCreateFunc) {
// script and style elements are left alone
if (!/^(script|style)$/.test(el.tagName)) {
var child = el.lastChild;
while (child) {
if (child.nodeType == 1) {
surroundInElement(child, regex, surrounderCreateFunc);
} else if (child.nodeType == 3) {
surroundMatchingText(child, regex, surrounderCreateFunc);
}
child = child.previousSibling;
}
}
}
// Reusable generic function
function surroundMatchingText(textNode, regex, surrounderCreateFunc) {
var parent = textNode.parentNode;
var result, surroundingNode, matchedTextNode, matchLength, matchedText;
while ( textNode && (result = regex.exec(textNode.data)) ) {
matchedTextNode = textNode.splitText(result.index);
matchedText = result[0];
matchLength = matchedText.length;
textNode = (matchedTextNode.length > matchLength) ?
matchedTextNode.splitText(matchLength) : null;
// Ensure searching starts at the beginning of the text node
regex.lastIndex = 0;
surroundingNode = surrounderCreateFunc(matchedTextNode.cloneNode(true));
parent.insertBefore(surroundingNode, matchedTextNode);
parent.removeChild(matchedTextNode);
}
}
// This function does the surrounding for every matched piece of text
// and can be customized to do what you like
function createSpan(matchedTextNode) {
var el = document.createElement("span");
el.style.color = "red";
el.appendChild(matchedTextNode);
return el;
}
// The main function
function wrapWords(container, words) {
// Replace the words one at a time to ensure "test2" gets matched
for (var i = 0, len = words.length; i < len; ++i) {
surroundInElement(container, new RegExp(words[i]), createSpan);
}
}
wrapWords(document.getElementById("container"), ["test2", "test"]);

Getting the contents of an element WITHOUT its children [duplicate]

This question already has answers here:
How to get the text node of an element?
(11 answers)
Closed 6 months ago.
I have a mild preference in solving this in pure JS, but if the jQuery version is simpler, then jQuery is fine too. Effectively the situation is like this
<span id="thisone">
The info I want
<span id="notthisone">
I don't want any of this nonsense
</span>
</span>
I effectively want to get
The info I want
but not
The info I want I don't want any of this nonsense
and I especially don't want
The info I want <span id="notthisone"> I don't want any of this nonsense </span>
which is unfortunately what I am getting right now...
How would I do this?
With js only:
Try it out: http://jsfiddle.net/g4tRn/
var result = document.getElementById('thisone').firstChild.nodeValue;
​alert(result);​
With jQuery:
Try it out: http://jsfiddle.net/g4tRn/1
var result = $('#thisone').contents().first().text();
alert(result);​
Bonus:
If there are other text nodes in the outer <span> that you want to get, you could do something like this:
Try it out: http://jsfiddle.net/g4tRn/4
var nodes = document.getElementById('thisone').childNodes;
var result = '';
for(var i = 0; i < nodes.length; i++) {
if(nodes[i].nodeType == 3) { // If it is a text node,
result += nodes[i].nodeValue; // add its text to the result
}
}
alert(result);
​
If you just want the first child then it's rather simple. If you are looking for the first text-only element then this code will need some modification.
var text = document.getElementById('thisone').firstChild.nodeValue;
alert(text);
Have you tried something like this?
var thisone = $("#thisone").clone();
thisone.children().remove();
var mytext = thisone.html();
FROM: http://viralpatel.net/blogs/2011/02/jquery-get-text-element-without-child-element.html
$("#foo")
.clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text(); //get the text of element
Pure JavaScript
In this pure JavaScript example, I account for the possibility of multiple text nodes that could be interleaved with other kinds of nodes. Pass a containing NodeList in from calling / client code.
function getText (nodeList, target)
{
var trueTarget = target - 1;
var length = nodeList.length; // Because you may have many child nodes.
for (var i = 0; i < length; i++) {
if ((nodeList[i].nodeType === Node.TEXT_NODE) && (i === trueTarget)) {
return nodeList.childNodes[i].nodeValue;
}
}
return null;
}
You might use this function to create a wrapper function that uses this one to accumulate multiple text values.
To get a string of the child text nodes and not the element or other child nodes from a given element:
function getTextNodesText(el) {
return Array.from(el.childNodes)
.filter((child) => child.nodeType === Node.TEXT_NODE)
.map((child) => child.textContent)
.join("");
}

Categories