JavaScript: Node List to Array Conversion - javascript

I am trying to convert Node List to Array. I want to print the list (caption 1,...caption 5), but it prints:
[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Caption</title>
<style>
.captn {
position: absolute;
padding: 10px;
margin: 200px auto;
text-align: center;
font-family:serif, fantasy;
font-size:36px;
color: #009933;
text-decoration: none;
text-transform: uppercase;
list-style-type: none;
}
</style>
</head>
<body>
<div>
<ul id = "caption" class="captn"><li id = "caption0">caption 0</li><li id = "caption1">caption 1</li><li id = "caption2">caption 2</li><li id = "caption3">caption 3</li><li id = "caption4">caption 4</li><li id = "caption5">caption 5</li></ul>
</div>
<script>
var msg;
var cap = [];
var capList;
var f = document.getElementsByClassName("captn");
msg = f.item(0).childNodes;
b = f.item(0).childNodes.length;
var classAr = Array.prototype.slice.call(msg);
document.write(classAr);
</script>
</body>
</html>

Use querySelectorAll and select all elements under class captn with an id beginning with caption, then convert the node list to array usingArray.from and lastly map through the array, returning a new array containing only the textContent
var captions = Array.from(
document.querySelectorAll('.captn [id^="caption"]')
);
var captionsText = captions.map(function(caption) {
return caption.textContent;
});
document.write(captionsText);
<div>
<ul id="caption" class="captn">
<li id="caption0">caption 0</li>
<li id="caption1">caption 1</li>
<li id="caption2">caption 2</li>
<li id="caption3">caption 3</li>
<li id="caption4">caption 4</li>
<li id="caption5">caption 5</li>
</ul>
</div>

You can use Array.from().
Array.from(nodeList)

First of all I want to thank #Red Mercury that his answer greatly boosted my knowledge in JavaScript. I am new to Stack Overflow and don't know how to mark his answer green, if there is a gold mark, I would do for him. Thank you Red Mercury.
What I was trying to do is to put captions list as a sliding captions. It was easy to do with arrays in Javascript, but I was unable to convert node list into array, because nodelist did not work in loops with innerHtml. So here is the solution:
<html>
<head>
<title>Slide 3</title>
<style>
.captn {
padding-top: 550px;
text-align:center;
font-family:serif, fantasy;
font-size:36px;
color: #009933;
text-decoration: none;
text-transform: uppercase;
}
</style>
</head>
<body>
<div>
<ul id = "caption" class="captn">
<li id = "caption0">caption 0</li>
<li id = "caption1">caption 1</li>
<li id = "caption2">caption 2</li>
<li id = "caption3">caption 3</li>
<li id = "caption4">caption 4</li>
<li id = "caption5">caption 5</li>
<li id = "atim">item</li>
<li id = "caption6">caption 6</li>
</ul>
</div>
<script>
var i = 0;
var j = 0;
var intv = 1000;
var msg = "";
var cap = [];
var capList = "";
var captions = Array.from(
document.querySelectorAll('.captn [id ^= "caption"]')
);
var captionsText = captions.map(function(caption) {
return caption.textContent;
})
for (i = 0; i < captions.length; i++) {
cap[i] = captionsText[i] + "<br>";
msg = cap[i];
capList += msg.replace(/\,/g, "");
}
b = captions.length;
function swapImage() {
var elm = document.getElementById("caption");
elm.innerHTML = cap[j];
if(j < b - 1 ) {
j++;
}
else {
j = 0;
}
setTimeout("swapImage()", intv);
}
window.onload=swapImage;
</script>
</body>
</html>

Related

Copy selected <li> to another <ul> with js

function addSelected(clicked_id) {
// alert(clicked_id);
const ul = document.getElementById("sortable2");
const listItems = ul.getElementsByTagName("li");
// const ul2 = document.getElementById('slottable1');
// Loop through the NodeList object.
for (let i = 0; i <= listItems.length - 1; i++) {
if (listItems[i].className == "selectedli") console.log(listItems[i]);
//need to copy these <li> tags in another <ul> list
}
}
<ul id="slottable">
//need to copy selected <li> here and also remove class from those selected <li> before adding here
</ul>
output of the console:
<li id="pc_103" class="selectedli">B73</li>
<li id="pc_104" class="selectedli">B74</li>
I have successfully printed li which I want to copy to another ul in console logs but not able to find the right code to copy them to my another ul. I also need to remove the class 'selectedli' from the li before adding it to the ul 'slottable'.
It's done by creating dynamic tag inside slottable.
See below example:
const getChild = document.getElementById("sortable2").children;
function addSelected() {
let createUl = document.createElement("ul");
createUl.id = "slottable";
document.getElementById("tagBox").appendChild(createUl);
for (let i = 0; i < getChild.length; i++) {
if (getChild[i].className == "selectedli")
{
var createLi = document.createElement("li");
createLi.id = getChild[i].id
createLi.classList.add(getChild[i].classList);
createLi.innerHTML = getChild[i].textContent;
createUl.appendChild(createLi);
console.log(getChild[i]);
}
}
document.getElementById("sortable2").innerHTML = "";
}
ul
{
list-style: none;
}
#sortable2
{
padding: 10px;
background: red;
width: 30px;
}
#slottable
{
padding: 10px;
background: green;
width: 30px;
}
<body>
<div id="tagBox">
</div>
<ul id="sortable2">
<li id="pc_103" class="selectedli">B73</li>
<li id="pc_104" class="selectedli">B74</li>
</ul>
<input type="button" onclick="addSelected()" value="submit">
</body>
The appendChild() method should work.
Like this:
sortable2.appendChild(selectedli)
To remove classes, use selectedli.classList.remove(selectedli)
You looking for something like that?
It copied from one ul to the new ul and removes the class.
classList.remove and appendChild:
lis.map((el) => {
el.classList.remove('selectedli');
el.innerText += ' (copied and without classs slectedli)'
ul2.appendChild(el)
})
const btn = document.getElementById('transfer');
btn.addEventListener('click', () => {
// copy from slottable to sortable2
const ul = document.getElementById("slottable").children;
const ul2 = document.getElementById("sortable2");
let lis = Object.values(ul);
lis.map((el) => {
el.classList.remove('selectedli');
el.innerText += ' (copied and without classs slectedli)'
ul2.appendChild(el)
})
ul.innerHTML = '';
});
.green {
background: green;
}
.gray {
background: gray;
}
<ul id="slottable" class="gray">
<li id="pc_103" class="selectedli">B73</li>
<li id="pc_104" class="selectedli">B74</li>
</ul>
<ul id="sortable2" class="green"></ul>
<button id="transfer">click </button>

How to target every first two or three elements alternatively in javascript loop

I am able to target only first 2 elements with change in background color. Like, first 2 elements background to red, and next 2 elements leaving as it is. And background red to 4th and 5th element..so on. I want to target every 2 elements alternatively. How can i change a variable value dynamically which can be easy everytime like if var count = 2; every first 2 elements red...if count = 4; every first 4 elements to red and next 4 to gray....Actually I wanted to use styling with dynamic value like element[i].clientWidth etc to elements. I just used background color for this example so that i can change it later according to my styling if once it works.
<style>
ul li {
list-style-type: none;
display: inline-block;
padding: 10px;
}
<style>
<ul id="pix" class="select">
<li class="">one</li>
<li class="">two</li>
<li class="">three</li>
<li class="">four</li>
<li class="">five</li>
<li class="">six</li>
<li class="">seven</li>
<li class="">eight</li>
<li class="">nine</li>
<li class="">ten</li>
</ul>
<script>
var pix = document.getElementById("pix");
var piximgs = pix.children;
var i;
for (i = 0; i < piximgs.length; i++) {
piximgs[i].style.background = "gray";
// if (i && (i % 2 == 0)) {
piximgs[i % 2].style.background = "red";
// }
}
</script>
Here is a modified solution with a variable count:
<style>
ul li {
list-style-type: none;
display: inline-block;
padding: 20px;
background-color: gray;
}
</style>
<ul id="pix" class="select">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
<li>seven</li>
<li>eight</li>
<li>nine</li>
<li>ten</li>
</ul>
<script>
var count = 3;
Array.from(document.querySelectorAll("#pix li"))
.forEach((li,i)=>
li.style.backgroundColor=Math.floor(i/count)%2?"red":"gray");
</script>
You could have a flag - next - which you toggle whenever there is a match for the mod division, so that you track that the next element should also be red.
<style>
ul li {
list-style-type: none;
display: inline-block;
padding: 20px;
background-color: gray;
}
</style>
<ul id="pix" class="select">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
<li>seven</li>
<li>eight</li>
<li>nine</li>
<li>ten</li>
</ul>
<script>
var pix = document.getElementById("pix");
var piximgs = pix.children;
var i;
var next = false;
for (i = 0; i < piximgs.length; i++) {
if(next) {
piximgs[i].style.background = "red";
next = false;
}
if (i % 4 == 0) {
piximgs[i].style.background = "red";
next = true;
}
}
</script>

Turning an ordered list into a table

Still pretty new at JavaScript. I'm trying to write a program where you replace an ordered list with a table. The table should have 2 columns and 3 rows. The first column has the numbers(1,2,3) and the right column has the names of the games. How do I get the table to replace the list and read the list items?
Here is the JSFiddle: http://jsfiddle.net/gmpc0acd/74/
HTML
<html>
<head>
<style>
table,td
{
border:1px solid black;
}
</style>
</head>
<body>
<p>Top Games</p>
<ol id="list">
<li id="element1">Halo</li>
<li id="element2">Portal</li>
</ol>
<button onclick="addNewGame(); this.disabled=true">Insert</button>
<button onclick="tableCreate()">Replace</button>
JavaScript
function addNewGame() {
let ol = document.getElementById("list");
let li = document.createElement("li");
li.appendChild(document.createTextNode("Rocket League"));
ol.appendChild(li);
list.insertBefore(li,list.childNodes[2]);
}
function tableCreate()
{
var x = document.createElement("TABLE");
x.setAttribute("id", "myTable");
document.body.appendChild(x);
var y = document.createElement("TR");
y.setAttribute("id", "myTr");
document.getElementById("myTable").appendChild(y);
var z = document.createElement("TD");
var t = document.createTextNode("want game names in here");
z.appendChild(t);
document.getElementById("myTr").appendChild(z);
}
I have added a div 'id' - 'tryme' and inside i got the list.
so when you click 'replace' it should clear the div using innerHtml and then build the table. ( appending the 'tryme' div )
edited
To get 'ol' children use
let elmList = document.getElementById('list').children;
now you can iterate it like an array and use its 'innerText'/'innerHtml' as you like.
In my example before clearing 'tryme' i have an array with the lists children.
as displayed in the console.
let trymeDiv = document.getElementById("tryme");
trymeDiv.innerHTML = "";
var x = document.createElement("TABLE");
x.setAttribute("id", "myTable");
document.getElementById('tryme').appendChild(x)
<p>Top Games</p>
<div id="tryme">
<ol id="list">
<li id="element1">Halo</li>
<li id="element2">Portal</li>
</ol>
</div>
<html>
<head>
<style>
table,
td {
border: 1px solid black;
}
</style>
</head>
<body>
<p>Top Games</p>
<div id="tryme">
<ol id="list">
<li id="element1">Halo</li>
<li id="element2">Portal</li>
</ol>
</div>
<button onclick="addNewGame(); this.disabled=true">Insert</button>
<button onclick="tableCreate()">Replace</button>
</body>
</html>
<script>
function addNewGame() {
let ol = document.getElementById("list");
let li = document.createElement("li");
li.appendChild(document.createTextNode("Rocket League"));
ol.appendChild(li);
list.insertBefore(li, list.childNodes[2]);
}
function tableCreate() {
let elmList = document.getElementById('list').children;
arrayOfGames = [];
for ( var i = 0; i < elmList.length; i++){
arrayOfGames.push(elmList[i].innerText);
}
console.log(arrayOfGames);
let trymeDiv = document.getElementById("tryme");
trymeDiv.innerHTML = "";
var x = document.createElement("TABLE");
x.setAttribute("id", "myTable");
document.getElementById('tryme').appendChild(x);
var y = document.createElement("TR");
y.setAttribute("id", "myTr");
document.getElementById("myTable").appendChild(y);
var z = document.createElement("TD");
var t = document.createTextNode("want game names in here");
z.appendChild(t);
document.getElementById("myTr").appendChild(z);
}
</script>

how to make li (active) and visible on click of its parent li

helo , i just wanted to make my li child visibile on the click of parent li,if you want to check what i want to make check out http://technologyvs.co.uk
go to the what client say section
var selector, elems, makeactive,//this is for li one
childSelector,childElems , makeChildActive;//this is for li two
selector = ".parent li";
elems = document.querySelectorAll(selector);
makeactive = function () {
for (var i = 0; i < elems.length; i++) {
elems[i].classList.remove('active');
this.classList.add('active');
}
}
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener("mousedown", makeactive);
}
childSelector = ".child li"
childElems = document.querySelectorAll(childSelector);
makeChildActive = function (){
for (var j=0;j<childElems.length;j++){
childElems[j].classList.remove('child-active');
this.classList.add('child-active');
}
}
for(var j=0; j<childElems.length;j++){
childElems[j].addEventListener("mousedown",makeChildActive);
}
li.active{
color: red;
}
.text li{
visibility:visible;
transition: all 1s ease-in-out;
}
li.child-active{
visibility: hidden;
width: 200px;
margin-left: 25px;
font-size: 25px;
}
<!Doctype html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="custom.css" type="text/css">
</head>
<body>
<h1>heloo</h1>
<ul class="parent">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</ul>
<ul class="child">
<li>text1</li>
<li>text2</li>
<li>text3</li>
<li>text4</li>
</ul>
<script src="custom.js"></script>
</body>
</html>
Heres the simple code to do it, there are probably some edge-cases that I am not looking at but in essence this will do the trick. I added the code to a modified version of yours in the snippet below so you can see it works. I have taken out all the code that was not necessary to show how this works.
// A handler that allows us to remember the 'i' value when executing the click
function eventHandlerClosure(i){
parents[i].addEventListener('click', function(e){
// disable the currently active one
var active = document.querySelector('.child li.active');
// (if there is one)
if(active) active.className = '';
// add the active class to the newly selected child
if(children[i]) children[i].className = 'active';
}, false);
}
// select all parents and children
var parents = document.querySelectorAll('.parent li');
var children = document.querySelectorAll('.child li');
// attach the click events
for(var i = 0; i < parents.length; i++) eventHandlerClosure(i);
function eventHandlerClosure(i){
parents[i].addEventListener('click', function(e){
var active = document.querySelector('.child li.active');
if(active) active.className = '';
children[i].className = 'active';
}, false);
}
var parents = document.querySelectorAll('.parent li');
var children = document.querySelectorAll('.child li');
for(var i = 0; i < parents.length; i++) eventHandlerClosure(i);
.child li { visibility: hidden; }
.child li.active { color: red; visibility: visible; }
<ul class="parent">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
</ul>
<ul class="child">
<li>text1</li>
<li>text2</li>
<li>text3</li>
<li>text4</li>
</ul>

