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

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

Related

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.

clearing the display in a javascript calculator after pressing "="

I'm new to coding and I built a Javascript calculator, but I can't get the display to clear after Im done with one calculation. Instead, the result of the first calculation goes into the input for the second calculation. For eg if I do 3+5 it'll give me 8, but if I then press 4, the display says 84 which is why its a problem. I can clear the screen via the clear button but it gets tedious after every single calculation. Thank you.
//select all the buttons
const buttons = document.querySelectorAll('button');
//select the <input type="text" class+"display" disabled> element
const display = document.querySelector('.display');
//add eventListener to each button
buttons.forEach(function(button) {
button.addEventListener('click',calculate);
});
//calculate function
function calculate(event) {
//current clicked buttons value
var clickedButtonValue = event.target.value;
if(clickedButtonValue === '=') {
//check if the display is not empty then only do the calculation
if(display.value !== "") {
//calculate and show the answer to display
display.value = eval(display.value);
}
//if any key except "=" pressed again clear display
button.addEventListener('click',clearDisplay);
} else if (clickedButtonValue === 'C') {
//clear everything on display
display.value = "";
} else {
//otherwise concatenate it to the display
display.value += clickedButtonValue;
}
}
function clearDisplay(clickedButtonValue) {
if(clickedButtonValue !== "=") {
display.value = "";
}
}
You can have a variable that keeps track of the calculated state. If it has been calculated, clear the display and reset the state
var calculated = false;
function calculate( event ){
var clickedButtonValue = event.target.value;
if ( calculated ) {
display.value = "";
calculated = false;
}
if(clickedButtonValue === '=') {
if(display.value !== "") {
//calculate and show the answer to display
display.value = eval(display.value);
calculated = true;
}
}
// the rest of your logic here
}

Javascript - a problem with a two-step text input word conversion

