• Vamos começar já ajustando nosso projeto para suportar os módulos ESM. Crie uma pasta “js” para melhor organizar os arquivos javascript e também altere o tipo da tag script no arquivo index.html para “module”:

    <!-- ... -->
    	<title>Projeto Prático Guiado 1</title>
      <link rel="stylesheet" href="style.css">
      <script src="js/index.js" type="module" defer></script>
    </head>
    <body>
    <!-- ... -->
    
  • Agora vamos começar. Mova o arquivo “index.js” para a pasta “js” criada e crie nela o arquivo “calculate.js”. Vamos mover para ele a função “calculate” do arquivo principal e fazer as devidas adaptações no código, nesse caso obtendo o input de resultado dentro da função:

    export default function calculate() {
      const resultInput = document.querySelector("#result")
      resultInput.value = "ERROR"
      resultInput.classList.add("error")
      const result = eval(input.value)
      resultInput.value = result
      resultInput.classList.remove("error")
    }
    
  • Outra parte da aplicação que podemos separar são os eventos de copiar para área de transferência e mudar o tema. Vamos começar pelo botão de copiar. Crie um arquivo “copyToClipboard.js” e exporte a função, fazendo as devidas adaptações:

    export default function copyToClipboard(ev) {
      const button = ev.currentTarget
      if (button.innerText === "Copy") {
        button.innerText = "Copied!"
        button.classList.add("success")
        navigator.clipboard.writeText(document.querySelector("#result").value)
      } else {
        button.innerText = "Copy"
        button.classList.remove("success")
      }
    }
    
  • Agora vamos para a função de mudança de tema. Crie o arquivo “themeSwitcher.js” e mova para ele a função de mudar o tema entre dark e light. Também será preciso obter os elementos main e root dentro da função:

    export default function switchTheme() {
      const main = document.querySelector("main")
      const root = document.querySelector(":root")
      if (main.dataset.theme === "dark") {
        root.style.setProperty("--bg-color", "#f1f5f9")
        root.style.setProperty("--border-color", "#aaa")
        root.style.setProperty("--font-color", "#212529")
        root.style.setProperty("--primary-color", "#26834a")
        main.dataset.theme = "light"
      } else {
        root.style.setProperty("--bg-color", "#212529")
        root.style.setProperty("--border-color", "#666")
        root.style.setProperty("--font-color", "#f1f5f9")
        root.style.setProperty("--primary-color", "#4dff91")
        main.dataset.theme = "dark"
      }
    }
    
  • Poderíamos parar por aqui, mas ainda há mais que podemos modularizar nessa aplicação. Vamos separar as funções ligadas aos eventos de digitação e clique nos botões da calculadora. Para isso, crie o arquivo “keyHandlers.js”. Nele precisaremos adaptar o código para conter as variáveis necessárias para o seu funcionamento, como o “input” e as “allowedKeys”. Também vamos precisar importar nossa função calculate() para o arquivo:

    import calculate from "./calculate.js"
    
    const input = document.querySelector('#input')
    
    export function handleButtonPress(ev) {
      const value = ev.currentTarget.dataset.value
      input.value += value
    }
    
    export function handleClear(ev) {
      input.value = ""
      input.focus()
    }
    
    export function handleTyping(ev) {
      ev.preventDefault()
      const allowedKeys = ["(", ")", "/", "*", "-", "+", "9", "8", "7", "6", "5", "4", "3", "2", "1", "0", ".", "%", " "]
      if (allowedKeys.includes(ev.key)) {
        input.value += ev.key
        return
      }
      if (ev.key === "Backspace") {
        input.value = input.value.slice(0, -1)
      }
      if (ev.key === "Enter") {
        calculate()
      }
    }
    
  • Para finalizar, vamos fazer os ajustes necessários no arquivo “index.js”, importando os módulos e então vamos testar a aplicação para ver se tudo continua funcionando como antes:

    import calculate from "./calculate.js"
    import copyToClipboard from "./copyToClipboard.js"
    import { handleButtonPress, handleClear, handleTyping } from "./keyHandlers.js"
    import switchTheme from "./switchTheme.js"
    
    document.querySelectorAll(".charKey").forEach(function (charKeyBtn) {
      charKeyBtn.addEventListener("click", handleButtonPress)
    })
    
    document.querySelector("#clear").addEventListener("click", handleClear)
    document.querySelector("#input").addEventListener("keydown", handleTyping)
    document.querySelector("#equal").addEventListener("click", calculate)
    document.querySelector("#copyToClipboard").addEventListener("click", copyToClipboard)
    document.querySelector("#themeSwitcher").addEventListener("click", switchTheme)