Hide elements if its childNodes are empty - javascript

My goal is to append button for hiding replies on comments and don't show this button if there are no replies for each comment.
Please, don't blame me so much for this code because I'm newbie and learning hard.
Here's the code:
var replies = document.querySelectorAll(".comments_list > .comment_item > .reply_comments"); //should check if .childNodes.length === 1
var comments = document.querySelectorAll(".comments_list > .comment_item");
var combodys = document.querySelectorAll(".comments_list > .comment_item > .comment_body");
addBtn();
function addBtn() {
for (var i = 0; i < comments.length; i++) {
var combody = combodys[i];
var btn = document.createElement("input");
btn.type = "button";
btn.className = "hidereplies";
btn.value = "show replies";
combody.appendChild(btn); //don't show if replies.childNodes.length === 1
}
}
After button added I want to check if comments contain replies and hide button when replies block is empty. Tried to check childNodes method and faced with problem that I have to "+1" to current "hidereplies" button value:
if (replies[6 + 1].childNodes.length === 1) {
document.querySelectorAll(".hidereplies")[6].style.display = "none";
}
So, for now I don't know how to cycle through all comments and hide "hidereplies" button if there are no replies.
Hope for a help to solve this problem in plain Javascript.
Thanks in advance!

Try
function getChildrenByClassName(el, className){
var children = [];
for (var i = 0; i < el.childNodes.length; i++) {
if (el.childNodes[i].className == className) {
children.push(el.childNodes[i]);
}
}
return children;
}
function addBtn() {
var comments = document.querySelectorAll(".comments_list > .comment_item"), comment, combody;
for (var i = 0; i < comments.length; i++) {
comment = comments[i];
var replies = comment.querySelectorAll('.reply_comments .comment_body');
if(replies.length > 0){
combody = getChildrenByClassName(comment, 'comment_body')[0];
if(combody){
var btn = document.createElement("input");
btn.type = "button";
btn.className = "hidereplies";
btn.value = "show replies";
combody.appendChild(btn); //don't show if replies.childNodes.length === 1
}
}
}
}
addBtn();
Demo: Fiddle

Related

Javascript passing info from one function to another

