AppendChild and InsertBefore - javascript

I'm having a little problem with hierarchy elements that are created dynamically.
Been trying to use insertBefore so they change place but no luck, wont get any errors but still I get the element under the other.
I have this function that creates a class called dice-window-wrapper and adds it to the page-content-wrapper.
var outerDiv = createElementWithClass('div', 'dice-window-wrapper'),
innerDiv = createElementWithClass('div', 'dice-menubar-wrapper');
outerDiv.appendChild(innerDiv);
document.getElementById("page-content-wrapper").appendChild(outerDiv);
And I get the print <div class="dice-window-wrapper">...</div>
No problem here.
Then I want to add an unordered list with some <li> tags, using this function:
icon_ul = createElementWithOutClass('ul');
var icon_ul = document.getElementById("page-menu-wrapper").appendChild(icon_ul);
icon_li = createElementWithId('li','icon-dice');
icon_ul.appendChild(icon_li);
document.getElementById("ul");
And the print will be <ul><li id="icon-dice"></li></ul>
The problem as I told is that <div class="dice-window-wrapper">...</div> should be under the string <ul><li id="icon-dice"></li></ul>.
But even if I change the icon_ul function from appendChild to insertBefore, nothing seems to change.

Try this:
document.getElementById("page-menu-wrapper").insertBefore(icon_ul, outerDiv);
insertBefore requires 2 parameters: what to add, and before what you want to add it.
See the documentation here:
var insertedElement = parentElement.insertBefore(newElement, referenceElement);
// ^ returns ^add to this element: ^ this new element, ^ before this existing element.
Okay, so the problem here is, assuming:
document.getElementById("page-menu-wrapper").insertBefore(icon_ul, outerDiv);
There, the parent of outerDiv isn't "page-menu-wrapper". Either replace that line with:
document.getElementById("page-content-wrapper").insertBefore(icon_ul, outerDiv);
Or replace:
document.getElementById("page-content-wrapper").appendChild(outerDiv);
// With
document.getElementById("page-menu-wrapper").appendChild(outerDiv);

Related

Inserting div into existing div with class only

