Use innerText to retrieve text from hidden HTML elements - javascript

I need to get the text from an html element which is hidden with css. I know that per the specs innerText will abide the css rules. But the alternative of using textContent ignores line break and tabs which I need to keep in the string.
Is there any way around this?
For simplicity please see the following example:
const inntxt = document.querySelector('.expandable').innerText
console.log(inntxt) // Here we don't get the hidden div's text.
const txtct = document.querySelector('.expandable').textContent
console.log(txtct) // Here the result removes the line break.
.hidden{
display: none;
}
<div class='expandable'>
<span class='visib'>
Red balloon
</span>
<br>
<span class='hidden'>
Yellow badge<br>Green ribbon
</span>
</div>
I guess one way around it would be to replace the <br> with my own char like # by appending it instead of the <br>, but there must be a better way no?
UPDATE
To be more clear the end result should be:
For example if you would console.log() the string in node, then the string from our innerText or textContent should be:
'Red balloon\nYellow Badge\nGreen ribbon'

It is very unintuitive that textContent doesn't retrieve <br> new lines.
I suggest using a dummy element in Javascript using innerHTML and replacing all <br> with \n<br>.
Take a look at this code, I think it solves your issue:
const expandable = document.querySelector('.expandable')
const auxEl = document.createElement('div')
auxEl.innerHTML = expandable.innerHTML.replace(/(\<br\>)/, '\n$1')
const textContent = auxEl.textContent
console.log({ textContent })
/* Yields
{
"textContent": "\n \n Red balloon\n \n \n Yellow badge\nGreen ribbon\n \n"
}
*/
.hidden {
display: none;
}
<div class='expandable'>
<div class='visib'>
Red balloon
</div>
<div class='hidden'>
Yellow badge<br>Green ribbon
</div>
</div>

Not sure about what you're trying to achieve here, but what you might want to do is change innerText to innerHTML and then the line breaks are preserved.
Unlike innerText, though, innerHTML lets you work with HTML rich
text and doesn't automatically encode and decode text. In other words,
innerText retrieves and sets the content of the tag as plain text,
whereas innerHTML retrieves and sets the content in HTML format.
Quoted from https://stackoverflow.com/a/19030857/4073621.

Kindly use the following script to get innerText
const inntxt = document.getElementsByClassName('expandable')[0].innerText;
console.log(inntxt);

Related

Text always leaves it's container when ever there is space around the text

I was trying to insert an element to an existing element. But each time I insert it, the text inside the element node to be appended will leave the element and stays outside the initial container, I found out that each time I called .trim() on it, it won't leave the container.
E.g
let txt = " space around the text ";
let node = `<span styly="prop:val;">${txt}</span>`;
let div = document.getElementById("myDiv");
div.innerHTML = node;
The result of the above code will be:
<div id="myDiv">
space around the text
<span style="prop:val"></span> //nothing inside the span
</div>
If I remove the spaces in the txt i.e calling on .trim() on the txt it will work as expected.
E.g:
let txt = " space around the text ";
let node = `<span style="prop:Val;">${txt.trim()}</span>`;
let div = document.getElementById("myDiv");
div.innerHTML = node;
The result of the above code will be: (it works fine now)
<div id="myDiv">
<span style="prop:val">space around the text</span>
</div>
I haven't experienced such problem, I don't know if it is JavaScript error or Dom parsing.
Thanks in advance.
I have figured out the problem with my code.
I was matching all new line and replacing them with <li> tag, so each time it matches it, it breaks out of the parent container.
Example;
I have an HTML code like below.
<div style=color=red>
<span style=color=green>element
<span style=color=blue> inner </span>
</span>
Some texts....
</span>
So matching every new line and replacing it with a <li> the element <li> will cause HTML parser to close the first <span> causing the text "Some text...." not being able to inherit the style color "green" from it's parent element.
The solution to my problem is closing every element before replacing new line with <li> as simple as that.

innerText on content editable doubling some line breaks