I've created a JS function that hides a certain amount of breadcrumbs if there are too many. They are replaced by a button (ellipsis), when you click the button the hidden breadcrumbs are revealed.
The Problem: I loop through the breadcrumbs to see if there are enough to hide. If there are I hide them. But I can't figure out how to then call the code to create the button. If I call the button code in the loop I get more than 1 button generated.
Right now the button will always appear whether there are enough breadcrumbs to hide or not.
In my mind, I would have the for loop with the if statement return true to what would then be the button function. But I can't figure out how to do this. Please offer any pointers for restructuring this code if you can.
Here's a Codepen: https://codepen.io/sibarad/pen/GRvpEbp
Basic HTML:
<nav aria-label="breadcrumb">
<ol class="c-breadcrumb mb-7 md:mb-8">
<li class="c-breadcrumb-item">
Breadcrumb 1
</li>
<li class="c-breadcrumb-item">
Breadcrumb 2
</li>
<li class="c-breadcrumb-item">
Longer Breadcrumb Name 03
</li>
</ol>
</nav>
Javascript:
function breadcrumb() {
// Target specific breadcrumbs, not 1st or last 2
let hiddenbreadcrumb = document.querySelectorAll('.c-breadcrumb-item:nth-child(1n+2):nth-last-child(n+3)');
// Loop through select breadcrumbs, if length is greater than x hide them.
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
if(hiddenbreadcrumb.length >= 3) {
hiddenbreadcrumb[i].style.display = "none";
}
}
// This would be the button function, but I don't know how to engage this only if the if statement above was met.
let li = document.createElement('li');
li.className = 'c-breadcrumb-item';
let ellipbutton = document.createElement('button');
ellipbutton.type = 'button';
ellipbutton.innerHTML = '...';
ellipbutton.className = 'c-breadcrumb_btn u-btn-clear';
ellipbutton.onclick = function() {
console.log("clicked");
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "flex";
}
li.style.display = "none";
};
li.appendChild(ellipbutton);
let container = document.querySelector('.c-breadcrumb-item:first-child');
container.insertAdjacentElement("afterend", li);
}
breadcrumb();
We can refactor your code slightly to achieve this - the if statement which checks whether there are more than 3 breadcrumbs doesn't need to be inside the for loop - it's redundant to keep checking the same value multiple times.
If we move that outside the loop then it can
a) prevent unnecessary looping when there aren't enough breadcrumbs, and
b) wrap around the button creation code as well, which should solve your problem.
For example:
if (hiddenbreadcrumb.length >= 3) {
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "none";
}
let li = document.createElement('li');
li.className = 'c-breadcrumb-item';
let ellipbutton = document.createElement('button');
ellipbutton.type = 'button';
ellipbutton.innerHTML = '...';
ellipbutton.className = 'c-breadcrumb_btn u-btn-clear';
ellipbutton.onclick = function() {
console.log("clicked");
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "flex";
}
li.style.display = "none";
};
let container = document.querySelector('.c-breadcrumb-item:first-child');
container.insertAdjacentElement("afterend", li);
}
It looks like some small initialization issues. This should correct it:
Change this:
let hiddenbreadcrumb = document.querySelectorAll('.c-breadcrumb-item:nth-child(1n+2):nth-last-child(n+3)');
// Loop through select breadcrumbs, if length is greater than x hide them.
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
if(hiddenbreadcrumb.length >= 3) {
hiddenbreadcrumb[i].style.display = "none";
}
}
to this:
let hiddenbreadcrumb = document.querySelectorAll('.c-breadcrumb-item');
if(hiddenbreadcrumb.length < 3)
return
for (var i = 1; i < hiddenbreadcrumb.length - 1; i++) {
hiddenbreadcrumb[i].style.display = "none";
}
Try this... it allows 3 li items as item1 ... item2ndLast, itemLast
(function () {
"use strict";
function breadcrumb() {
let hiddenbreadcrumb = document.querySelectorAll(".c-breadcrumb-item:nth-child(1n+2)");
if (hiddenbreadcrumb.length <= 3) return;
for (var i = 1; i < hiddenbreadcrumb.length - 1; i++) {
hiddenbreadcrumb[i].style.display = "none";
}
let li = document.createElement("li");
li.className = "c-breadcrumb-item";
let ellipbutton = document.createElement("button");
ellipbutton.type = "button";
ellipbutton.innerHTML = "...";
ellipbutton.className = "c-breadcrumb_btn u-btn-clear";
ellipbutton.onclick = function () {
console.log("clicked");
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "flex";
}
li.style.display = "none";
};
li.appendChild(ellipbutton);
let container = document.querySelector(".c-breadcrumb-item:first-child");
container.insertAdjacentElement("afterend", li);
}
breadcrumb();
})();

How to change the background of multiple buttons when reading from Session Storage

