JavaScript Function onClick only works once - javascript

I have been working on learning JavaScript, and I have a piece of JavaScript which is supposed to open a hamburger menu on the top left of the page.
The thing is, the code works once, but for some reason the if{} statement is not working the second time:
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 = "272px";
getSidebarTitle.style.opacity = "0.5";
let arrayLength = getSidebarLinks.length();
for(let i = 0; i < arrayLength; 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(let i = 0; i < arrayLength; i++){
getSidebarLinks[i].style.opacity = "0";
}
getSidebarUl.style.visibility = "hidden";
toggleNavStatus = false;
}
}
JavaScript Code
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html" />
<meta name="author" content="XeroXipher" />
<link rel="stylesheet" type="text/css" href="styles.css"/>
<title>End World</title>
</head>
<body>
<nav class="nav-main">
<div class="btn-toggle-main" onclick="toggleNav()"></div>
<ul>
<li>Home</a></li>
<li>Cities</li>
<li>Forums</li>
<li>Account Settings</li>
</ul>
</nav>
<aside>
<nav class="nav-sidebar">
<ul>
<li><span>Navigation</span></li>
<li>Cities</li>
<li>Forums</li>
<li>Account Settings</li>
<li>Logout</li>
</ul>
</nav>
</aside>
</body>
<script src="main.js"></script>
</html>
HTML Code
I have a good understanding on how if, else works and I cannot figure out what isn't working.
It seems to run the if(false) correctly but not run else if(true);"
I have a good understanding on how if, else works and I cannot figure out what isn't working.
It seems to run the if(false) correctly but not run else if(true);"

There is a bug if you take a look at the console when trying to get the length.
let arrayLength = getSidebarLinks.length();
just remove the parentheses after the 'length'
let arrayLength = getSidebarLinks.length;

let arrayLength = getSidebarLinks.length();
length is not a method. So, no need of function call.
On removing the parantheses, the click me toggles elements visible and invisible.

I hope this might helpful for your question. Instead of using if/else we can use javascript toggle. The thing your code not working was, one is tpe validation and elment will loss visiblity after first click.
let toggleNav = function() {
let getUl = document.querySelector(".toggle-ul");
getUl.classList.toggle("visible");
}
.btn-toggle-main{
cursor:pointer;
}
.toggle-ul{
display:none;
}
.toggle-ul.visible{
display:block;
}
<nav class="nav-main">
<div class="btn-toggle-main" onclick="toggleNav()">Click Me</div>
<ul class="toggle-ul visible">
<li>Home</a></li>
<li>Cities</li>
<li>Forums</li>
<li>Account Settings</li>
</ul>
</nav>

Try to replace
toggleNavStatus = true;
by
return true;
and
toggleNavStatus = false;
by
return false;
I'm not absolutely sure about it, but I guess as your function lacks a defined return value, it returns a standard value in the end that is assigned to toggleNavStatus, overwriting the value you set before.

Related

Using for loop for delete button

Good evening guys. I am learning javascript. After learning some basics, I decided to make TODO LIST and got the todo list code from the internet. But I have a question on my mind. My code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div>
<h2>ToDo</h2>
<input type="text" id="inputum" />
<button onclick="fonksiyonum()">Ekle</button>
</div>
<ul id="yeniUl"></ul>
<script>
function fonksiyonum() {
var liEkle = document.createElement('li');
var inputtaYazanlar = document.getElementById('inputum').value;
var textim = document.createTextNode(inputtaYazanlar);
liEkle.appendChild(textim);
document.getElementById('yeniUl').appendChild(liEkle);
document.getElementById('inputum').value = '';
var button = document.createElement('BUTTON');
var hiks = document.createTextNode('\u00D7');
button.appendChild(hiks);
liEkle.appendChild(button);
button.className = 'close';
var close = document.getElementsByClassName('close');
for (i = 0; i < close.length; i++) {
close[i].onclick = function () {
var div = this.parentElement;
div.style.display = 'none';
};
}
}
</script>
</body>
</html>
As I understand it, for (i = 0; i < close.length; i++) is used to get the button.close[i].onclick = function () shows the function that will run when the button is pressed. But why close[i] what does the letter 'i' mean here? After that there is var div = this.parentElement. I don't understand this.parentElement. I would be happy if someone could explain the concept of parent element to me.
close.length is actually List/Array of all the Buttons. You can tell by the Elements in getElementsByClassName.
So you are looping through all the Close Buttons and adding an onclick() method to each.
list = [btn0, btn1]
list.length // length = 2
// for i=0; i<list.length; i++
// 1st pass, i == 0:
list[0] // btn0
// 2st pass, i == 1:
list[1] // btn1
// 3rd pass, i == 2
// i is not less than length, 2, end.
For the parentElement I always look at the tabs, Just go 1 left tab over and up; that's the parent! That's why formatting is important, to make this easy!
<div> <!-- <- Parent -->
<h2>ToDo</h2>
<input type="text" id="inputum" />
<button onclick="fonksiyonum()">Ekle</button> <!-- <- Button --->
</div>