I am trying to read multi line user input on a content editable div, and I don't get the right number of line breaks when I read the input with contentEditableDiv.innerText.
I tried textContent, but it doesn't return any line break, while innerText returns too many sometimes. innerHTML doesn't seem appropriate since I don't want any HTML code, just text.
If my div contains:
a
b
It returns "a↵b" (97 10 98 in the example)
But if my <div> contains:
a
b
innerText returns a↵↵↵b (one too many ↵, 97 10 10 10 98 in the example)
var input = document.getElementById("input");
var button = document.getElementById("button");
var result = document.getElementById("result");
button.addEventListener("click", (event) => {
var charCodes = "";
for (var i = 0; i < input.innerText.length; ++i) {
charCodes += input.innerText.charCodeAt(i) + " ";
}
result.innerText = charCodes;
});
<div id="input" contenteditable="true" spellcheck="true" style="border:1px #000 solid"></div>
<button id="button">check</button>
<div id="result"></div>
The standard is a bit vague:
UAs should offer a way for the user to request an explicit line break at the caret position without breaking the paragraph, e.g. as the default action of a keydown event whose identifier is the "Enter" key and that has a shift modifier set. Line separators are typically found within a poem verse or an address. To insert a line break, the user agent must insert a br element.
If the caret is positioned somewhere where phrasing content is not allowed (e.g. in an empty ol element), then the user agent must not insert the br element directly at the caret position. In such cases the behavior is UA-dependent, but user agents must not, in response to a request to insert a line separator, generate a DOM that is less conformant than the DOM prior to the request.
To conform this definition, it is safe to wrap the <br> element into <div>, which Chrome does, but it is UA dependent, so you should not rely on this. The side effect on this behavior and the cause of your problem is that both div and br elements produces line break in the innerText property.
The innerHTML of a↵↵b looks like this in Chrome:
a
<div>
<br>
<div>
<br>
<div>
b
</div>
</div>
</div>
But if you paste it (instead of typing char by char) it looks like this
<div>a</div>
<div>
<br>
</div>
<div>
<br>
</div>
<div>b</div>
To reduce the line breaks, you need to further process the innerHTML and treat
<div><br></div> after every input change as a single line-break and then read the innerText (with caution on places where phrasing content like br is not allowed, but in real life browsers can handle them well).

Javascript line-break not working

I have this really big text where I want to add line breaks in order to look better on my application. I have tried using
"<br>", "\n"
to cut the text in pieces. I have ven tried to change the width of the span but nothing seems to be working. What am I doing wrong? Any help appreciated.
<span id="instr" style="color: white; font-size: 15pt;"></span>
<script type="text/javascript">
function instructions(){
....
document.getElementById("instr").textContent = "Really biiiiiiiiiiiiiiiiiiiiiiiiig text here";
}
</script>
To set <br /> line breaks you need to use innerHTML property:
document.getElementById("instr").innerHTML = "Really<br />biiiiiiiiiiiiiiiiiiiiiiiiig<br/ >text here";
You could use the CSS white-space property to wrap text. See here for more information: https://developer.mozilla.org/en-US/docs/CSS/white-space
Use document.getElementById("instr").innerHTML to insert <br>.
since span is inline element, I would not use it. I would try div or p elements. If you have to, look into word-wrap property
Just use innerText instead of textContent. Then you can use \n.
document.getElementById("instr").innerText = "Really biiiiiiiiiiiiiiiiiiiiiiiiig\n text here";
Or use innerHTML along with <br/>.
document.getElementById("instr").innerHTML = "Really biiiiiiiiiiiiiiiiiiiiiiiiig<br/> text here";
jsFiddle: http://jsfiddle.net/phCmH/

Why JavaScript converts my < into >

JavaScript converts my < into >. I want to alert it but my message is with encoded marks like ##&*()}{>?>? - how to display it normally but prevent from executing as HTML code?
<span id="ID" onClick="alertIt(this.id);">
<p>Some string with special chars: ~!##&*()}{>?>?>|{">##$#^#$</p>
<p>Why when clicked it gives something like this:</p>
<p>'<br>
Some string with special chars: ~!##&*()}{>?>?>|... and so on
<br>'</p>
</span>
<script type="text/javascript">
function alertIt(ID)
{
var ID = ID;
var content = document.getElementById(ID).innerHTML;
alert(content);
}
</script>
Use innerText instead of innerHTML. http://jsfiddle.net/WVf95/
Your problem is that you use the wrong approach to get the text to display with alert().
Some characters are illegal in HTML text (they are used for HTML tags and entities). innerHTML will make sure that text is properly escaped (i.e. you can see tags and escaped text).
If you want to see tag and text in alert(), there is no solution.
If you want only the text, then you will have to extract it yourself. There is no built-in support for that. It's also not really trivial to implement. I suggest to include jQuery in your page; then you can get the text with:
function alertIt(ID) {
alert($(ID).text());
}
Using textContent instaed of innerHTML or innerText is a solution.

How do I change the text of a span element using 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");

Categories

Resources