Javascript FAQ drop down

Im trying to create a simple FAQ drop down but for some reason it is not working. Would you mind taking a look?
Thanks guys!
CSS
#faqs h3 { cursor:pointer; }
#faqs h3.active { color:#d74646; }
#faqs div { height:0; overflow:hidden; position:relative; }
#faqs div p { padding:0; margin-bottom:15px; }
JavaScript:
$(document).ready(function() {
$('#faqs h3').each(function() {
var tis = $(this),
state = false,
answer = tis.next('div')
.hide()
.css('height','auto')
.slideUp();
tis.click(function() {
state = !state;
answer.slideToggle(state);
tis.toggleClass('active',state);
});
});
});
HTML
<div id="faqs">
<h3>This is question 1?</h3>
<div>
<p>This is the answer to question #1.</p>
</div>
<h3>This is question 2?</h3>
<div>
<p>This is the answer to question #2.</p>
</div>
</div>
The functions below can be used for what you need:
HTML
<div id="QA">
<ul>
<li>Question 1</li>
<li>Answer 1</li>
<li>Question 2</li>
<li>Answer 2</li>
</ul>
<ul>
<li>Question 3</li>
<li>Answer 3</li>
<li>Question 4</li>
<li>Answer 4</li>
</ul>
</div>
JavaScript:
<script type="text/javascript">
function toggle(tag) {
var x=document.getElementsByName(tag)[0];
var a = x.parentNode
if (a.style.display=='block'){
a.style.display='none'
}else{
a.style.display='block'
}
}
function init() {
//this function will add show hide functionality to paired list items,
//as long as the answer is a list item straight after the question list item.
//You can also have as many separate lists as you want.
//all lists must be contained within a div with id QA
var obj = document.getElementById('QA');
var elements = obj.getElementsByTagName('li');
var index = 1
//add javascript to question elements
//you could also add styling to question elements here
for (var i=0; i < elements.length; i+=2){
var element = elements[i];
element.innerHTML = "<a href='javascript:toggle(" + index + ")'>" + element.innerHTML + "</a>"
index = index + 1
}
//add bookmark to answer elements and add styling
var index = 1
for (var i=1; i < elements.length; i+=2){
var element = elements[i];
element.innerHTML = "<a name='" + index + "' id='" + index + "'></a>" + element.innerHTML
index = index + 1
element.style.padding = '0px 0px 10px 20px' //add indent to answer
element.style.listStyleType = 'none' //remove bullet
element.style.display = 'none' //hide answer element
}
}
window.onload = init;
</script>

Categories