I have a dropdown list which is populated by Javascript.
Whilst deciding what should be the default value to show on load, I realised that the following properties showed exactly the same values:
innerText
innerHTML
label
text
textContent
outerText
My own research shows bench marking tests or comparisons between a few of them, but not all.
I can use my own common sense and choose 1 or the other as they provide the same result, but, I'm concerned this is not going to be a good idea if the data were to change.
My findings are:
innerText will show the value as is and ignores any HTML formatting which may be included
innerHTML will show the value and apply any HTML formatting
label appears to be the same as innerText, so I can't see the difference
text appears to be the same as innerText but the jQuery shorthand version
textContent appears to the same as innerText but keeps formatting (such as \n)
outerText appears to be the same as innerText
My research can only take me so far as I can only test what I can think of or read what is published, can any one confirm though if my research is correct and if there is anything special about label and outerText?
From MDN:
Internet Explorer introduced element.innerText. The intention is pretty much the same [as textContent] with a couple of differences:
Note that while textContent gets the content of all elements, including <script> and <style> elements, the mostly equivalent IE-specific property, innerText, does not.
innerText is also aware of style and will not return the text of hidden elements, whereas textContent will.
As innerText is aware of CSS styling, it will trigger a reflow, whereas textContent will not.
So innerText will not include text that is hidden by CSS, but textContent will.
innerHTML returns the HTML as its name indicates. Quite often, in order to retrieve or write text within an element, people use innerHTML. textContent should be used instead. Because the text is not parsed as HTML, it's likely to have better performance. Moreover, this avoids an XSS attack vector.
In case you missed that, let me repeat it more clearly: Do not use .innerHTML unless you specifically intend to insert HTML within an element and have taken the necessary precautions to ensure that the HTML you are inserting cannot contain malicious content. If you only want to insert text, use .textContent or if you need to support IE8 and earlier, use feature detection to switch off between .textContent and .innerText.
A main reason that there are so many different properties is that different browsers originally had different names for these properties, and there still isn't complete cross-browser support for all of them. If you are using jQuery, you should stick to .text() since that is designed to smooth out cross-browser differences.*
For some of the others: outerHTML is basically the same as innerHTML, except that it includes the start and end tags of the element it belongs to. I can't seem to find much description of outerText at all. I think that is probably an obscure legacy property and should be avoided.
Addendum to JLRishe's otherwise excellent answer:
The reason innerText and outerText both exist is for symmetry with innerHTML and outerHTML. This becomes important when you assign to the property.
Suppose you've got an element e with HTML code <b>Lorem Ipsum</b>:
e.innerHTML = "<i>Hello</i> World!"; => <b><i>Hello</i> World!</b>
e.outerHTML = "<i>Hello</i> World!"; => <i>Hello</i> World!
e.innerText = "Hello World!"; => <b>Hello World!</b>
e.outerText = "Hello World!"; => Hello World!
A dropdown list comprises a collection of Option objects, so you should use the .text property to inspect the textual representation of the element, i.e.
<option value="123">text goes here</option>
^^^^^^^^^^^^^^
Btw,
.text appears to be the same as .innerText but the JQuery shorthand version
That's not correct; $(element).text() is the jQuery version whereas element.text is the property access version.
text and label remove extra spaces. I got these results when querying options in a dropdown:
e.textContent = "A B C D "
e.text = "A B C D"
e.label = "A B C D"
textContent will not format (\n)
See the browsers compatibility http://www.quirksmode.org/dom/html/ if you are targeting specific browsers. Because it seems like they all have their own way of doing things. That is why is is better to use JQuery .text() (http://api.jquery.com/text/) if you do not want to fiddle around.
Related
Kind of a newbie to this but I have followed a totorial on a memory game as an attempt to understand the syntax of JS but am stuck on making the round result print in a instead of showing up as a alert
here is a codepen here.
how can I print round in a <span> <!-- result here--> </span> rather than like this alert("result")
How can I make it set to a span instead of being an alert?
Browsers parse HTML into a tree of objects called Document Object Model (DOM). Using JavaScript you can query the DOM to get individual nodes, and then change them.
To get your span, you would typically use document.getElementById or document.querySelector (there are other functions that can fetch collections of related nodes, like document.getElementsByClassName or document.querySelectorAll). The former identify nodes by the property named in the method name (ID, or class name, respectively); the latter ones use CSS selectors. (All of the getElement... functions can be replicated using the newer querySelector and querySelectorAll interface, though you have to know how to use CSS selectors. I almost never use getElement... functions any more.) There are also functions that use XPath, though this is a bit more advanced subject.
Once you have the node, you can change its content using e.g. .textContent or .innerHTML properties, the former being for plain text, the latter for HTML.
For example, if this is the only span on the page, this suffices:
document.querySelector('span').textContent = "Result";
<span></span>
If on the other hand you have more of them, you would need some way to target the correct one. I will also demonstrate how you can style it using HTML:
const node = document.querySelector('#result_goes_here');
node.innerHTML = "<strong>Result</strong> in bold!";
<span id="result_goes_here"></span>
If you are trying to add the result inside the HTML SPAN and not in the alert box. You can do it something like this:
document.getElementById("span_ID").innerHTML = the_variable_result_here;
Hope that helps!
I am just beginning to learn client-side JavaScript and using an online tutorial, so please bear with me.
This question is based on my understanding of the following:
To access the properties of the document's body, the syntax is "document.body", which returns all the elements in the body.
Similarly when you access the head, you use "document.head". Makes sense and most importantly, it works.
However, when I attempt to access elements WITHIN the body or head following the same logic, I get a return value of "undefined". For example, document.body.h1, returns "undefined", in spite of there being an h1 element inside the body element.
Further, when I enter document.head.title -- "undefined".
Strangely, however, when I enter "document.title", it returns the string value associated with the title tag.
I thought in order to access the title, you would have to access it through the head, since it is an element nested inside the head. But ok, that's fine. Using the same logic, I should then be able to enter document.h1 and get its value. Nope, instead, I get undefined.
Would someone be kind enough to explain to me why this behavior is so inconsistent. Thanks in advance.
You've really asked two questions:
Why document.title rather than document.head.title?
and
Why doesn't document.body.h1 return an element if there's an h1 in the body?
document.title
document.title is historical. Various parts of the browser environment were developed somewhat ad hoc by multiple different people/organizations in the 1990s. :-) That said, it's the title of the document, so this isn't an unreasonable place to put it, even if you use the title tag in head.
document.body.h1
One answer is: Because no one decided to design it that way. There were some early things like document.all (a list of all elements in the document) and even tag-specific ones (I forget exactly what they were, but they weren't a million miles off your document.body.h1 — I think document.tags.h1 or something, where again it was a list.)
But another answer is: Because the DOM is a tree. body can have multiple h1 elements, both as direct children and as children of children (or deeper); collectively, descendants. Creating automatic lists with all of these proved not to be scalable to large documents.
Instead, you can query the DOM (either the entire document, or just the contents of a specific element) via a variety of methods:
getElementById - (Just on document) Get an element using its id attribute value.
querySelector - Find the first element matching a CSS selector (can use it on document or on an element). Returns null if there were no matches.
querySelectorAll - Get a list of all elements matching a CSS selector (can use it on document or on an element). You can rely on getting back a list; its length may be 0, of course.
getElementsByTagName - Get a list of all elements with a given tag name (such as "h1").
getElementsByClassName - (No support in IE8 and earlier) Get a list of all elements with a given class.
There are many more. See MDN's web documentation and/or the WHAT-WG DOM Standard for more.
Some of the automatic lists persist (they got so much use that they had to be maintained/kept), such as document.forms, document.links, the rows property on HTMLTableElement and HTMLTableSectionElement instances, the cells property on HTMLTableRowElement instances, and various others.
document.head.title is a thing... but not what you might think.
title is an attribute that is applicable to all html elements; that is, it is a global attribute. It's meaning is 'advisory information'; one use is to display a tooltip:
<span title="hover over me and you'll see this">information</span>
So, all elements have a title attribute - including head. The title element - which is completely different - should be a child of the head though. So you might be tempted to set its value via document.head.title = "my title" , but document.head.title is not the head's title element, it's a property of the head element.
What you're actually doing is setting the title property on the head element:
<head title="my title">.... </head>
... which isn't what you want at all.
The correct way to set the title is document.title, which is a shortcut way of doing
document.querySelector("title").innerText = "my title"
Somewhat by accident, I found out that a span inserted directly inside a tbody stays in place when done with JavaScript (insertBefore), where such invalid DOM would if created with literal HTML lead to the span being placed before the entire table.
I expected either the same behaviour as with literal HTML or some DOM Exception being thrown.
E.g. this HTML
<table>
<thead><tr><th>Table Header</th></td></thead>
<tbody>
<span>from HTML → goes up</span>
<tr><td>Table Contents</td></tr>
</tbody>
</table>
with this JavaScript:
var span = document.createElement('span'),
tbody = document.querySelector('tbody');
span.innerHTML = 'Created with JS → stays in place';
tbody.insertBefore(span, tbody.querySelector('tr'));
renders "Created with JS → stays in place" between the header and the first row; the original, literal, span moves outside of the table.
Is this normal, and can/should I count on this? (It behaves the same in FF, Chrome, Opera, IE >= 9 (not tested below)).
Also, is there a way to query the DOM whether content of a certain type would (under normal circumstances) be valid at a certain point in the DOM? This is actually what I wanted to do when I found out about this quirk (which it is, imho).
The fiddle is here: http://jsfiddle.net/xr37g9kw/2/
As for "is this normal, and can/should I count on this?" Sadly, yes. But mostly you should be aware of the node types you are working with. NB, in case of table, there are a handful of not so well known DOM methods (HTMLTableElement.rows. InsertRow() and so on).
As for "is there a way to query the DOM whether content of a certain type would (under normal circumstances) be valid at a certain point in the DOM?" nothing built-in for this exact purpose, but you could exploit one native feature of JavaScript -> DOM API: you can let browser to re-parse HTML chunk in the "literal way". Yes, I am speaking about innerHTML.
In your fiddle, adding**tbody.outerHTML = tbody.outerHTML** "fixes" the structure, so you could hypothetically take some DOM node, look at its DOM tree, clone, "re-eval" it and compare with original.
Yes, that is the default behavior, as you saw. It's not valid HTML of course as you can check here http://www.freeformatter.com/html-validator.html if you input the HTML.
How would you access the value of an em tag in javascript?
This is the element I'm trying to access: <em id='tag_IS_System_Agent'></em>
which displays: John Smith
I'm trying to access it via javascript:
document.getElementById("emailFrame").src
= "http://www.website.org/mail.php?cid="
+IS_ATTR_ID.value
+"&name="+document.write("<em id=\"tag_IS_System_Agent\"> <\/em>")
+"&em="+email;`
Any idea? I know that document.write("<em id=\"tag_IS_System_Agent\"> <\/em>") is wrong and I'm stumped and not sure what to do.
Accessing the value based on your markup would be:
var myValue = document.getElementById("tag_IS_System_Agent").textContent
By “the value of an ‘em’ tag”, you apparently mean the content of an em element. If the element has an id attribute, as in your example, you can use the getElementById method of document to access the element node in the DOM. Then you can get the content of the element, serialized as HTML, using the innerHTML property. Note that this will include markup for inner elements, if any. So the expression you would use would be
document.getElementById('tag_IS_System_Agent').innerHTML
Instead of innerHTML, you could use textContent, which gives you just the textual content, without any inner tags. However, this is less widely supported (e.g., not in IE 8). If there is no inner markup, the results are the same, but innerHTML is thus safer.
I am copying a table cell with javascript.
It works fine, just that it doesn't copy the style.
I wanted to copy like below, but that didn't work.
newCell.style=oldCell.style;
So I figured that for my text-align, I have to copy it like this:
newCell.style.textAlign=oldCell.style.textAlign;
That worked, but whenever I add a new style item, I have to remember to register it here.
So, my problem now is how can I loop over the style and copy every item in there?
With chrome, I managed to do it like this:
var strAttribute = GetDomNameFromAttributeName(oRow.cells[1].style[0]);
var styletocopy = eval('oRow.cells[1].style.'+strAttribute);
eval("newCell.style."+strAttribute+"='"+styletocopy+"'"); // //newCell.style.textAlign='center';
But that doesn't work with IE. Haven't tested it with FF, but assume chrome compatibiity.
Is there any way to loop over the style elements in IE?
Or is there any better way to copy all style elements?
eval('oRow.cells[1].style.'+strAttribute)
Never use eval like this(*). In JavaScript you can access a property whose name is stored in a string using square brackets. object.plop is the same as object['plop']:
to.style[name]= from.style[name];
(*: never use eval at all if you can help it. There are only a few very specific and rare occasions you need it.)
Is there any way to loop over the style elements
The style object is supposed to support the DOM Level 2 CSS CSSStyleDeclaration interface. You could loop over the rules and apply them to another element like this:
for (var i= from.style.length; i-->0;) {
var name= from.style[i];
to.style.setProperty(name,
from.style.getPropertyValue(name),
priority= from.style.getPropertyPriority(name)
);
}
in IE?
No, IE does not support the whole CSSStyleDeclaration interface and the above won't work. However there is a simpler way not involving looping that will work on IE and the other browsers too:
to.style.cssText= from.style.cssText;
As simple as that! IE doesn't quite preserve the CSS text the way it should, but the difference doesn't matter for simple inline style copying.
However, as Pikrass said (+1), if you are copying a whole element and not just the styles, cloneNode is by far the most elegant way to do that.
You can copy a DOM Element with all its content (including attributes) with .cloneNode(true) :
var clonedTr = document.getElementById('id').cloneNode(true);
Then clonedTr is an exact copy of the tr #id.
The "true" means you want to copy the content of the element.
To copy all style elements from one node to another you can use
newCell.setAttribute('style', oRow.cells[1].getAttribute('style'))