I'm making a little app, which has to append 3 elements to another element, by using this code:
var MyElem1= document.createElement("div");
ParentElem.appendChild(MyElem1);
This works just fine, but i was wondering if there is a way to create a full element, like this for example:
var MyElem1= document.createElement('<div style="some-styling: here;">Some InnerHtml Here</div>');
ParentElem.appendChild(MyElem1);
I know i can add those properties to the element after i create it, but i'm hopping there's a way to do it inline like that (Something that works cross-browser).
I saw on W3Schools (yes i know i should stop using it) the createElement function requires only the element type (div, span, button, etc...).
You could create a dummy container and create all elements you want inside it by replacing its innerHTML property, and then getting the .firstChild.
Here is a reusable function for it
var elementFactory = (function (){
var dummy = document.createElement('div');
return function(outerHtml){
var node;
dummy.innerHTML = outerHtml;
node = dummy.firstChild;
dummy.removeChild(node);
return node;
}
})();
and use it like this
var MyElem1 = elementFactory('<div style="some-styling: here;">Some InnerHtml Here</div>'),
MyElem2 = elementFactory('<div style="some-other-styling: here;">Some Other InnerHtml Here</div>');
Demo at http://jsfiddle.net/5De3p/1/
Related
I want to create an HTML element (a div) using javascript to use that as a tooltip.
I can create the simple element by doing:
const element = document.createElement("div");
element.id = "myID"
and that works fine...however, I want to add a table (and some other HTML) inside the tooltip, so I was trying to do
element.appendChild(childElement); //where the childElement is another document.createElement("") that contains all the HTML I want.
or:
element.insertAdjacentHTML('afterbegin', '<table></table>');
however, nothing happens. there's no error, but it won't append it either. Am I missing something?
If it matters, this is happening inside the contentScripts.js of a chrome extension I'm building.
EDIT
Full code of div creation:
const element = document.createElement("div");
element.id = "tooltip-creation";
element.classList.add("tooltip");
const childElement = document.createElement("div");
childElement.id = "data";
//I've attempted to do .appendChild, innerHTML, and .insertAdjacentHTML (as can be seen here) and neither works but no error is given.
element.appendChild(childElement);
element.insertAdjacentHTML('afterbegin','<table border="1"><tr><td><strong>OMG</strong></td></tr></table>');
element.innerHTML = "<table border="1"><tr><td><strong>OMG</strong></td></tr></table>";
Separately I have 2 functions that do:
document.addEventListener("mouseover", function(e){
if (e.target.classList.contains("tooltip")) {
createTooltip(e);
}
});
document.addEventListener("mouseout", function(e){
if (e.target.classList.contains("tooltip")) {
removeAllTooltips();
}
});
I think your issue is that you're not actually appending the tooltip to anything. You need to append your element to a node that is already in the DOM. Here is a working example (without any CSS) that I got from your code, the only difference being that I appended the element node to an existing element in the DOM called root.
https://jsfiddle.net/irantwomiles/09o7vuj5/12/
Can anyone please explain briefly what documentFragment actually does? I have been searching for a clear explanation but I don't get any until now.
what I read is, documentFragment is something like DOM like structure where we can add modify DOM elements without interrupting the actual flow of the document.
I also read, documentFragment is faster than appending each element into DOM one by one. It felt to me like, documentFragment does not recalculate styles every time so it is faster.
I have two examples,
DOING IT IN FRAGMENT WAY:
var frag = document.createDocumentFragment();
var div1 = document.createElement("div");
var div2 = document.createElement("div");
frag.appendChild(div1);
frag.appendChild(div2);
document.getElementById("someId").appendChild(frag);
DOING IT IN NORMAL WAY:
var div = document.createElement("div");
var div1 = document.createElement("div");
var div2 = document.createElement("div");
div.appendChild(div1);
div.appendChild(div2);
document.getElementById("someId").appendChild(div);
what actually happens in the above two examples?
There's an important difference between "the fragment way" and "the normal way":
Using document.createElement:
const div = document.createElement('div');
div.appendChild(document.createTextNode('Hello'));
div.appendChild(document.createElement('span'));
document.body.appendChild(div);
console.log(div.childNodes); // logs a NodeList [#text 'Hello', <span>]
This results in the following DOM structure:
<body>
<div>
Hello
<span></span>
</div>
</body>
Using DocumentFragment:
const frag = document.createDocumentFragment();
frag.appendChild(document.createTextNode('Hello'));
frag.appendChild(document.createElement('span'));
document.body.appendChild(frag);
console.log(frag.childNodes); // logs an empty NodeList
This results in the following DOM structure:
<body>
Hello
<span></span>
</body>
That means that calling appendChild or insertBefore with an instance of DocumentFragment moves the child nodes of the document fragment to the new parent node. After that, the document fragment is empty.
As you have correctly mentioned, it can be more efficient to create a document fragment and append multiple elements to it than to append those elements to the real DOM one by one, causing the browser to re–render parts of the page every time. Because the contents of the document fragment are not visible on screen, the page has to be re–rendered only once.
Whenever you create a large DOM structure, it can be advisable to create it within a document fragment and append that to the DOM when you're done.
For appending only 2 childs you will not see any performance issue. Imagine that you have an array of books that includes 100 items and you want to append them to the DOM. You would write this code:
let books=[,,,,,,,,,,,,,,,,]
let bookList;
document.addEventListener('DOMContentLoaded',load)
function load(){
bookList=document.getElementById('books')
books.forEach(book=>{
let li=document.createElement('li')
li.textContext=book
li.class="bookItem"
// here is the headache part
bookList.appendChild(li)
}))
}
So you are going to loop through 100 times and each time, you are going to tell the browser that redraw the screen. This will take up a lot of resources. Depending on the system that you are using, you might see the screen is flickering.
with fragment I would write load like this:
function load(){
bookList=document.getElementById('books')
let df=new DocumentFragment()
books.forEach(book=>{
let li=document.createElement('li')
li.textContext=book
li.class="bookItem"
// we are appending to df not to the bookList
df.appendChild(li)
})
// I collected all list elements inside DocumentFragment
// Now I append it to the bookList
bookList.appendChild(df)
}
creating document fragment is like creating a div. But it does not add any Html to the page. You are not going to see in HTML source code:
<DocumentFragment></DocumentFragment>
It is just an empty container that is used to hold other parts of Html. a fragment can be injected and cloned in a single operation instead of having to inject and clone each
individual node over and over again. We are achieving exact same thing with much better performance.
I want to create a div element on page load event but my script is not working as expected.
function createfn(){
//debugger;
var element = document.createElement("div");
var para = document.createTextNode('The man who mistook his wife for a hat');
element.appendChild(para);
document.getElementByTagName(body).appendChild(element);
}
window.onload=createfn();
What is it wrong with this code?
a few issues:
first the tag name body needs to be wrapped in quotes. in your code you are passing an undeclared variable called body.
Secondly, its getElementsByTagName() asthis function returns multiple elements in an array.
Lastly, you need to target the first body element:
function createfn(){
//debugger;
var element = document.createElement("div");
var para = document.createTextNode('The man who mistook his wife for a hat');
element.appendChild(para);
document.getElementsByTagName('body')[0].appendChild(element);
}
window.onload=createfn();
jsfiddle
I have a function called "StartMsg"
that I want to add text to a div element with the id "Screen". But sadly I known only basic JS, here is what I have so far;
function StartMsg() {
document.getElementById('Screen').innerHTML = "The game was created.";
}
But it overwrites all of my previous text (Yes I know it's supposed to do that, I'm trying to find a way to not overwrite but add!).
Use textContent and con-cat the new string
document.getElementById('Screen').textContent += " The game was created.";
JSFIDDLE
You can try createTextNode() method,
var your_div = document.getElementById('Screen');
var your_text = document.createTextNode("text added");
your_div.appendChild(your_content);
Using innerHTML will remove all listeners within the div element
You can also use the append method.
For example:
$('variable').append('some text');
I am trying to use native javascript to append a string of html to a target div. This works fine using:
var selector = document.getElementById('divid');
var str = '<div><h1>string of html content</h1></div>';
selector.innterHTML += str;
Except whenever the document contains an iframe it seems to hide the frame when appending the innerhtml. I tried a work around as follows:
var selector = document.getElementById('divid');
var str = '<div><h1>string of html content</h1></div>';
var div = document.createElement('div');
div.innerHTML = str;
selector.appendChild(div);
This works but now I am creating an unnecessary div container, is there a way to do this without creating a new element that won't erase the iframe?
Except whenever the document contains an iframe it seems to hide the frame when appending the innerhtml
See "innerHTML += ..." vs "appendChild(txtNode)" for the reason - modifying innerHTML creates a new iframe that reloads. Also have a look at What is better, appending new elements via DOM functions, or appending strings with HTML tags?
This works but now I am creating an unnecessary div container
Just don't create an extra div, you have one in your HTML anyway:
var selector = document.getElementById('divid');
var div = selector.appendChild(document.createElement('div'));
div.innerHTML = '<h1>string of html content</h1>';
is there a way to do this without creating a new element that won't erase the iframe?
You can also use the native insertAdjacentHTML method which is the equivalent to jQuery's append with a HTML string:
var selector = document.getElementById('divid');
selector.insertAdjacentHTML('beforeend', '<div><h1>string of html content</h1></div>');
This seems to work.
var parser = new DOMParser();
var el = parser.parseFromString(str, "text/html");
selector.appendChild(el.childNodes[0]);