How to replace only text content on an element? - javascript

I have the following structure:
<li>
<a><i>...</i>Some Text Here!</a>
<input>
<a></a>
</li>
I want just to change the string Some Text Here! under the element li without affecting (removing or changing) anything else, that is all its child nodes.
Apparently, textContent, if set, removes all descendant elements. Other similar methods seem to do the same thing. I have searched for a while, but no solution seems to solve this.
I can set classes or ids to whatever element you see in the structure, if that helps.

You can also get the element contents and check each nodeType to be a TEXT_NODE
Jquery version:
$('a').contents().filter(function () {
return this.nodeType === Node.TEXT_NODE;
})
.each(function () {
this.nodeValue = 'Something else';
});
Javascript version:
var nodes = document.getElementsByTagName('a')[0].childNodes;
for (var i in nodes){
if (nodes[i].nodeType === Node.TEXT_NODE)
nodes[i].nodeValue = 'Something else';
}

Supposing you already have the <a> tag in a variable anchor:
anchor.lastChild.textContent = 'My text';
Look at the example below:
var anchor = document.querySelector('a');
anchor.lastChild.textContent = 'Other text';
<li>
<a><i>Lalala...</i>Some Text Here!</a>
<input>
<a></a>
</li>

Use Element.childNodes which covers text nodes along with elements and replace their textContent:
document.getElementsByTagName('a')[0].childNodes[1].textContent='Something else';
It obviously depends on how many tags there are, whether there are spaces between them, which text you want to replace, etc.
A demo:
document.getElementsByTagName('p')[0].childNodes[1].textContent = ' Something else.';
<p><i>I’m an element.</i> Some Text Here!</p>

You can't. Corrected.
However, for cleanliness sake you should wrap the text in a span and then replace the contents of the span. It's much easier to read, like so:
HTML
<li>
<a><i>...</i><span class="replace-me">Some text here!</span></a>
</li>
jQuery
$('.replace-me').text('Some new text here now!');

Related

Get text inside parent div

I'm trying to get a text from an element, which isn't the first parent of the string. i.e.
<div id="wrp">
<h1>
this is the text I want
</h1>
</div>
let's say I got the div parent by element=document.getElementById("wrap") and now I want to get it's final text without looking inside all it's children : h1 and a. just the text that I see on the site.
Is it possible? Please show me an example.
You can use both innerText or textContent, but innerText doesn't works on Firefox. So, a crossbrowser solution:
var text = element.innerText || element.textContent;
JSBin. Interesting comparision about them.
You want to chain your queries so that you get the anchor tag after you get the wrap div (assuming you will never add more divs inside the anchor tag, which would be a bit weird):
var wrap = document.getElementById("wrap");
var text = wrap.getElementsByTagName("a")[0].innerHTML;
If you take a look at the Mozilla article it has more examples on how to do this. Alternatively there is textContent but since you stated that you might add more elements at a later date, if they have text in them too then you end up needing to refactor:
var wrap = document.getElementById("wrap");
var text = document.getElementById("wrap").textContent;

jQuery Selector Confusion

I have the following code..
<span class="under">
texthere
<ul class="list">
<li> list text here</li>
</ul>
</span>
When i run $(".under").text() I get "textherelist text here" .
I've tried $(".under :not(.list)").text() and get underfined.
I also dont get the correct output for $(".under").not(".list").text()
So my last attemp was $(".list").parent().text()
which results in textherelist text here
Where am i going wrong with something so simple?
p.s. doesn't have to be jQuery can be JavaScript if its simpler.
Wanted result: texthere
So I'm guessing you're after the text : texthere ?
var elem = $(".under").clone(),
text = $.trim(elem.children().remove().end().text());
FIDDLE
Clone the element, remove all children elements and get the remaining text.
​
From the docs:
Description: Get the combined text contents of each element in the set
of matched elements, including their descendants.
So yes, that behavior is expected.
You can try this to get only the immediate text node of a selector:
$('.under').contents().filter(function(){ return(this.nodeType == 3); }).text()
Explanation:
.contents() (docs) returns the children of a selector, including textnodes
Description: Get the children of each element in the set of matched
elements, including text and comment nodes.
.filter() takes a callback to return only things you need, based on this, you are only taking those with nodeType == 3, which is a text node.
http://jsfiddle.net/R4Pzf/
Here you go:
var text = $('.under').contents(':not(.list)').text();
Example:
http://jsfiddle.net/ak4FU/1/

Replace text inside a div without affecting any HTML tags inside of it

I see that this has been asked many times. But, unfortunately I have not come across a straight forward solution. Most solutions revolve around multiple nodes within the div.
So here's problem. I have the following markup:
<div class="test">Text1<span></span></div>
I need "Text1" to be replaced with "Text2" without affecting the span tag and event handlers attached to the span tag.
Doing something like $('.test')html('Text2<span></span>') does replace the text. But, removes the event handlers on the span tag, which is not desired. I am looking for a quick and efficient method for this one.
Wrap replaceable text with a tag:
<div class="test"><span class="test-text">Text1</span><span></span></div>
You can access the Text Node itself with contents. Now if you know that the element starts with text you can do this:
$($('.test').contents()[0]).replaceWith('New Text')​;
Now if you didn't know the location in the array of the Text Node, you can filter with:
return this.nodeType === 3;
and compare the text values (if you know those).
Fiddle
if you would add event handler with .live or .on functions (depends on jQuery version) .html('Text2') would work just fine.
On the assumption that the text to be replaced will always precede the existing span, that it will always be the firstChild and that it will be an unwrapped textNode:
$('.test').click(
function() {
this.firstChild.nodeValue = 'Text2';
});​
JS Fiddle demo.
To ensure that only the first textNode is changed, regardless of where it's found within the .test element:
$('.test').click(
function(e) {
var newText = 'Text2',
children = e.target.childNodes;
for (var i=0,len=children.length;i<len;i++){
if (children[i].nodeName == '#text'){
children[i].nodeValue = newText;
return false;
}
}
});​
JS Fiddle demo.

