Volver
Ctrl+Space
◑
Copiar
Descargar
Restaurar
Ejecutar
Ctrl+Enter
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Eventos en JS — Ejemplo 4</title> <style> body { font-family: Arial, sans-serif; padding: 20px; background: #fff; max-width: 520px; } h3 { margin: 22px 0 8px; font-size: 15px; color: #333; } /* Calculadora */ .calc-wrap { border: 2px solid #F7DF1E; border-radius: 10px; padding: 20px; background: #fffde7; } .calc-display { background: #1a1a1a; color: #F7DF1E; font-family: monospace; font-size: 28px; text-align: right; padding: 14px 18px; border-radius: 6px; margin-bottom: 14px; min-height: 58px; word-break: break-all; letter-spacing: 1px; } .calc-display .expresion { font-size: 13px; color: #888; display: block; text-align: right; min-height: 18px; margin-bottom: 4px; } .calc-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; } .calc-btn { padding: 16px 0; border: none; border-radius: 6px; font-size: 16px; font-weight: bold; cursor: pointer; font-family: inherit; transition: filter 0.15s, transform 0.1s; } .calc-btn:hover { filter: brightness(0.92); } .calc-btn:active { transform: scale(0.95); } .btn-num { background: #fff; color: #222; border: 1px solid #ddd; } .btn-op { background: #F7DF1E; color: #333; } .btn-eq { background: #333; color: #F7DF1E; } .btn-clear { background: #fee2e2; color: #dc2626; } .btn-span2 { grid-column: span 2; } /* Historial */ .historial { margin-top: 16px; background: #f9f9f9; border: 1px solid #eee; border-radius: 6px; padding: 10px 14px; max-height: 130px; overflow-y: auto; font-family: monospace; font-size: 13px; } .historial div { padding: 2px 0; border-bottom: 1px solid #f0f0f0; color: #555; } .historial div:last-child { border-bottom: none; } /* Atajos */ .atajos { font-size: 12px; color: #888; margin-top: 10px; } .atajos .kbd { display: inline-block; background: #eee; border: 1px solid #ccc; border-radius: 4px; padding: 1px 6px; font-family: monospace; } .flash { animation: flash 0.2s ease; } @keyframes flash { 0%,100%{background:#fffde7} 50%{background:#fff3a0} } </style> </head> <body> <h2>Calculadora — Eventos de clic y teclado</h2> <div class="calc-wrap"> <div class="calc-display"> <span class="expresion" id="expresion"></span> <span id="display">0</span> </div> <div class="calc-grid"> <!-- Fila 1 --> <button class="calc-btn btn-clear" data-accion="clear">C</button> <button class="calc-btn btn-clear" data-accion="backspace">⌫</button> <button class="calc-btn btn-op" data-accion="porcentaje">%</button> <button class="calc-btn btn-op" data-op="÷">÷</button> <!-- Fila 2 --> <button class="calc-btn btn-num" data-num="7">7</button> <button class="calc-btn btn-num" data-num="8">8</button> <button class="calc-btn btn-num" data-num="9">9</button> <button class="calc-btn btn-op" data-op="×">×</button> <!-- Fila 3 --> <button class="calc-btn btn-num" data-num="4">4</button> <button class="calc-btn btn-num" data-num="5">5</button> <button class="calc-btn btn-num" data-num="6">6</button> <button class="calc-btn btn-op" data-op="−">−</button> <!-- Fila 4 --> <button class="calc-btn btn-num" data-num="1">1</button> <button class="calc-btn btn-num" data-num="2">2</button> <button class="calc-btn btn-num" data-num="3">3</button> <button class="calc-btn btn-op" data-op="+">+</button> <!-- Fila 5 --> <button class="calc-btn btn-num btn-span2" data-num="0">0</button> <button class="calc-btn btn-num" data-accion="decimal">.</button> <button class="calc-btn btn-eq" data-accion="igual">=</button> </div> </div> <div class="historial" id="historial"> <div style="color:#bbb;">El historial aparece acá...</div> </div> <div class="atajos"> <strong>Atajos de teclado:</strong> <span class="kbd">0-9</span> números <span class="kbd">+ - * /</span> operaciones <span class="kbd">Enter</span> igual <span class="kbd">Escape</span> limpiar <span class="kbd">Backspace</span> borrar </div> <script> // Eventos en JavaScript - Ejemplo 4: Calculadora interactiva const display = document.getElementById("display"); const expresion = document.getElementById("expresion"); const historial = document.getElementById("historial"); const calcWrap = document.querySelector(".calc-wrap"); let valorActual = "0"; let operador = null; let primerValor = null; let esperandoSegundo = false; let expresionStr = ""; // ── Actualizar pantalla ─────────────────────────────────────────────── function actualizarDisplay() { display.textContent = valorActual; expresion.textContent = expresionStr; } // ── Agregar dígito ──────────────────────────────────────────────────── function ingresarDigito(digito) { if (esperandoSegundo) { valorActual = digito; esperandoSegundo = false; } else { valorActual = valorActual === "0" ? digito : valorActual + digito; } actualizarDisplay(); } // ── Decimal ─────────────────────────────────────────────────────────── function ingresarDecimal() { if (esperandoSegundo) { valorActual = "0."; esperandoSegundo = false; } else if (!valorActual.includes(".")) { valorActual += "."; } actualizarDisplay(); } // ── Operador ────────────────────────────────────────────────────────── function ingresarOperador(op) { const val = parseFloat(valorActual); if (primerValor !== null && !esperandoSegundo) { const resultado = calcular(primerValor, val, operador); valorActual = String(resultado); agregarHistorial(`${primerValor} ${operador} ${val} = ${resultado}`); } primerValor = parseFloat(valorActual); operador = op; expresionStr = `${primerValor} ${op}`; esperandoSegundo = true; actualizarDisplay(); } // ── Calcular resultado ──────────────────────────────────────────────── function calcular(a, b, op) { switch (op) { case "+": return redondear(a + b); case "−": return redondear(a - b); case "×": return redondear(a * b); case "÷": return b !== 0 ? redondear(a / b) : "Error"; default: return b; } } function redondear(n) { return Math.round(n * 1e10) / 1e10; } // ── Igual ───────────────────────────────────────────────────────────── function igual() { if (operador === null || esperandoSegundo) return; const a = primerValor; const b = parseFloat(valorActual); const res = calcular(a, b, operador); agregarHistorial(`${a} ${operador} ${b} = ${res}`); expresionStr = `${a} ${operador} ${b} =`; valorActual = String(res); primerValor = null; operador = null; esperandoSegundo = false; actualizarDisplay(); } // ── Limpiar ─────────────────────────────────────────────────────────── function limpiar() { valorActual = "0"; operador = null; primerValor = null; esperandoSegundo = false; expresionStr = ""; actualizarDisplay(); } // ── Backspace ───────────────────────────────────────────────────────── function borrarUltimo() { if (esperandoSegundo) return; valorActual = valorActual.length > 1 ? valorActual.slice(0, -1) : "0"; actualizarDisplay(); } // ── Porcentaje ──────────────────────────────────────────────────────── function porcentaje() { valorActual = String(redondear(parseFloat(valorActual) / 100)); actualizarDisplay(); } // ── Historial ───────────────────────────────────────────────────────── function agregarHistorial(entrada) { const placeholder = historial.querySelector("[style*='color:#bbb']"); if (placeholder) placeholder.remove(); const div = document.createElement("div"); div.textContent = entrada; historial.insertBefore(div, historial.firstChild); if (historial.children.length > 10) { historial.lastChild.remove(); } } // ── Feedback visual al presionar tecla ──────────────────────────────── function flashBtn(selector) { const btn = document.querySelector(selector); if (!btn) return; btn.classList.add("flash"); setTimeout(() => btn.classList.remove("flash"), 200); } // ── LISTENER: clic en los botones (delegación en .calc-grid) ───────── document.querySelector(".calc-grid").addEventListener("click", (e) => { const btn = e.target.closest(".calc-btn"); if (!btn) return; if (btn.dataset.num !== undefined) ingresarDigito(btn.dataset.num); if (btn.dataset.op !== undefined) ingresarOperador(btn.dataset.op); if (btn.dataset.accion === "igual") igual(); if (btn.dataset.accion === "clear") limpiar(); if (btn.dataset.accion === "backspace") borrarUltimo(); if (btn.dataset.accion === "decimal") ingresarDecimal(); if (btn.dataset.accion === "porcentaje") porcentaje(); }); // ── LISTENER: teclado ──────────────────────────────────────────────── document.addEventListener("keydown", (e) => { if (e.key >= "0" && e.key <= "9") { ingresarDigito(e.key); flashBtn(`[data-num="${e.key}"]`); } else if (e.key === ".") { ingresarDecimal(); flashBtn("[data-accion='decimal']"); } else if (e.key === "+") { ingresarOperador("+"); flashBtn("[data-op='+']"); } else if (e.key === "-") { ingresarOperador("−"); flashBtn("[data-op='−']"); } else if (e.key === "*") { ingresarOperador("×"); flashBtn("[data-op='×']"); } else if (e.key === "/") { e.preventDefault(); ingresarOperador("÷"); flashBtn("[data-op='÷']"); } else if (e.key === "%" ) { porcentaje(); flashBtn("[data-accion='porcentaje']"); } else if (e.key === "Enter" || e.key === "=") { e.preventDefault(); igual(); flashBtn("[data-accion='igual']"); } else if (e.key === "Escape") { limpiar(); flashBtn("[data-accion='clear']"); } else if (e.key === "Backspace") { borrarUltimo(); flashBtn("[data-accion='backspace']"); } }); </script> </body> </html>