Getting infinity loop when I append div to existing divs? - javascript

I had took some program test online,from there I got some infinity loop error in appending new div to existing div.
<div id="one">
<div id="two"></div>
</div>
And this JS code is to add new div:
appendChildren();
function appendChildren() {
var allDivs = document.getElementsByTagName("div");
for (var i = 0; i < allDivs.length; i++) {
var newDiv = document.createElement("div");
allDivs[i].appendChild(newDiv);
console.log(allDivs[i]);
}
}
I want the HTML to look like this:
<div id="one">
<div id="two">
<div></div>
</div>
<div></div>
</div>
But at run time the program doesn't stop looping. Why? I couldn't guess! So can I run that appendChildren() only one time or is there another solution?

document.getElementsByTagName("div") is a live collection - it always reflects the actual data.
It means that when you append a div item, it is automatically appended to your collection. So, it never ends.
You can copy your collection using [].slice.call so that it doesn't change.
Here is the working demo snippet:
function appendChildren() {
var allDivs = [].slice.call(document.getElementsByTagName("div"));
for (var i = 0; i < allDivs.length; i++) {
var newDiv = document.createElement("div");
allDivs[i].appendChild(newDiv);
console.log(allDivs[i]);
}
}
appendChildren();
// For demonstration purposes only:
document.getElementById('html').innerText = document.getElementById('one').outerHTML;
<div id="one">
<div id="two">
</div>
</div>
<pre id="html"></pre>
The html element displays the HTML result - however, it looks bad. You may use developer tools to see the actual structure in a familiar way.

Related

Move all elements with class inside div

I'm brand new to js, and tried to move every elements with certain class inside a certain div.
I made some research and saw a solution that works with id, but when I tried to change it to classNames it didn't work anymore.
Is there anything more to write ?
Here is my HTML
<div class="bottom">bottom 1</div>
<div class="bottom">bottom 2</div>
<div id="top">top</div>
and my script so far
document.getElementById('top').appendChild(document.getElementsByClassName('bottom'))
console.log(document.getElementById('top').innerHTML)
I understood that appendChild didn't work because document.getElementsByClassName('bottom') is an array string instead of a node, but I have absolutely no idea what a node is, neither how to change my code for it to work.
I would really appreciate any help at all !
Thanks.
const t = document.getElementById('top');
[...document.getElementsByClassName('bottom')].map(el => t.appendChild(el));
<div class="bottom">bottom 1</div>
<div class="bottom">bottom 2</div>
<div id="top">top</div>
You can try this:
const top = document.getElementById('top');
Array.from(document.getElementsByClassName('bottom')).forEach(bottom => top.appendChild(bottom))
const top = document.getElementById('top');
var elements = document.getElementsByClassName("myclass");
[].forEach.call(elements, function(el) {
el.appendChild(bottom);
});
u can also use this syntax but its not compatible with older browsers like IE:
document.querySelectorAll('.myclass').forEach(...)
var html = '';
var elems = document.getElementsByClassName('bottom');
for (let i = 0; i < elems.length; i++) {
html += elems[i].outerHTML;
}
document.getElementById('top').innerHTML = html;

How access second div with same id using querySelectorAll javascript?

