creating html by javascript DOM (realy basic question) - javascript

i'm having some trouble with javascript. Somehow i can't get started (or saying i'm not getting any results) with html elements creation by javascript.
i'm not allowed to use:
document.writeln("<h1>...</h1>");
i've tried this:
document.getElementsByTagName('body').appendChild('h1');
document.getElementsByTagName('h1').innerHTML = 'teeeekst';
and this:
var element = document.createElement('h1');
element.appendChild(document.createTextNode('text'));
but my browser isn't showing any text. When i put an alert in this code block, it does show. So i know the code is being reached.
for this school assignment i need to set the entire html, which normally goes into the body, by javascript.
any small working code sample to set a h1 or a div?
my complete code:
<html>
<head>
<title>A boring website</title>
<link rel="stylesheet" type="text/css" href="createDom.css">
<script type="text/javascript">
var element = document.createElement('h1');
element.innerHTML = "Since when?";
document.body.appendChild(element);
</script>
</head>
<body>
</body>
</html>

getElementsByTagName returns a NodeList (which is like an array of elements), not an element. You need to iterate over it, or at least pick an item from it, and access the properties of the elements inside it. (The body element is more easily referenced as document.body though.)
appendChild expects an Node, not a string.
var h1 = document.createElement('h1');
var content = document.createTextNode('text');
h1.appendChild(content);
document.body.appendChild(h1);
You also have to make sure that the code does not run before the body exists as it does in your edited question.
The simplest way to do this is to wrap it in a function that runs onload.
window.onload = function () {
var h1 = document.createElement('h1');
var content = document.createTextNode('text');
h1.appendChild(content);
document.body.appendChild(h1);
}
… but it is generally a better idea to use a library that abstracts the various robust event handling systems in browsers.

Did you append the element to document?
Much the same way you're appending text nodes to the newly created element, you must also append the element to a target element of the DOM.
So for example, if you want to append the new element to a <div id="target"> somewhere are the page, you must first get the element as target and then append.
//where you want the new element to do
var target = document.getElementById('target');
// create the new element
var element = document.createElement('h1');
element.appendChild(document.createTextNode('text'));
// append
target.appendChild(element);

create element, add html content and append to body
var element = document.createElement('h1');
element.innerHTML = 'teeeekst';
document.body.appendChild(element);

Related

Can I create a self-closing element with createElement?

I'm trying to append a line of HTML before all the children of the body.
Right now I have this:
// Prepend vsr-toggle
var vsrToggle = document.createElement("div");
vsrToggle.innerHTML = "<input type='checkbox' name='sr-toggle' id='srToggle'><label for='srToggle' role='switch'>Screen reader</label>"
document.body.insertBefore(vsrToggle, pageContent);
It's working fine because the HTML is being added to the created div. However, I need to prepend this element without wrapping it in a div.
Is there a way to prepend the HTML without first creating an element? If not, can I create the input as a self-closing element and append the label to it?
Is there a better way to achieve this?
Cheers!
Use document.createDocumentFragment() to create a node, that isn't automatically added to the document. You can then add elements to this fragment and finally add it to the document.
This is a good link: Document fragment
How to use:
var fragment = document.createDocumentFragment();
fragment.innerHTML = '<input />';
document.body.appendChild(fragment);
I ended up using createRange and createContextualFragment to turn the string into a node that I could prepend using insertBefore.:
// Prepend vsr-toggle
var vsrToggle = document.createRange().createContextualFragment("<input
type='checkbox' name='sr-toggle' id='srToggle'><label for='srToggle'
role='switch'>Screen reader</label>");
document.body.insertBefore(vsrToggle, pageContent);
Edit: As Poul Bak showed, there is a very useful feature in the DOM API for that. Creating elements separately (instead of having them parsed as a string) allows more control over the elements added (for example you can outright attach an event listener without queryiing it from the DOM later), but for a larger amounts of elements it quickly becomes very verbose.
Create each element separately, and insert it before the body content using
document.body.insertBefore(newNode, document.body.firstChild);
const vsrToggle = document.createElement("input");
vsrToggle.name="sr-toggle";
vsrToggle.id="srToggle";
vsrToggle.type="checkbox";
const vsrToggleLabel = document.createElement("label");
vsrToggleLabel.setAttribute("for", vsrToggle.id);
vsrToggleLabel.setAttribute("role", "switch");
vsrToggleLabel.textContent = "Screen reader";
document.body.insertBefore(vsrToggle, document.body.firstChild);
document.body.insertBefore(vsrToggleLabel, document.body.firstChild);
<body>
<h1>Body headline</h1>
<p>Some random content</p>
</body>

How to properly create a textNode and append to a specific place?

I am trying to simply append a textNode to <h1> and then append it to the body into a <div id="prob3">, but I get this error TypeError: bdy.appendChild is not a function on bdy.appendChild(header);. What is wrong with this piece of code?
JavaScript Code (embedded in the head tag):
function init()
{
var bdy = document.getElementsByTagName("body");
var header = document.createElement("h1");
var txt = document.createTextNode("Hello World!");
header.appendChild(txt);
bdy.appendChild(header);
}
HTML:
<body onload="init();">
<div id="prob3">
<!--Created TextNode goes Here-->
</div>
</body>
You can just use:
document.body.appendChild(header);
Your code wasn't working because:
var bdy = document.getElementsByTagName("body");
retrieves a list of elements, not a single element. You could have used:
var bdy = document.getElementsByTagName("body")[0];
to get the first element from the list, but there's no point in doing it this way since document.body is already predefined for you.
getElementsByTagName gets you a NodeList, and you can’t append to that – you would have to get out the first element of that list first, getElementsByTagName("body")[0].appendChild.
But every browser understands document.body as a shortcut to the body element.
In this method call:
var bdy = document.getElementsByTagName("body");
Notice "elements" is plural. Which means in all likelihood it returns an array-like structure (in this case a NodeList). Arrays naturally don't have a .appendChild method. You can tell this by inspecting bdy in a debugger, or more bluntly by console.log-ing it.

Alternatives to document.write

I am in a situation where it seems that I must use document.write in a javascript library. The script must know the width of the area where the script is defined. However, the script does not have any explicit knowledge of any tags in that area. If there were explicit knowledge of a div then it would be as simple as this:
<div id="childAnchor"></div>
<script ref...
//inside of referenced script
var divWidth = $("#childAnchor").width();
</script>
So, inside of the referenced script, I am thinking of doing using document.write like this:
<script ref...
//inside of referenced script
var childAnchor = "z_87127XNA_2451ap";
document.write('<div id="' + childAnchor + '"></div>');
var divWidth = $("#" + childAnchor).width();
</script>
However, I do not really like the document.write implementation. Is there any alternative to using document.write here? The reason that I cannot simply use window is that this is inside of a view which is rendered inside of a master view page. Window would not properly get the nested area width.
The area is pretty much in here:
<body>
<div>
<div>
<div>
AREA
The AREA has no knowledge of any of the other divs.
This just occurred to me, and I remembered your question: the script code can find the script block it is in, so you can traverse the DOM from there. The current script block will be the last one in the DOM at the moment (the DOM still being parsed when the code runs).
By locating the current script block, you can find its parent element, and add new elements anywhere:
<!doctype html>
<html>
<head>
<style>
.parent .before { color: red; }
.parent .after { color: blue; }
</style>
</head>
<body>
<script></script>
<div class="parent">
<span>before script block</span>
<script>
var s = document.getElementsByTagName('script');
var here = s[s.length-1];
var red = document.createElement("p");
red.className = 'before';
red.innerHTML = "red text";
here.parentNode.insertBefore(red, here);
var blue = document.createElement("p");
blue.className = 'after';
blue.innerHTML = "blue text";
here.parentNode.appendChild(blue);
</script>
<span>after script block</span>
</div>
<script></script>
</body>
</html>​
http://jsfiddle.net/gFyK9/2/
Note the "blue text" span will be inserted before the "after script block" span. That's because the "after" span does not exist in the DOM at the moment appendChild is called.
However there's a very simple way to make this fail.
There is no alternative to this method. This is the only way that the script can find the width of the element that it is nested in without knowing anything about the DOM that it is loaded into.
Using document.write() when used appropriately is legitimate. Although, appending a new element to the DOM is preferable, it is not always an available option.
if you know which child element it is you can use the param nth child in jquery.
otherwise youll need to iterate through them with each()
Create and append the child like this:
var el = document.createElement('div');
el.id='id';
document.body.appendChild(el);
However I'm not really sure what you want to do with this to get the width of whatever, it will probably return 0.

IE9, Javascript: Create and append a new element

I'm having some serious trouble getting my code to work in IE9, works fine in Chrome & Firefox but I throws some errors. Here are my 2 functions:
function insertHTML(content){
var body=document.getElementsByTagName('body');
body[0].appendChild(createElement(content));
}
function createElement(string){
var container=document.createElement('div');
container.innerHTML=string;
var element=container.firstChild.cloneNode(true);
return element;
}
I've tried severel methods for this and none seem to work, I'll explain exactly what I need to do...
...I need to create a new element from an html string, the string is sent back from an ajax call so my script will have almost no idea what it contains until it gets it.
I did try using element.innerHTML but this is no good, because if i have one html element (form) on the screen and the user enters data into it, and then when another element is inserted it will wipe all the user-entered data from the first form. I was doing element.innerHTML+=newData;
So basically, I need 2 things:
1) A way to create a new element from an html string.
2) A way to append the element to the document body.
It all needs to work cross-browser and I'm not allowed to use jQuery, also the new element cannot be contained in a div parent item, it has to have the body as its parent.
Thanks very much for your help,
Richard
innerHTML is read write and will destroy anything inside your div. use with extreme care
function insertHTML( htmlString ){
var bodEle = document.getElementsByTagName('body');
var divEle = createElement("div");
divEle.innerHTML = htmlString;
bodEle.appendChild(divEle);
}
So basically, I need 2 things:
A way to create a new element from an html string.
A way to append the element to the document body.
It all needs to work cross-browser and I'm not allowed to use jQuery, also the new element cannot be contained in a div parent item, it has to have the body as its parent.
The following was tested in IE8
<!DOCTYPE html>
<html>
<body>
<script>
var divBefore = document.createElement('div');
var divAfter = document.createElement('div');
var htmlBefore = '<span><span style="font-weight: bold">This bold text</span> was added before</span>';
var htmlAfter = '<span><span style="font-weight: bold">This bold text</span> was added after</span>';
divBefore.innerHTML = htmlBefore;
divAfter.innerHTML = htmlAfter;
document.body.appendChild(divBefore);
setTimeout(function() {
document.body.appendChild(divAfter);
}, 0);
</script>
<div>This content was here first</div>
</body>
</html>
Renders
This bold text was added before
This content was here first
This bold text was added after
https://www.browserstack.com/screenshots/7e166dc72b636d3dffdd3739a19ff8956e9cea96
In the above example, if you don't need to be able to prepend to the body (i.e. insert content before what already exists), then simply place the script tag after the original content and don't use setTimeout.
<!DOCTYPE html>
<html>
<body>
<div>This content was here first</div>
<script>
var divAfter = document.createElement('div');
var htmlAfter = '<span><span style="font-weight: bold">This bold text</span> was added after</span>';
divAfter.innerHTML = htmlAfter;
document.body.appendChild(divAfter);
</script>
</body>
</html>