I'm trying to get all the buttons on this page begin neutral and then turn red when the page loads and finally turn green whenever a checklist on the next page is completed. I can only seem to get the first button to work but the others aren't doing anything. Any advice? All other attempts are in the comments.
function initial(){
if (localStorage.getItem("run") == null) {
/* var form = document.getElementById("myForm");
var idObject = {};
idObject[form.elements[0].id].("false");
for(var i = 1; i < form.length ; i++){
idObject[form.elements[i].id].push("false");
}
sessionStorage.setItem("savedIds",JSON.stringify(idObject)); */
/* var ids = [ {area:"kitchen",done:"true"},
{area:"livingroom",done:"false"},
{area:"bathroom",done:"false"},
{area:"dining",done:"false"},
{area:"bredroom",done:"false"}]; */
/* var ids = {"kitchen":false,
"livingroom":true,
"bathroom":false,
"dining":false,
"bedroom":false}; */
var ids = [false,false,false,false,false];
sessionStorage.setItem("savedIds",JSON.stringify(ids));
localStorage.setItem("run", true);
}
}
function loader(){
var form = document.getElementById("myForm");
var obj = JSON.parse(sessionStorage.getItem("savedIds"));
for(var i = 0;i < 5;i++){
if(obj[i] == true){
document.getElementById(form.elements[i].id).style.backgroundColor = "green";
return false;
}else{
document.getElementById(form.elements[i].id).style.backgroundColor = "red";
return false;
}
}
}
So I have mentioned this on the forum but I haven't been able to quite solve this. It is killing me since I have spent days on this alone. Any advice would be great!
Something to note, this is the function on the checklist page that reads the checklist and turns the buttons to green. There is also an issue where the color doesn't change the green because of a "VM915:1 Uncaught SyntaxError: Unexpected token , in JSON at position 4"
function checkTasks(form){
var count = 0;
for(var i = 0;i<form.task.length;i++){
if(form.task[i].checked){
count++;
}
}
if(count == form.task.length){
var obj = JSON.parse(sessionStorage.getItem("savedIds"));
obj[0] = true;
sessionStorage.setItem("savedIds",obj);
//sessionStorage.setItem("kitchen","true");
window.open("http://localhost:8080/Project/home.html","_self");
}else{
alert("You have not completed all the tasks! Please check all the boxes to indicate you have completed the tasks. If there is an issue, write it in the other box.");
}
}
function initial(){
if (localStorage.getItem("unitrun") === null) {
var form = document.getElementById("myForm");
var tot = form.length;
for(var i = 0; i < tot ; i++){
sessionStorage.setItem(form.elements[i].id,"false");
}
localStorage.setItem("unitrun", true);
}
}
function loader(){
var form = document.getElementById("myForm");
var tot = form.length;
for(var i = 0; i < tot ; i++){
if(sessionStorage.getItem(form.elements[i].id) === "true"){
document.getElementById(form.elements[i].id).disabled = true;
}else{
document.getElementById(form.elements[i].id).disabled = false;
}
}
}
function checkTasks(form){
var count = 0;
var list = document.getElementById("tasks").getElementsByTagName("li");
var tot = list.length;
for(var i = 0;i < tot;i++){
if(form.task[i].checked){
count++;
}
}
if(count == tot){
sessionStorage.setItem("kitchen","true");
window.open("http://localhost:8080/Project/home.html","_self");
}else{
alert("You have not completed all the tasks! Please check all the boxes to indicate you have completed the tasks. If there is an issue, write it in the other box.");
}
}
The best way to do this (IMO) is maximizing the power of CSS
for example:
CSS
button.myBtn {
color: initial;
}
body.loaded button.myBtn {
color: red;
}
body.processed button.myBtn {
color: green;
}
Add class myBtn to all of the buttons whose color you want to change. Then in your javascript all you need to do is add class loaded and class processed to document.body to get all of your buttons' colors to change.

Javascript toggle menu opening but not closing

I'm in the process of learning JS and have made a collapsable navbar. I got the menu to open upon clicking the button, but it will not close. I've searched this site for answers but anything I've found refers to Bootstrap. This is just pure JS. I've also looked over my code for hours trying to spot a syntax error or anything that could be going wrong. Any help would be greatly appreciated!
Here is my code:
let toggleNavStatus = false;
let toggleNav = function() {
let getSidebar = document.querySelector(".nav-sidebar");
let getSidebarUl = document.querySelector(".nav-sidebar ul");
let getSidebarTitle = document.querySelector(".nav-sidebar span");
let getSidebarLinks = document.querySelectorAll(".nav-sidebar a");
if (toggleNavStatus === false) {
getSidebarUl.style.visibility = "visible";
getSidebar.style.width = "315px";
getSidebarTitle.style.opacity = "0.5";
let arrayLength = getSidebarLinks.length;
for (i = 0; i < array.length; i++) {
getSidebarLinks[i].style.opacity = "1";
}
toggleNavStatus = true;
}
else if (toggleNavStatus === true) {
getSidebar.style.width = "50px";
getSidebarTitle.style.opacity = "0";
let arrayLength = getSidebarLinks.length;
for (i = 0; i < array.length; i++) {
getSidebarLinks[i].style.opacity = "0";
}
getSidebarUl.style.visibility = "hidden";
toggleNavStatus = false;
}
}
In your for-loops you need to change array.length to arrayLength.
See this codepen