Here I am making a word conversion tool which changes a certain word X into Y, or X to Y to Z by using javascript.
Progress: HERE
Here is the entire javascript:
var conversion = {
"one":"two",
};
var conversion2 = {
"two":"three",
};
var maxLength = Object.keys(conversion)
.reduce((a, b) => a.length > b.length ? a : b)
.length;
function convert (text) {
var converted = "";
var cur = 0;
while (cur < text.length) {
var testedPhoneme;
var symbol = undefined;
for (var length = maxLength; length > 0; length --) {
testedPhoneme = text.substr(cur, length);
if (conversion[testedPhoneme]) {
symbol = conversion[testedPhoneme];
break; // stop the loop
}
}
if (symbol) {
converted += symbol;
cur += testedPhoneme.length;
}
else {
converted += text[cur]
cur++;
}
}
return converted
}
var maxLength2 = Object.keys(conversion2)
.reduce((a, b) => a.length > b.length ? a : b)
.length;
function convert2 (text) {
var converted2 = "";
var cur2 = 0;
while (cur2 < text.length) {
var testedPhoneme2;
var symbol2 = undefined;
for (var length = maxLength2; length > 0; length --) {
testedPhoneme2 = text.substr(cur2, length);
if (conversion2[testedPhoneme2]) {
symbol2 = conversion2[testedPhoneme2];
break; // stop the loop
}
}
if (symbol2) {
converted2 += symbol2;
cur2 += testedPhoneme2.length;
}
else {
converted2 += text[cur2]
cur2++;
}
}
return converted2
}
function onInputTextChange(txt) {
var outputTextareaElem = document.getElementById("output_textarea");
var div = document.createElement("div");
var outputHtmlEntities = convert(txt);
div.innerHTML = outputHtmlEntities;
outputTextareaElem.value = div.innerText;
}
function onOutputTextChange(txt) {
var outputTextareaElem2 = document.getElementById("output_textarea2");
var div = document.createElement("div");
var outputHtmlEntities2 = convert2(txt);
div.innerHTML = outputHtmlEntities2;
outputTextareaElem2.value = div.innerText;
}
In the page that I made so far, there are three <textarea>s; Input, Output and Output2.
Currently, thanks to this piece of code;
var conversion = {
"one":"two",
};
var conversion2 = {
"two":"three",
};
If one is typed into Input, Output renders two. If two is manually typed into Output, three gets rendered in Output2.
Here is the problem, I want to render three in Output2 only through typing one into Input, but a direct two-step conversion seems unavailable yet. In other words, Input > Output (one > two) and Output > Output2 (two > three) conversion is available, but Input > Output > Output2 (one > two > three) is unavailable.
What needs to be done to solve this? Any help would be appreciated.
Ok, not exactly what you asked, but I could do something that works
Here is the example : https://jsfiddle.net/alias_gui3/8knw57u0/94/
how to use it :
to add new characters OR new languages/scripts
just complete the dictionnary :
var dictionnary = [
{
latin: "u",
japanese: "う",
emoji: "👋"
// add any script for every characters
},{
latin: "ku",
japanese: "く",
emoji: "👀"
},{
latin: "tsu",
japanese: "つ",
emoji: "🤖"
}
// add any character with the same format
]
to add new textareas :
give your textarea a recognizable id (eg. id="cyrillic")
then connect your textarea with this method:
// connect your textareas below !!
addTextArea(
document.querySelector("#latin"),
"latin"
);
addTextArea(
document.querySelector("#japanese"),
"japanese"
);
addTextArea(
document.querySelector("#emoji"),
"emoji"
);
// add new textarea with a new language here
then all the connections are done, you can edit all your textareas, if they recognise a character they will translate it in all the other textareas
full code
var dictionnary = [
{
latin: "u",
japanese: "う",
emoji: "👋"
// add any script for every characters
},{
latin: "ku",
japanese: "く",
emoji: "👀"
},{
latin: "tsu",
japanese: "つ",
emoji: "🤖"
}
// add any character with the same format
]
// calculate the max length for each language :
var max = {}
dictionnary.forEach(
char => {
Object.keys(char).forEach(script => {
max[script] = max[script]
? char[script].length > max[script]
? char[script].length
: max[script]
: char[script].length
})
}
)// now max contains the maximum length of sequence
// for each language
function findSymbol (
originSymbol,
originScript,
destinationScript
) {
for (var i = 0; i < dictionnary.length; i++) {
var char = dictionnary[i];
if (char[originScript] === originSymbol) {
return char[destinationScript]
}
}
return false // if not found
}
function translate (
text,
originScript,
destinationScript
) {
var cur = 0;
var translated = "";
var maxLength = max[originScript]
while (cur < text.length) {
var testedPhoneme;
var symbol = false;
for (var length=maxLength; length > 0; length--) {
testedPhoneme = text.substr(cur, length);
symbol = findSymbol(
testedPhoneme,
originScript,
destinationScript
)
if (symbol) {
break; // stop the loop
}
}
if (symbol) {
translated += symbol;
cur += testedPhoneme.length;
}
else {
translated += text[cur];
cur++;
}
}
return translated
}
var textareas = []; // the list of your textareas
function addTextArea(element, originScript) {
textareas.push({
element: element,
script: originScript
})
element.addEventListener("input", function (e) {
signalTextChanged(element, originScript)
});
}
function signalTextChanged (
originElement,
originScript
) {
var originText = originElement.value;
textareas.forEach(function (textarea) {
if (textarea.element !== originElement) {
var translated = translate(
originText,
originScript,
textarea.script
)
textarea.element.value = translated;
}
})
}
// connect your textareas below !!
addTextArea(
document.querySelector("#latin"),
"latin"
);
addTextArea(
document.querySelector("#japanese"),
"japanese"
);
addTextArea(
document.querySelector("#emoji"),
"emoji"
);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
</script>
</head>
<body>
<center>
<h1>Latin to foreign script converter 3</h1>
<p>type in u, ku, tsu in the FIRST panel</p>
<textarea
id="latin"
autofocus=""
placeholder="type text in latin ! (u ku or tsu)"
rows="10"
style="width:300px"></textarea>
<textarea
id="japanese"
rows="10"
placeholder="type text in japanese !"
style="width:300px"></textarea>
<textarea
id="emoji"
rows="10"
placeholder="type text in emojis !!"
style="width:300px"></textarea>
</center>
</center>
</body>
</html>
I'm not sure if I fully understand what you're trying to achieve here
There are some duplications in your code, what if you'll have 10 fields for output, will you create a special function for each of them?
Try to simplify things.
One way would be to loop through all of your lists as follows:
Put all your conversation in a list
var lists = [conversion, conversion2];
Add isInNextList function to check if your text is a key in the next list
function isInNextList(index, key) {
if (lists.length < index) {
return false;
}
return Object.keys(lists[index]).includes(key);
}
change your onInputTextChange function as follow:
function onInputTextChange(txt) {
var index = 0;
var text = txt;
while (isInNextList(index, text)) {
var outputTextareaElem = document.getElementById(
'output_textarea_' + index
);
var div = document.createElement('div');
text = lists[index][text]; //next key
index++;
div.innerHTML = text;
outputTextareaElem.value = div.innerText;
}
}
change your output textarea's ids to contain the index
id="output_textarea_0"
id="output_textarea_1"
There are other improvements that can be made like:
Creating the output fields dynamically,
Clear output fields etc.