How to use jQuery selector/find() against text string without inserting into the DOM?

I have a text string i'm trying to select the spans from using jQuery. I'd like to grab the spans w/o adding the element to the dom -- if that's possible?
After reading the jquery docs i was under the assumption that i could create a fragment by wrapping the string in a jquery selector tag, then using.find() to find the elements i want.
I have code that is similar to this but from the looks of the last line, it's obvious that no spans are being selected; any help would be greatly appreciated:
// 'text' is normally generated automatically...
// just made it an escaped string for example purposes.
var text ="<span id=\"blah1\">Y</span><br/><span id=\"blah2\">o</span><br/>";
var spans = $(text).find('span');
console.log(text); // => <span id="blah1">Y</span><br/><span id="blah2">o</span><br/>
console.log(spans.length); // => 0
Thanks.
You want to use filter(), not find()
var text ="<span id=\"blah1\">Y</span><br/><span id=\"blah2\">o</span><br/>";
var spans = $(text).filter('span');
console.log(spans.length);
jsFiddle
From the jQuery docs
filter:
The supplied selector is tested against each element; all elements
matching the selector will be included in the result.
find:
the .find() method allows us to search through the descendants of
these elements in the DOM tree and construct a new jQuery object from
the matching elements.
with your html fragment, there is no wrapper element, so there is no descendants, hence why find() does not work.
You are basically doing:
var elems = jQuery("<span id=\"blah1\">Y</span>").add("<br/>").add("<span id=\"blah2\">o</span>").add("<br/>");
If you want find to work with find(), you need to wrap it in an element.
var text ="<span id=\"blah1\">Y</span><br/><span id=\"blah2\">o</span><br/>";
var spans = jQuery("<div></div>").append(text).find("span");
console.log(spans.length);
You want to use filter in this case:
var text ="<span id=\"blah1\">Y</span><br/><span id=\"blah2\">o</span><br/>";
var spans = $(text).filter('span');
console.log(spans.length); // 2
Demo: http://jsfiddle.net/ambiguous/TGY3J/
Or wrap it in a <div> and use find:
var text ="<span id=\"blah1\">Y</span><br/><span id=\"blah2\">o</span><br/>";
var spans = $('<div>' + text + '</div>').find('span');
console.log(spans.length); // 2
Demo: http://jsfiddle.net/ambiguous/qbCjk/
find works on descendants but without the <div> wrapper, your $(text) doesn't have any <span> descendants. Wrapping your HTML in a <div> is probably your best bet, that way you don't have to worry about how deep your desired elements are.

Add text before or after an HTML element

If i have an HTML element like <div> with some text inside or another elements can I add before or after this div some text data without an html element, just plain text?
I'd like to use only pure Javascript.
Something like :
<div id="parentDiv">
my text must be added here
<div id="childDiv"></div>
</div>
Yes, you can create a text node with document.createTextNode('the text')
Then you can insert it like an element, with appendChild or insertBefore.
Example that insert a text before #childDiv:
var text = document.createTextNode('the text');
var child = document.getElementById('childDiv');
child.parentNode.insertBefore(text, child);
Just for the record:
div.insertAdjacentHTML( 'beforeBegin', yourText );
where div is your child-DIV.
Live demo: http://jsfiddle.net/ZkzDk/
If you just need text, I find that element.insertAdjacentText(position, text) is flexible for many scenarios and is also compatible with older browsers like IE6. Where position is exactly where you want the text to be and text is the text node or just a string. The options are:
'beforebegin' Before the element itself.
'afterbegin' Just inside the element, before its first child.
'beforeend' Just inside the element, after its last child.
'afterend' After the element itself.
Like this:
let div = document.getElementById('parentDiv');
div.insertAdjacentText('afterbegin', 'My Plain Text..');
In regards to the topic and the users question for inserting before or after, here is an example for after:
var text = document.createTextNode("my text must be added here.");
var childTag = document.getElementById("childDiv");
childTag.parentNode.insertBefore(text, childTag.nextSibling);
If the childTag does not have any siblings, it is okay because the insertBefore method handles this case and simply adds it as the last child.
Also can possibly use the appendChild() method after creating text node then add your childTag via the parentNode.
You can add text node. Create node - document.createTextNode('text') and then insert/append/replace - do whatever you want.
Something like this should do it:
<script type="text/javascript">
var parent = document.getElementById('parentDiv');
var sibling = document.getElementById('childDiv');
var text = document.createTextNode('new text');
parent.insertBefore(text, sibling);
</script>

Categories