how to decrease or increase a number bu pressing the button Java script - javascript

Hey guys i've made buttons of '+' and '-' and there is a number which i need to increase or decrease while pressing the + or -, here my code but it isn't working. Will be glad if you can help me.
thank you!
button class="plus_minus"></button><span class="number">1</span><button class="minus_plus"></button>
my JS
const plus = document.querySelector('.plus_minus'),minus = document.querySelector('.minus_plus');
let number = parseInt(document.querySelector('.number'));
plus.addEventListener('click',() => {number++ ;});
minus.addEventListener('click',() => {number--;
});

Anyway, I would suggest this:
HTML :
<button class="minus">-</button><span id="number">1</span><button class="plus">+</button>
One class for "minus" button and one class for "plus" button. In your code you didn't differenciate them.
JS:
const minus = document.querySelector('.minus')
const plus = document.querySelector('.plus');
plus.addEventListener('click',() => document.getElementById("number").textContent++);
minus.addEventListener('click',() => document.getElementById("number").textContent--);
Add two listeners that directly increment/decrement the value.

I updated your code and it will help you.
let number = parseInt(document.querySelector('.number'));
document.querySelector('.number') returns element with "number" classname , not it's content text.
document.querySelector('.number').innerText returns the element's content text.
let oldVal = 1;
let newVal = oldVal++;
// output: newVal = 1 oldVal = 2
let oldVal = 1;
let newVal = ++oldVal;
// output: newVal = 2 oldVal = 2
const plus = document.querySelector('.plus_minus'),
minus = document.querySelector('.minus_plus');
let number_el = document.querySelector('.number');
plus.addEventListener('click', () => {
let val = parseInt(number_el.innerText);
number_el.innerText = ++val;
});
minus.addEventListener('click', () => {
let val = parseInt(number_el.innerText);
number_el.innerText = --val;
});
<button class="plus_minus">+</button>
<span class="number">1</span>
<button class="minus_plus">-</button>

Right now you number variable is reference of the span element.
You should get the value (innerHTML) of that
let number = parseInt(document.querySelector('.number').innerHTML);
In the event listener you should update the DOM (innertHTML of span) again after the value is updated.
plus.addEventListener('click',() => {
number++ ;
document.querySelector('.number').innerHTML = number;
});
minus.addEventListener('click',() => {
number--;
document.querySelector('.number').innerHTML = number;
});

Related

Star Rating Js + html with symfony

