Appendchild only works on last element - javascript

I am trying to create an element in JavaScript and apply it to all elements by class name. For this example I will use a paragraph for ease. The purpose of creating an element by JavaScript however is because I want to create a different element later on in my code.
In the code I am using, only the last element of the array of elements will contain the element created by the JavaScript. Could anyone explain why this is happening and what I could do to solve the problem accordingly to my requirement? I am trying to apply a whole element inside another element (so not just a value or property of a paragraph element).
My code:
//Creating my element:
let myElement = document.createElement("p");
/*let text = document.createTextNode("test");
myElement.appendChild(text);*/ //<-- Enable following to see text in result or check developer console for added paragraphs
//Single example:
let ele = document.getElementById("bar");
ele.appendChild(myElement);
//Not working...:
//Now class:
let eles = document.getElementsByClassName("foo");
for (i = 0; i < eles.length; i++) {
//eles[i].innerHTML = "abc";//<-- Does work (but hardcoded)?
//eles[i].innerHTML = myElement;//<-- returns "[object HTMLParagraphElement]"?
eles[i].appendChild(myElement); //<!-- Does work only for last element in array?
}
<div class="foo" id="bar">
</div>
<div class="foo">
</div>
<div class="foo">
</div>
<div class="foo">
<!-- Only this one will obtain the the paragraph element? -->
</div>
JSFiddle

You need to use cloneNode of element <p>, because appendChild moves it from its current position to the new position. See documentation
//Creating my element:
const myElement = document.createElement("p");
myElement.innerHTML = 'paragraph';
//Single example:
const ele = document.getElementById("bar");
ele.appendChild(myElement.cloneNode(true));
//Now class:
const eles = document.getElementsByClassName("foo");
for (let i = 0; i < eles.length; i++) {
eles[i].appendChild(myElement.cloneNode(true));
}
.foo {
border: 1px solid #333;
}
.foo p {
font-weight: bold;
}
<div class="foo" id="bar">
bar:
</div>
<div class="foo">
foo1
</div>
<div class="foo">
foo2
</div>
<div class="foo">
foo3
</div>

Your <p> element is appended only to the last because it is assigned to the myElementvariable. And because that variable is declared before your loop, each iteration will move the <p> tag through all your <div.foo>.
But if you declare your paragraph inside your for loop, a new one is created and appended to each of your blocks, because there are all different elements.
let eles = document.getElementsByClassName("foo");
for (i = 0; i < eles.length; i++) {
let myElement = document.createElement("p");
myElement.innerText = 'I am a paragraph.';
eles[i].appendChild(myElement);
}
<div class="foo" id="bar">
</div>
<div class="foo">
</div>
<div class="foo">
</div>
<div class="foo">
</div>

Related

JQuery append multiple child content to parent element

