'How do I prevent the input of a number like 2.2.2 in my calculator?

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)
    }
}


Solution 1:[1]

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'))  // "valid input"
console.log(validate('1.2.3')) // "invalid input"

I'm not sure if this is faster or slower but it should theoretically be faster I guess.

Solution 2:[2]

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 > 2

An example:

const hasManySigns = (str, sign) => str.split(sign).length > 2

let foo = '1.2.3'
const validate = str => hasManySigns(str, '.') ? 'incorrect input' : 'correct input'

console.log(validate(foo))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2