Can't figure out why it isn't working, anymore

So been trying to learn more javascript, by doing small projects that are simple but are starting stuff. One of the projects is a to-do app which for some people is really simple, but for me as a starter it's quite complex.
Now here is the thing, I had it working for the most part, I can add stuff, and one thing only HALF works, I wrote a bit that adds a X button to a li element. Now it works when I put the li element in the HTML page itself, but when it's added through javascript, it doesn't.
There is no error, it was working before but for some reason it.. broke.
<!DOCTYPE html>
<head>
<title>To Do App!</title>
<link rel="stylesheet" type="text/css" href="CSS/stylesheet.css">
</head>
<body>
<div id="h1Div">
<h1> To-do app! </h1>
<input type="text" id="inputForList">
<input type="button" id="btnInput" value="Add me!" onclick="btnFunction()">
</div>
<ul id="ulSection">
<li>Test 1</li>
<li>Test 2</li>
</ul>
<script src="Scripts/javascript.js"></script>
</body>
This is the HTML page, super simple.
//Adds li element with input from a textbox
function btnFunction(){
var cLi = document.createElement("li");
var inpList = document.getElementById("inputForList").value;
var txtNode = document.createTextNode(inpList);
cLi.appendChild(txtNode);
//Check to see if anything is filled in, otherwise send message. And 'appends' it to the list item
if(inpList === ''){
alert("Voeg wat toe!");
} else {
document.getElementById("ulSection").appendChild(cLi);
}
// Reset value of Textbox to ""
document.getElementById("inputForList").value = "";
}
//Sets a 'x' on every element.
var ulList = document.getElementsByTagName("li");
var i;
for(i = 0; i < ulList.length; i++){
var span = document.createElement("span");
var xBtn = document.createTextNode("\u00D7");
span.className = "Done";
span.appendChild(xBtn);
ulList[i].appendChild(span);
}
And this is the Javascript.
As stated, it worked before. But for some reason, now the bottom section, the X button (\u00D7) part, it sn't working on the 'new stuff' that I add through the text input..
Your code is good, you just need to do the same thing you did in
var ulList = document.getElementsByTagName("li");
var i;
for (i = 0; i < ulList.length; i++) {
var span = document.createElement("span");
var xBtn = document.createTextNode("\u00D7");
span.className = "Done";
span.appendChild(xBtn);
ulList[i].appendChild(span);
}
in btnFunction() (with the exception of the for loop, which isn't needed in the function, as only one element is added at a time). The reason for this is your code only runs when the page is loaded, or when it is specifically told to run (in your case, on a button click). if you just create an element the js doesn't know to update it with an x, you have to tell it to do so.
//Adds li element with input from a textbox
function btnFunction() {
var cLi = document.createElement("li");
var inpList = document.getElementById("inputForList").value;
var txtNode = document.createTextNode(inpList);
cLi.appendChild(txtNode);
//Check to see if anything is filled in, otherwise send message. And 'appends' it to the list item
if (inpList === '') {
alert("Voeg wat toe!");
} else {
document.getElementById("ulSection").appendChild(cLi);
var ulList = document.getElementsByTagName("li");
var span = document.createElement("span");
var xBtn = document.createTextNode("\u00D7");
span.className = "Done";
span.appendChild(xBtn);
ulList[ulList.length-1].appendChild(span);
}
// Reset value of Textbox to ""
document.getElementById("inputForList").value = "";
}
//Sets a 'x' on every element.
var ulList = document.getElementsByTagName("li");
var i;
for (i = 0; i < ulList.length; i++) {
var span = document.createElement("span");
var xBtn = document.createTextNode("\u00D7");
span.className = "Done";
span.appendChild(xBtn);
ulList[i].appendChild(span);
}
<!DOCTYPE html>
<head>
<title>To Do App!</title>
<link rel="stylesheet" type="text/css" href="CSS/stylesheet.css">
</head>
<body>
<div id="h1Div">
<h1> To-do app! </h1>
<input type="text" id="inputForList">
<input type="button" id="btnInput" value="Add me!" onclick="btnFunction()">
</div>
<ul id="ulSection">
<li>Test 1</li>
<li>Test 2</li>
</ul>
<script src="Scripts/javascript.js"></script>
</body>

Too Much Recursion Error When Trying to Find All HTML Comments

The script below is meant to find all html comments in the page (there are 4) and return them as one string. I ran the script below and received a "Too Much Recursion" error.
Have I created an infinite loop or did I do something else?
function findComment()
{
var olElement = document.getElementById("everything");//this is the id for my body element
var comments = new Array();
if (olElement.nodeType == 8)
{
comments[comments.length] = olElement;
} else if(olElement.childNodes.length>0)
{
for (var i = 0; i<olElement.childNodes.length; i++)
{
comments = comments.concat(findComment(olElement.childNodes[i]));
}
}
alert(comments);
}
//window.onload = countListItems;
//window.onload = countTagItems;
//window.onload = getElements;
window.onload = findComment;
This is a rough cut version of how you could do it with a recursion. It is not really elegant but will do the work:
function fico(el){
if (el.nodeType==8) return [el.textContent.trim()]
else return [...el.childNodes].map(fico);
}
console.log(fico(document.querySelector("#everything")).toString().replace(/,+/g,", "));
<body id="everything">
<div>something <!-- comment1 -->
<div>with something inside
<!-- comment2 -->
<div>and something further<div>
<span>inside
<!-- comment3 --></span>
it
</div>
more regular text
<!-- comment4 --> and enough.
</div></body>
Depending on the html input the function will return an array of subarrays with further levels of subarrays. To flatten it I used the Array-method toString() and then replace() with a regular expression to throw out the multiple commas in the result. There is still a superfluous one at the beginning ;-)
And here is an alternative version that uses a global comments array like you used in your code:
var comments=[];
function fico(el){
if (el.nodeType==8) comments.push(el.textContent.trim());
else [...el.childNodes].forEach(fico);
}
fico(document.querySelector("#everything")); // collect comments ...
console.log(comments.join(', ')); // ... and display them
<body id="everything">
<div>something <!-- comment1 -->
<div>with something inside
<!-- comment2 -->
<div>and something further<div>
<span>inside
<!-- comment3 --></span>
it
</div>
more regular text
<!-- comment4 --> and enough.
</div></body>
Move the olElements variable outside the function and pass in the element you want to search. The recursion you have is always starting with 'everything';
var comments = new Array();
function findComment(element)
{
if (element.nodeType == 8)
{
comments[comments.length] = element;
} else if(element.childNodes.length>0)
{
for (var i = 0; i<element.childNodes.length; i++)
{
comments = comments.concat(findComment(element.childNodes[i]));
}
}
return comments;
}
var olElement = document.getElementById("everything");//this is the id for my body element
alert(findComment(olElement));
Update: I tried both methods above and received error that either "element" or "el" is null. So...progress. I've pulled together my full code and html and posted below:
<!DOCTYPE html>
<html>
<head>
<title>A Simple Page</title>
<script>
var comments = new Array();
function findComment(element)
{
if (element.nodeType == 8)
{
comments[comments.length] = element;
} else if(element.childNodes.length>0)
{
for (var i = 0; i<element.childNodes.length; i++)
{
comments = comments.concat(findComment(element.childNodes[i]));
}
}
return comments;
}
//window.onload = countListItems;
//window.onload = countTagItems;
//window.onload = getElements;
var olElement = document.getElementById("everything");//this is the id for my body element
window.onload = alert(findComment(olElement));
</script>
</head>
<body>
<div id="everything">
<h1>Things to Do</h1><!--this is a title-->
<ol id="toDoList"><!--this is a list-->
<li>Mow the lawn</li><!--this is a list item-->
<li>Clean the windows</li>
<li>Answer your email</li>
</ol>
<p id="toDoNotes">Make sure all these things are done so you can get some rest.</p>
</div>
</body>
</html>