createElement (input) with Id ;with counter ,Id1,Id2,Id3

i trie to generate dynamic Input fields with unique Ids but i stucked:
function addTxtBx(){
var txtBxHolder = document.getElementById('txtBoxHolder');
var newTxtBx = document.createElement('input');
newTxtBx.type = 'text';
var i=1;
//newTxtBx.id = document.getElementById("txtWaypoint"[i])
if(i<10){
newTxtBx.id = "txtWaypoint"+[i];
i++;
break;
}
txtBoxHolder.appendChild(newTxtBx);
}
i tried it with a for() but always got Id='name'9,
i know im an trainee. :)
I think so where you miss to loop it properly.
function addTextBox(ops) {
var no = document.getElementById('id1').value;
for (var i = 0; i < Number(no); i++) {
var text = document.createElement('input');
text.type = "text";
text.id = "txtWaypoint" + i; //id created dynamically
document.getElementById('divsection').appendChild(text);
}
}
Try it

Xpages - Remove selected items from an array

Does anyone know how to remove selected items from an array?
var view:NotesView = getComponent("viewPanel2");
var UtbildningarArray = new Array();
viewScope.col = view.getSelectedIds();
if (viewScope.col.length > 0){
for (i=0; i<viewScope.col.length; i++){
var docid = viewScope.col[i];
if (docid != null) {
var doc = database.getDocumentByID(docid);
UtbildningarArray.push(doc.getItemValueString("Namn"))
}
}
}
document1.removeItemValue("Utbildningar",UtbildningarArray);
document1.save();
I have tried, removeEntry and splice but I don't get it work.
Thanks,
Jonas
Edit:
You are right, have added this in the code:
var view:NotesView = getComponent("viewPanel2");
var UtbildningarArray = new Array();
var UtbildningarArray = new Array();
var FieldUtbArray = new Array(getComponent('inputHidden1').getValue());
viewScope.col = view.getSelectedIds();
if (viewScope.col.length > 0){
for (i=0; i<viewScope.col.length; i++){
var docid = viewScope.col[i];
if (docid != null) {
var doc = database.getDocumentByID(docid);
UtbildningarArray.push(doc.getItemValueString("Namn"))
}
}
}
document1.replaceItemValue("Utbildningar",FieldUtbArray.slice(UtbildningarArray));
document1.save();
I'm saving what the user selected in a hidden input, and when the user clicks the "Remove programs" button I display the selected courses in the view. Then should the user be able to click a checkbox and remove the selected course(s). Now when I save nothing happens.
I think you need to show more what you want to remove.
Below you have to code snippets that will remove an entry from an js array.
http://openntf.org/XSnippets.nsf/snippet.xsp?id=remove-an-entry-from-an-array-of-strings
http://dontpanic82.blogspot.se/2010/10/code-snippet-arraysplice-according-to.html
I got it work!
for (var i = 0; i < FieldUtbArray.length; i++) {
found = false;
// find a[i] in b
for (var j = 0; j < UtbildningarArray.length; j++) {
if (FieldUtbArray[i] == UtbildningarArray[j]) {
found = true;
break;
}
}
if (!found) {
result.push(FieldUtbArray[i]);
}
}

Categories

Resources