How to append text to a div element?

I’m using AJAX to append data to a <div> element, where I fill the <div> from JavaScript. How can I append new data to the <div> without losing the previous data found in it?
Try this:
var div = document.getElementById('divID');
div.innerHTML += 'Extra stuff';
Using appendChild:
var theDiv = document.getElementById("<ID_OF_THE_DIV>");
var content = document.createTextNode("<YOUR_CONTENT>");
theDiv.appendChild(content);
Using innerHTML:
This approach will remove all the listeners to the existing elements as mentioned by #BiAiB. So use caution if you are planning to use this version.
var theDiv = document.getElementById("<ID_OF_THE_DIV>");
theDiv.innerHTML += "<YOUR_CONTENT>";
Beware of innerHTML, you sort of lose something when you use it:
theDiv.innerHTML += 'content';
Is equivalent to:
theDiv.innerHTML = theDiv.innerHTML + 'content';
Which will destroy all nodes inside your div and recreate new ones. All references and listeners to elements inside it will be lost.
If you need to keep them (when you have attached a click handler, for example), you have to append the new contents with the DOM functions(appendChild,insertAfter,insertBefore):
var newNode = document.createElement('div');
newNode.innerHTML = data;
theDiv.appendChild(newNode);
If you want to do it fast and don't want to lose references and listeners use: .insertAdjacentHTML();
"It does not reparse the element it is being used on and thus it does not corrupt the existing elements inside the element. This, and avoiding the extra step of serialization make it much faster than direct innerHTML manipulation."
Supported on all mainline browsers (IE6+, FF8+,All Others and Mobile): http://caniuse.com/#feat=insertadjacenthtml
Example from https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
// <div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// At this point, the new structure is:
// <div id="one">one</div><div id="two">two</div>
If you are using jQuery you can use $('#mydiv').append('html content') and it will keep the existing content.
http://api.jquery.com/append/
IE9+ (Vista+) solution, without creating new text nodes:
var div = document.getElementById("divID");
div.textContent += data + " ";
However, this didn't quite do the trick for me since I needed a new line after each message, so my DIV turned into a styled UL with this code:
var li = document.createElement("li");
var text = document.createTextNode(data);
li.appendChild(text);
ul.appendChild(li);
From https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent :
Differences from innerHTML
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.
Even this will work:
var div = document.getElementById('divID');
div.innerHTML += 'Text to append';
An option that I think is better than any of the ones mentioned so far is Element.insertAdjacentText().
// Example listener on a child element
// Included in this snippet to show that the listener does not get corrupted
document.querySelector('button').addEventListener('click', () => {
console.log('click');
});
// to actually insert the text:
document.querySelector('div').insertAdjacentText('beforeend', 'more text');
<div>
<button>click</button>
</div>
Advantages to this approach include:
Does not modify the existing nodes in the DOM; does not corrupt event listeners
Inserts text, not HTML (Best to only use .insertAdjacentHTML when deliberately inserting HTML - using it unnecessarily is less semantically appropriate and can increase the risk of XSS)
Flexible; the first argument to .insertAdjacentText may be beforebegin, beforeend, afterbegin, afterend, depending on where you'd like the text to be inserted
you can use jQuery. which make it very simple.
just download the jQuery file add jQuery into your HTML
or you can user online link:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
and try this:
$("#divID").append(data);
The following method is less general than others however it's great when you are sure that your last child node of the div is already a text node. In this way you won't create a new text node using appendData MDN Reference AppendData
let mydiv = document.getElementById("divId");
let lastChild = mydiv.lastChild;
if(lastChild && lastChild.nodeType === Node.TEXT_NODE ) //test if there is at least a node and the last is a text node
lastChild.appendData("YOUR TEXT CONTENT");
java script
document.getElementById("divID").html("this text will be added to div");
jquery
$("#divID").html("this text will be added to div");
Use .html() without any arguments to see that you have entered.
You can use the browser console to quickly test these functions before using them in your code.
Why not just use setAttribute ?
thisDiv.setAttribute('attrName','data you wish to append');
Then you can get this data by :
thisDiv.attrName;

Categories