How can I get user input in java script and display this input on page?

I am new to java and am trying to create a game that simulates hangman. I am trying to get the letters from the user after they input on keyboard. However, when I type something it doesn't make any difference, it doesn't output whether it is correct or incorrect. I think I may not be using the event in my guessLetter() function correctly, any help would be greatly appreciated.
window.addEventListener("DOMContentLoaded", function() {
var word = ['taco'];
let randNum = Math.floor(Math.random() * word.length);
let chosenWord = word[randNum];
let underScore = [];
let docUnderScore = document.getElementsByClassName('underScore');
let docRightGuess = document.getElementsByClassName('rightGuess');
let docWrongGuess = document.getElementsByClassName('wrongGuess');
console.log(chosenWord); //lets grader cheat
let generateUnderscore = () => {
for (let i = 0; i < chosenWord.length; i++) {
underScore.push('_');
}
return underScore;
}
document.onkeyup = function guessLetter(event) {
let letter = String.fromCharCode(event.keyCode || event.code).toLowerCase();
if (chosenWord.indexOf(letter) > -1) {
rightWord.push(letter);
underScore[chosenWord.indexOf(letter)] = letter;
docUnderScore[0].innerHTML = underScore.join(' ');
docRightGuess[0].innerHTML = rightWord;
if (underScore.join('') === chosenWord) {
alert('CONGRATS! YOU WIN!!!');
} else {
wrongWord.push(letter);
docWrongGuess[0].innerHTML = wrongWord;
}
}
underScore[0].innerHTML = generateUnderscore().join(' ');
}
});
<!DOCTYPE html>
<html>
<head>
<h1> Hangman </h1>
<div id="guesses">
<div class="letter" id="letter" </div>
</div>
</head>
<body>
</body>
<div class="container">
<div class="underScore">_ _ _ _</div>
<div class="rightGuess"> right guess </div>
<div class="wrongGuess"> wrong guess </div>
</div>
</html>
In the JS console, ReferenceErrors are being thrown as a result of the fact that the rightWord and wrongWord variables have not been defined.
You are writing the in head tag why ? it doesn't shown in your web page , place the html tags within body.

