Attempting to Build a Calculator with JS - javascript

Just finished a code to build a calculator from a YT tutorial. The calculator looks great but I can't get it to work. I don't understand I did everything in the video verbatim. Can anyone help me out? I watched the video a few times but I just can't get it to work and can't figure out why. I'm guessing it's something wrong with the appendNumber variable. But I'm not sure still a newb to JS.
class Calculator {
constructor(previousOperandTextElement, currentOperandTextElement) {
this.previousOperandTextElement = previousOperandTextElement
this.currentOperandTextElement = currentOperandTextElement
this.clear()
}
clear(){
this.currentOperand = ''
this.previousOperand = ''
this.operation = undefined
}
delete(){
this.currentOperand = this.currentOperand.toString().slice(0, -1)
}
appendNumber(number) {
if(number === '.' && this.currentOperand.includes('.')) return
this.currentOperand = this.currentOperand.toString() + number.toString()
}
chooseOperation(operation){
if (this.currentOperand === '') return
if (this.previousOperand !== '') {
this.compute()
}
this.operation = operation
this.previousOperand = this.currentOperand
this.currentOperand = ''
}
compute(){
let computation
const prev = parseFloat(this.previousOperand)
const current = parseFloat(this.currentOperand)
if (isNaN(prev) || is NaN(current)) return
switch (this.operation){
case '+':
computation = prev + current
break
case '-':
computation = prev - current
break
case '*':
computation = prev * current
break
case '&#247':
computation = prev / current
break
default:
return
}
this.currentOperand = computation
this.operation = undefined
this.previousOperand = ''
}
getDisplayNumber(number) {
const stringNumber = number.toString()
const interDigits = parseFloat(stringNumber.split('.')[0])
const decimalDigits = stringNumber.split('.')[1]
let interDisplay
if (isNaN(interDigits)) {
integerDisplay = ''
} else {
integerDisplay integerDigits.tpLocaleString('en', {
maximumFractionDigits: 0 })
if(decimalDigits != null) {
return `$(integerDisplay).$(decimalDigits)`
}else{
return itegerDisplay
}
}
updateDisplay(){
this.currentOperandTextElement.innerText =
this.getDisplayNumber(this.currentOperand)
if(this.operation !=null){
this.previousOperandTextElement.innerText =
$(this.getDisplayNumber(this.previousOperand) $(this.operation)
}else {
this.previousOperandTextElement = ''
}
}
const numberButtons = document.querySelectorAll('[data-number]')
const operationButtons = document.querySelectorAll('[data-operation]')
const equalsButton = document.querySelector('[data-equals]')
const deleteButton = document.querySelector('[data-delete]')
const allClearButton = document.querySelector('[data-all-clear]')
const previousOperandTextElement = document.querySelector('[data-previous-operand]')
const currentOperandTextElement = document.querySelector('[data-current-operand]')
const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement)
numberButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.appendNumber(button.innerText)
calculator.updateDisplay()
})
})
operationButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.chooseOperation(button.innerText)
calculator.updateDisplay()
})
})
equalsButton.addEventListener('click, button => {
calculator.compute()
calculator.updateDisplay()
})
allClearButton.addEventListener('click, button => {
calculator.clear()
calculator.updateDisplay()
})
deleteButton.addEventListener('click, button => {
calculator.delete()
calculator.updateDisplay()
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>New JS</title>
<style>
*, *::before, *::after{
box-sizing:border-box;
font-weight:normal;
font-family: Gotham Rounded, sans-serif;
color:Blue;
}
body{
padding:0;
margin:0;
background: linear-gradient(to right,blue, green);
}
.calculator-grid{
display:grid;
justify-content:center;
align-content:center;
min-height:100vh;
grid-template-columns:repeat(4, 100px);
grid-template-rows: minmax(120px, auto) repeat(5, 100px);
}
.calculator-grid > button {
cursor:pointer;
font-size: 2rem;
border:1px solid white;
outline:none;
background-color:rgba(255, 255, 255, .75);
}
.calculator-grid > button:hover{
background-color:rgba(255, 255, 255, .9);
}
.span-two{
grid-column: span 2;
}
.output{
grid-column:1 /-1;
background-color:rgba(0,0, .75);
display:flex;
align-items:flex-end;
justify-content: space-around;
flex-direction:column;
padding:10px;
word-wrap; break-word;
word-break:break-all;
}
.output .previous-operand{
color:rgba(255, 255, 255, .75);
font-size: 1.5rem;
}
.output .current-operand{
color:white;
font-size:2.5rem;
}
</style>
<script src="calculator.js" defer> </script>
</head>
<body>
<div class="calculator-grid">
<div class="output">
<div data-previous-operand class="previous-operand"></div>
<div data-current-operand class="current-operand"></div>
</div>
<button data-all-clear class="span-two">AC</button>
<button data-delete>DEL</button>
<button data-operation>+</button>
<button data-number>1</button>
<button data-number>2</button>
<button data-number>3</button>
<button data-operation>*</button>
<button data-number>4</button>
<button data-number>5</button>
<button data-number>6</button>
<button data-operation> &#247 </button>
<button data-number>7</button>
<button data-number>8</button>
<button data-number>9</button>
<button data-operation>-</button>
<button data-number>.</button>
<button data-number>0</button>
<button data-equals class="span-two">=</button>
</div>
</body>
</html>

Errors in your code are mostly syntactic. For example, your code does not have .innerText for this.previousOperandTextElement = by default. The string - $ {this.getDisplayNumber (this.previousOperand)} $ {this.operation} was without quotes. The line integerDisplay = integerDigits.toLocaleString ('en', {maximumFractionDigits: 0}) was missing an equal sign.
class Calculator {
constructor(previousOperandTextElement, currentOperandTextElement) {
this.previousOperandTextElement = previousOperandTextElement
this.currentOperandTextElement = currentOperandTextElement
this.clear()
}
clear() {
this.currentOperand = ''
this.previousOperand = ''
this.operation = undefined
}
delete() {
this.currentOperand = this.currentOperand.toString().slice(0, -1)
}
appendNumber(number) {
if (number === '.' && this.currentOperand.includes('.')) return
this.currentOperand = this.currentOperand.toString() + number.toString()
}
chooseOperation(operation) {
if (this.currentOperand === '') return
if (this.previousOperand !== '') {
this.compute()
}
this.operation = operation
this.previousOperand = this.currentOperand
this.currentOperand = ''
}
compute() {
let computation
const prev = parseFloat(this.previousOperand)
const current = parseFloat(this.currentOperand)
if (isNaN(prev) || isNaN(current)) return
switch (this.operation) {
case '+':
computation = prev + current
break
case '-':
computation = prev - current
break
case '*':
computation = prev * current
break
case '÷':
computation = prev / current
break
default:
return
}
this.currentOperand = computation
this.operation = undefined
this.previousOperand = ''
}
getDisplayNumber(number) {
const stringNumber = number.toString()
const integerDigits = parseFloat(stringNumber.split('.')[0])
const decimalDigits = stringNumber.split('.')[1]
let integerDisplay
if (isNaN(integerDigits)) {
integerDisplay = ''
} else {
integerDisplay = integerDigits.toLocaleString('en', { maximumFractionDigits: 0 })
}
if (decimalDigits != null) {
return `${integerDisplay}.${decimalDigits}`
} else {
return integerDisplay
}
}
updateDisplay() {
this.currentOperandTextElement.innerText =
this.getDisplayNumber(this.currentOperand)
if (this.operation != null) {
this.previousOperandTextElement.innerText =
`${this.getDisplayNumber(this.previousOperand)} ${this.operation}`
} else {
this.previousOperandTextElement.innerText = ''
}
}
}
const numberButtons = document.querySelectorAll('[data-number]')
const operationButtons = document.querySelectorAll('[data-operation]')
const equalsButton = document.querySelector('[data-equals]')
const deleteButton = document.querySelector('[data-delete]')
const allClearButton = document.querySelector('[data-all-clear]')
const previousOperandTextElement = document.querySelector('[data-previous-operand]')
const currentOperandTextElement = document.querySelector('[data-current-operand]')
const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement)
numberButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.appendNumber(button.innerText)
calculator.updateDisplay()
})
})
operationButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.chooseOperation(button.innerText)
calculator.updateDisplay()
})
})
equalsButton.addEventListener('click', button => {
calculator.compute()
calculator.updateDisplay()
})
allClearButton.addEventListener('click', button => {
calculator.clear()
calculator.updateDisplay()
})
deleteButton.addEventListener('click', button => {
calculator.delete()
calculator.updateDisplay()
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>New JS</title>
<style>
*, *::before, *::after{
box-sizing:border-box;
font-weight:normal;
font-family: Gotham Rounded, sans-serif;
color:Blue;
}
body{
padding:0;
margin:0;
background: linear-gradient(to right,blue, green);
}
.calculator-grid{
display:grid;
justify-content:center;
align-content:center;
min-height:100vh;
grid-template-columns:repeat(4, 100px);
grid-template-rows: minmax(120px, auto) repeat(5, 100px);
}
.calculator-grid > button {
cursor:pointer;
font-size: 2rem;
border:1px solid white;
outline:none;
background-color:rgba(255, 255, 255, .75);
}
.calculator-grid > button:hover{
background-color:rgba(255, 255, 255, .9);
}
.span-two{
grid-column: span 2;
}
.output{
grid-column:1 /-1;
background-color:rgba(0,0, .75);
display:flex;
align-items:flex-end;
justify-content: space-around;
flex-direction:column;
padding:10px;
word-wrap; break-word;
word-break:break-all;
}
.output .previous-operand{
color:rgba(255, 255, 255, .75);
font-size: 1.5rem;
}
.output .current-operand{
color:white;
font-size:2.5rem;
}
</style>
<script src="calculator.js" defer> </script>
</head>
<body>
<div class="calculator-grid">
<div class="output">
<div data-previous-operand class="previous-operand"></div>
<div data-current-operand class="current-operand"></div>
</div>
<button data-all-clear class="span-two">AC</button>
<button data-delete>DEL</button>
<button data-operation>+</button>
<button data-number>1</button>
<button data-number>2</button>
<button data-number>3</button>
<button data-operation>*</button>
<button data-number>4</button>
<button data-number>5</button>
<button data-number>6</button>
<button data-operation> &#247 </button>
<button data-number>7</button>
<button data-number>8</button>
<button data-number>9</button>
<button data-operation>-</button>
<button data-number>.</button>
<button data-number>0</button>
<button data-equals class="span-two">=</button>
</div>
</body>
</html>

Related

Calculator display

If you calculate (45 - 5), the calculator will return 40 but if you click on the 5 it will concatenate 40 and 5 and it will make '405', I wanted the calculator to clear the display when I press the 5 to start a new operation so that the user doesn't have to manually clear the calculator with AC, I know I need to program a method that checks if an operation has been completed or not but I can't get it to work, can you help me? what I need to do? what code do i need to write to make this work? my github: https://github.com/JackHeroes/Calculator
class CalcController{
constructor(){
this._timeEl = document.querySelector('#time');
this._dateEl = document.querySelector('#date');
this._historicEl = document.querySelector('#historic');
this._displayCalcEl = document.querySelector('#display');
this._audio = new Audio('/audio/click.wav');
this._audioOnOff = false;
this._currentDate;
this._locale = 'pt-BR';
this._operation = [];
this._readyToClear = false;
this._lastNumber = '';
this._lastOperator = '';
this.initialize();
this.initButtonsEvents();
this.initKeyboard();
}
initialize(){
this.playAudio(true);
this.setDisplayDateTime();
setInterval(() =>{
this.setDisplayDateTime();
}, 1000);
this.setLastNumberToDisplay();
document.querySelector('#audio').addEventListener('click', e =>{
this.toggleAudio();
})
let icon = document.querySelector('#audio');
icon.addEventListener('click', e =>{
if(icon.classList.contains('bi-volume-up-fill')){
icon.classList.remove('bi-volume-up-fill');
icon.classList.add('bi-volume-mute-fill');
} else{
icon.classList.remove('bi-volume-mute-fill');
icon.classList.add('bi-volume-up-fill');
}
});
}
toggleAudio(){
this._audioOnOff = !this._audioOnOff;
}
playAudio(){
if(this._audioOnOff){
this._audio.currentTime = 0;
this._audio.play();
}
}
initKeyboard(){
document.addEventListener('keyup' , e =>{
this.playAudio();
switch(e.key){
case 'Escape':
this.clearAll();
break;
case 'Backspace':
this.clearEntry();
break;
case '+':
case '-':
case '*':
case '/':
this.addOperation(e.key);
break;
case 'Enter':
case '=':
this.calc();
break;
case ',':
case '.':
this.addDot();
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
this.addOperation(parseInt(e.key));
break;
}
});
}
setDisplayDateTime(){
this.displayTime = this.currentDate.toLocaleTimeString(this._locale)
this.displayDate = this.currentDate.toLocaleDateString(this._locale, {day: '2-digit', month: 'long', year: 'numeric'})
}
setLastNumberToDisplay(){
let lastNumber = this.getLastItem(false);
if(!lastNumber) lastNumber = [0];
this.displayCalc = lastNumber;
}
addEventListenerAll(element, events, fn){
events.split(' ').forEach(event =>{
element.addEventListener(event, fn, false);
});
}
clearAll(value){
let alreadyCalled = false;
if (!alreadyCalled) {
this._operation = [];
this._lastNumber = '';
this._lastOperator = '';
this.setLastNumberToDisplay();
if(value) this.addOperation(value);
this._readyToClear = false;
alreadyCalled = true;
}
}
clearEntry(){
this._operation.pop();
this.setLastNumberToDisplay();
}
ClearLast(){
}
getLastOperation(){
return this._operation[this._operation.length-1];
}
setLastOperation(value){
this._operation[this._operation.length-1] = value;
}
isOperator(value){
return (['+','-','*','/'].indexOf(value) > -1);
}
pushOperation(value){
this._operation.push(value);
if(this._operation.length > 3){
this.calc();
}
}
addOperation(value){
if(isNaN(this.getLastOperation())){
if(this.isOperator(value)){
this.setLastOperation(value);
} else{
this.pushOperation(value);
this.setLastNumberToDisplay();
}
} else{
if(this.isOperator(value)){
this.pushOperation(value);
} else{
let newValue;
if(this.getLastOperation().toString() !== '0'){
newValue = this.getLastOperation().toString() + value.toString();
} else{
newValue = value.toString();
}
this.setLastOperation(newValue);
this.setLastNumberToDisplay();
}
}
if (this._readyToClear){
this.clearAll(value);
this._readyToClear = false;
return
}
}
addDot(){
let lastOperation = this.getLastOperation();
if(typeof lastOperation === 'string' && lastOperation.split('').indexOf('.') > -1) return;
if(this.isOperator(lastOperation) || lastOperation === undefined){
this.pushOperation('0.');
} else{
this.setLastOperation(lastOperation.toString() + '.');
}
this.setLastNumberToDisplay();
}
getResult(){
return eval(this._operation.join(''));
}
getLastItem(isOperator = true){
let lastItem;
for(let i = this._operation.length - 1; i >= 0; i--){
if(this.isOperator(this._operation[i]) == isOperator){
lastItem = this._operation[i];
break;
}
}
if(lastItem == 0){
return lastItem;
} else if(!lastItem){
lastItem = (isOperator) ? this._lastOperator : this._lastNumber;
}
return lastItem;
}
calc() {
let last = '';
this._lastOperator = this.getLastItem();
if (this._operation.length < 3) {
let firstItem = this._operation[0];
this._operation = [firstItem, this._lastOperator, this._lastNumber];
} else if (this._operation.length > 3) {
last = this._operation.pop();
this._lastNumber = this.getResult();
} else if (this._operation.length == 3) {
this._lastNumber = this.getLastItem(false);
}
let result = this.getResult();
this._operation = [result];
if (last) this._operation.push(last);
this.setLastNumberToDisplay();
}
setError(){
this.displayCalc = 'Erro';
}
execBtn(value){
this.playAudio();
switch(value){
case 'ac':
this.clearAll();
break;
case 'ce':
this.clearEntry();
break;
case 'cl':
this.ClearLast();
break;
case 'division':
this._readyToClear = false;
this.addOperation('/');
break;
case 'multiplication':
this._readyToClear = false;
this.addOperation('*');
break;
case 'subtraction':
this._readyToClear = false;
this.addOperation('-');
break;
case 'addition':
this._readyToClear = false;
this.addOperation('+');
break;
case 'dot':
this.addDot();
break;
case 'equal':
this.calc();
this._readyToClear = true;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
this.addOperation(parseInt(value));
break;
default:
this.setError();
break;
}
}
initButtonsEvents(){
let buttons = document.querySelectorAll('#buttons > section > button');
buttons.forEach((btn, index) =>{
this.addEventListenerAll(btn, 'click drag', e =>{
let textBtn = btn.className.replace('btn-', '');
this.execBtn(textBtn);
});
});
}
get displayTime(){
return this._timeEl.innerHTML;
}
set displayTime(value){
return this._timeEl.innerHTML = value;
}
get displayDate(){
return this._dateEl.innerHTML
}
set displayDate(value){
return this._dateEl.innerHTML = value
}
get displayHistoric(){
return this._historicEl.innerHTML
}
set displayHistoric(value){
return this._historicEl.innerHTML = value
}
get displayCalc(){
return this._displayCalcEl.innerHTML;
}
set displayCalc(value){
if (value.toString().length > 10){
this.setError();
return false;
}
this._displayCalcEl.innerHTML = value;
}
get currentDate(){
return new Date();
}
set currentDate(value){
this._currentDate = value;
}
}
window.calculator = new CalcController;
#font-face {
font-family: 'Digital-7';
src: url('/font/digital-7.ttf');
}
#calculator-container {
height: 100vh;
width: 100vh;
}
#calculator {
background-color: #B5ACEA;
border-radius: .5rem;
box-shadow: 0px 10px 0px 0px #8468EC;
width: fit-content;
}
#audio {
color: #F5F5F5;
cursor: pointer;
font-size: 2rem;
}
#display-container {
background-color: #3D2C8D;
border-radius: .5rem;
box-shadow: inset 0px 5px 0px 0px #1C0C5B;
font-family: 'Digital-7', sans-serif;
height: fit-content;
}
#time,
#date,
#historic,
#display {
color: #F5F5F5;
}
#historic {
height: 1rem;
}
#display {
font-size: 3rem;
height: 4rem;
}
#buttons button {
background-color: #3D2C8D;
border-radius: .5rem;
box-shadow: 0px 5px 0px 0px #1C0C5B;
color: #F5F5F5;
font-size: 1.5rem;
height: 5rem;
margin-bottom: .5rem;
margin-top: .5rem;
transition-duration: 1s, .1s;
transition-property: background-color, transform;
transition-timing-function: ease;
width: 5rem;
}
#buttons button:hover {
background-color: #1C0C5B;
}
#buttons button:active {
transform: translateY(5px);
}
#buttons .btn-ac,
#buttons .btn-ce,
#buttons .btn-cl,
#buttons .btn-equal {
background-color: #8468EC;
}
#buttons .btn-equal {
flex-grow: 2;
}
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculator</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.10.3/font/bootstrap-icons.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container-fluid d-flex justify-content-center align-items-center" id="calculator-container">
<div class="container-fluid p-4" id="calculator">
<section class="mb-2">
<i class="bi bi-volume-up-fill" id="audio"></i>
</section>
<section class="display mb-2" id="display-container">
<div class="d-flex justify-content-between ps-2 pe-2 pt-2">
<p class="m-0" id="time"></p>
<p class="m-0" id="date"></p>
</div>
<div class="d-flex justify-content-end ps-2 pe-2">
<p class="m-0" id="historic"></p>
</div>
<div class="d-flex justify-content-end ps-2 pe-2 pb-2">
<p class="m-0" id="display">0</p>
</div>
</section>
<div id="buttons">
<section class="d-flex gap-2">
<button class="btn-ac">AC</button>
<button class="btn-ce">CE</button>
<button class="btn-cl"><i class="bi bi-x-octagon"></i></button>
<button class="btn-division">÷</button>
</section>
<section class="d-flex gap-2">
<button class="btn-7">7</button>
<button class="btn-8">8</button>
<button class="btn-9">9</button>
<button class="btn-multiplication">x</button>
</section>
<section class="d-flex gap-2">
<button class="btn-4">4</button>
<button class="btn-5">5</button>
<button class="btn-6">6</button>
<button class="btn-subtraction">-</button>
</section>
<section class="d-flex gap-2">
<button class="btn-1">1</button>
<button class="btn-2">2</button>
<button class="btn-3">3</button>
<button class="btn-addition">+</button>
</section>
<section class="d-flex gap-2">
<button class="btn-0">0</button>
<button class="btn-dot">.</button>
<button class="btn-equal">=</button>
</section>
</div>
</div>
</div>
<script src="/js/controller/CalcController.js"></script>
<script src="/js/calculator.js"></script>
</body>
</html>
Your code needs some additional state (by this I mean data or information) so that it knows if it should clear the display when a new button is pressed. A simple boolean variable would suffice such as shouldClear which the code sets to true when you press equals and back to false again after pressing any other button and clearing the display.

