How do I change the text of a span element using JavaScript? - javascript

If I have a span, say:
<span id="myspan"> hereismytext </span>
How do I use JavaScript to change "hereismytext" to "newtext"?

For modern browsers you should use:
document.getElementById("myspan").textContent="newtext";
While older browsers may not know textContent, it is not recommended to use innerHTML as it introduces an XSS vulnerability when the new text is user input (see other answers below for a more detailed discussion):
//POSSIBLY INSECURE IF NEWTEXT BECOMES A VARIABLE!!
document.getElementById("myspan").innerHTML="newtext";

Using innerHTML is SO NOT RECOMMENDED.
Instead, you should create a textNode. This way, you are "binding" your text and you are not, at least in this case, vulnerable to an XSS attack.
document.getElementById("myspan").innerHTML = "sometext"; //INSECURE!!
The right way:
span = document.getElementById("myspan");
txt = document.createTextNode("your cool text");
span.appendChild(txt);
For more information about this vulnerability:
Cross Site Scripting (XSS) - OWASP
Edited nov 4th 2017:
Modified third line of code according to #mumush suggestion: "use appendChild(); instead".
Btw, according to #Jimbo Jonny I think everything should be treated as user input by applying Security by layers principle. That way you won't encounter any surprises.

EDIT: This was written in 2014. A lot has changed. You probably don't care about IE8 anymore. And Firefox now supports innerText.
If you are the one supplying the text and no part of the text is supplied by the user (or some other source that you don't control), then setting innerHTML might be acceptable:
// * Fine for hardcoded text strings like this one or strings you otherwise
// control.
// * Not OK for user-supplied input or strings you don't control unless
// you know what you are doing and have sanitized the string first.
document.getElementById('myspan').innerHTML = 'newtext';
However, as others note, if you are not the source for any part of the text string, using innerHTML can subject you to content injection attacks like XSS if you're not careful to properly sanitize the text first.
If you are using input from the user, here is one way to do it securely while also maintaining cross-browser compatibility:
var span = document.getElementById('myspan');
span.innerText = span.textContent = 'newtext';
Firefox doesn't support innerText and IE8 doesn't support textContent so you need to use both if you want to maintain cross-browser compatibility.
And if you want to avoid reflows (caused by innerText) where possible:
var span = document.getElementById('myspan');
if ('textContent' in span) {
span.textContent = 'newtext';
} else {
span.innerText = 'newtext';
}

document.getElementById('myspan').innerHTML = 'newtext';

I use Jquery and none of the above helped, I don't know why but this worked:
$("#span_id").text("new_value");

Here's another way:
var myspan = document.getElementById('myspan');
if (myspan.innerText) {
myspan.innerText = "newtext";
}
else
if (myspan.textContent) {
myspan.textContent = "newtext";
}
The innerText property will be detected by Safari, Google Chrome and MSIE. For Firefox, the standard way of doing things was to use textContent but since version 45 it too has an innerText property, as someone kindly apprised me recently. This solution tests to see if a browser supports either of these properties and if so, assigns the "newtext".
Live demo: here

In addition to the pure javascript answers above, You can use jQuery text method as following:
$('#myspan').text('newtext');
If you need to extend the answer to get/change html content of a span or div elements, you can do this:
$('#mydiv').html('<strong>new text</strong>');
References:
.text(): http://api.jquery.com/text/
.html(): http://api.jquery.com/html/

You may also use the querySelector() method, assuming the 'myspan' id is unique as the method returns the first element with the specified selector:
document.querySelector('#myspan').textContent = 'newtext';
developer.mozilla

Many people still come across this question (in 2022) and the available answers are not really up to date.
Use innerText is the best method
As you can see in the MDM Docs innerText is the best way to retrieve and change the text of a <span> HTML element via Javascript.
The innerText property is VERY well supported (97.53% of all web users according to Caniuse)
How to use
Simple retrieve and set new text with the property like this:
let mySpan = document.getElementById("myspan");
console.log(mySpan.innerText);
mySpan.innerText = "Setting a new text content into the span element.";
Why better than innerHTML ?
Don't use innerHTML to updating the content with user inputs, this can lead to major vulnerability since the string content you will set will be interpreted and converted into HTML tags.
This means users can insert script(s) into your site, this is known as XSS attacks/vulnerabilities (Cross-site scripting).
Why better than textContent ?
First point textContent isn't supported by IE8 (but I think in 2022 nobody cares anymore).
But the main element is the true difference of result you can get using textContent instead of innerText.
The example from the MDM documentation is perfect to illustrate that, so we have the following setup:
<p id="source">
<style>#source { color: red; } #text { text-transform: uppercase; }</style>
<span id=text>Take a look at<br>how this text<br>is interpreted
below.</span>
<span style="display:none">HIDDEN TEXT</span>
</p>
If you use innerText to retrieve the text content of <p id="source"> we get:
TAKE A LOOK AT
HOW THIS TEXT
IS INTERPRETED BELOW.
This is perfectly what we wanted.
Now using textContent we get:
#source { color: red; } #text { text-transform: uppercase; }
Take a look athow this textis interpreted
below.
HIDDEN TEXT
Not exactly what you expected...
This is why using textContent isn't the correct way.
Last point
If you goal is only to append text to a <p> or <span> HTML element, the answer from nicooo. is right you can create a new text node and append it to you existing element like this:
let mySpan = document.getElementById("myspan");
const newTextNode = document.createTextNode("Youhou!"),
mySpan.appendChild(newTextNode);

Like in other answer, innerHTML and innerText are not recommended, it's better use textContent. This attribute is well supported, you can check it this:
http://caniuse.com/#search=textContent

document.getElementById("myspan").textContent="newtext";
this will select dom-node with id myspan and change it text content to new text

You can do document.querySelector("[Span]").textContent = "content_to_display";

Can't be used with HTML code insertion, something like:
var a = "get the file <a href='url'>the link</a>"
var b = "get the file <a href='url'>another link</a>"
var c = "get the file <a href='url'>last link</a>"
using
document.getElementById("myspan").textContent=a;
on
<span id="myspan">first text</span>
with a timer but it just shows the reference target as text not runing the code, even tho it does shows correctly on the source code. If the jquery approch is not really a solution, the use of:
document.getElementById("myspan").innerHTML = a to c;
is the best way to make it work.

const span = document.querySelector("#span");
const btn = document.querySelector("#changeBtn");
btn.addEventListener("click", () => {
span.innerText = "text changed"
})
<span id="span">Sample Text</span>
<button id="changeBtn">Change Text</button>

For this span
<span id="name">sdfsdf</span>
You can go like this :-
$("name").firstChild.nodeValue = "Hello" + "World";

(function ($) {
$(document).ready(function(){
$("#myspan").text("This is span");
});
}(jQuery));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="myspan"> hereismytext </span>
user text() to change span text.

I used this one document.querySelector('ElementClass').innerText = 'newtext';
Appears to work with span, texts within classes/buttons

For some reason, it seems that using "text" attribute is the way to go with most browsers.
It worked for me
$("#span_id").text("text value to assign");

Related

Changing the text of a Label in javascript doesn't work

I am trying to change the text of a Label using javascript like this in an aspx page
document.getElementById('DetailSection_EssLabel1').Text = "Revised Date";
But when I am in the debugging mode on IE by using F12 button, this is what I see for the field,
<SPAN class=FormFieldHeader id=DetailSection_EssLabel1 Text="Revised Date">Assigned Completion Date</SPAN>
Though the text is changed to Revised Date, it is still showing Assigned Completion Date in the front end. Can someone tell me what I am missing. Thanks
If you want to set a label's text, you'd better use textContent property, like this:
document.getElementById('DetailSection_EssLabel1').textContent = "Revised Date";
innerText is not a standard property and you'll definitely get an issue in FireFox
Neither innerText nor textContent are cross-browser compatible if you include IE 8 and older.
Using the jQuery text method is typically the easy button.
if jQuery is not an option, the most compatible way with pure DOM is to use text nodes, for example:
var outputDiv = document.getElementById('DetailSection_EssLabel1');
var childNodes = outputDiv.childNodes;
// nodeType == 3 is a text node
if (!(childNodes.length == 1 && childNodes[0].nodeType == 3)) {
outputDiv.innerHTML = ''; // one way to clear any existing content
outputDiv.appendChild(document.createTextNode(''));
}
outputDiv.childNodes[0].nodeValue = 'Revised Text';
Fiddle: https://jsfiddle.net/4m0wpjdo/1/
EDIT: I also wanted to mention that using innerHTML to inject text is really not a good idea. It's all too easy to forget to escape special characters when using this approach. This opens you up to incorrect display of the text at best and XSS attacks at worst (if user-supplied text is included).
Use innertext
document.getElementById('DetailSection_EssLabel1').innerText="Revised Date";
Native Javascript objects do not have a text property, but they do have innerHTML and innerText properties. To change the text of an element, you can use either:
document.getElementById('DetailSection_EssLabel1').innerHTML = "Revised Date";.
or document.getElementById('DetailSection_EssLabel1').innerText = "Revised Date";.

Difference between textContent vs innerText

What is the difference between textContent and innerText in JavaScript?
Can I use textContent as follows:
var logo$ = document.getElementsByClassName('logo')[0];
logo$.textContent = "Example";
The key differences between innerText and textContent are outlined very well in Kelly Norton's blogpost: innerText vs. textContent. Below you can find a summary:
innerText was non-standard, textContent was standardized earlier.
innerText returns the visible text contained in a node, while textContent returns the full text. For example, on the following HTML <span>Hello <span style="display: none;">World</span></span>, innerText will return 'Hello', while textContent will return 'Hello World'. For a more complete list of differences, see the table at http://perfectionkills.com/the-poor-misunderstood-innerText/ (further reading at 'innerText' works in IE, but not in Firefox).
As a result, innerText is much more performance-heavy: it requires layout information to return the result.
innerText is defined only for HTMLElement objects, while textContent is defined for all Node objects.
Be sure to also have a look at the informative comments below this answer.
textContent was unavailable in IE8-, and a bare-metal polyfill would have looked like a recursive function using nodeValue on all childNodes of the specified node:
function textContent(rootNode) {
if ('textContent' in document.createTextNode(''))
return rootNode.textContent;
var childNodes = rootNode.childNodes,
len = childNodes.length,
result = '';
for (var i = 0; i < len; i++) {
if (childNodes[i].nodeType === 3)
result += childNodes[i].nodeValue;
else if (childNodes[i].nodeType === 1)
result += textContent(childNodes[i]);
}
return result;
}
textContent is the only one available for text nodes:
var text = document.createTextNode('text');
console.log(text.innerText); // undefined
console.log(text.textContent); // text
In element nodes, innerText evaluates <br> elements, while textContent evaluates control characters:
var span = document.querySelector('span');
span.innerHTML = "1<br>2<br>3<br>4\n5\n6\n7\n8";
console.log(span.innerText); // breaks in first half
console.log(span.textContent); // breaks in second half
<span></span>
span.innerText gives:
1
2
3
4 5 6 7 8
span.textContent gives:
1234
5
6
7
8
Strings with control characters (e. g. line feeds) are not available with textContent, if the content was set with innerText. The other way (set control characters with textContent), all characters are returned both with innerText and textContent:
var div = document.createElement('div');
div.innerText = "x\ny";
console.log(div.textContent); // xy
For those who googled this question and arrived here. I feel the most clear answer to this question is in MDN document: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent.
You can forgot all the points that may confuse you but remember 2 things:
When you are trying to alter the text, textContent is usually the property you are looking for.
When you are trying to grab text from some element, innerText approximates the text the user would get if they highlighted the contents of the element with the cursor and then copied to the clipboard. And textContent gives you everything, visible or hidden, including <script> and <style> elements.
Both innerText & textContent are standardized as of 2016. All Node objects (including pure text nodes) have textContent, but only HTMLElement objects have innerText.
While textContent works with most browsers, it does not work on IE8 or earlier. Use this polyfill for it to work on IE8 only. This polyfill will not work with IE7 or earlier.
if (Object.defineProperty
&& Object.getOwnPropertyDescriptor
&& Object.getOwnPropertyDescriptor(Element.prototype, "textContent")
&& !Object.getOwnPropertyDescriptor(Element.prototype, "textContent").get) {
(function() {
var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText");
Object.defineProperty(Element.prototype, "textContent",
{
get: function() {
return innerText.get.call(this);
},
set: function(s) {
return innerText.set.call(this, s);
}
}
);
})();
}
The Object.defineProperty method is availabe in IE9 or up, however it is available in IE8 for DOM objects only.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
textContent is supported by most browsers. It is not supported by ie8 or earlier, but a polyfill can be used for this
The textContent property sets or returns the textual content of the specified node, and all its descendants.
See http://www.w3schools.com/jsref/prop_node_textcontent.asp
Aside from all the differences that were named in the other answers, here is another one which I discovered only recently:
Even though the innerText property is said to've been standardised since 2016, it exhibits differences between browsers: Mozilla ignores U+200E and U+200F characters ("lrm" and "rlm") in innerText, while Chrome does not.
console.log(document.getElementById('test').textContent.length);
console.log(document.getElementById('test').innerText.length);
<div id="test">[‎]</div>
Firefox reports 3 and 2, Chrome reports 3 and 3.
Not sure yet if this is a bug (and if so, in which browser) or just one of those quirky incompatibilities which we have to live with.
textContent returns full text and does not care about visibility, while innerText does.
<p id="source">
<style>#source { color: red; }</style>
Text with breaking<br>point.
<span style="display:none">HIDDEN TEXT</span>
</p>
Output of textContent:
#source { color: red; } Text with breakingpoint. HIDDEN TEXT
Output of innerText ( note how innerText is aware of tags like <br>, and ignores hidden element ):
Text with breaking point.
Another useful behavior of innerText compared to textContent is that newline characters and multiple spaces next to each other will be displayed as one space only, which can be easier to compare a string.
But depending on what you want, firstChild.nodeValue may be enough.
document.querySelector('h1').innerText/innerHTML/textContent
.querySelector('h1').innerText - gives us text inside. It sensitive to what is currently being displayed or staff that's being hidden is ignored.
.querySelector('h1').textContent - it's like innerText but it does not care about what is being displayed or what's actually showing to user. It will show all.
.querySelector('h1').innerHTML = <i>sdsd</i> Will work* - retrieves full contents, including the tag names.
innerHTML will execute even the HTML tags which might be dangerous causing any kind of client-side injection attack like DOM based XSS.
Here is the code snippet:
<!DOCTYPE html>
<html>
<body>
<script>
var source = "Hello " + decodeURIComponent("<h1>Text inside gets executed as h1 tag HTML is evaluated</h1>"); //Source
var divElement = document.createElement("div");
divElement.innerHTML = source; //Sink
document.body.appendChild(divElement);
</script>
</body>
</html>
If you use .textContent, it will not evaluate the HTML tags and print it as String.
<!DOCTYPE html>
<html>
<body>
<script>
var source = "Hello " + decodeURIComponent("<h1>Text inside will not get executed as HTML</h1>"); //Source
var divElement = document.createElement("div");
divElement.textContent = source; //Sink
document.body.appendChild(divElement);
</script>
</body>
</html>
Reference: https://www.scip.ch/en/?labs.20171214

Is it a good practice to put html code with plain text as a value of an attribute?

Is it considered a good or a bad practice to put text and html code as a value of an attribute, here is an example :
<script>
var name = '<h3>name</h3>Here goes a description about the name attribute';
var elem = document.getElementById('monElem');
elem.innerHTML = name;
</script>
knowing the fact that the text between html tags is a static text not a dynamic one.
If it is a bad practice then is the solution to use a template engine ?
If the purpose is to show/hide this static HTML on demand, then it might be even better not to dynamically add and remove it from your HTML document, but to show/hide it via CSS:
<body>
<div id="hoverMe" onmouseout="showHelp(0)" onmousemove="showHelp(1)">
Hover me to learn about "name"
</div>
<div id="monElem" style="display:none">
<h3>name</h3>
Here goes a description about the name attribute
</div>
</body>
<script>
var elem = document.getElementById('monElem');
function showHelp(show) {
elem.style.display = show ? '' : 'none';
}
</script>
This will also have better performance than adding the elements to the DOM at the moment of need.
Unless you are using this code to generate a lot of DOM content, i.e. execute it a few hundred or thousand times, you'll be good.
Just for completeness I'd like to mention that there's a few other ways of generating HTML content from Javascript:
document.createElement
document.createDocumentFragment
<template> element
The performance of these three is generally higher than using innerHTML, but the differences between the three are currently pretty inconsistent between browsers and browser versions.
Also, <template> isn't fully supported in all browsers yet and won't be supported in older browsers.
It depends on styleguide in your team, but in most cases it's a bad practice.
The better solution is when you'll create new element throught javascript:
var h3 = document.createElement("h3");
var text = document.createTextNode("Any name … .");
h3.appendChild(text);
var elem = document.getElementById('monElem');
elem.insertBefore(h3, elem.firstChild);
Why is it better? Just because it's faster, more conviniet and predictable.
Read more about document methods on w3schools.

Why isn't there a document.createHTMLNode()?

I want to insert html at the current range (a W3C Range).
I guess i have to use the method insertNode. And it works great with text.
Example:
var node = document.createTextNode("some text");
range.insertNode(node);
The problem is that i want to insert html (might be something like "<h1>test</h1>some more text"). And there is no createHTMLNode().
I've tried to use createElement('div'), give it an id, and the html as innerHTML and then trying to replace it with it's nodeValue after inserting it but it gives me DOM Errors.
Is there a way to do this without getting an extra html-element around the html i want to insert?
Because "<h1>test</h1>some more text" consists of an HTML element and two pieces of text. It isn't a node.
If you want to insert HTML then use innerHTML.
Is there a way to do this without getting an extra html-element around the html i want to insert?
Create an element (don't add it to the document). Set its innerHTML. Then move all its child nodes by looping over foo.childNodes.
In some browsers (notably not any version of IE), Range objects have an originally non-standard createContextualFragment() that may help. It's likely that future versions of browsers such as IE will implement this now that it has been standardized.
Here's an example:
var frag = range.createContextualFragment("<h1>test</h1>some more text");
range.insertNode(frag);
Try
function createHTMLNode(htmlCode, tooltip) {
// create html node
var htmlNode = document.createElement('span');
htmlNode.innerHTML = htmlCode
htmlNode.className = 'treehtml';
htmlNode.setAttribute('title', tooltip);
return htmlNode;
}
From: http://www.koders.com/javascript/fid21CDC3EB9772B0A50EA149866133F0269A1D37FA.aspx
Instead of innerHTML just use appendChild(element); this may help you.
If you want comment here, and I will give you an example.
The Range.insertNode() method inserts a node at the start of the Range.
var range = window.getSelection().getRangeAt(0);
var node = document.createElement('b');
node.innerHTML = 'bold text';
range.insertNode(node);
Resources
https://developer.mozilla.org/en-US/docs/Web/API/range/insertNode

Javascript Removing Whitespace When It Shouldn't?

I have a HTML file that has code similar to the following.
<table>
<tr>
<td id="MyCell">Hello World</td>
</tr>
</table>
I am using javascript like the following to get the value
document.getElementById(cell2.Element.id).innerText
This returns the text "Hello World" with only 1 space between hello and world. I MUST keep the same number of spaces, is there any way for that to be done?
I've tried using innerHTML, outerHTML and similar items, but I'm having no luck.
HTML is white space insensititive which means your DOM is too. Would wrapping your "Hello World" in pre block work at all?
In HTML,any spaces >1 are ignored, both in displaying text and in retrieving it via the DOM. The only guaranteed way to maintain spaces it to use a non-breaking space .
Just a tip, innerText only works in Internet Explorer, while innerHTML works in every browser... so, use innerHTML instead of innerText
The pre tag or white-space: pre in your CSS will treat all spaces as meaningful. This will also, however, turn newlines into line breaks, so be careful.
Just an opinion here and not canonical advice, but you're headed for a world or hurt if you're trying to extract exact text values from the DOM using the inner/outer HTML/TEXT properties via Javascript. Different browsers are going to return slightly different values, based on how the browser "sees" the internal document.
If you can, I'd change the HTML you're rendering to include a hidden input, something like
<table>
<tr>
<td id="MyCell">Hello World<input id="MyCell_VALUE" type="hidden" value="Hello World" /></td>
</tr>
</table>
And then grab your value in javascript something like
document.getElementById(cell2.Element.id+'_VALUE').value
The input tags were designed to hold values, and you'll be less likely to run into fidelity issues.
Also, it sounds like you're using a .NET control of some kind. It might be worth looking through the documentation (ha) or asking a slightly different question to see if the control offers an official client-side API of some kind.
Just checked it and it looks like wrapping with the pre tag should do it.
Edit: I am wrong, ignore me.
You can get a text node's nodeValue, which should correctly represent its whitespace.
Here is a function to recursively get the text within a given element (and it's library-safe, won't fail if you use something that modifies Array.prototype or whatever):
var textValue = function(element) {
if(!element.hasOwnProperty('childNodes')) {
return '';
}
var childNodes = element.childNodes, text = '', childNode;
for(var i in childNodes) {
if(childNodes.hasOwnProperty(i)) {
childNode = childNodes[i];
if(childNode.nodeType == 3) {
text += childNode.nodeValue;
} else {
text += textValue(childNode);
}
}
}
return text;
};
This is a bit hacky, but it works on my IE.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title></title>
</head>
<body>
<div id="a">a b</div>
<script>
var a = document.getElementById("a");
a.style.whiteSpace = "pre"
window.onload = function() {
alert(a.firstChild.nodeValue.length) // should show 4
}
</script>
</body>
</html>
Some notes:
You must have a doctype.
You cannot query the DOM element before window.onload has fired
You should use element.nodeValue instead of innerHTML et al to avoid bugs when the text contains things like < > & "
You cannot reset whiteSpace once IE finishes rendering the page due to what I assume is an ugly bug
If someone could format my last post correctly it would look more readable. Sorry, I messed that one up. Basically the trick is create create a throwaway pre element, then append a copy of your node to that. Then you can get innerText or textContent depending on the browser.
All browsers except IE basically do the obvious thing correctly. IE requires this hack since it only preserves white-space in pre elements, and only when you access innerText.
This following trick preserves white-space in innerText in IE
var cloned = element.cloneNode(true);
var pre = document.createElement("pre");
pre.appendChild(cloned);
var textContent = pre.textContent
? pre.textContent
: pre.innerText;
delete pre;
delete cloned;

Categories

Resources