I'm trying to create a new div in Javascript with two spans in it, each containing a string of text. They are then meant to be inserted before div.two in div.inner.
The div I'm trying to insert it into only has a class and I cannot target it by any ID, unfortunately.
I have also created a codepen here: https://codepen.io/lisaschumann/pen/BXqJKY
Any help is massively appreciated!
HTML
<html>
<div class="inner">
<div class="one"></div>
<div class="two"></div>
</div>
</html>
JS
window.onload=function(){
var infobox = document.createElement("div");
infobox.classList.add('infobox');
var spanOne = document.createElement("div");
var spanOneText = document.createTextNode('Important text 1');
var spanTwo = document.createElement("div");
var spanTwoText = document.createTextNode('Important text 2');
spanOne.appendChild(spanOneText);
spanTwo.appendChild(spanTwoText);
infobox.appendChild(spanOne);
infobox.appendChild(spanTwo);
var targetDiv = document.getElementsByClassName("inner");
targetDiv.insertBefore(infobox, targetDiv.childNodes[1]);
}
Errors:
Cannot read property '1' of undefined
at window.onload
The main issue is that getElementsByClassName returns a live collection of nodes rather than one node and so you would need to access the correct node in that list similar to an array: targetDiv[0], perhaps.
The easier method is to use querySelector to grab the element you want using its class, for example:
var parent = document.querySelector(".inner");
var two = document.querySelector(".two");
parent.insertBefore(infobox, two);
But! there's even a shortcut method you can use here that allows you to add an HTML string direct to the DOM which might save you a bit of time, and some code.
// Create the HTML
const html = `
<div>
<span>Text alpha</span>
<span>Text beta</span>
</div>`;
// Grab the element containing your "two" class
const two = document.querySelector('.inner .two');
// Using insertAdjacentHTML to add the HTML before the two element
two.insertAdjacentHTML('beforebegin', html);
<div class="inner">Inner
<div class="one">one</div>
<div class="two">two</div>
</div>
insertAdjacentHTML
This doesn't work because of these lines
var targetDiv = document.getElementsByClassName("inner");
targetDiv.insertBefore(infobox, targetDiv.childNodes[1]);
document.getElementsByClassName returns a NodeList. targetDiv.childNodes is undefined, because childNodes doesn't exist on a NodeList.
You need to either use a list operation like Array.prototype.forEach, change getElementsByClassName to getElementByClassName (note the s) or access the first node in the node list using the array indexer syntax.
I assume you meant to do something like this:
var targetDiv = document.getElementByClassName('inner')
targetDiv.insertBefore(infobox, targetDiv.childNodes[1])
This will insert a node in between the first and second child of the first DOM node with the class inner.
Try this out , targetDiv is an array by default due to the getElementsByClassName method , even though it has a single element.Hence you need to specify the index i.e. 0 ( as it's the first element of the array)
var targetDiv = document.getElementsByClassName("inner")[0]; targetDiv.insertBefore(infobox, targetDiv.children[1]); }
Using JQuery
$(document).ready(function(){
$(`<div>Important text 1<span></span>Important text 2<span></span></div>`).insertBefore( ".inner .two" );
)
I would encourage you to use JQuery and then shift to vanilla javascript later on. You can do simple tasks like this in just few lines of code and it is also easily debuggable because of that

Failed to execute removeChild on Node

Other stack answers such as this and this seem to be specialized cases and I believe my case is more generalized. I am doing this in my js:
var markerDiv = document.createElement("div");
markerDiv.innerHTML = "<div id='MyCoolDiv' style='color: #2b0808'>123</div>";
document.getElementById("playerContainer").appendChild(markerDiv);
// after a brief delay, REMOVE the appended child
setTimeout(function(){
var myCoolDiv = document.getElementById("MyCoolDiv");
document.getElementById("playerContainer").removeChild(myCoolDiv);
}, 1500);
Everything works correctly and as expected (the div is correctly appended and I can see it) until removeChild() is called, at which time I get the error Failed to execute 'removeChild' on 'Node'.
What am I doing wrong?
Your myCoolDiv element isn't a child of the player container. It's a child of the div you created as a wrapper for it (markerDiv in the first part of the code). Which is why it fails, removeChild only removes children, not descendants.
You'd want to remove that wrapper div, or not add it at all.
Here's the "not adding it at all" option:
var markerDiv = document.createElement("div");
markerDiv.innerHTML = "<div id='MyCoolDiv' style='color: #2b0808'>123</div>";
document.getElementById("playerContainer").appendChild(markerDiv.firstChild);
// -------------------------------------------------------------^^^^^^^^^^^
setTimeout(function(){
var myCoolDiv = document.getElementById("MyCoolDiv");
document.getElementById("playerContainer").removeChild(myCoolDiv);
}, 1500);
<div id="playerContainer"></div>
Or without using the wrapper (although it's quite handy for parsing that HTML):
var myCoolDiv = document.createElement("div");
// Don't reall need this: myCoolDiv.id = "MyCoolDiv";
myCoolDiv.style.color = "#2b0808";
myCoolDiv.appendChild(
document.createTextNode("123")
);
document.getElementById("playerContainer").appendChild(myCoolDiv);
setTimeout(function(){
// No need for this, we already have it from the above:
// var myCoolDiv = document.getElementById("MyCoolDiv");
document.getElementById("playerContainer").removeChild(myCoolDiv);
}, 1500);
<div id="playerContainer"></div>
For me, a hint to wrap the troubled element in another HTML tag helped. However I also needed to add a key to that HTML tag. For example:
// Didn't work
<div>
<TroubledComponent/>
</div>
// Worked
<div key='uniqueKey'>
<TroubledComponent/>
</div>
The direct parent of your child is markerDiv, so you should call remove from markerDiv as so:
markerDiv.removeChild(myCoolDiv);
Alternatively, you may want to remove markerNode. Since that node was appended directly to videoContainer, it can be removed with:
document.getElementById("playerContainer").removeChild(markerDiv);
Now, the easiest general way to remove a node, if you are absolutely confident that you did insert it into the DOM, is this:
markerDiv.parentNode.removeChild(markerDiv);
This works for any node (just replace markerDiv with a different node), and finds the parent of the node directly in order to call remove from it. If you are unsure if you added it, double check if the parentNode is non-null before calling removeChild.
I was wraped it with <> </> as a parent when I changed it to normal , div , its worked fine
As others have mentioned, myCoolDiv is a child of markerDiv not playerContainer. If you want to remove myCoolDiv but keep markerDiv for some reason you can do the following
myCoolDiv.parentNode.removeChild(myCoolDiv);
JSFiddle
I'd a similar problem in the vue.js project. Then, I got a hint on changing the fragment wrapper to an HTML element. The most common use case for fragments is probably when you need to return multiple elements. With fragments this is easy and you don't need your typical wrapper div for the elements. Its short syntax is <></>.
Basically, I used the fragment pattern in Vue then I got the above error rendering the component dynamically using transition. It appears that the dynamic component(which entails multiple elements) needed to be wrapped with an HTML element, not a fragment.
// Vuejs
<transition
name="router-anim"
enter-active-class="animated animated-enter"
mode="out-in"
leave-active-class="animated animated-exit"
>
<router-view /> // dynamic rendering based on current route using vue-router
</transition>

javascript elements/tags array DOM node access

what's the different between using:
// assuming using elements/tags 'span' creates an array and want to access its first node
1) var arrayAccess = document.getElementsByTagName('elementName')[0]; // also tried property items()
vs
// assuming I assign an id value to the first span element/tag
// specifically calling a node by using it's id value
2) var idAccess = document.getElementById('idValue');
then if I want to change the text node....when using example 1) it will not work, for example:
arrayAccess.firstChild.nodeValue = 'some text';
or
arrayAccess.innerText/innerHTML/textContent = 'some text';
If I "access" the node through its id value then it seems to work fine....
Why is it that when using array it does not work? I'm new to javascript and the book I'm reading does not provide an answer.
Both are working,
In your first case you need to pass the tag name instead of the element name. Then only it will work.
There might be a case that you trying to set input/form elements using innerHTML. At that moment you need to use .value instead of innerHTML.
InnerHTML should be used for div, span, td and similar elements.
So your html markup example:
<div class="test">test</div>
<div class="test">test1</div>
<span id="test">test2</span>
<button id="abc" onclick="renderEle();">Change Text</button>
Your JS code:
function renderEle() {
var arrayAccess = document.getElementsByTagName('div')[0];
arrayAccess.innerHTML = "changed Text";
var idEle = document.getElementById('test');
idEle.innerHTML = "changed this one as well";
}
Working Fiddle
When you use document.getElementsByTagName('p'), the browser traverses the rendered DOM tree and returns a node list (array) of all elements that have the matching tag.
When you use document.getElementById('something'), the browser traverses the rendered DOM tree and returns a single node matching the ID if it exists (since html ID's are unique).
There are many differences when to use which, but one main factor will be speed (getElementById is much faster since you're only searching for 1 item).
To address your other question, you already have specified that you want the first element in the returned nodeList (index [0]) in your function call:
var arrayAccess = document.getElementsByTagName('elementName')[0];
Therefore, arrayAccess is already set to the first element in the returned query. You should be able to access the text by the following. The same code should work if you used document.getElementById to get the DOM element:
console.log(arrayAccess.textContent);
Here's a fiddle with an example:
http://jsfiddle.net/qoe30w2w/
Hope this helps!

How to write to a <div> element using JavaScript?

I've searched around using Google and Stack Overflow, but I haven't seemed to find a answer to this. I want to write text inside a <div> element, using JavaScript, and later clear the <div> element, and write more text into it. I am making a simple text adventure game.
This is what I am trying to do:
<DOCTYPE!HTML>
<body>
<div class="gamebox">
<!-- I want to write in this div element -->
</div>
</body>
As a new user to JavaScript, how would I be able to write inside the div element gamebox? Unfortunately, my JavaScript skills are not very good, and it would be nice if you can patiently explain what happens in the code.
You can use querySelector to get a reference to the first element matching any CSS selector. In your case, a class selector:
var div = document.querySelector(".gamebox");
querySelector works on all modern browsers, including IE8. It returns null if it didn't find any matching element. You can also get a list of all matching elements using querySelectorAll:
var list = document.querySelectorAll(".gamebox");
Then you access the elements in that list using 0-based indexes (list[0], list[1], etc.); the length of the list is available from list.length.
Then you can either assign HTML strings to innerHTML:
div.innerHTML = "This is the text, <strong>markup</strong> works too.";
...or you can use createElement or createTextNode and appendChild / insertBefore:
var child = document.createTextNode("I'm text for the div");
div.appendChild(span); // Put the text node in the div
Those functions are found in the DOM. A lot of them are now covered in the HTML5 specification as well (particularly Section 3).
Select a single element with document.querySelector or a collection with document.querySelectorAll.
And then it depends, on what you want to do:
Writing Text into the div or create an Element and append it to the div.
Like mentioned getElementsByClassName is faster. Important to know it when you use this you get returned an array with elements to reach the elment you want you specify its index line [0], [1]
var gameBox = document.getElementsByClassName('gamebox')[0];
Here how you can do it
//returns array with elements
var gameBox = document.getElementsByClassName('gamebox');
//inner HTML (overwrites fsd) this can be used if you direcly want to write in the div
gameBox[0].innerHTML ='<p>the new test</p>';
//Appending when you want to add extra content
//create new element <p>
var newP = document.createElement('p');
//create a new TextNode
var newText = document.createTextNode("i'm a new text");
//append textNode to the new element
newP.appendChild(newText);
//append to the DOM
gameBox[0].appendChild(newP);
https://developer.mozilla.org/en-US/docs/Web/API/document.createElement
https://developer.mozilla.org/en-US/docs/Web/API/document.getElementsByClassName

How to append an Object to a DOM Element with JQuery append(), add() or appendTo()?

I can't seem to get this working, even though I have the idea it is perfectly correct. Consider the following code:
<script type="text/javascript>
ul = $(".qtrans_language_chooser");
parent = ul.parent();
activeLangLi = ul.children("li.active");
parent.prepend('<ul class="qtrans_active_language"></ul>');
activeLangUl = $(".qtrans_active_language");
o = activeLangLi.appendTo(activeLangUl);
activeLangLi.remove();
</script>
All I'm trying to do is add activeLangLi to the empty activeLangUl. But no matter if I use append(), appendTo() or add() it never shows up.
Remove this line:
activeLangLi.remove();
This removes the elements from the DOM. append and appendTo will move (not copy) the elements from the current location to the new one. If you remove them afterwards, well, then they are gone.
You could also optimize your code to:
var ul = $(".qtrans_language_chooser");
$('<ul class="qtrans_active_language"></ul>')
.prependTo(ul.parent())
.append(ul.children("li.active"));
Don't forget to use var.

Categories

Resources