I'm working on a project with symfony 4. I want to implement a star rating system. I display 5 stars in each row in a table. I have two problems, one is more important than the other.
So the first issue is that I want to be able to retrieve the value of the star I selected. If I select 5 stars, I want to get that value back in my entity controller.
The second issue is that, currently, let's say I have 5 items in my table, so 5 rows. Currently, if I select 5 stars in one row it's selected for all rows and I can't select another value anymore. So, it's global or something.
Here is the javascript I'm using:
<script>
const stars = document.querySelectorAll('.star');
let check = false;
stars.forEach(star => {
star.addEventListener('mouseover', selectStars);
star.addEventListener('mouseleave', unselectStars);
star.addEventListener('click', activeSelect);
})
function selectStars(e) {
const data = e.target;
const etoiles = priviousSiblings(data);
if (!check) {
etoiles.forEach(etoile => {
etoile.classList.add('hover');
})
}
}
function unselectStars(e) {
const data = e.target;
const etoiles = priviousSiblings(data);
if (!check) {
etoiles.forEach(etoile => {
etoile.classList.remove('hover');
})
}
}
function activeSelect(e) {
if (!check) {
check = true;
document.querySelector('.note').innerHTML = 'Note ' + e.target.dataset.note;
}
}
function priviousSiblings(data) {
let values = [data];
while (data === data.previousSibling) {
if (data.nodeName === 'I') {
values.push(data);
}
}
return values;
}
</script>
And Here is the twig.html I'm displaying:
<td>
<i class="star" data-note="1">★</i>
<i class="star" data-note="2">★</i>
<i class="star" data-note="3">★</i>
<i class="star" data-note="4">★</i>
<i class="star" data-note="5">★</i>
<i class="note">Note:</i>
</td>
I want to be able to retrieve the value once I made a selection, and to have a different selection for each row I have.
The problem is with the "mouseover" and "mouseleave" event handlers - selectStars and unselectStars. In "selectStars", you are adding the class to only one star. And in "unselectStars", you were not resetting, or applying the "remove" class method to other stars.
Anyway, here is how I have achieved what you are trying to do:
const ratings = document.querySelectorAll('.rating');
ratings.forEach(rating =>
rating.addEventListener('mouseleave', ratingHandler)
);
const stars = document.querySelectorAll('.rating .star');
stars.forEach(star => {
star.addEventListener('mouseover', starSelection);
star.addEventListener('mouseleave', starSelection);
star.addEventListener('click', activeSelect);
});
function ratingHandler(e) {
const childStars = e.target.children;
for(let i = 0; i < childStars.length; i++) {
const star = childStars.item(i)
if (star.dataset.checked === "true") {
star.classList.add('hover');
}
else {
star.classList.remove('hover');
}
}
}
function starSelection(e) {
const parent = e.target.parentElement
const childStars = parent.children;
const dataset = e.target.dataset;
const note = +dataset.note; // Convert note (string) to note (number)
for (let i = 0; i < childStars.length; i++) {
const star = childStars.item(i)
if (+star.dataset.note > note) {
star.classList.remove('hover');
} else {
star.classList.add('hover');
}
}
}
function activeSelect(e) {
const parent = e.target.parentElement
const childStars = parent.children;
const dataset = e.target.dataset;
const note = +dataset.note; // Convert note (string) to note (number)
for (let i = 0; i < childStars.length; i++) {
const star = childStars.item(i)
if (+star.dataset.note > note) {
star.classList.remove('hover');
star.dataset.checked = "false";
} else {
star.classList.add('hover');
star.dataset.checked = "true";
}
}
const noteTextElement = parent.parentElement.lastElementChild.children.item(0)
noteTextElement.innerText = `Note: ${note}`;
}
You might notice I have a .rating class component. This is a div which I have created to hold all these "stars". Here is a link to a codepen I have created. Feel free to play around with it.
And as a note, please provide codepen (or any other) demos so that we can debug a bit better and faster.
I hope the codepen link would help you solve your problem.

How can I create a reset button for this game?

