I'm new to Javascript and I'm trying to figure out why the .nextElementSibling is not grabbing the next element in the listHere's my HTML structure:
<div class="container">
<div id="User1" class="area-left">
<h1>User 1: Sylvr</h1><br>
</div>
<div id="ItemTree" class="area-center">
<h1>Bolt: Item Tree</h1><br>
<ul class="col_ul">
<li><span>[+]</span> Bolt
<ul>
<li>Zap</li>
<li><span>[+]</span> Gift of Bolt</li>
<ul>
<li>Icy Runestone</li>
<li>Superior Sigil of Air</li>
<li><span>[+]</span> Gift of Metal</li>
<li><span>[+]</span> Gift of Lightning</li>
</ul>
<li><span>[+]</span> Gift of Mastery</li>
<li><span>[+]</span> Gift of Fortune</li>
</ul>
</li>
</ul>
</div>
<div id="User2" class="area-right">
<h1>User 2: Gylen</h1><br>
</div>
</div>
<div id="GuildBank" class="container-bottom">
<h1></h1>
</div>
Here's the script that I'm using:
<script>
window.onload = function () {
var li_ul = document.querySelectorAll(".col_ul li ul");
for (var i = 0; i < li_ul.length; i++) {
li_ul[i].style.display = "none"
};
var exp_li = document.querySelectorAll(".col_ul li > span");
for (var i = 0; i < exp_li.length; i++) {
exp_li[i].style.cursor = "pointer";
exp_li[i].onclick = showul;
};
function showul () {
nextul = this.nextElementSibling;
if(nextul.style.display == "block")
nextul.style.display = "none";
else
nextul.style.display = "block";
}}
</script>
For some reason, the this.nextElementSibling part works once but then gives me a null value for any of the other nested lists. Any help would be much appreciated, thanks.
You are getting null on this.nextElementSibling because there is no next sibling that's an element!!
<li><span>[+]</span> Gift of Bolt</li>
If you look at this line you will find that you have already closed the <li> tagand hence there is no sibling for the <span> and you get a null. To fix this, simply wrap the <ul> next to the <li> inside <li>...</li>.
Check this solution on JSFiddle
Related
I put a main div in it, but for loop broke after one child recursion ends, what should I do to check every children with recusion?
here is output:
direct: DIV main
direct: DIV basicFrame
direct: DIV basicFrame__name
direct: SPAN name
and loop broke after a first recursion ends.
as you can see, after first recursion (main -> basicFrame -> basicFrame__name -> name)
its loop broke (not passed to next children, infoFrame)
output supposed to print these too
direct: DIV infoFrame
direct: SPAN info
..and etc
this is js code
var typeDisplay = async function (target, findType) {
if (findType == "id")
{
target = document.getElementById(target);
target = [target];
}
else if (findType == "direct")
{
console.log("direct: " + target.tagName + " " + target.className); //output maker
target = [target];
}
for (let ind = 0; ind < target.length; ind++)
{
const label = target[ind]; //get label from selection
if (label != null)
{
for (let ind; ind < label.children.length; ind++); //get children of label
{
const subLabel = label.children[ind];
if (typeof(subLabel) == "object")
{
// doing some work
typeDisplay(subLabel, "direct"); //recursion to it's children
}
}
}
}
return;
};
and this is input html form for js script
<div class="main" id="typeTarget"> <!--first parameter of function-->
<div class="basicFrame">
<div class="basicFrame__name">
<span class="name">
wow
</span>
<button class="pen">
<i class="fas fa-file-image"></i>
</button>
</div>
<div class="faceFrame">
<img src="image.png" alt="no image" title="image">
</div>
</div class="infoFrame">
<span class="info">
Info :
<br>
<ul>
<li>this is list</li>
<li>list :
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
</li>
</ul>
</span>
</div>
<!--load java script-->
<script>
typeDisplay("typeTarget", "id");
</script>
Need help with using js script.
<ul class="producers-links">
<li class="section_All active-producer">A-Z</li>
<li class="section_0-9">0-9</li>
<li class="section_A">A</li>
<li class="section_B">B</li>
<li class="section_C">C</li>
</ul>
And
<div class="producers-list">
<div class="producers-container" id="producers-0-9">
<div class="break-producers">0-9</div>
</div>
<div class="producers-container" id="producers-A">
<div class="break-producers">A</div>
Producer 1
</div>
<div class="producers-container" id="producers-B">
<div class="break-producers">B</div>
Producer 2
</div>
<div class="producers-container" id="producers-C">
<div class="break-producers">C</div>
Producer 3
</div>
</div>
How to make js script that will allow user click on list element then all divs from producers-list will get display:none without this one which was clicked at list.
var producersList = document.querySelectorAll('ul.producers-links>li');
var producersLists = document.querySelectorAll('div.producers-list>div.producers-container');
for (var i = 0; i < producersList.length; i++) {
producersList[i].addEventListener('click', function () {
document.querySelector('.active-producer').classList.remove('active-producer');
this.classList.add('active-producer');
var index = 0,
length = producersList.length;
for (; index < length; index++) {
producersLists[index].style.display = "none";
}
});
}
This allow me to hide all elements from producers-container but i don't know how to show only one element clicked before at list.
First of all you should use classes instead of id in the second list in order to have the ability to add more procedures in the future
try this:
<ul class="producers-links">
<li id="section_All" class="active-producer">A-Z</li>
<li id="section_0-9">0-9</li>
<li id="section_A">A</li>
<li id="section_B">B</li>
<li id="section_C">C</li>
</ul>
<div class="producers-list">
<div class="producers-container section_0-9 section_All">
<div class="break-producers">0-9</div>
</div>
<div class="producers-container section_A section_All">
<div class="break-producers">A</div>
Producer 1
</div>
<div class="producers-container section_B section_All">
<div class="break-producers">B</div>
Producer 2
</div>
<div class="producers-container section_C section_All">
<div class="break-producers">C</div>
Producer 3
</div>
</div>
var producersList = document.querySelectorAll('ul.producers-links > li');
var producersLists = document.querySelectorAll('.producers-container');
for (var i = 0; i < producersList.length; i++) {
producersList[i].addEventListener('click', function () {
document.querySelector('.active-producer').classList.remove('active-producer');
this.classList.add('active-producer');
for (var index = 0; index < producersLists.length ; index++) {
var currElement = producersLists[index];
var hide = !currElement.classList.contains(this.id);
producersLists[index].style.display = hide? "none" : "block";
}
});
}
On click, you can sequentially:
- hide all
- select the one having the same end of id than the textContent of the clicked item (or select all if text is A-Z)
var producersList = document.querySelectorAll('ul.producers-links>li');
var producersLists = document.querySelectorAll('div.producers-list>div.producers-container');
// add eventlistener...
producersList.forEach(x => {
x.addEventListener("click", x => {
hideAll();
document.querySelector('.active-producer').classList.remove('active-producer');
x.target.classList.add('active-producer');
const txt = x.target.textContent;
selectForText(txt);
});
});
// hide/show all...
function hideAll(bShow) {
const cl = bShow === true?"block":"none";
producersLists.forEach(x => x.style.display = cl);
}
// select for text...
function selectForText(txt) {
if(txt === "A-Z") {
// select all...
hideAll(true);
return;
}
// the [...nodelist] part allows to 'cast' to proper array, and to have access to find() function...
const found = [...producersLists].find(q => q.id.split("producers-")[1] === txt);
if(found) {
found.style.display = "block";
}
else {
// ???
}
}
.active-producer {
color: #19f;
}
<ul class="producers-links">
<li class="section_All active-producer">A-Z</li>
<li class="section_0-9">0-9</li>
<li class="section_A">A</li>
<li class="section_B">B</li>
<li class="section_C">C</li>
</ul>
And
<div class="producers-list">
<div class="producers-container" id="producers-0-9">
<div class="break-producers">0-9</div>
</div>
<div class="producers-container" id="producers-A">
<div class="break-producers">A</div>
Producer 1
</div>
<div class="producers-container" id="producers-B">
<div class="break-producers">B</div>
Producer 2
</div>
<div class="producers-container" id="producers-C">
<div class="break-producers">C</div>
Producer 3
</div>
</div>
I'm trying to make the rest of my chat room app disabled while a modal is open. I've been using element.disable = true to disable the buttons and this has worked. I have a ul where each li is the name of a chat room that is clickable and opens up its respective chat room in another container. I'm trying to disable the lis using the same disable.true method. I'm using a for loop to iterate through the array of lis, but it isn't working.
I used console.log to view the variable with the array stored in it (var lis) as well as the console.log(lis.length). The console shows that the array has a length of 5 but returns lis.length as 0.
Would be much appreciated if someone could tell me what I'm doing incorrectly.
HTML:
<div class"home-template" id="home">
<div class="rooms-container">
<h1 class="app-title">Bloc Chat</h1>
<ul id="rooms-list">
<li class="room-item" id="room-item" ng-repeat="chat in home.chatRooms">
{{ chat.$value }}
</li>
</ul>
<button class="btn btn-warning" id="new-room-button" type="button" ng-click="home.open()">New room</button>
<button class="btn btn-warning" id="delete-cookies-button" type="button" ng-click="home.deleteCookies()">Delete Cookie for testing</button>
</div>
<div class="messages-container">
<h1 class="current-room" ng-bind="home.activeRoom"></h1>
<ul class="messages-list">
<li class="message-bubble" ng-repeat="message in home.messages">
<div class="username">{{ message.username }}</div>
<div class="sentAt">{{ message.sentAt }}</div>
<div class="content">{{ message.content }}</div>
</li>
</ul>
</div>
</div>
JavaScript in a home controller:
home.cookieDisplay = $cookies.get('blocChatCurrentUser');
var modals = document.getElementsByClassName('modal');
var lis = document.getElementsByClassName('room-item');
var newButton = document.getElementById('new-room-button');
var delButton = document.getElementById('delete-cookies-button');
if (modals.length === 0) {
newButton.disabled = false;
delButton.disabled = false;
for (var i = 0; i < lis.length; i++) {
lis[i].disabled.false;
}
} else if (modals.length !== 0) {
newButton.disabled = true;
delButton.disabled = true;
for (var i = 0; i < lis.length; i++) {
// lis[i].setAttribute('display', 'none');
lis[i].disabled.true;
}
}
Here's what my console looks like:
You can't disable the li itself.
You can either disable the anchor tag (a) in it for example like this (refernece):
document.getElementById("tab_c").childNodes[0].onclick = function() {return false;};
Or you can set pointer-events:noneas it has been done using CSS (reference):
.disabled {
pointer-events:none; //This makes it not clickable
opacity:0.6; //This grays it out to look disabled
}
What I need to get all value of multiple li from the HTML code.
<div class="row">
<div style="margin-left:11px">
<strong>Detail Product</strong>
</div>
<div class="col-sm-12">
<ul class="item-highlights">
<li>4G LTE</li>
<li>Dual Sim</li>
<li>RAM 1GB</li>
</ul>
</div>
<div class="col-sm-12">
<ul class="item-highlights">
<li>ROM 8GB</li>
<li>Screen 5.5</li>
<li>Warranty 1 Year</li>
</ul>
</div>
This how i get with javascript:
var test = document.getElementById('block-system-main').getElementsByClassName('item-highlights item-highlights')[0].innerHTML;
and i get the answer:
<li>4G LTE</li><li>Dual Sim</li><li>RAM 1GB</li>
Heres an easy to understand answer.
var items = document.querySelectorAll( ".item-highlights li");
var values = [];
for( var n = 0; n < items.length; n++)
values.push( items[n].innerHTML);
If you know css then its simple to change the call to "querySelectorAll" as it is only comparing things through the same way css does, So you can change it however you like.
Expanding on #Tushar comment:
var test = '';
[].forEach.call( document.querySelectorAll('#block-system-main .item-highlights'), function(item) { return test += item.innerText; })
Check demo - Fiddle.
You should be able to select every li using querySelectorAll and then map those values. It would look like this:
var listItems = Array.prototype.slice.call(document.querySelectorAll('li'));
var vals = listItems.map(function (item) {
return item.innerHTML;
});
Example:
http://jsbin.com/zumewidoyo/edit?html,js,console
If you want to select every li element you can do something like this:
Live Preview
HTML
<div class="row">
<div style="margin-left:11px">
<strong>Detail Product</strong>
</div>
<div class="col-sm-12">
<ul class="item-highlights">
<li>4G LTE</li>
<li>Dual Sim</li>
<li>RAM 1GB</li>
</ul>
</div>
<div class="col-sm-12">
<ul class="item-highlights">
<li>ROM 8GB</li>
<li>Screen 5.5</li>
<li>Warranty 1 Year</li>
</ul>
</div>
JavaScript
//store the list elements
var lists = document.getElementsByTagName('li');
//array to hold the li elements
var liElements = [];
//loop through the lists
for (var i = 0; i < lists.length; i++) {
//add the li element values to the array
liElements.push(lists[i].innerHTML);
}
//show the results
alert(liElements.join("\n"));
The function getElementsByClassName return an array. Just iterate over it instead of using the "[0]" to get only the first element.
function getValue() {
var test = document.getElementById('block-system-main').getElementsByClassName('item-highlights');
var array = [];
for (var i = 0; i < test.length; i++) {
var liList = test[i].getElementsByTagName('li');
for (var j = 0; j < liList.length; j++)
array.push(liList[j].innerHTML);
}
return array;
}
alert(getValue());
<div id="block-system-main">
<div class="row">
<div style="margin-left:11px">
<strong>Detail Product</strong>
</div>
<div class="col-sm-12">
<ul class="item-highlights">
<li>4G LTE</li>
<li>Dual Sim</li>
<li>RAM 1GB</li>
</ul>
</div>
<div class="col-sm-12">
<ul class="item-highlights">
<li>ROM 8GB</li>
<li>Screen 5.5</li>
<li>Warranty 1 Year</li>
</ul>
</div>
</div>
</div>
I'm trying to get my javascript function that creates a html table in my content div on my website. The problem is, that it is not displayed inside the div but under it. How can I put it inside?
<div id="tab-container" class='tab-container'>
<ul class='etabs'>
<li class='tab'>Start</li>
<li class='tab'>Schichtplan</li>
<li class='tab'>Rechnung</li>
<li class='tab'>Kontakt</li>
</ul>
<div class='panel-container'>
<div id="tabs1-start">
Test page 1
</div>
<div id="tabs1-schicht">
<script type"text/javascript">
tableCreate();
</script>
</div>
<div id="tabs1-rechnung">
Test page3
</div>
<div id="tabs1-kontakt">
Test page4
</div>
</div>
</div>
This is my basic website with the navigationbar. When I run it with xampp the js function tableCreate(); is displayed after the panel-container div closes.
Here is my js code:
function tableCreate(){
//var schicht=["datum","schicht","schicht","schicht","dispo","schicht","schicht","schicht","schicht","schicht","schicht","dispo"];
var body=document.getElementsByTagName('body')[0];
var tbl=document.createElement('table');
tbl.style.width='100%';
tbl.setAttribute('border','1');
var tbdy=document.createElement('tbody');
for(var i=0;i<28;i++){
var tr=document.createElement('tr');
for(var j=0;j<12;j++){
if(i==27 && j==12){
break
} else {
var td=document.createElement('td');
td.appendChild(document.createTextNode('schicht'))
tr.appendChild(td)
}
}
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
body.appendChild(tbl)
Thanks in advance.
Use document.getElementById('tabs1-schicht'); instead of document.getElementsByTagName('body')[0];
Replace
body.appendChild(tbl)
with
var div4=document.getElementById("tabs1-kontakt");
div4.appendChild(tbl);
You code should be something like this:
<html>
<head>
<script>
function tableCreate() {
//var schicht=["datum","schicht","schicht","schicht","dispo","schicht","schicht","schicht","schicht","schicht","schicht","dispo"];
var body = document.getElementById('tabs1-schicht');
var tbl = document.createElement('table');
tbl.style.width = '100%';
tbl.setAttribute('border', '1');
var tbdy = document.createElement('tbody');
for (var i = 0; i < 28; i++) {
var tr = document.createElement('tr');
for (var j = 0; j < 12; j++) {
if (i == 27 && j == 12) {
break
} else {
var td = document.createElement('td');
td.appendChild(document.createTextNode('schicht'))
tr.appendChild(td)
}
}
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
body.appendChild(tbl)
}
</script>
</head>
<body>
<div id="tab-container" class='tab-container'>
<ul class='etabs'>
<li class='tab'>Start</li>
<li class='tab'>Schichtplan</li>
<li class='tab'>Rechnung</li>
<li class='tab'>Kontakt</li>
</ul>
<div class='panel-container'>
<div id="tabs1-start">
Test page 1
</div>
<div id="tabs1-schicht">
<script>
tableCreate();
</script>
</div>
<div id="tabs1-rechnung">
Test page3
</div>
<div id="tabs1-kontakt">
Test page4
</div>
</div>
</div>
</body>
</html>
#astro I looked up your suggestion. I changed my table creation to something simular to stackoverflow.com/a/1413984/4344444. It works now. thanks a lot =D