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

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

Related

Replace non-code text on webpage

I searched through a bunch of related questions that help with replacing site innerHTML using JavaScript, but most reply on targetting the ID or Class of the text. However, my can be either inside a span or td tag, possibly elsewhere. I finally was able to gather a few resources to make the following code work:
$("body").children().each(function() {
$(this).html($(this).html().replace(/\$/g,"%"));
});
The problem with the above code is that I randomly see some code artifacts or other issues on the loaded page. I think it has something to do with there being multiple "$" part of the website code and the above script is converting it to %, hence breaking things.using JavaScript or Jquery
Is there any way to modify the code (JavaScript/jQuery) so that it does not affect code elements and only replaces the visible text (i.e. >Here<)?
Thanks!
---Edit---
It looks like the reason I'm getting a conflict with some other code is that of this error "Uncaught TypeError: Cannot read property 'innerText' of undefined". So I'm guessing there are some elements that don't have innerText (even though they don't meet the regex criteria) and it breaks other inline script code.
Is there anything I can add or modify the code with to not try the .replace if it doesn't meet the regex expression or to not replace if it's undefined?
Wholesale regex modifications to the DOM are a little dangerous; it's best to limit your work to only the DOM nodes you're certain you need to check. In this case, you want text nodes only (the visible parts of the document.)
This answer gives a convenient way to select all text nodes contained within a given element. Then you can iterate through that list and replace nodes based on your regex, without having to worry about accidentally modifying the surrounding HTML tags or attributes:
var getTextNodesIn = function(el) {
return $(el)
.find(":not(iframe, script)") // skip <script> and <iframe> tags
.andSelf()
.contents()
.filter(function() {
return this.nodeType == 3; // text nodes only
}
);
};
getTextNodesIn($('#foo')).each(function() {
var txt = $(this).text().trim(); // trimming surrounding whitespace
txt = txt.replace(/^\$\d$/g,"%"); // your regex
$(this).replaceWith(txt);
})
console.log($('#foo').html()); // tags and attributes were not changed
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo"> Some sample data, including bits that a naive regex would trip up on:
foo<span data-attr="$1">bar<i>$1</i>$12</span><div>baz</div>
<p>$2</p>
$3
<div>bat</div>$0
<!-- $1 -->
<script>
// embedded script tag:
console.log("<b>$1</b>"); // won't be replaced
</script>
</div>
I did it solved it slightly differently and test each value against regex before attempting to replace it:
var regEx = new RegExp(/^\$\d$/);
var allElements = document.querySelectorAll("*");
for (var i = 0; i < allElements.length; i++){
var allElementsText = allElements[i].innerText;
var regExTest = regEx.test(allElementsText);
if (regExTest=== true) {
console.log(el[i]);
var newText = allElementsText.replace(regEx, '%');
allElements[i].innerText=newText;
}
}
Does anyone see any potential issues with this?
One issue I found is that it does not work if part of the page refreshes after the page has loaded. Is there any way to have it re-run the script when new content is generated on page?

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";.

innerHTML to ascii

I am attempting to write my own piece of Javascript that converts html to ascii code (for learning purposes) so that the browser will render the code as you would see it in a text editor.
After looking around on Stack I have gotten as far as below. I am trying to turn an html element into a string; at this stage I am just trying to .replace() the angular brackets into ascii. If anyone could tell me where I am going wrong as far as having my test <body> tag showing up in the console that would be much appreciated.
<code class="lang-html">
<body></body>
</code>
(function() {
var html = $('.lang-html').innerHTML;
html.replace('<', '<');
html.replace('>', '>');
console.log(html);
});
Just to clarify, I am expecting that the console would spit out <body></body>.
Any help would be much appreciated.
A few things:
$('.lang-html').innerHTML
Assuming this is jQuery, this won't work. .innerHTML only works on raw DOM elements, like what's returned from document.getElementById(...). Instead, $('.lang-html') returns a jQuery collection, which has its own accessor methods. You should do:
$('.lang-html').html() // get the HTML as text from this element
Moving on, .replace() won't modify the original string. It returns a new copy. In the simplest case you can do:
var html = $('.lang-html')
.html()
.replace('<', '<')
.replace('>', '>');
But you still have to re-assign it to the HTML source. Again, jQuery provides a simple API for this.
$('.lang-html').html(html);
However, there's one more problem. .replace() only replaces the first match in a string. To replace all of them, you need to construct a regex and use the /g (global) flag. Here's the complete code:
var $element = $('.lang-html');
var html = $element.html()
.replace(/</g, '<')
.replace(/>/g, '>');
$element.html(html)
If you want get html code representation of an DOMElement in your browser then you won't need the replace to escape the html special chars. But you can use the browser to take care of all edge cases.
You could just use innerHTML/outerHTML and textContent.
This will e.g. will replace the content of the body with its html code representation.
var elm = document.getElementsByTagName('body')[0];
elm.textContent = elm.outerHTML;
Or if you just want to have the result as string but not displayed in the browsers then you could wrap that into a function:
function escapeHTML(html) {
var div = document.createElement('div');
div.textContent = html;
return div.innerHTML;
}
console.log( escapeHTML('<div>test</div>') );
You can also do a
$('.lang-html').prop("innerText")
which will hand you back the contents of that div, as real text.
No further translation should be needed.
Actually <body> tags will not be returned in the innerHTML of the posted code because the HTML is invalid. To explain:
To cater for changes to the DOM made in Javascript, browsers dynamically create innerHTML strings from the DOM by inspecting child elements of a specified node and generating HTML code from them.
Since <body> tags are only valid immediately following the head section, browsers silently respond to the <code> tag in your post by first creating a body element in which to place it. The <body> tags which follow are then ignored because they are invalid in this position. Hence there is no body element child of the code node, and no body tags in its innerHTML
Update (2): To pretty print the HTML without viewing page source you could try.
(function() {
var body = document.body;
var html = body.parentNode.outerHTML;
html = html.replace(/</g, '<');
html = html.replace(/>/g, '>');
html = html.replace(/\ /g, " ");
html = html.replace(/\n/g, '<br>\n');
// console.log(html);
body.innerHTML = html;
body.style.fontFamily = "monospace";
});

javascript: extracting text from html

I am getting html content as below:
var test='<div id="test">Raj</div>';
How can i retrieve value Raj from above html content using javascript.
It sounds like you're trying to extract the text "Raj" from that HTML snippet?
To get the browser's HTML parser to do your dirty work for you:
// create an empty div
var div = document.createElement("div");
// fill it with your HTML
div.innerHTML = test;
// find the element whose text you want
test = div.getElementById("test");
// extract the text (innerText for IE, textContent for everyone else)
test = test.innerText || test.textContent;
Or in jQuery:
test = $(test).text();
If you use jQuery (I cannot believe I just said that ;)) you can get at the content immediately you wrap it in $(test).html
Someone else will tell you how to get at the innerHTML using a selector since everybody here are jQuery gurus but me
Update: somebody just did while I was editing: javascript: extracting text from html - see comments or updates to that
var test = getElementById('test')
try that

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