Here, I have two div on my webpage both div have almost same data.
accept type attribute.
My first div attribute have type="timeline".
and Second div attribute type ="slideshow".
When my page load it only detects the first div.
But I have a condition if my div type equal to slideshow then my code run but it detects only first div.
Here is my code.
<div type='timeline' id='slide'>
<section>
<header>Title One</header>
<article>Content</article>
</section>
<section>
<header>Title Two</header>
<article>Content</article>
</section>
<section>
<header>Title Three</header>
<article>Content</article>
</section>
<section>
<header>Title Four</header>
<article>Content</article>
</section>
</div>
var divSlide = document.querySelectorAll('#slide');
var myNodeList = divSlide.length;
for(i = 0; i < myNodeList.length; i++) {
var divMain = document.getElementById("slide");
console.log(divMain);
var align = divMain.getAttribute("type");
console.log(align);
console.log(myNodeList)
if(align=='slideshow'){
console.log("my working code");
}
}
What should i do.
Help will be appreciated.
You have a few of mistakes in your code that we need to fix first.
First, you shouldn't use the same id value more than once in your code so you need to replace the id with a class (even though our code can still work with id here).
Second mistake - in your for loop you are using the wrong variable "myNodeList.length", myNodeList variable already is the length so it does not have a length property. you should instead use the divSlide variable like this:
for(i = 0; i < divSlide.length; i++)
Third mistake- in order to access the current item that is being looped over you should use the variable that holds the list (which is divSlide here)and then add to it i in brackets to indicate the current index in use, like this
var divMain = divSlide[i];
// instead of this: var divMain = document.getElementById("slide");
Fourth - you should in most cases use triple = signs to check for values. so instead of == you should use ===
this is how the code will look like finally:
var divSlide = document.querySelectorAll('#slide');
var myNodeList = divSlide.length;
document.addEventListener("DOMContentLoaded", functionName)
function functionName(){
for(i = 0; i < divSlide.length; i++) {
var divMain = divSlide[i];
var align = divMain.getAttribute("type");
if(align ==='slideshow'){
console.log("my working code");
}
}
}
and this is codepen example
You can get div by type attribute like this:
HTML
<div type='timeline' id='slide'>
this is timeline
</div>
<div type='slideshow' id='slide'>
this is slideshow
</div>
JS
$('#slide[type=slideshow]') // get div that has id='slide' and type='slideshow'
Online Demo (jsFiddle)

Why wont my onclick not remove any of my classes?

I have a huge problem here.
I can't get my onclick to work as I want .. So I hope someone here can help me.
#NiceToKnow
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="nice"></div>
<div id="cards" class="video"></div>
I want it to display: none; every of my class="nice", so you only can see class="video", but nothing happens at all.
You are selecting the elements of the class not the class itself. So you will have to loop through the elements as javascript can only edit what is in the DOM not the CSS classes that effect your elements. So getElementsByClassName returns an array of nodes in which we must loop through and hide each one. Click runsnippet below to see this work
function changeNice(){
//ASSIGN ELEMENTS TO ARRAY
elementsofClass=document.getElementsByClassName('nice');
for(i=0; i<elementsofClass.length; i++){
//HIDE SELECTED ELEMENT
elementsofClass[i].style.display='none';
}}
#NiceToKnow
<div id="cards1" class="nice">TEST 1</div>
<div id="cards2" class="nice">TEST 2</div>
<div id="cards3" class="nice">TEST 3</div>
<div id="cards4" class="video">I don't HIDE</div>
Also don't use duplicate ID. This will cause errors later when trying to select your elements.
The getElementsByClassName will return an array, so we need to iterate through the array and hide one by one.
So it is better to declare a function and define the logic inside that. Please see the example below.
window.hideAllniceClass = function () {
var elems = document.getElementsByClassName('nice');
for (var i = 0; i != elems.length; ++i) {
elems[i].style.display = "none"; // hidden has to be a string
}
}
#NiceToKnow
<div id="cards1" class="nice">Test Content</div>
<div id="cards2" class="nice">Test Content</div>
<div id="cards3" class="nice">Test Content</div>
<div id="cards4" class="video">Test Video Content</div>
DEMO
Change your code to something like that:
var elems = document.getElementsByClassName('nice');
for(var i = 0; i < elems.length; i++) {
elems[i].style.display = 'none'
}
You have to iterate on the results returned by getElementsByClassName.
jsfiddle
You can create a loop that will loop through all the nice elements and then display none like this: https://jsfiddle.net/7vf9pz8u/
<script>
function hide(){
for(ct=0; ct < 3; ct++){
document.getElementsByClassName('nice')[ct].style.display='none'
}
}
</script>
getElementsByClassName returns array of all the match elements so you will have to provide index or loop through all of them to change their property.
Change your code to this
document.getElementsByClassName('nice')[0].style.display='none'
//For every element
var e = document.getElementsByClassName('nice');
for (i = 0; i < e.length; i++) {
e[i].style.display = "none";
}
As your divs do not have unique names they are in an array cards[].
So to access a particular div you need to reference the the array to that particular div. The quoted solution should work.