I have to add multiple child content to parent element dynamically using jquery , here is the example code I am referring https://github.com/linslin/pagingSlider ,
The code is so,
<div id="wrapper">
<div class="slidepage-container myPageContainerClass">
<div id="badges-slidepage-1" page="1" class="psPage center current">
<div class="content">
<h2>Page 1</h2>
</div>
</div>
<div id="badges-slidepage-2" page="2" class="psPage right">
<div class="content">
<h2>Page 2</h2>
</div>
</div>
<div id="badges-slidepage-3" page="3" class="psPage right">
<div class="content">
<h2>Page 3</h2>
</div>
</div>
<div id="badges-slidepage-4" page="4" class="psPage right">
<div class="content">
<h2>Page 4</h2>
</div>
</div>
</div>
I am able to add child elements to parent
var parentwrapper= $("<div/>").attr('id', 'wrapper');
var firstDiv= $("<div/>").addClass("slidepage-container myPageContainerClass");
var firstPage= $("<div/>").attr("id", "badges-slidepage-1").attr("page", "1").addClass("psPage center current");
var contentDiv= $("<div/>").addClass("content");
var firstcontent= $("<div/>").addClass("dealerNextTo dealerRectangleBox rectangleTopLeft").text("promptText");
var secondPage = $("<div/>").attr("id", "badges-slidepage-2").attr("page", "2").addClass("psPage right");
var secondContent= $("<div/>").addClass("dealerNextTo dealerRectangleBox rectangleTopLeft").text("promptText");
var myFinalVar = $(parentwrapper).append(firstDiv).append(firstPage).append(contentDiv).append(firstcontent).append(secondPage).append(secondContent);
$(myFinalVar).appendTo('body');
but it is adding to firstpage ContentDiv only,
How to achieve it. Any ideas? (I'm new to Jquery)
The problem is that you are chaining appends to add the elements you created like this:
var myFinalVar = $(parentwrapper).append(firstDiv).append(firstPage).append(contentDiv)
.append(firstcontent).append(secondPage).append(secondContent);
When you chain appends, elements do not get added to the previous element in the chain, they are all added directly to the first element. In your code, you are adding all elements as direct children of parentwrapper.
You need to add each child (or set of siblingss) to their parent separately, e.g. you need to add only firstDiv to parentwrapper:
var myFinalVar = $(parentwrapper).append(firstDiv);
firstPage and secondPage are being appended to the same parent, so you can chain those like this:
$(firstDiv).append(firstPage).append(secondPage); // appending to the SAME parent
Working Example:
var parentwrapper = $("<div/>").attr('id', 'wrapper');
var firstDiv = $("<div/>").addClass("slidepage-container myPageContainerClass");
var firstPage = $("<div/>").attr("id", "badges-slidepage-1").attr("page", "1").addClass("psPage center current");
var contentDiv = $("<div/>").addClass("content");
var firstcontent = $("<div/>").addClass("dealerNextTo dealerRectangleBox rectangleTopLeft").text("Page 1 content div");
var secondPage = $("<div/>").attr("id", "badges-slidepage-2").attr("page", "2").addClass("psPage right");
var secondContent = $("<div/>").addClass("dealerNextTo dealerRectangleBox rectangleTopLeft").text("Page 2 content div");
var myFinalVar = $(parentwrapper).append(firstDiv);
// chain appends to add to the SAME div
$(firstDiv).append(firstPage).append(secondPage);
$(firstPage).append(contentDiv);
$(contentDiv).append(firstcontent);
$(secondPage).append(secondContent);
$(myFinalVar).appendTo('body');
#wrapper { padding: 10px; background: #eee; }
.slidepage-container.myPageContainerClass,
.content,
.psPage,
.dealerNextTo{ border: 1px solid blue; padding: 10px;}
.psPage { margin-bottom:20px; }
.rectangleTopLeft { background: lightblue; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
FYI you also seem to be missing an element on the secondPage elements - it doesn't have a .content div.
Here is what you may want to try:
// append first content to contentDiv
contentDiv.append(firstcontent);
// append contentDiv to firstPage
firstPage.append(contentDiv);
// append firstPage to firstDiv
firstDiv.append(firstPage);
// again append secondContent to secondPage
secondPage.append(secondContent);
firstDiv.append(secondPage);
var myFinalVar = $(parentwrapper).append(firstDiv);
$(myFinalVar).appendTo('body');

How to make selector choose div class and with tag name of p?

Hello I am kind of stuck right now. I am trying to make my script choose all paragraph inside a div class of change but I don't really understand how to do it. The html looks something like this in the body
<body>
<div id="top" class="change">
<p> Microsoft </p>
<p> Apple </p>
<p> Sony </p>
</div>
<div id="middle">
<p> Disney </p>
<p> Nintendo </p>
<p> Sony </p>
</div>
<div id="bottom" class="change">
<p> Ice</p>
<p> Tea</p>
<p> Water</p>
</div>
</body>
I am trying to make it so when the mouse cursor touches anything that has a class of change in a paragraph, it will change the color to a color of my choice but I don't know how to do it with selectors with pure javascript. This is the current code I have but it is not working. I can only use javascript
var fontChange = document.getElementsByClass("change").getElementsByTagName("p");
for (let i = 0; i < changeFont.length; i++) {
changeFont[i].onmouseover=function() {
this.style.color = "red";
}
}
for (let i = 0; i < changeFont.length; i++) {
changeFont[i].onmouseout=function() {
this.style.color = "black";
}
}
There's no function getElementsByClass, it's getElementsByClassName.
document.getElementsByClassName() returns a collection (see What do querySelectorAll, getElementsByClassName and other getElementsBy* methods return?), you have to index it to use getElementsByTagName on the elements that it returns.
var fontChange = [];
var change = document.getElementsByClassName("change");
for (var i = 0; i < change.length; i++) {
var paras = [].slice.call(change[i].getElementsByTagName("p"));
fontChange.concat(paras);
}
Or you could just use querySelectorAll
var fontChange = document.querySelectorAll(".change p");
You also have a typo. You set the variable fontChange, but then use changeFont in the loop.
You can achieve what you want without javascript, just add this code to your css
.change p:hover {
color: red;
}

How to add a div between two divs by Javascript

I am using wordpress and I want to add some html code on page using Javascript. I don't want to make child theme then edit php files. It is risky and I don't know about php.
I want to add a sibling div. This is an example code as default.
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
Now I want to add my custom div and its inside html between both div1 and div2.
<div class="mydiv">
<div class="mydivinside">
Text
</div>
</div>
Please let me know how is it possible using Javascript.
There are (at least) two ways, the first:
// document.querySelector() finds, and returns, the first element
// matching the supplied selector (or null, if no element is found):
var el1 = document.querySelector('.div1');
// here we create an adjacent element from the string of HTML,
// the 'afterend' argument states that this adjacent element
// follows the el1 node, rather than preceding it or appearing
// within:
el1.insertAdjacentHTML('afterend', '<div class="mydiv"><div class="mydivinside">Text</div></div>');
var div1 = document.querySelector('.div1');
div1.insertAdjacentHTML('afterend', '<div class="mydiv"><div class="mydivinside">Text</div></div>');
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
And the second where you first create that <div> to be inserted, and then use parentNode.insertBefore():
var htmlString = '<div class="mydiv "><div class="mydivinside">Text</div></div>',
// here we create a <div> element:
div = document.createElement('div'),
// we retrieve the element after which the new
// element should be inserted:
div1 = document.querySelector('.div1');
// assign the supplied HTML string to the innerHTML of the
// created element:
div.innerHTML = htmlString;
// and use parentNode.insertBefore to insert the desired element
// (the first argument) before the element identified in the
// second argument, which is the nextSibling of the found
// 'div1' element:
div1.parentNode.insertBefore(div.firstChild, div1.nextSibling);
var htmlString = '<div class="mydiv "><div class="mydivinside">Text</div></div>',
div = document.createElement('div'),
div1 = document.querySelector('.div1');
div.innerHTML = htmlString;
div1.parentNode.insertBefore(div.firstChild, div1.nextSibling);
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
References:
document.createElement().
document.querySelector().
Element.insertAdjacentHTML().
Node.firstChild.
Node.insertBefore().
Node.nextSibling.
Node.parentNode.
Use Node#insertBefore method.
// create a div element
var div = document.createElement('div');
// set class name
div.className = 'mydiv';
// set html contents
div.innerHTML = ' <div class="mydivinside"> Text </div>';
// get .div2 element
var ele = document.querySelector('.div2');
// insert before the .div2 element by getting
// its parent node
ele.parentNode.insertBefore(div, ele);
<div class="div1">
<div class="div1inside">
Text
</div>
</div>
<div class="div2">
<div class="div2inside">
Text
</div>
</div>
You can just use the before method to append a div between both div1 and div2. Here is the example:
$('.div2inside').before("<div class='mydiv'><div class='mydivinside'>Text</div></div>");
You could do something like this?
var firstDiv = document.getElementById('div1');
firstDiv.parentNode.insertBefore(document.getElementById('new-div'), firstDiv.nextSibling);
This however assumes that your new-div is already in the dom.
EDIT: to create a the new-div on the fly you can use #david-thomas's solution https://stackoverflow.com/a/41425079/1768337
This link will be helpfull to get the above result.
https://plainjs.com/javascript/manipulation/insert-an-element-after-or-before-another-32/

Adding a child element to all divs of the same class

I'm attempting to add a child span to all div's with the same class.
I can achieve this to a individual element by targeting its Id
HTML
<div id="h1" class="header">Hello </div>
<hr>
<div id="h2" class="header">what about this one </div>
JavaScript
var header = document.getElementById('h1');
var newSpan = document.createElement("span");
header.appendChild(newSpan);
newSpan.innerHTML = "i'm here";
However when I change it to
var header = document.getElementsByClassName('header');
It fails to work.
Can anyone see where I'm going wrong?
JSFiddle
To do that you need to iterate over them, since getElementsByClassName() returns an array like html element collection. You can use for loop
var headers = document.getElementsByClassName('header');
for (var i = 0; i < headers.length; i++) {
var newSpan = document.createElement("span");
newSpan.innerHTML = "i'm here";
headers[i].appendChild(newSpan);
}
<div id="h1" class="header">Hello</div>
<hr>
<div id="h2" class="header">what about this one</div>
or you can use Array.prototype.forEach with call() to iterate over it
var headers = document.getElementsByClassName('header');
[].forEach.call(headers,function(ele) {
var newSpan = document.createElement("span");
newSpan.innerHTML = "i'm here";
ele.appendChild(newSpan);
})
<div id="h1" class="header">Hello</div>
<hr>
<div id="h2" class="header">what about this one</div>
For more about iteration check :- For loop for HTMLCollection elements
The javascript document.getElementById will return only one Id, but document.getElementByClassName will return a collection of array-like objects and it should be used here.
I have updated your js code to :
var header = document.getElementsByClassName('header');
//console.log(header);
for(var i=0;i<header.length;i++){
var newSpan = document.createElement("span");
header[i].appendChild(newSpan);
newSpan.innerHTML = "i'm here";
}
and HTML code to :
<div id="h1" class="header">Hello </div>
<hr>
<div id="h2" class="header">what about this one </div>
HTML code had some slight mistake of class"header" instead class="header"
Fiddle
You can consider inserting the text as CSS generated content:
.header::after {
content: "i'm here";
}
<div id="h1" class="header">Hello </div>
<hr />
<div id="h2" class="header">what about this one </div>

javascript onclick get the div id?

Is it possible to get the ids of the 2 div tags on clicking the button, using javascript?
<div id="main">
<div id="content">
</div>
<button onclick="function();">show it</button>
</div>
I have 2 div tags here. The 1st div is in the main div while the content div is inside the main div and the button is inside the main div as well.
Is it possible to get the main and content id of the 2 div tags on clicking the button?
EXPECTED OUTPUT when I press the button:
alert: main
alert: content
You need to pass the element to the function. Then you can use parentNode to get the DIV that contains the button. From there, you can use querySelector to find the first DIV in the parent.
function showIt(element) {
var parent = element.parentNode;
alert(parent.id);
var content = parent.querySelector("div");
alert(content.id);
}
<div id="main">
<div id="content">
</div>
<button onclick="showIt(this);">show it</button>
</div>
<div id="main2">
<div id="content2">
</div>
<button onclick="showIt(this);">show it</button>
</div>
<div id="main3">
<div id="content3">
</div>
<button onclick="showIt(this);">show it</button>
</div>
document.getElementById('button').onclick = function () {
var divs = document.querySelectorAll('div');
for (var i = 0; i < divs.length; i++) {
var id = divs[i].getAttribute('id');
alert(id);
}
};
http://jsfiddle.net/jm5okh69/1/
This should work in all browsers and uses the cleaner .id method.
var button = document.getElementById('button');
button.onclick = getIDs;
function getIDs(){
var id,divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
id = divs[i].id // .id is a method
alert(id);
}
}
<div id="main">
<div id="content"></div>
<button id="button">show it</button>
</div>

Categories

Resources