0

I wrote a calculator on pure JS using DOM. And the problem I've faced was that if I input an expression using buttons and push "=" button, everything works great. I mean the expression is being replaced by result. But if I paste expression to input using CTRL-V, then nothing happens. Expression remains in input form and is not replaced by result. Even though I can console the result. Here's the code

class Calculator extends HTMLElement {
  constructor() {
    super()
    this.defaultValue = 0
    this.root = document.getElementById('root')
    this.calcContainer = document.createElement('div')
    this.calcContainer.setAttribute('class', 'calculator card border border-dark')
    this.root.appendChild(this.calcContainer)

    this.addInput()

    this.onClickButton = (e, button) => {
      e.preventDefault()
      const newValue =
        this.input.value == this.defaultValue ? button : `${this.input.value}${button}`
      this.input.setAttribute('value', newValue)
    }
    this.addSpecialSymbols()
    this.addNumbers()
    this.addOperators()
  }

  addInput() {
    let value = this.defaultValue
    this.input = document.createElement('input')
    this.input.setAttribute('value', value)
    this.calcContainer.appendChild(this.input)
  }
  addSpecialSymbols() {
    specialSymbolsArr.map((item) => {
      const button = document.createElement('button')
      const { className, innerHtml, action } = item
      button.setAttribute('class', className)
      button.innerHTML = innerHtml
      button.addEventListener('click', action.bind(this))
      this.calcContainer.appendChild(button)
    })
  }
  addNumbers() {
    const numbers = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    numbers.forEach((num) => {
      const button = document.createElement('button')
      button.innerText = num
      button.setAttribute('type', 'button')
      button.setAttribute('class', 'btn btn-outline-info')
      if (num === 0) {
        button.setAttribute('class', 'zero btn btn-outline-secondary')
      }
      button.addEventListener('click', (e) => {
        this.onClickButton(e, num)
      })
      this.calcContainer.appendChild(button)
    })
  }

  addOperators() {
    ids.forEach((id) => {
      const button = document.createElement('button')
      const { className, innerHtml, operator } = entities[id]

      button.innerHTML = innerHtml
      button.setAttribute('type', 'button')
      button.setAttribute('class', className)

      if (operator !== '=') {
        button.addEventListener('click', (e) => {
          this.onClickButton(e, operator)
        })
      } else {
        button.addEventListener('click', () => {
          console.log(this.input.value)
          this.input.setAttribute('value', `${getResult(this.input.value)}`)
          // this.input.value = getResult(this.input.value)
          console.log(this.input.value)
        })
      }

      this.calcContainer.appendChild(button)
    })
  }
}

In this part of code I logged values of input and it showed expression both times. Even though setAttribute had to change expression for result.

          console.log(this.input.value)
          this.input.setAttribute('value', `${getResult(this.input.value)}`)
          console.log(this.input.value)
        }) 

If I change initialisation of value manually then it works fine. But afterwards inout becomes 'blocked', buttons doesn't affect input.

button.addEventListener('click', () => {
          console.log(this.input.value)
          this.input.value = getResult(this.input.value)
          console.log(this.input.value)
        })

I guess this is conflict of setAttribute method and initialisation of of input value by browser while pasting something to input. Could somebody help please to solve this problem?

tresor13
  • 57
  • 8

0 Answers0