JavaScript function doesn't recognize my HTML element

I have a problem with my JavaScript function, in the "for" part it doesn't recognize the HTML elements when I use i to refer to the list position, but when I use [0] or [1], for example, it does recognize it. So there must be a problem with the loop part but I can't figure out what is it, here is the code:
(function () {
"use strict";
window.animacion_click_menu = function (id) {
var i;
var menu = document.getElementById('menu').getElementsByTagName('LI');
var bloqueActual = document.getElementById(id);
for (i = 0; i <= menu.length; i++) { //recorre los LI devolviendolos a su posicion original
menu[i].style.marginLeft = -40;
menu[i].style.opacity = 1;
}
bloqueActual.style.marginLeft = 200;
bloqueActual.style.opacity = 0;
};
})();
and here's my html:
<head>
<meta charset="UTF-8">
<title>Mario Luque Marchena</title>
<meta charset="utf-8">
<link rel="stylesheet" href="css/estilos.css">
</head>
<body>
<center>
<h1 class="titulo">Bienvenid#</h1>
</center>
<div id="main-screen">
<ul id="menu">
<center>
<li id="sobremi" onclick="window.animacion_click_menu('sobremi');">Sobre mi</li>
<li id="portafolios" onclick="animacion_click_menu('portafolios');">Portafolios</li>
<li id="animacion" onclick="animacion_click_menu('animacion');">Animacion</li>
<li id="back-end" style="border-bottom-style: dashed;" onclick="animacion_click_menu('back-end');">Back-End</li>
</center>
</ul>
</div>
<script type="text/javascript" src="js/animaciones.js"></script>
</body>
if you have any suggestions to make the code better, are welcome too, i'm learning to code. thank you!, and sorry for the bad english in case it was
Your error is really on the for loop.
Take a look on:
for (i = 0; i <= menu.length; i++) {
it should be:
for (i = 0; i <= menu.length-1; i++) {
Otherwise, it will try to iterate from 0 to 5 while your menu array has only 4 items.
The result is that in the last iteration, when you try to access the element menu with the inexistent index (menu[5]) you get the error:
Uncaught TypeError: Cannot read property 'style' of undefined
Other possibility to overcome this is to change <= to < and work with the loop as:
for (i = 0; i < menu.length; i++) {
use window.onload() or
$('document').ready(function(){
//Put your code here
})
I think your code is getting executed before DOM creation.

Categories

Resources