Can a function be inside another function?

I am working on a library project but my function called changeColor inside the readStatus function does not appear to be working.
I've tried separating it but having two event listeners on the same button does not appear to work. My goal is for readStatus function to allow a user to update the status of a book from no to yes when finished with the book.
Likewise, I want to change the background color of the div (class: card) when yes to be green and no to be red.
Can anyone tell me what I'm doing wrong?
let myLibrary = [];
function Book(title, author, pages, read) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
function addBookToLibrary(title, author, pages, read) {
let book = new Book(title, author, pages, read);
myLibrary.push(book);
displayOnPage();
}
function displayOnPage() {
const books = document.querySelector(".books");
const removeDivs = document.querySelectorAll(".card");
for (let i = 0; i < removeDivs.length; i++) {
removeDivs[i].remove();
}
let index = 0;
myLibrary.forEach((myLibrarys) => {
let card = document.createElement("div");
card.classList.add("card");
books.appendChild(card);
for (let key in myLibrarys) {
let para = document.createElement("p");
para.textContent = `${key}: ${myLibrarys[key]}`;
card.appendChild(para);
}
let read_button = document.createElement("button");
read_button.classList.add("read_button");
read_button.textContent = "Read ";
read_button.dataset.linkedArray = index;
card.appendChild(read_button);
read_button.addEventListener("click", readStatus);
let delete_button = document.createElement("button");
delete_button.classList.add("delete_button");
delete_button.textContent = "Remove";
delete_button.dataset.linkedArray = index;
card.appendChild(delete_button);
delete_button.addEventListener("click", removeFromLibrary);
function removeFromLibrary() {
let retrieveBookToRemove = delete_button.dataset.linkedArray;
myLibrary.splice(parseInt(retrieveBookToRemove), 1);
card.remove();
displayOnPage();
}
function readStatus() {
let retrieveBookToToggle = read_button.dataset.linkedArray;
Book.prototype = Object.create(Book.prototype);
const toggleBook = new Book();
if (myLibrary[parseInt(retrieveBookToToggle)].read == "yes") {
toggleBook.read = "no";
myLibrary[parseInt(retrieveBookToToggle)].read = toggleBook.read;
} else if (myLibrary[parseInt(retrieveBookToToggle)].read == "no") {
toggleBook.read = "yes";
myLibrary[parseInt(retrieveBookToToggle)].read = toggleBook.read;
}
let colorDiv = document.querySelector(".card");
function changeColor() {
for (let i = 0; i < length.myLibrary; i++) {
if (myLibrary[i].read == "yes") {
colorDiv.style.backgroundColor = "green";
} else if (myLibrary[i].read == "no") {
colorDiv.style.backgroundColor = "red";
}
}
}
displayOnPage();
}
index++;
});
}
let add_book = document.querySelector(".add-book");
add_book.addEventListener("click", popUpForm);
function popUpForm() {
document.getElementById("data-form").style.display = "block";
}
function closeForm() {
document.getElementById("data-form").style.display = "none";
}
let close_form_button = document.querySelector("#close-form");
close_form_button.addEventListener("click", closeForm);
function intakeFormData() {
let title = document.getElementById("title").value;
let author = document.getElementById("author").value;
let pages = document.getElementById("pages").value;
let read = document.getElementById("read").value;
if (title == "" || author == "" || pages == "" || read == "") {
return;
}
addBookToLibrary(title, author, pages, read);
document.getElementById("data-form").reset();
}
let submit_form = document.querySelector("#submit-form");
submit_form.addEventListener("click", function (event) {
event.preventDefault();
intakeFormData();
});
* {
margin: 0;
padding: 0;
background-color: rgb(245, 227, 205);
}
.books {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
text-align: center;
margin: 20px;
gap: 10px;
}
.card {
border: 1px solid black;
border-radius: 15px;
padding: 10px;
}
.forms {
display: flex;
flex-direction: column;
align-items: center;
}
form {
margin-top: 20px;
}
select,
input[type="text"],
input[type="number"] {
width: 100%;
box-sizing: border-box;
}
.buttons-container {
display: flex;
margin-top: 10px;
}
.buttons-container button {
width: 100%;
margin: 2px;
}
.add-book {
margin-top: 20px;
}
#data-form {
display: none;
}
.read_button {
margin-right: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Document</title>
</head>
<body>
<div class="container">
<div class="forms">
<button class="add-book">Add Book To Library</button>
<div class="pop-up">
<form id="data-form">
<div class="form-container">
<label for="title">Title</label>
<input type="text" name="title" id="title" />
</div>
<div class="form-container">
<label for="author">Author</label>
<input type="text" name="author" id="author" />
</div>
<div class="form-container">
<label for="pages">Pages</label>
<input type="number" name="pages" id="pages" />
</div>
<div class="form-container">
<label for="read">Read</label>
<select name="read" id="read">
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
</div>
<div class="buttons-container">
<button type="submit" id="submit-form">Submit Form</button>
<button type="button" id="close-form">Close Form</button>
</div>
</form>
</div>
</div>
<div class="books"></div>
</div>
<script src="script.js"></script>
</body>
</html>
A couple things needed.
First, you should put the readStatus and removeFromLibrary functions outside of the foreach loop.
Then I think you are wanting changeColor to run whenever readStatus is run. Either put the changeColor code directly inside the readStatus or put changeColor() inside readStatus.
I think you want the Book to not be a function but a class.

Button array is empty after I copied from another array that has the whole set of HTMLCollection

I want to store all the existing button names into an array(copyAllButtons) by using the push function.
However, after the for-loop, there is still nothing inside copyAllButtons.
I am trying to make a reset function that required the array(copyAllButtons) to restore all the button names saved.
Can anyone help me? Thank you.
var all_buttons = document.getElementsByTagName('button'); //all button names are saved
var copyAllButtons = [];
console.log(all_buttons);
for (let i = 0; i < all_buttons.length; i++) {
copyAllButtons.push(all_buttons[i].classList[1]);
}
console.log(copyAllButtons); //####Button array is empty####
This is my file:
https://drive.google.com/file/d/1qbAAHClxJhNQUFyvrSklbGwX9tbsEsL8/view?usp=sharing
message of console.log(copyAllButtons)
element inside all_buttons
code related:JS
//challenge4
var all_buttons = document.getElementsByTagName('button'); //all button names are saved
var copyAllButtons = [];
console.log(all_buttons);
for (let i = 0; i < all_buttons.length; i++) {
copyAllButtons.push(all_buttons[i].classList[1]);
}
console.log(copyAllButtons); //####Button array is empty####
function buttonColorChange(buttonThingy) {
if (buttonThingy.value === 'red') {
buttonsRed();
} else if (buttonThingy.value === 'green') {
buttonsGreen();
} else if (buttonThingy.value === 'reset') {
buttonsColorReset();
} else if (buttonThingy.value === 'random') {
randomColors();
}
}
function buttonsRed() {
for (let i = 0; i < all_buttons.length; i++) {
all_buttons[i].className = 'btn btn-danger';
}
}
function buttonsGreen() {
for (let i = 0; i < all_buttons.length; i++) {
all_buttons[i].className = 'btn btn-success';
}
}
function buttonsColorReset() { //##function that i am working on##
for (let i = 0; i < all_buttons.length; i++) {
all_buttons[i].classList.remove(all_buttons[i].classList[1]);
all_buttons[i].classList.add(copyAllButtons[i]);
}
}
function randomColors() {
for (let i = 0; i < all_buttons.length; i++) {
var x = Math.floor(Math.random() * 4);
var y = ['btn-primary', 'btn-danger', 'btn-warning', 'btn-success'];
all_buttons[i].className = 'btn ' + y[x];
}
}
HTML
<div class="container-4">
<h2 id="change-my-color">Challenge 4:Change the color of all buttons</h2>
<div class="flex-box-pick-color">
<form action="">
<select name="backdrop" id="background" onChange="buttonColorChange(this)">
<option value="random">Random</option>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="reset">Reset</option>
</select>
</form>
<button class="btn btn-primary">Wee!</button>
<button class="btn btn-danger">Yahoo!</button>
<button class="btn btn-warning">Google!</button>
<button class="btn btn-success">Facebook!</button>
</div>
</div>
CSS:
.container-1, .container-2 , .container-3 ,.container-4{
border: 1px solid blue;
width:75%;
margin: 0 auto;
text-align: center;
}
.flex-box-container-1, .flex-box-container-2,.flex-box-rps,.flex-box-pick-color{
display:flex;
border:1px solid purple;
padding: 10px;
flex-wrap:wrap;
flex-direction: row;
justify-content: space-around;
}
All my code for reference:
javascript:
function ageInDays() {
var birthYear = prompt("What year were you born?")
var days = (2021 - birthYear) * 365
var h1 = document.createElement('h1')
var textAnswer = document.createTextNode('You are ' + days + ' days old')
h1.setAttribute('id', 'days');
h1.appendChild(textAnswer)
document.getElementById('flex-box-result').appendChild(h1)
}
function reset() {
document.getElementById('days').remove()
}
function generateCat() {
var image = document.createElement('img');
var div = document.getElementById('flex-cat-gen');
image.src = "https://thecatapi.com/api/images/get?format=src&type=gif&size=small";
div.appendChild(image);
}
//challenge3 rock paper scissors
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function randToRpsInt() {
return Math.floor(Math.random() * 3);
}
function numberToChoice(number) {
return ['rock', 'paper', 'scissors'][number]
}
function rpsGame(yourChoice) {
var result;
console.log(yourChoice.id);
var humanChoice, botChoice;
var message
humanChoice = yourChoice.id;
botChoice = numberToChoice(randToRpsInt());
console.log(botChoice);
if (humanChoice === 'rock') {
if (botChoice === 'rock') {
result = "tie"
console.log("tie");
}
else if (botChoice === 'paper') {
result = "lost"
console.log("You Lost>_<");
}
else {
result = "win"
console.log("You Win OAO");
}
}
else if (humanChoice === 'paper') {
if (botChoice === 'rock') {
result = "win";
console.log("You Win OAO");
}
else if (botChoice === 'scissors') {
result = "lost";
console.log("You Lost>_<");
}
else {
result = "tie";
console.log("tie");
}
}
//scissors
else {
if (botChoice === 'paper') {
result = "win";
console.log("You Win OAO");
}
else if (botChoice === 'rock') {
result = "lost";
console.log("You Lost>_<");
}
else {
result = "tie";
console.log("tie");
}
}
message = finalMessage(result);
rpsFrontEnd(humanChoice, botChoice, message);
}
function finalMessage(result) {
if (result === "lost")
return { 'message': 'You lost!', 'color': 'red' };
else if (result === "win")
return { 'message': 'You won!', 'color': 'green' };
else
return { 'message': 'You tied!', 'color': 'yellow' };
}
function rpsFrontEnd(humanImageChoice, botImageChoice, finalMessage) {
var imagesDatabase = {
'rock': document.getElementById('rock').src,
'paper': document.getElementById('paper').src,
'scissors': document.getElementById('scissors').src
}
document.getElementById('rock').remove();
document.getElementById('paper').remove();
document.getElementById('scissors').remove();
var humanDiv = document.createElement('div');
var botDiv = document.createElement('div');
var messageDiv = document.createElement('div');
humanDiv.innerHTML = "<img src='" + imagesDatabase[humanImageChoice] + "' height=150 width=150 style='box-shadow: 0px 10px 50px rgba(37,50,233,1);'>"
botDiv.innerHTML = "<img src='" + imagesDatabase[botImageChoice] + "' height=150 width=150 style='box-shadow: 0px 10px 50px rgba(3243,38,24,1);'>"
messageDiv.innerHTML = "<h1 style='color: " + finalMessage['color'] + "; font-size: 60px;padding:30px; '>" + finalMessage['message'] + "</h1>"
document.getElementById('flex-box-rps-div').appendChild(humanDiv);
document.getElementById('flex-box-rps-div').appendChild(messageDiv);
document.getElementById('flex-box-rps-div').appendChild(botDiv);
}
//challenge4
var all_buttons = document.getElementsByTagName('button'); //all button names are saved
var copyAllButtons = [];
console.log(all_buttons);
for (let i = 0; i < all_buttons.length; i++) {
copyAllButtons.push(all_buttons[i].classList[1]);
}
console.log(copyAllButtons); //####Button array is empty####
function buttonColorChange(buttonThingy) {
if (buttonThingy.value === 'red') {
buttonsRed();
} else if (buttonThingy.value === 'green') {
buttonsGreen();
} else if (buttonThingy.value === 'reset') {
buttonsColorReset();
} else if (buttonThingy.value === 'random') {
randomColors();
}
}
function buttonsRed() {
for (let i = 0; i < all_buttons.length; i++) {
all_buttons[i].className = 'btn btn-danger';
}
}
function buttonsGreen() {
for (let i = 0; i < all_buttons.length; i++) {
all_buttons[i].className = 'btn btn-success';
}
}
function buttonsColorReset() { //##function that i am working on##
for (let i = 0; i < all_buttons.length; i++) {
all_buttons[i].classList.remove(all_buttons[i].classList[1]);
all_buttons[i].classList.add(copyAllButtons[i]);
}
}
function randomColors() {
for (let i = 0; i < all_buttons.length; i++) {
var x = Math.floor(Math.random() * 4);
var y = ['btn-primary', 'btn-danger', 'btn-warning', 'btn-success'];
all_buttons[i].className = 'btn ' + y[x];
}
}
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<title>challenge game</title>
</head>
<body>
<script src="home.js"></script>
<div class="container-1">
<h2>Challenge 1: Your Age in Days</h2>
<div class="flex-box-container-1">
<div> <button class="btn btn-primary" onclick="ageInDays()">Click Me</button></div>
<div> <button class="btn btn-danger" onclick="reset()">Reset</button></div>
</div>
</div>
<div class="flex-box-container-1">
<div id="flex-box-result">
</div>
</div>
<div class="container-2">
<h2>Challenge 2: Cat Generator</h2>
<button class="btn btn-success" id="cat-generator" onClick="generateCat()">Generate Cat</button>
<div class="flex-box-container-2" id="flex-cat-gen">
</div>
</div>
<div class="container-3">
<h2>Challenge 3:Rock,Paper,Scissors</h2>
<div class="flex-box-rps" id="flex-box-rps-div">
<img id="rock" src="https://cdn.drawception.com/images/panels/2017/2-4/wqmCPbxybn-4.png" alt=""
onClick="rpsGame(this)" width="250" height="250">
<img id="paper" src="https://sc04.alicdn.com/kf/UTB8apntp0nJXKJkSaiyq6AhwXXaR.jpg" alt="" onClick="rpsGame(this)"
width="250" height="250">
<img id="scissors" src="https://www.collinsdictionary.com/images/full/scissors_100136453.jpg" alt=""
onClick="rpsGame(this)" width="250" height="250">
</div>
</div>
<div class="container-4">
<h2 id="change-my-color">Challenge 4:Change the color of all buttons</h2>
<div class="flex-box-pick-color">
<form action="">
<select name="backdrop" id="background" onChange="buttonColorChange(this)">
<option value="random">Random</option>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="reset">Reset</option>
</select>
</form>
<button class="btn btn-primary">Wee!</button>
<button class="btn btn-danger">Yahoo!</button>
<button class="btn btn-warning">Google!</button>
<button class="btn btn-success">Facebook!</button>
</div>
</div>
</body>
</html>
CSS:
.container-1, .container-2 , .container-3 ,.container-4{
border: 1px solid blue;
width:75%;
margin: 0 auto;
text-align: center;
}
.flex-box-container-1, .flex-box-container-2,.flex-box-rps,.flex-box-pick-color{
display:flex;
border:1px solid purple;
padding: 10px;
flex-wrap:wrap;
flex-direction: row;
justify-content: space-around;
}
.flex-box-container-1 div{
display:flex;
padding: 10px;
border: 1 px solid black;
align-items: center;
}
.flex-box-container-2 img{
margin:10px;
box-shadow: 0px 10px 50px rgba(0,0,0,0.7);
}
.flex-box-rps img:hover{
box-shadow: 0px 10px 50px rgba(37,50,233,1);
}
Map button properties to a new array for later use, a minimal reproducable example.
// map button.btn properties to strings with id and class list
const all_buttons = [...document.querySelectorAll('button.btn')]
.map(b => `button#${b.id}, class: ${[...b.classList].join(', ')}`);
console.log(all_buttons);
// so ...
// save original classNames
const initialButtonClasses = [...document.querySelectorAll('button')]
.map(bttn => [...bttn.classList]);
// replacement classes
const green = [`btn`, `green`];
document.addEventListener(`click`, handle);
function handle(evt) {
if (evt.target.dataset.reset) {
return document.querySelectorAll('button.btn')
.forEach((btn, i) => {
btn.classList.remove(...btn.classList);
btn.classList.add(...initialButtonClasses[i]);
});
}
if (evt.target.dataset.green) {
return document.querySelectorAll('button.btn')
.forEach((btn, i) => {
btn.classList.remove(...btn.classList);
btn.classList.add(...green);
});
}
}
.green {
color: green;
}
<button id="a" class="btn z">bttnA</button>
<button id="b" class="btn y">bttnB</button>
<button id="c" class="btn x">bttnC</button>
<button data-green="1">all green</button>
<button data-reset="1">reset</button>
After searching for a long time, I found that I made a mistake in index.html, script tag should be put at the end of the body.

Javascript: How to check the winning state of all boxes/cells in a Tic Tac Toe game?

Ive attempted to make Tic Tac Toe as a javascript learning project and Im currently testing the first row winning state for Player 1, but for some reason every time the 3rd box is clicked regardless if the 1st and 2nd box has been clicked, it displays the winning message. Obviously thats not how tic tac toe works, as you need 3 in a row not 1 or 2.
Im using 2 arrays to test the winning state. 1 array for the boxes that have been already been clicked by the player, and 1 array that contains the winning combination for the first row. My goal was to test using an if statement to see if the boxes already clicked by the player matches the ones in the array with the winning combo.
I have tried using the .every method
for(let i=0;i<fRowBoxes.length;i++){
let fRowWin= () => X_Checked.includes((fRowBoxes[0],fRowBoxes[1],fRowBoxes[2])) ;
if(fRowBoxes.every(fRowWin) === true){
msg.innerHTML =`<h1> ${player1} Wins! </h1>`;
}
.textContent
if((fRowBoxes[0] && fRowBoxes[1] && fRowBoxes[2]).textContent == " x "){
msg.innerHTML =`<h1> ${player1} Wins! </h1>`;
}
and the .includes method
function checkScore(){
if (X_Checked.includes(fRowBoxes[0] && fRowBoxes[1] && fRowBoxes[2])){/*Only checks for fRowBoxes[2]?*/
msg.innerHTML =`<h1> ${player1} Wins! </h1>`;
}
}
Still nothing seems to work or it leads to the same result, any advice or suggestions would be highly appreciated.
let player1 = `<div class="symbol x"> x </div>`;
let player2 = `<div class="symbol o"> o </div>`;
let turn = player1;
let gridBoxes = document.querySelector('.grid').children;
let boxes = [];/*Stores all boxes in 3x3 grid*/
for(let i = 0; i < gridBoxes.length; i++){
boxes.push(gridBoxes[i]);
}
const msg = document.querySelector('div.msg ');
let fRowBoxes = [boxes[0],boxes[1],boxes[2]];/*Array with first row boxes*/
let sRowBoxes = [boxes[3],boxes[4],boxes[5]];
let tRowBoxes = [boxes[6],boxes[7],boxes[8]];
let fColBoxes = [boxes[0],boxes[3],boxes[6]];
let sColBoxes = [boxes[1],boxes[4],boxes[7]];
let tColBoxes = [boxes[2],boxes[5],boxes[8]];
let dBoxes1 =[boxes[0],boxes[4],boxes[8]];
let dBoxes2 = [boxes[2],boxes[4],boxes[6]];
let X_Checked = [];/*Stores boxes clicked by player 1*/
let O_Checked = [];
msg.display ='block';
function checkScore(){
if (X_Checked.includes(fRowBoxes[0] && fRowBoxes[1] && fRowBoxes[2])){/*Only checks for fRowBoxes[2]?*/
msg.innerHTML =`<h1> ${player1} Wins! </h1>`;
}
}
const tictactoe = (function(){/*START*/
msg.innerHTML = `<h1>Player 1 (X)</h1>`;
for(let i = 0; i<boxes.length; i++){
boxes[i].addEventListener('click',() =>{
if(boxes[i].value){
boxes[i].click(false);
}
else if(boxes[i].textContent === ""){
boxes[i].innerHTML = turn;
checkPlayer();
/**------------------------------------------- */
if (turn === player1){
O_Checked.push(boxes[i]);
console.log(O_Checked);
checkScore();/*Checks for a winner*/
}
else if (turn === player2){
X_Checked.push(boxes[i]);
console.log( X_Checked);
checkScore();
}
}
});}
}());/*END*/
let checkPlayer = (function(){
if(turn === player1){
turn = player2;
msg.innerHTML = `<h1>Player 2 (O)</h1>`;
}
else if(turn === player2){
turn = player1;
msg.innerHTML = `<h1>Player 1 (X)</h1>`;
}
});
let player1 = `<div class="symbol x"> x </div>`;
let player2 = `<div class="symbol o"> o </div>`;
let turn = player1;
let gridBoxes = document.querySelector('.grid').children;
let boxes = [];
for(let i = 0; i < gridBoxes.length; i++){
boxes.push(gridBoxes[i]);
}
const msg = document.querySelector('div.msg ');
let fRowBoxes = [boxes[0],boxes[1],boxes[2]];
let sRowBoxes = [boxes[3],boxes[4],boxes[5]];
let tRowBoxes = [boxes[6],boxes[7],boxes[8]];
let fColBoxes = [boxes[0],boxes[3],boxes[6]];
let sColBoxes = [boxes[1],boxes[4],boxes[7]];
let tColBoxes = [boxes[2],boxes[5],boxes[8]];
let dBoxes1 =[boxes[0],boxes[4],boxes[8]];
let dBoxes2 = [boxes[2],boxes[4],boxes[6]];
let X_Checked = [];
let O_Checked = [];
msg.display ='block';
function checkScore(){
if (X_Checked.includes(fRowBoxes[0] && fRowBoxes[1] && fRowBoxes[2])){
msg.innerHTML =`<h1> ${player1} Wins! </h1>`;
}
}
const tictactoe = (function(){/*START*/
msg.innerHTML = `<h1>Player 1 (X)</h1>`;
for(let i = 0; i<boxes.length; i++){
boxes[i].addEventListener('click',() =>{
if(boxes[i].value){
boxes[i].click(false);
}
else if(boxes[i].textContent === ""){
boxes[i].innerHTML = turn;
checkPlayer();
/**------------------------------------------- */
if (turn === player1){
O_Checked.push(boxes[i]);
console.log(O_Checked);
checkScore();
}
else if (turn === player2){
X_Checked.push(boxes[i]);
console.log( X_Checked);
checkScore();
}
}
});}
}());/*END*/
let checkPlayer = (function(){
if(turn === player1){
turn = player2;
msg.innerHTML = `<h1>Player 2 (O)</h1>`;
}
else if(turn === player2){
turn = player1;
msg.innerHTML = `<h1>Player 1 (X)</h1>`;
}
});
*{box-sizing:border-box;}
body{
margin:0;
padding:0;
font-family:arial;
}
.container{
display:flex;
height:100vh;
width:100%;
position:relative;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: tomato;
/* background-image:linear-gradient(to right, tomato, black, rgb(225, 225, 225)); */
}
.box:hover{
background-color:rgb(230,230,230);
transition: .4s ease-in-out;
}
.box,.grid{
cursor:pointer;
}
.box{
display:flex;
flex-direction:column;
justify-content: center;
align-items:center;
background-color:black;
}
.symbol{
font-size:4em;
font-style:bold;
font-family:arial;
text-transform:uppercase;
text-shadow:0px 0px 5px rgb(100,100,100);
}
.x{
color:tomato;
}
.o{
color:white;
}
.grid{
display: grid;
width: 350px;
grid-gap:10px;
border-radius:10px;
border:solid 10px white;
background-color:white;
grid-template-rows: repeat(3,100px);
grid-template-columns: repeat(3,1fr);
box-shadow: 0px 1px 8px rgb(50, 50, 50);
}
/* .grid:nth-child(even) */
.msg{
color:white;
position:absolute;
text-shadow: 0px 1px 3px rgb(50, 50, 50);
top:15px;
font-size:2em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv ="author" content="Carl Dawkins">
<meta name ="description" content="A Tic Tac Toe Game">
<link type="text/css" href="../css/style.css" rel="stylesheet">
<title>TicTacToe</title>
</head>
<body>
<div class="container">
<div class="msg"> </div>
<div class="grid">
<div id="box-1" class="box" ></div>
<div id="box-2" class="box" ></div>
<div id="box-3" class="box" ></div>
<div id="box-4" class="box" ></div>
<div id="box-5" class="box" ></div>
<div id="box-6" class="box" ></div>
<div id="box-7" class="box" ></div>
<div id="box-8" class="box" ></div>
<div id="box-9" class="box" ></div>
</div>
</div>
<script src="../js/script.js"></script>
</body>
</html>
You are storing elements to array and try to compare elements.
I think comparing value (o or x) or id (box-1 ...) is better
X_Checked.every(e => e.innerText.trim() == 'x')

Proper way of selecting created element?

I am getting an error message of TypeError: Node.removeChild: Argument 1 is not an object when trying to select my 'resetBtn' in my removeReset() function. You will have to click the game until you or the player wins five times. The reset button shows up, it gets clicked and even though it goes away I still get this error.
What is the proper way to target this element?
The error message is coming from this
document.body.removeChild(document.querySelector('#buttonReset'));
In the removeReset(). Below is the javascript and html code. Thank you
const resetBtn = document.createElement("button");
resetBtn.id = 'buttonReset';
const rock = document.getElementById('submitRock');
const paper = document.getElementById('submitPaper');
const scissors = document.getElementById('submitScissors');
rock.addEventListener("click", function() {
choices = ['rock', 'paper', 'scissors'];
playRound(choices[0]);
});
paper.addEventListener('click', function() {
choices = ['rock', 'paper', 'scissors'];
playRound(choices[1]);
});
scissors.addEventListener('click', function() {
choices = ['rock', 'paper', 'scissors'];
playRound(choices[2]);
});
function updateScore() {
if (document.getElementById("ps").innerText === '5') {
document.getElementById("finalScore").innerText = `Player Wins!`;
alert('Player Wins')
remove();
} else if (document.getElementById("cs").innerText === '5') {
document.getElementById("finalScore").innerText = `Computer Wins!`;
alert('Computer Wins')
remove();
}
}
function playRound(playerChoice) {
computerChoice = choices[Math.floor(Math.random() * 3)]
if (computerChoice === choices[0] && playerChoice === choices[2]) {
document.getElementById("cs").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
} else if (computerChoice === choices[1] && playerChoice === choices[0]) {
document.getElementById("cs").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
} else if (computerChoice === choices[2] && playerChoice === choices[1]) {
document.getElementById("cs").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
} else if (computerChoice === playerChoice) {
document.getElementById('scoreboard').textContent = `Draw! Computer picked ${computerChoice} and you picked ${playerChoice}!`;
updateScore();
} else document.getElementById('scoreboard').textContent = `You win! You picked ${playerChoice} and the computer picked ${computerChoice}.`;
document.getElementById("ps").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
}
function remove() {
document.getElementById("ps").innerText = 0;
document.getElementById("cs").innerText = 0;
resetBtn.innerText = 'Reset';
resetBtn.setAttribute("style",
`display: block; margin: 0 auto 7.5rem auto; background-color: blue; color: white; padding: 2rem; font-size: 5rem; `);
document.getElementById('rock').removeChild(rock);
document.getElementById('paper').removeChild(paper);
document.getElementById('scissors').removeChild(scissors);
document.getElementById('body').appendChild(resetBtn);
}
function removeReset() {
document.body.removeChild(document.querySelector('#buttonReset'));
document.getElementById('rock').appendChild(rock);
document.getElementById('paper').appendChild(paper);
document.getElementById('scissors').appendChild(scissors);
}
resetBtn.addEventListener('click', function() {
removeReset();
});
resetBtn.addEventListener('click', function() {
removeReset();
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Rock Paper Scissors</title>
<link rel="stylesheet" href="index.css" />
</head>
<body id="body">
<h1 class="title">Welcome to Rock, Paper, Scissors!</h1>
<h2 class="title-sub">Against the computer....</h2>
<h1 id="scoreboard"></h1>
<h1 id="finalScore"></h1>
<div id="scoreContainer">
<div id="playerScore">
<h3 class="playersTitle playerColor">Player</h3>
<p id="ps"></p>
</div>
<div id="computerScore">
<h3 class="playersTitle computerColor">Computer</h3>
<p id="cs"></p>
</div>
</div>
<div id="options">
<div id="rock">
<button id="submitRock">ROCK</button>
</div>
<div id="paper">
<button id="submitPaper">PAPER</button>
</div>
<div id="scissors">
<button id="submitScissors">SCISSORS</button>
</div>
</div>
<div id='resetContainer'></div>
<p id="winner"></p>
<script type="text/javascript" src="console.js"></script>
</body>
</html>
You are setting 2 listeners on the click of the resetBtn:
resetBtn.addEventListener('click', function() {
removeReset();
});
resetBtn.addEventListener('click', function() {
removeReset();
});
So when you click on reset, both the listeners are triggered ; the first listener works well, but the second can't remove the element because it doesn't exist anymore.
Just remove one of the listener and it will work well.
Don't append and remove the button. Put it in the HTML, and change its display style.
You also have redundant click listeners, as mentioned in the other answer. If you use this solution, you won't get an error because of it, but you should still remove the extra one.
const resetBtn = document.querySelector("#buttonReset");
const rock = document.getElementById('submitRock');
const paper = document.getElementById('submitPaper');
const scissors = document.getElementById('submitScissors');
rock.addEventListener("click", function() {
choices = ['rock', 'paper', 'scissors'];
playRound(choices[0]);
});
paper.addEventListener('click', function() {
choices = ['rock', 'paper', 'scissors'];
playRound(choices[1]);
});
scissors.addEventListener('click', function() {
choices = ['rock', 'paper', 'scissors'];
playRound(choices[2]);
});
function updateScore() {
if (document.getElementById("ps").innerText === '5') {
document.getElementById("finalScore").innerText = `Player Wins!`;
alert('Player Wins')
remove();
} else if (document.getElementById("cs").innerText === '5') {
document.getElementById("finalScore").innerText = `Computer Wins!`;
alert('Computer Wins')
remove();
}
}
function playRound(playerChoice) {
computerChoice = choices[Math.floor(Math.random() * 3)]
if (computerChoice === choices[0] && playerChoice === choices[2]) {
document.getElementById("cs").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
} else if (computerChoice === choices[1] && playerChoice === choices[0]) {
document.getElementById("cs").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
} else if (computerChoice === choices[2] && playerChoice === choices[1]) {
document.getElementById("cs").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
} else if (computerChoice === playerChoice) {
document.getElementById('scoreboard').textContent = `Draw! Computer picked ${computerChoice} and you picked ${playerChoice}!`;
updateScore();
} else document.getElementById('scoreboard').textContent = `You win! You picked ${playerChoice} and the computer picked ${computerChoice}.`;
document.getElementById("ps").innerText = Number(document.getElementById("cs").innerText) + 1;
updateScore();
}
function remove() {
document.getElementById("ps").innerText = 0;
document.getElementById("cs").innerText = 0;
document.getElementById('rock').removeChild(rock);
document.getElementById('paper').removeChild(paper);
document.getElementById('scissors').removeChild(scissors);
resetBtn.style.display = "block";
}
function removeReset() {
resetBtn.style.display = "none";
document.getElementById('rock').appendChild(rock);
document.getElementById('paper').appendChild(paper);
document.getElementById('scissors').appendChild(scissors);
}
resetBtn.addEventListener('click', function() {
removeReset();
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Rock Paper Scissors</title>
<link rel="stylesheet" href="index.css" />
</head>
<body id="body">
<h1 class="title">Welcome to Rock, Paper, Scissors!</h1>
<h2 class="title-sub">Against the computer....</h2>
<h1 id="scoreboard"></h1>
<h1 id="finalScore"></h1>
<div id="scoreContainer">
<div id="playerScore">
<h3 class="playersTitle playerColor">Player</h3>
<p id="ps"></p>
</div>
<div id="computerScore">
<h3 class="playersTitle computerColor">Computer</h3>
<p id="cs"></p>
</div>
</div>
<div id="options">
<div id="rock">
<button id="submitRock">ROCK</button>
</div>
<div id="paper">
<button id="submitPaper">PAPER</button>
</div>
<div id="scissors">
<button id="submitScissors">SCISSORS</button>
</div>
</div>
<div id='resetContainer'></div>
<p id="winner"></p>
<button id="buttonReset" style="display: none; margin: 0 auto 7.5rem auto; background-color: blue; color: white; padding: 2rem; font-size: 5rem;">Reset</button>
<script type="text/javascript" src="console.js"></script>
</body>
</html>

Categories