A continuación, te presento un código HTML básico para una página web que permite gestionar un presupuesto familiar simple. Este código incluye campos para ingresos, gastos en diferentes categorías y calcula el balance.
HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Presupuesto Familiar</title>
<style>
body {
font-family: sans-serif;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="number"] {
width: 150px;
padding: 5px;
margin-bottom: 10px;
box-sizing: border-box;
}
#resultado {
font-weight: bold;
margin-top: 10px;
}
</style>
</head>
<body>
<h1>Presupuesto Familiar</h1>
<label for="ingresos">Ingresos:</label>
<input type="number" id="ingresos" value="0">
<h2>Gastos</h2>
<label for="vivienda">Vivienda:</label>
<input type="number" id="vivienda" value="0">
<label for="alimentacion">Alimentación:</label>
<input type="number" id="alimentacion" value="0">
<label for="transporte">Transporte:</label>
<input type="number" id="transporte" value="0">
<label for="otros">Otros:</label>
<input type="number" id="otros" value="0">
<div id="resultado">Balance: 0</div>
<script>
const ingresos = document.getElementById('ingresos');
const vivienda = document.getElementById('vivienda');
const alimentacion = document.getElementById('alimentacion');
const transporte = document.getElementById('transporte');
const otros = document.getElementById('otros');
const resultado = document.getElementById('resultado');
function calcularPresupuesto() {
const ingresosValor = parseFloat(ingresos.value) || 0;
const viviendaValor = parseFloat(vivienda.value) || 0;
const alimentacionValor = parseFloat(alimentacion.value) || 0;
const transporteValor = parseFloat(transporte.value) || 0;
const otrosValor = parseFloat(otros.value) || 0;
const gastosTotales = viviendaValor + alimentacionValor + transporteValor + otrosValor;
const balance = ingresosValor - gastosTotales;
resultado.textContent = `Balance: ${balance}`;
}
ingresos.addEventListener('input', calcularPresupuesto);
vivienda.addEventListener('input', calcularPresupuesto);
alimentacion.addEventListener('input', calcularPresupuesto);
transporte.addEventListener('input', calcularPresupuesto);
otros.addEventListener('input', calcularPresupuesto);
</script>
</body>
</html>
Explicación del código:
- HTML: Estructura la página con campos de entrada (
<input type="number">
) para ingresos y diferentes categorías de gastos. También incluye un elemento (<div id="resultado">
) para mostrar el balance. - CSS (dentro de
<style>
): Da un estilo básico a la página, como la fuente y el espaciado. - JavaScript:
- Obtiene referencias a los elementos HTML usando
document.getElementById()
. - Define una función
calcularPresupuesto()
que:- Obtiene los valores de los campos de entrada y los convierte a números usando
parseFloat()
. El|| 0
asegura que si el campo está vacío, se use 0. - Calcula los gastos totales y el balance.
- Actualiza el contenido del elemento
#resultado
con el balance calculado.
- Obtiene los valores de los campos de entrada y los convierte a números usando
- Añade «escuchadores de eventos» (
addEventListener
) a cada campo de entrada. Cada vez que se modifica un campo ('input'
), se llama a la funcióncalcularPresupuesto()
.
- Obtiene referencias a los elementos HTML usando
Cómo usar este código:
- Copia el código y guárdalo en un archivo con extensión
.html
(por ejemplo,presupuesto.html
). - Abre el archivo
presupuesto.html
en tu navegador web.
Ahora tendrás una página web funcional donde puedes ingresar tus ingresos y gastos, y ver el balance automáticamente actualizado.
Mejoras que se pueden añadir:
- Más categorías de gastos: Puedes agregar más campos de entrada para otras categorías relevantes para tu presupuesto.
- Formato de moneda: Puedes usar JavaScript para formatear el balance y los valores de entrada como moneda.
- Almacenamiento local: Puedes usar
localStorage
osessionStorage
para guardar los datos del presupuesto y que no se pierdan al cerrar la página. - Gráficos: Puedes usar bibliotecas de JavaScript como Chart.js para visualizar el presupuesto con gráficos.
- Validación de entrada: Puedes agregar validación para asegurar que solo se ingresen números válidos.
Este código te proporciona una base sólida para crear tu propia herramienta de presupuesto familiar. Puedes adaptarlo y mejorarlo según tus necesidades.
Mejorar con un Estilo CSS
Presupuesto Familiar con Bootstrap
Presupuesto Familiar
<div class="mb-3">
<label for="ingresos" class="form-label">Ingresos:</label>
<input type="number" class="form-control" id="ingresos" value="0">
</div>
<h2>Gastos</h2>
<div class="mb-3">
<label for="vivienda" class="form-label">Vivienda:</label>
<input type="number" class="form-control" id="vivienda" value="0">
</div>
<div class="mb-3">
<label for="alimentacion" class="form-label">Alimentación:</label>
<input type="number" class="form-control" id="alimentacion" value="0">
</div>
<div class="mb-3">
<label for="transporte" class="form-label">Transporte:</label>
<input type="number" class="form-control" id="transporte" value="0">
</div>
<div class="mb-3">
<label for="otros" class="form-label">Otros:</label>
<input type="number" class="form-control" id="otros" value="0">
</div>
<div id="resultado" class="alert alert-info">Balance: 0</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script>
const ingresos = document.getElementById('ingresos');
const vivienda = document.getElementById('vivienda');
const alimentacion = document.getElementById('alimentacion');
const transporte = document.getElementById('transporte');
const otros = document.getElementById('otros');
const resultado = document.getElementById('resultado');
function calcularPresupuesto() {
const ingresosValor = parseFloat(ingresos.value) || 0;
const viviendaValor = parseFloat(vivienda.value) || 0;
const alimentacionValor = parseFloat(alimentacion.value) || 0;
const transporteValor = parseFloat(transporte.value) || 0;
const otrosValor = parseFloat(otros.value) || 0;
const gastosTotales = viviendaValor + alimentacionValor + transporteValor + otrosValor;
const balance = ingresosValor - gastosTotales;
resultado.textContent = `Balance: ${balance}`;
}
ingresos.addEventListener('input', calcularPresupuesto);
vivienda.addEventListener('input', calcularPresupuesto);
alimentacion.addEventListener('input', calcularPresupuesto);
transporte.addEventListener('input', calcularPresupuesto);
otros.addEventListener('input', calcularPresupuesto);
</script>
Explicación del código JavaScript:
- Selección de elementos: Se obtienen referencias a los elementos HTML relevantes usando
document.getElementById()
. - Función
calcularPresupuesto()
: Esta función realiza los cálculos:- Obtiene los valores de los campos de entrada y los convierte a números usando
parseFloat()
. El operador|| 0
se utiliza para asignar 0 en caso de que el campo esté vacío o contenga un valor no numérico. - Calcula los gastos totales sumando los valores de las categorías de gastos.
- Calcula el balance restando los gastos totales a los ingresos.
- Actualiza el contenido del elemento
#resultado
con el balance calculado.
- Obtiene los valores de los campos de entrada y los convierte a números usando
- Event Listeners: Se añaden «escuchadores de eventos» (
addEventListener
) a cada campo de entrada. Cada vez que el valor de un campo cambia ('input'
), se ejecuta la funcióncalcularPresupuesto()
, actualizando el balance en tiempo real.
Conservar los Datos en el Presupuesto Familiar
Hay varias maneras de lograr que un visitante conserve los datos introducidos en un formulario de presupuesto, dependiendo de cuánto tiempo quieras que se conserven y si necesitas que los datos persistan entre diferentes sesiones del navegador. Aquí te presento las opciones más comunes:
1. Almacenamiento local en el navegador (LocalStorage o SessionStorage):
Esta es la opción más sencilla para conservar datos en el navegador del usuario sin necesidad de un servidor.
- LocalStorage: Los datos se guardan de forma persistente en el navegador del usuario, incluso después de cerrar la ventana o el navegador. Los datos solo se eliminan si el usuario borra la caché del navegador o si el código los elimina explícitamente.
- SessionStorage: Los datos se guardan solo durante la sesión actual del navegador. Se eliminan automáticamente cuando el usuario cierra la pestaña o la ventana.
Ejemplo con LocalStorage (recomendado para este caso):
JavaScript
// Guardar datos
function guardarDatos() {
const ingresos = document.getElementById('ingresos').value;
const vivienda = document.getElementById('vivienda').value;
// ... guardar otros campos
localStorage.setItem('ingresos', ingresos);
localStorage.setItem('vivienda', vivienda);
// ... guardar otros campos
}
// Cargar datos al cargar la página
function cargarDatos() {
const ingresosGuardado = localStorage.getItem('ingresos');
const viviendaGuardado = localStorage.getItem('vivienda');
// ... cargar otros campos
if (ingresosGuardado) {
document.getElementById('ingresos').value = ingresosGuardado;
}
if (viviendaGuardado) {
document.getElementById('vivienda').value = viviendaGuardado;
}
// ... cargar otros campos
}
// Llamar a guardarDatos() cada vez que cambie un input
const inputs = document.querySelectorAll('input[type="number"]'); // Selecciona todos los inputs numéricos
inputs.forEach(input => {
input.addEventListener('input', guardarDatos);
});
// Llamar a cargarDatos() al cargar la página
window.addEventListener('load', cargarDatos);
// ... (resto del código JavaScript)
Explicación:
guardarDatos()
: Esta función se encarga de guardar los valores de los campos en ellocalStorage
usandolocalStorage.setItem(clave, valor)
. La clave es una cadena que identifica el dato (ej. ‘ingresos’), y el valor es el valor del campo.cargarDatos()
: Esta función se ejecuta al cargar la página (window.addEventListener('load', cargarDatos)
) y recupera los datos dellocalStorage
usandolocalStorage.getItem(clave)
. Si existen datos guardados para una clave, se asignan al campo correspondiente.- Se añade un event listener a todos los inputs numéricos para que se guarden los datos cada vez que se modifica un campo.
2. Cookies:
Las cookies son otra forma de almacenar datos en el navegador del usuario, pero tienen algunas limitaciones en cuanto a tamaño y pueden ser bloqueadas por el usuario. No son la opción más recomendada para este caso, pero te la menciono por completitud.
3. Almacenamiento en el servidor (Base de datos):
Si necesitas que los datos persistan entre diferentes dispositivos o que estén disponibles para el usuario en futuras visitas, la mejor opción es almacenar los datos en un servidor en una base de datos. Esto requiere un backend (un lenguaje de programación en el servidor como PHP, Python, Node.js, etc.) y una base de datos (MySQL, PostgreSQL, MongoDB, etc.).
Ejemplo de flujo con almacenamiento en el servidor:
- El usuario introduce los datos en el formulario.
- Se envía una petición al servidor (generalmente usando AJAX) con los datos.
- El servidor guarda los datos en la base de datos, asociándolos al usuario (por ejemplo, usando un ID de usuario o una sesión).
- Cuando el usuario regresa, se realiza una petición al servidor para recuperar los datos asociados a ese usuario.
Esta opción es más compleja de implementar, pero es la más robusta y escalable.
4. URL Parameters (para compartir el presupuesto):
Si lo que quieres es que el usuario pueda compartir el presupuesto con otra persona, puedes usar parámetros en la URL.
Ejemplo:
Si el usuario introduce ingresos = 1000 y vivienda = 500, la URL podría ser:
mipagina.com/presupuesto?ingresos=1000&vivienda=500
Luego, con JavaScript, puedes leer los parámetros de la URL y rellenar el formulario. Esta opción es útil para compartir, pero no para persistir los datos entre sesiones.
Validación del Formulario
si quieres impedir que se introduzcan letras en los campos destinados a números, necesitas agregar validación con JavaScript. Hay varias maneras de hacerlo, y te presento las más comunes y efectivas:
1. Validar con input
event y expresión regular (Recomendado):
Esta es la forma más robusta y versátil. Usamos una expresión regular para verificar que el valor ingresado solo contenga dígitos.
JavaScript
const inputsNumericos = document.querySelectorAll('input[type="number"]');
inputsNumericos.forEach(input => {
input.addEventListener('input', function() {
this.value = this.value.replace(/[^0-9]/g, ''); // Elimina cualquier caracter que no sea un dígito
guardarDatos(); // Guardar los datos después de la validación
});
});
Explicación:
document.querySelectorAll('input[type="number"]')
: Selecciona todos los elementosinput
de tiponumber
en el documento.addEventListener('input', function() { ... })
: Escucha el eventoinput
, que se dispara cada vez que el valor del campo cambia.this.value.replace(/[^0-9]/g, '')
: Esta es la parte clave. Utiliza una expresión regular:/[^0-9]/
: Coincide con cualquier caracter que no sea un dígito (0-9).g
: Indica que la búsqueda es global (reemplaza todas las coincidencias).''
: Reemplaza las coincidencias con una cadena vacía, es decir, las elimina.
guardarDatos();
: Llama a la función que guarda los datos en LocalStorage, asegurando que se guarden los datos ya validados.
2. Validar con keydown
event (Menos recomendado, pero útil para control más fino):
Este método te permite controlar qué teclas se presionan, pero es más complejo de manejar correctamente (por ejemplo, hay que tener en cuenta las teclas de control, retroceso, etc.).
JavaScript
const inputsNumericos = document.querySelectorAll('input[type="number"]');
inputsNumericos.forEach(input => {
input.addEventListener('keydown', function(event) {
if (event.key < '0' || event.key > '9') { // Si no es un dígito
if (event.key !== 'Backspace' && event.key !== 'Tab' && event.key !== 'ArrowLeft' && event.key !== 'ArrowRight' ) { // Permite retroceso y tabulación
event.preventDefault(); // Evita que se ingrese el caracter
}
}
});
});
Explicación:
- Escucha el evento
keydown
, que se dispara cuando se presiona una tecla. event.key
: Obtiene la tecla presionada.- Comprueba si la tecla no es un dígito.
event.preventDefault()
: Evita que se ingrese el carácter en el campo.- Se añaden excepciones para permitir teclas como «Backspace», «Tab», «Flecha Izquierda» y «Flecha Derecha» para una mejor experiencia de usuario.
3. Usar el atributo pattern
de HTML5 (Limitado):
Puedes usar el atributo pattern
en el propio HTML, pero tiene limitaciones y no es tan flexible como JavaScript.
HTML
<input type="number" pattern="[0-9]*" id="ingresos" value="0">
pattern="[0-9]*"
indica que solo se permiten dígitos. Sin embargo, el usuario aún puede copiar y pegar texto con letras.
Código completo con la validación recomendada (expresión regular):
Aquí te incluyo el código completo con la validación usando expresiones regulares, que es la opción más robusta:
HTML
<!DOCTYPE html>
<html lang="es">
<head>
</head>
<body>
<div class="container">
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
const inputs = document.querySelectorAll('input[type="number"]');
const resultado = document.getElementById('resultado');
function guardarDatos() {
try{
inputs.forEach(input => {
localStorage.setItem(input.id, input.value)
})
} catch (error) {
console.error("Error al guardar en LocalStorage:", error);
}
}
function cargarDatos() {
try{
inputs.forEach(input => {
input.value = localStorage.getItem(input.id) || 0;
})
} catch (error) {
console.error("Error al cargar en LocalStorage:", error);
}
calcularPresupuesto();
}
function calcularPresupuesto() {
let ingresosValor = parseFloat(document.getElementById('ingresos').value) || 0;
let gastosTotales = 0;
inputs.forEach(input => {
if (input.id != 'ingresos'){
gastosTotales += parseFloat(input.value) || 0;
}
})
const balance = ingresosValor - gastosTotales;
resultado.textContent = `Balance: ${balance}`;
}
inputs.forEach(input => {
input.addEventListener('input', function() {
this.value = this.value.replace(/[^0-9]/g, '');
guardarDatos();
calcularPresupuesto();
});
});
window.addEventListener('load', cargarDatos);
</script>
</body>
</html>
Con este código, los campos de tipo number
solo aceptarán dígitos, resolviendo el problema que mencionabas. Además, se ha añadido la llamada a calcularPresupuesto()
dentro del listener de los inputs y en cargarDatos()
para que el balance se actualice correctamente al cargar la página y al modificar los valores.