Taking var with JS prompt - how can I make it through HTML form?

I've been learning HTML/CSS/JavaScript for a couple of weeks now, and I am currently practicing on a mini project, which consists of letting people answer math questions, and validating their answers.
My current progress can be seen at http://dany.faceflow.com
I know I am probably not using the best strategy to develop this mini game, so any advice would be useful on that. However right now, the problem is that I am taking the user answer with a variable through JS prompt, and I want to do it via an HTML form (less annoying).
In my source code you can see this line within the function:
var userInput = prompt(numb1 + symbol + numb2);
Then, still in the same function, I have an if/else structure to compare the user's answer with the right answer. The code works, I just don't know how to make the prompt HTML-based instead. I've tried an html form with an ID and in the JS using getElementById, document.write and some other stuff but I never got it to work for that part.
(Here's all the JS)
var number1 = function() {
var numb1 = Math.floor(Math.random() * 41) + 10;
return numb1;
}
var number2 = function() {
var numb2 = Math.floor(Math.random() * 41) + 10;
return numb2;
}
var userAnswer = function() {
var numb1 = number1();
var numb2 = number2();
var randomSymbol = Math.random();
if (randomSymbol > 0.5) {
var symbol = "+";
} else {
var symbol = "-";
}
// add the math question in the html bubble
document.getElementById('bubble').innerHTML = numb1 + symbol + numb2;
// Prompts the user to give an answer. Change this to HTML.
var userInput = prompt(numb1 + symbol + numb2);
//var userInput = document.getElementById('tw').value;
if (symbol == "+" && userInput == (numb1 + numb2)) {
document.getElementById('feedback').innerHTML = "Congratulations!";
} else if (symbol == "+" && userInput !== (numb1 + numb2)) {
document.getElementById('feedback').innerHTML = "Wrong!";
} else if (symbol == "-" && userInput == (numb1 - numb2)) {
document.getElementById('feedback').innerHTML = "Congratulations!";
} else if (symbol == "-" && userInput !== (numb1 - numb2)) {
document.getElementById('feedback').innerHTML = "Wrong!";
} else {
alert("Something wrong happened. Try again.");
}
return userInput;
}
(The HTML)
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="css/stylesheet.css" />
<script src="js/script.js"></script>
<title>Improve Your Math Skills!</title>
</head>
<body>
<center>
<button onclick="userAnswer()">PLAY NOW!</button>
<div id="bubble"></div>
<div id="feedback"></div>
<!-- <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> -->
</center>
</body>
</html>
Thank you
You can use an input tag instead of the prompt. Change the HTML just as in Dinesh's answer;
<div id="bubble"></div>
<div id="inp" style="display: none;">
<input type="text" id="ans"></input> <button id="subBtn">Submit</button>
</div>
<div id="feedback"></div>
Now, for the JavaScript, there a few things to consider. Firstly, you have
var number1 = function() {
var numb1 = Math.floor(Math.random() * 41) + 10;
return numb1;
}
var number2 = function() {
var numb2 = Math.floor(Math.random() * 41) + 10;
return numb2;
}
Both functions do exactly the same thing; you don't need two separate functions to get two separate random numbers. So, only one function will suffice.
var number = function() {
return Math.floor(Math.random() * 41) + 10;
};
Secondly, now we have two functions. userAnswer to post a new question when 'Play Now!' is clicked and, say, evalAnswer to evaluate the answer written in the input field when 'Submit' is clicked.
In userAnswer, you generate two new random numbers and figure out which operation will be conducted on them. At this point, you can simply evaluate the answer yourself and store it in a global variable. This makes things easier when you evaluate the answer, you only need to do a simple comparison.
Other than that, you update innerHTML for bubble and display the div inp.
In evalAnswer, you get the value from ans and compare it with the previously computed value of the current answer, and then accordingly update feedback.innerHTML.
Here's the code;
//variable to maintain the current answer
var curAns = 0;
//Here, I get all the DOMElements I will use
var playBtn = document.getElementById('playBtn');
var bubble = document.getElementById('bubble');
var inp = document.getElementById('inp');
var ans = document.getElementById('ans');
var subBtn = document.getElementById('subBtn');
var feedback = document.getElementById('feedback');
//I add the event listeners
//This is equivalent to using 'onclick'
//in the HTML, and doing it this way is only
//my personal preference
playBtn.addEventListener('click', function() {userAnswer();}, false);
subBtn.addEventListener('click', function() {evalAnswer();}, false);
//Function to get random number
var number = function() {
return Math.floor(Math.random() * 41) + 10;
};
//This function will be executed when 'Play Now!' is clicked.
var userAnswer = function() {
//Get two separate random numbers in
//numb1 and numb2
var numb1 = number();
var numb2 = number();
var symbol = '';
var randomSymbol = Math.random();
//Determine the operation to be used
//and compute the corresponding correct answer for the current
//question
if (randomSymbol > 0.5) {
symbol = "+";
curAns = numb1+numb2;
} else {
symbol = "-";
curAns = numb1-numb2;
}
//Add math question to bubble
bubble.innerHTML = 'What is ' + numb1 + ' ' + symbol + ' ' + numb2 + '?';
feedback.innerHTML = '';
//Make inp div visible
inp.style.display = 'block';
//Reset input value to ''
ans.value = '';
};
//This function will be executed when 'Submit' is clicked
var evalAnswer = function() {
//Simply compare input value with computed
//answer and update feedback
if(parseInt(ans.value) !== curAns) {
feedback.innerHTML = 'Wrong answer, try again!';
}
else {
feedback.innerHTML = 'You got it right, congratulations!';
}
};
Here's a working example.
Hope that helped!
What I understand from your question is that you need the same functionality in HTML itself rather than driven by JS in a prompt box, if so,the below additions to your code should help:
HTML adition:
<div id="bubble"></div>
<div id="check_ans_div" style="display:none;">
<input type="text" id="txt_answer" />
<input type="submit" value="Check Answer" onclick="checkanswer()" />
</div>
<div id="feedback"></div>
JS changes:
var number1 = function() {
var numbx = Math.floor(Math.random() * 41) + 10;
return numbx;
}
var number2 = function() {
var numby = Math.floor(Math.random() * 41) + 10;
return numby;
}
var numb1=0; var numb2=0;
var userAnswer = function() {
numb1 = number1();
numb2 = number2();
var randomSymbol = Math.random();
if (randomSymbol > 0.5) {
var symbol = "+";
} else {
var symbol = "-";
}
// add the math question in the html bubble
document.getElementById('bubble').innerHTML = numb1 + symbol + numb2;
if(document.getElementById('check_ans_div').style.display=='none')
document.getElementById('check_ans_div').style.display='block';
document.getElementById('txt_answer').value='';
}
function checkanswer(){
var userInput= document.getElementById('txt_answer').value;
if (symbol == "+" && userInput == (numb1 + numb2)) {
document.getElementById('feedback').innerHTML = "Congratulations!";
} else if (symbol == "+" && userInput !== (numb1 + numb2)) {
document.getElementById('feedback').innerHTML = "Wrong!";
} else if (symbol == "-" && userInput == (numb1 - numb2)) {
document.getElementById('feedback').innerHTML = "Congratulations!";
} else if (symbol == "-" && userInput !== (numb1 - numb2)) {
document.getElementById('feedback').innerHTML = "Wrong!";
} else {
alert("Something wrong happened. Try again.");
}
}

Categories