I have my current code posted, I'm trying to create a reset button. A button has already been created in my HTML, and I'm grabbing it at the bottom, and adding an event listener, which isn't working for some reason, also trying to figure out the correct code to add it for my game resets when the button is clicked. However having a difficult time with the syntax.
// Array of words
const words = ['planet', 'stars', 'astroid', 'moon', 'satilite', 'orbit', 'universe', 'umbra', 'lunar', 'space', 'astronomy', 'eclipse', 'nebula', 'mars', 'meteorite']
// guesses Array
let myGuesses = []
//variables
let wordSpace = ' - '
let guess = ' '
let space; //number of spaces in word
//score
let tries = 10
let counter ;
//Get random word
let index = Math.floor(Math.random()* words.length)
//play function
function play() {
let userInput = prompt(`would you like to play spaceman? (Y/N)`, "Y")
console.log(words[index])
for(let i = 0; i < words[index].length; i++){
console.log(words[0][i])
let div = document.createElement('div')
div.classList.add('letters')
div.innerHTML=' - '//words[0][i]
document.querySelector('.word-space').append(div)
}
}
//handle click function, inactivates buttons, and changes color to grey; once clicked
let handleclick = e => {
e.target.removeEventListener('click', handleclick)
e.target.style.backgroundColor= 'grey'
console.log(e.target.innerHTML)
myGuesses.push(e.target.innerHTML)
console.log(myGuesses)
console.log(words[index].includes(e.target.innerHTML))
if(words[index].includes(e.target.innerHTML)){
document.querySelector('.word-space').innerHTML= ' '
// let correct = document.createElement('ul')
for(let i = 0; i < words[index].length; i++){
// correct.setAttribute('id','correctLetters' )
// let guess= document.createElement('li')
// guess.setAttribute('class','guess')
console.log(words[0][i])
let div = document.createElement('div')
div.classList.add('letter')
if (myGuesses.includes(words[index][i])){
div.innerHTML = words[index][i]
} else {
div.innerHTML = ' - '
}
document.querySelector('.word-space').append(div)
}
getNumOfTries()
} else {
tries --
getNumOfTries()
}
}
function ans () {
const buttons = document.querySelectorAll('.letter')
buttons.forEach(letter => letter.addEventListener('click',handleclick))
}
ans()
function getNumOfTries (){
console.log(tries)
const showTries = document.querySelector('#myTries')
showTries.innerHTML = ' You have ' + tries + ' tries'
if(tries < 1){
setTimeout(() =>{prompt(`Would you like to try again? (Y,N)`, 'Y')
showTries.innerHTML = 'You loose!'
},2000)
}
// if(tries > 0 && words[index].length === myGuesses.length) {
if(tries > 0 && Array.from(document.querySelectorAll('.letters')).every(letter => letter.innerHTML !== ' - ')) {
// showTries.innerHTML = 'You Win!'
setTimeout(() =>{alert(`You Win!`)
showTries.innerHTML = 'You Win!'
},1000)
}
}
//reset game
let tryAgain = document.querySelector('.Try-Again')
tryAgain.addEventListener('clcik', play)
prevent
div.innerHTML=' - '//words[0][i]
document.querySelector('.word-space').append(div)
play()
You've got a typo there :)
tryAgain.addEventListener('clcik', play)
some notes to the written code:
you don't need to reference the element, if you're not going to use it elsewhere, just do:
document.querySelector('.Try-Again')?.addEventListener('click', play);
i'm not sure about what the "prevent" should do here
you haven't defined a global reference to a "div" parameter that you want to use at:
div.innerHTML=' - '//words[0][i]
use semicolon ';' by the end of each executed code for better code clarity + checkout some coding standards
use code editors like Visual Studio code or other tools - they usually have some basic code formatter (learn they shortcuts, it will optimize your coding process) + other usefull features like clicking through defined param references etc.

Can you use decrement/increment operator but skip 0 in JavaScript just like how continue works?

I have here a number counter code where it has increment and decrement buttons. Whenever you click a button, it does its job of incrementing and decrementing the value of the input.
// =number_counter
function decrement(e) {
const btn = e.target.parentNode.parentElement.querySelector(
'button[data-action="decrement"]'
);
const target = btn.nextElementSibling;
let value = Number(target.value);
value--;
target.value = value;
toggleRowClass(btn, value, ["bg-red-200", "item-returned"]);
}
function increment(e) {
const btn = e.target.parentNode.parentElement.querySelector(
'button[data-action="decrement"]'
);
const target = btn.nextElementSibling;
let value = Number(target.value);
value++;
target.value = value;
toggleRowClass(btn, value, ["bg-red-200", "item-returned"]);
}
const decrementButtons = document.querySelectorAll(
`button[data-action="decrement"]`
);
const incrementButtons = document.querySelectorAll(
`button[data-action="increment"]`
);
decrementButtons.forEach(btn => {
btn.addEventListener("click", decrement);
});
incrementButtons.forEach(btn => {
btn.addEventListener("click", increment);
});
This time, I wanted to skip 0 when clicking the buttons having the input value as either -1 or 1. Can I add a behavior such as continue; without the loop and just having increment/decrement operators?
Continue does't exist outside of the loops. The simplest solution for you is to add a condition inside increment/decrement where you would check if the current value is -1/1 and add additional logic in those cases :)
The solution was just to set the value = 1 or value = -1;
function decrement(e) {
const btn = e.target.parentNode.parentElement.querySelector(
'button[data-action="decrement"]'
);
const target = btn.nextElementSibling;
let value = Number(target.value);
value--;
if (value == 0) {
value = -1;
target.value = value;
} else {
target.value = value;
}
toggleRowClass(btn, value, ["bg-red-200", "item-returned"]);
}
function increment(e) {
const btn = e.target.parentNode.parentElement.querySelector(
'button[data-action="decrement"]'
);
const target = btn.nextElementSibling;
let value = Number(target.value);
value++;
if (value == 0) {
value = 1;
target.value = value;
} else {
target.value = value;
}
toggleRowClass(btn, value, ["bg-red-200", "item-returned"]);
}
Sorry I have missed it.

