I have been working on a simple JS calculator using an OOP approach. I am struggling to create a fix that prevents the input of extra decimals. For example, a user can input 3.2.1.5. Ideally, this calculator would display the entire expression on the digital calculator screen before solving it and returning the result. With this in mind, simply preventing a user from adding a second decimal would prevent them from adding(or whatever operator they may choose) multiple decimals together. I have considered using .split() and .join() on operators in the input, but it is beginning to get convoluted as there are multiple operators to consider. Ideally, I want to avoid regex.
const keys = document.querySelector('.calc-buttons');
keys.addEventListener('click', event => {
const {target} = event
const {value} = target
if(!target.matches('button')){
return
}else{
calculator.parseInput(value)
//console.log(value)
}
})
const calculator = {
displayText: '0',
prevTotal: null,
parseInput(value){
//have any of the special buttons(AC, decimal, =) been clicked?
switch(value){
case '=':
//calculate answer
this.calcAnswer(this.displayText)
break
case 'AC':
//clear screen & stored values
this.clearAll()
break
case '.':
//create decimal
if(this.displayText == 0){
//pass'0.'
this.addText('0.')
}else{
//add value to text string
this.addText(value)
}
break
default:
//add value to text string
this.addText(value)
break
}
},
addText(value){
if(this.displayText == '0'){
this.displayText = ''
}else if(this.prevTotal !== null){
this.displayText = this.prevTotal
this.prevTotal = null
}
//check if previous input is a number
if(isNaN( (value)) && isNaN( (this.displayText))){
if(isNaN(this.displayText.slice(-1))){
return
}
}else if(value == '.' && this.displayText.slice(-1) == '.'){
return
}
this.displayText = value
//output display text to screen
this.outputText(this.displayText)
},
outputText(text){
document.querySelector('.screen').value = text
},
calcAnswer(equation){
let result = Function("return " equation)()
this.outputText(result)
//console.log(equation)
//console.log(result)
this.prevTotal = result
},
clearAll(){
this.displayText = '0',
this.prevTotal = null
this.outputText(this.displayText)
}
}
CodePudding user response:
You can create a simple function to avoid repetition of code and hiding unnecessary details in functions. In addition, it helps to reduce convolution.
So create a function which will check eligibility of input and based on result just notify user or remove last incorrect character.
The sketch of function could like this:
const hasManySigns = (str, sign) => str.split(sign).length > 1
An example:
const hasManySigns = (str, sign) => str.split(sign).length > 1
let foo = '1.2.3'
const validate = str => hasManySigns(str, '.') ? 'incorrect input' : 'correct input'
console.log(validate(foo))
CodePudding user response:
Functions are based on StepUp's answer (which is wrong AFAIK; it should be .length > 2
but I can't comment yet)
const hasManySymbols = (str, symbol) => {
const firstIndex = str.indexOf(symbol) // find the first occurrence of the symbol
if(firstIndex == -1) return false // if there is no first occurrence there are not many symbols
return str.indexOf(symbol, firstIndex 1) != -1 // whether or not there is a second occurrence
}
const validate = str => hasManySymbols(str, '.') ? 'invalid input' : 'valid input'
console.log(validate('1.23'))
console.log(validate('1.2.3'))
I'm not sure if this is faster or slower but it should theoretically be faster I guess.