skip to Main Content

i’ve started a calculator project along a course I’m doing on Javascript, however even though the code is identical to what they’ve done (or at least to what they taught) I’ve found trouble in replicating the same result.
What happens is that when I press enter the button that was previously clicked gets clicked again and I have no idea why. The backspace simply doesn’t work.

What was supposed to happen was clicking the enter key and the calculate() function being triggered,thus completing the calculation that was onscreen. The backspace key was supposed to delete one number from the display.

function createCalculator(){
    
    return {
        display: document.querySelector('.display'),
        btnClear: document.querySelector('.btn-clear'),




        // Methods go below, attributes above 


        start(){
            this.buttonClick();
            this.pressEnter();
            this.pressBackspace();
        },

        clearDisplay(){
            this.display.value = '';
        },
        
        pressEnter(){
            document.addEventListener('keyup', (e) => {
                const key = e.target
                if( key.keycode === 13) {
                    this.calculate() }
            })
        },

        pressBackspace(){
            document.addEventListener('keyup', (e) => {
                const key = e.target
                if( key.keycode === 8) {
                    this.deleteNumber() }
            })
        },


        deleteNumber(){
            this.display.value = this.display.value.slice(0, -1)
        },

        buttonClick(){
            document.addEventListener('click', function(e) {
                let element = e.target
                
                if ( element.classList.contains('btn-num')){
        
                    this.btnForDisplay(element.innerText); 
                }

                if(element.classList.contains('btn-clear')){
                    this.clearDisplay();
                }

                if(element.classList.contains('btn-del')){
                    this.deleteNumber();
                }

                if(element.classList.contains('btn-eq')){
                    this.calculate()
                }
            }.bind(this)) 
        },

        btnForDisplay(valor){
            this.display.value += valor;
        },

        // The function that allows the calculations to occur 
        calculate(){
            let conta = this.display.value
            try {
                conta = eval(conta) // I know using eval might be a security compromise
                if(typeof conta === "Nan" || typeof conta === "undefined" || typeof conta === "null"){
                    alert("Conta inválida")
                    return
                }
                this.display.value = String(conta)
            }catch (e){
                alert("Conta inválida")
                return
            }
        },
    };
}

const calculator = createCalculator()
calculator.start()

2

Answers


  1. You’re dealing with a common issue using the this pointer.

    Your event listeners are called by the window object. In JavaScript that means this will be the window object instead of the calculator.

    In each event listener use calculator instead of this for a quick fix.

    The proper solution requires binding the functions to the calculator.

    Here is how you would do it for the pressEnter function:

    calculator.pressEnter = calculator.pressEnter.bind(calculator);
    
    Login or Signup to reply.
  2. You have multiple things going on here.

    You are trying to get the code from the e.target, which is the document/body element, which don’t have have the keyCode or code properties.

    What you need to do is get the code from the event itself.

    So, you have to change it to:

    if( e.keycode === 13) {
        this.calculate() 
    }
    

    Then, the property, which you are trying to get, is keyCode and not keycode. But it is advisable not to use keyCode anymore, since it has been deprecated for some time.

    It is better to either use code or key.

    So, your two options are:

    if( e.code === 'Enter') {
        this.calculate() 
    }
    

    or

    if( e.key === 'Enter') {
        this.calculate() 
    }
    

    Also, it might be helpful to add preventDefault as the first thing inside the listener, just to prevent any unwanted default behaviors.

    And Dan Mullin explained about the this in their answer.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search