Prevent user to type more than one decimal dot in a JS calculator

In my calculator project with Javascript I'm trying to prevent a user to input multiple decimal points if there is one already (example : 5.2.3.56 not allowed).
All the numbers, decimal and operator buttons that the user clicks on are pushed and stored in an array.
How can I check if there is a dot already and disable the button using an array of values?
const numButtons = document.querySelectorAll('.number');
const opButtons = document.querySelectorAll('.operation');
const display = document.querySelector('.display');
const decimal = document.querySelector('.decimal');
let opClicked;
let resultArray = [];
// Event listeners
numButtons.forEach(number => {
number.addEventListener('click', function(e) {
numClicked = e.target.textContent;
if (display.textContent === '0') {
display.textContent = '';
} else if (resultArray[resultArray.length - 1] === opClicked){
display.textContent = '';
}
resultArray.push(numClicked);
display.textContent += numClicked
});
opButtons.forEach(operator => {
operator.addEventListener('click', function(e) {
empty();
opClicked = e.target.textContent;
resultArray.push(opClicked);
operate();
});
decimal.addEventListener('click', function(e) {
let decimalClicked = e.target.textContent;
resultArray.push(decimalClicked);
display.textContent += decimalClicked;
});
decimal.addEventListener('click', function(e) {
var decimalClicked = e.target.textContent;
if(resultArray.includes(decimalClicked) == false){
resultArray.push(decimalClicked);
display.textContent += decimalClicked;
}
});
The code above checks the resultArray to see if it contains a decimal, if it does not, then it appends the decimal to the array

How to increase numbers line by line

Plunker.
I have Implemented the above plunker, In that plunker the rowId is increasing with Alphabets.Like the below
There will be + and ++ and - buttons in that component.
If I press + then The Rowid will start from Starting Alphabet(A).
If I press ++ Then The parent rowid + starting with Starting Alphabet means(AA).
And Again if I press ++ then parent rowId + starting with Starting Alphabet means(AAA). Like this it will increase.
Please access the Plunker here.
But I want to achieve that functionality with Numbers means
For single plus it should show 1, For ++ it should show 111 like this I need to achieve.
Can you please help me to do this functionality.
var newRow = {
"rowId": "A"
}
$scope.componentList = [];
$scope.componentList.push(angular.copy(newRow));
$scope.addParentRow = function(rowId) {
var newGridRow = angular.copy(newRow);
var lastChar = getListOfSameLevel(rowId, true); //isParentRow
var parentId = rowId.length > 1 ? rowId.slice(0, rowId.length - 1) : "";
newGridRow.rowId = parentId + getNextChar(lastChar);
$scope.componentList.push(newGridRow);
}
$scope.addChildRow = function(rowId) {
var newGridRow = angular.copy(newRow);
var lastChar = getListOfSameLevel(rowId, false);
if (rowId.length === lastChar.length) {
newGridRow.rowId = rowId + "A";
} else {
var parentId = lastChar.length > 1 ? lastChar.slice(0, lastChar.length - 1) : "";
newGridRow.rowId = parentId + getNextChar(getLastChar(lastChar));
}
$scope.componentList.push(newGridRow);
};
var getNextChar = function(inputChar) {
return String.fromCharCode(inputChar.charCodeAt(0) + 1);
};
var getLastChar = function(fullStr) {
return fullStr.slice(-1);
};
You need to change the initial value of newRow.rowId from A to 1 and to change the initiation of the next digits from A to 1 in the addChildRow function like this :
if (rowId.length === lastChar.length) {
newGridRow.rowId = rowId + "1";
}
Here is your plunker with numbers

Categories