Find respective divs, create new divs and append the ones that were found

so i am in a bit of a jam here and having a really hard time trying to solve this dilemma.
Here is what i am trying to do:
There is a container div (id=posts) full of other divs (name=posts).
I want it to grab in those divs and, by even/odd position, append them inside 2 other divs.
These 2 other divs are generated by javascript, one floats left and the other floats right.
Then i want it to empty the container div and insert the floating divs.
So far i have managed everything but one thing; it is only using the first found div...
Here is the HTML code:
<div id="posts">
<div name="posts">
left
</div>
<div name="posts">
right
</div>
<div name="posts">
left
</div>
<div name="posts">
right
</div>
<div name="posts">
left
</div>
<div name="posts">
right
</div>
<div name="posts">
left
</div>
<div name="posts">
right
</div>
</div>
Here is the script that i have been working with so far:
<script type="text/javascript">
var container = document.getElementById("posts");
var posts = document.getElementsByName("posts");
var rdiv = document.createElement("div");
rdiv.style.backgroundColor = "#0F0";
rdiv.style.cssFloat = "right";
rdiv.style.clear = "right";
var ldiv = document.createElement("div");
ldiv.style.backgroundColor = "#F00";
ldiv.style.cssFloat = "left";
ldiv.style.clear = "left";
for (i=0; i<posts.length; i++){
if (i%2){
rdiv.appendChild(posts[i]);
}else{
ldiv.appendChild(posts[i]);
}
}
container.innerHTML = "";
container.appendChild(rdiv);
container.appendChild(ldiv);
</script>
Now what this is doing is that it creates the left and right floating divs normally, but it only appends the first div inside both, the rest goes kabluey, can anyone help me with this one?
The main issue you are having is: appending a live element to another element, removes the element from its original location, causing problems with the loop.
To fix this, store the elements into a temporary array, appending them to their corresponding div's only once the looping is done:
var temp1 = [], temp2 = [];
for (i=0; i<posts.length; i++){
if (i%2){
temp1.push(posts[i]);
}else{
temp2.push(posts[i]);
}
}
for(var i = 0; i < temp1.length; i++) {
rdiv.appendChild(temp1[i]);
}
for(var i = 0; i < temp2.length; i++) {
ldiv.appendChild(temp2[i]);
}
You can see the full working example here: http://jsfiddle.net/FqSMw/

Change DIV order with jquery

I'm working on a client's HTML based site and need to randomly order a set of Divs on refresh of a page. I would normally handle this through PHP and a database call, but it's a static site.
So, I'm wondering if anyone knows how to randomly display a set of div's using jquery?
Here's an example:
<div class="myItems">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
and on refresh, it might change to:
<div class="myItems">
<div class="item">2</div>
<div class="item">3</div>
<div class="item">1</div>
</div>
Anyone know how to do that?
This willl do it
function reorder() {
var grp = $(".myItems").children();
var cnt = grp.length;
var temp,x;
for (var i = 0; i < cnt; i++) {
temp = grp[i];
x = Math.floor(Math.random() * cnt);
grp[i] = grp[x];
grp[x] = temp;
}
$(grp).remove();
$(".myItems").append($(grp));
}
Actually it's pretty simple:
$(".myItems").html($(".myItems .item").sort(function(){
return Math.random()-0.5;
}));
That's it!
Enjoy.
Another simple way is ...
1. create an array
2. generate a random number and check if it is Odd or Even
3. If odd, add your div to the top (shift method). If even, add your div to the bottom (push method).
4. So this way you will have your divs arranged randomly in the array.
5. Now simple join the array and append it to your Page.
var divArray = [];
for(var i=0; i<divs.length; i++){
//generate random number
if(rand_num == odd)
divArray.push( div[i] );
else
divArray.shift( div[i] );
}
$(myElem).html( divArray.join("") );

Categories

Resources