aimenu

Repaso Final

1. localStorage

GUARDAR ARRAY DE USUARIOS:

function guardarUsuarios(user) {

    usuarios.push(user);
    localStorage.setItem("user", JSON.stringify(usuarios));
}

RECUPERAR ARRAY DE USUARIOS:

function cargarUsuarios() {

    let local = localStorage.getItem("user");
    if (local == null) {
        usuarios = [];
    } 
    else {
    usuarios = JSON.parse(local);
     }
}

REGISTRO DE USUARIO:

document.addEventListener("DOMContentLoaded",function(){
//importante cargar el DOM primero
    const crear = document.getElementById("crear");
    crear.addEventListener("click", registroUsuario);
    cargarUsuarios();
});

function registroUsuario() {

    const login = document.getElementById("login").value;
    const password = document.getElementById("password").value;
    let user = new Usuario(login, password);
    guardarUsuarios(user);
    alert("Te has registrado con exito");
    window.location = 'login.html';
}

LOGIN DE USUARIOS:

document.addEventListener("DOMContentLoaded", function(){

    cargarUsuarios();
    const iniciar = document.getElementById("iniciar");
    iniciar.addEventListener("click",auth);
});

  

function auth() {

    const login = document.getElementById("login").value;
    const password = document.getElementById("password").value;
    let existe = false;
    
    for(let usuario of usuarios) {
    
        usuario.__proto__ = new Usuario();
        if(login === usuario.nombre) {
            if(password === usuario.contraseña) {
            
                alert("Bienvenido " + usuario.nombre)
                window.location = "chat.html";
            
            }
        existe = true;
        
        }
    
    }
    if(existe == false){
    alert("NO hemos encontrado ese usuario");
    }
}

PARA INCLUIR CODIGO DE OTROS ARCHIVOS JS COMO CLASES,VARIABLES,FUNCIONES:

<script src="main.js"></script> //clases,funciones,variables globales
<script src="login.js"></script> //archivo js de la página

EJEMPLO DEL MAIN:

let usuarios = [];

// Clases Predefinidas
class Usuario {

    constructor(nombre,contraseña) {
    this.nombre = nombre;
    this.contraseña = contraseña;
    }

  

    cambiarNombre(nombreNuevo){
    this.nombre = nombreNuevo;
    }
};

  

class Chat {
    mensajes = [];
    constructor(usuario1, usuario2) {
    this.usuario1 = usuario1;
    this.usuario2 = usuario2;
    }
    añadir(mensaje) {
    this.mensajes.push(mensaje);
    }
};

  

class Mensaje {

    constructor(contenido,usuario,destinario) {
    this.contenido = contenido;
    this.usuario = usuario;
    this.destinario = destinario;

    }

    mostrar() {
    return '<div class="mensajes">' + this.contenido + '</div>';
    }
};

//Funciones Globales
function guardarUsuarios(user) {

usuarios.push(user);
localStorage.setItem("user", JSON.stringify(usuarios));
}

function cargarUsuarios() {

    let local = localStorage.getItem("user");
    if (local == null) {
        usuarios = [];
    } 
    else {
    usuarios = JSON.parse(local);
     }
}

CARRITO DE COMPRA:

ejemplo de articulo:
<article id="articulo1">
  <img src="images/gt-2000_12black.jpg" alt="Running GT-2000 12" title="GT-2000 12">
  <div class="datos-productos">
    <div class="colores-fav">
      <label for="color1">Colores:</label>
      <select name="color1" id="color1">
        <option value="negro">Negro</option>
        <option value="azul">Azul</option>
        <option value="blanco">Blanco</option>
      </select>
    </div>
    <img src="images/fav.jpg" alt="Añadir a favoritos" title="Añadir a favoritos">
    <div id="modelo1" class="modelo">GT-2000 12</div>
    <div id="descripcion1" class="descripcion">Zapatillas De Hombre</div>
    <div id="precio1" class="precio">€ 160,00</div>
    <button onclick="cesta(1)">Añadir a la cesta</button>
  </div>
</article>

index.js:

// Función para obtener el artículo
function cesta(id_articulo) {
  // Obtener valores de DOM
  let modelo = document.getElementById("modelo" + id_articulo).textContent;
  let precio = document.getElementById("precio" + id_articulo).textContent;
  let color = document.getElementById("color" + id_articulo).value;

  // Obtener carrito del LocalStorage y convertirlo a objeto
  carritoLocal = JSON.parse(localStorage.getItem("carrito"));

  // Generar el producto
  let producto = new Producto(modelo, precio, color);

  // Transformar objeto a clase Carrito
  carritoLocal.__proto__ = new Carrito();

  // Agregar el producto al carrito
  carritoLocal.agregarProducto(producto);

  // Guardar carrito
  guardarCarrito();
}
clases.js:

Js con objetos ,variables y funciones globales que se importarán antes del script principal como index.js , carrito.js

// Variable Global Para Almacenar Carrito
let carritoLocal;

// Clase de Carrito
class Carrito {
  constructor() {
    this.productos = new Array();
    this.cantidad = 0;
  }

  agregarProducto(producto) {
    this.productos.push(producto);
    this.cantidad++;
  }
}

// Clase del Producto
class Producto {
  constructor(modelo, precio, color) {
    this.modelo = modelo;
    this.precio = precio;
    this.color = color;
  }
}

function guardarCarrito() {
  document.getElementById("n_articulos").textContent = carritoLocal.cantidad;
  localStorage.setItem("carrito", JSON.stringify(carritoLocal));
}

// Función para cargar el carrito desde el LocalStorage
function cargarLocal() {
  if (localStorage.getItem("carrito") === null) {
    carritoLocal = new Carrito();
    localStorage.setItem("carrito", JSON.stringify(carritoLocal));
    console.log(carritoLocal);
  } else {
    carritoLocal = JSON.parse(localStorage.getItem("carrito"));
    console.log(carritoLocal);
  }

  carritoLocal.__proto__ = new Carrito();
  document.getElementById("n_articulos").textContent = carritoLocal.cantidad;
}

// Ejecutar cargarLocal cada 500 ms
id = setInterval(cargarLocal, 500);

// Llamar cargarLocal cuando se inicie por primera vez
cargarLocal();

Carrito: donde se muestran los productos seleccionados de la pagina anterior

<h1>Cesta de la compra</h1>
<button onclick="location.href='index.html'">Volver a productos</button>
<div id="productos"></div>

carrito.js: sacar productos con la opcion de borrarlos

const panelProducto = document.getElementById("productos");

function eliminar(id) {
  carritoLocal.productos.splice(id, 1);

  panelProducto.innerHTML = "";
  for (id in carritoLocal.productos) {
    const producto = carritoLocal.productos[id];
    panelProducto.innerHTML += `
    <div class="producto">
      <span class="modelo">${producto.modelo}</span>
      ${producto.color}
      ${producto.precio}
      <button onclick="eliminar(${id})">Eliminar</button>
    </div>`;
  }

  carritoLocal.quitarCantidad();
  guardarCarrito();
}

function cargarCarrito() {
  if (localStorage.getItem("carrito") == null) {
    carritoLocal = new Carrito();
    localStorage.setItem("carrito", JSON.stringify(carritoLocal));
    console.log(carritoLocal);
  } else {
    carritoLocal = JSON.parse(localStorage.getItem("carrito"));
    console.log(carritoLocal);
  }

  carritoLocal.__proto__ = new Carrito();
  panelProducto.innerHTML = "";

  for (id in carritoLocal.productos) {
    const producto = carritoLocal.productos[id];
    panelProducto.innerHTML += `
    <div class="producto">
      <span class="modelo">${producto.modelo}</span>
      ${producto.color}
      ${producto.precio}
      <button onclick="eliminar(${id})">Eliminar</button>
    </div>`;
  }
}

cargarCarrito();
id = setInterval(cargarCarrito, 500);

2. Fechas en JavaScript (Objeto Date)

  1. Date Constructor - Crea una nueva instancia de Date:
let fechaActual = new Date();
console.log(fechaActual); // Muestra la fecha y hora actual
  1. getFullYear - Devuelve el año de la fecha especificada:
let fecha = new Date();
let anio = fecha.getFullYear();
console.log(anio); // Ej. 202## 5. Objeto `Array`5
  1. getMonth - Devuelve el mes de la fecha especificada (0-11):
let fecha = new Date();
let mes = fecha.getMonth();
console.log(mes); // Ej. 0 para enero
  1. getDate - Devuelve el día del mes de la fecha especificada:
let fecha = new Date();
let dia = fecha.getDate();
console.log(dia); // Ej. 13
  1. getDay - Devuelve el día de la semana de la fecha especificada (0-6, donde 0 es domingo):
let fecha = new Date();
let diaSemana = fecha.getDay();
console.log(diaSemana); // Ej. 1 para lunes
  1. getHours - Devuelve la hora de la fecha especificada:
let fecha = new Date();
let horas = fecha.getHours();
console.log(horas); // Ej. 14
  1. getMinutes - Devuelve los minutos de la fecha especificada:
let fecha = new Date();
let minutos = fecha.getMinutes();
console.log(minutos); // Ej. 58
  1. getSeconds - Devuelve los segundos de la fecha especificada:
let fecha = new Date();
let segundos = fecha.getSeconds();
console.log(segundos); // Ej. 10
  1. setFullYear - Establece el año para una fecha:
let fecha = new Date();
fecha.setFullYear(2030);
console.log(fecha); // Muestra la fecha con el año 2030
  1. setMonth - Establece el mes para una fecha (0-11):
let fecha = new Date();
fecha.setMonth(11); // Diciembre
console.log(fecha); // Muestra la fecha con el mes actualizado
  1. setDate - Establece el día del mes para una fecha:
let fecha = new Date();
fecha.setDate(25);
console.log(fecha); // Muestra la fecha con el día actualizado
  1. toLocaleDateString - Devuelve la fecha en una cadena con formato localizado:
let fecha = new Date();
let fechaLocal = fecha.toLocaleDateString('es-ES');
console.log(fechaLocal); // Ej. "13/1/2025"
  1. toISOString - Devuelve la fecha en formato ISO 8601:
let fecha = new Date();
let fechaISO = fecha.toISOString();
console.log(fechaISO); // Ej. "2025-01-13T13:58:10.000Z"
  1. toDateString - Devuelve la fecha en una cadena legible:
let fecha = new Date();
let fechaCadena = fecha.toDateString();
console.log(fechaCadena); // Ej. "Mon Jan 13 2025"

SOLSTICIO:

// Solicito el año al usuario
let input = parseInt(prompt("Indica hasta que año quieres que te muestre los solsticios de verano desde el año 2000"));

// Supongamos que el solsticio de verano cae el día 20 y el 21 todos los años
let dia = new Date(2000, 5, 20);
let dia2 = new Date(2000, 5, 21);
let array = [];

// Valido el input del usuario, el primer año en tener solsticio a partir del 2000 es 2003
if (input >= 2003) {
    for (let i = 2000; i <= input; i++) {
        dia = new Date(i, 5, 20);
        dia2 = new Date(i, 5, 21);

        if (dia.getDay() == 6) {
        //Meto los años que cumplen con la condición e imprimo las fechas
            array.push(dia.getFullYear());
            document.write(dia.toDateString() + "<br>");
        } else if (dia2.getDay() == 6) {
            // Lo mismo que en el bloque de arriba pero con el día 21
            array.push(dia2.getFullYear());
            document.write(dia2.toDateString() + "<br>");
        }
    }

    document.write("<br>Hay un total de " + array.length + " días<br>");
    document.write("<br>" + array);
} else if (input < 2003 && input >= 2000) {
    alert("No hay ningún solsticio desde el 2000 al " + input);
} else {
    alert("ERROR: recarga la página e introduce un valor numérico válido");
}

3. Métodos para Trabajar con Strings

  1. charAt - Devuelve el carácter en una posición específica:
let texto = "Bogdan dev docs";
let letra = texto.charAt(7);
console.log(letra); // "d"
  1. concat - Une dos o más strings y devuelve una nueva string:
let texto1 = "Bogdan";
let texto2 = "dev docs";
let frase = texto1.concat(" ", texto2);
console.log(frase); // "Bogdan dev docs"
  1. includes - Determina si una string contiene otra string específica:
let texto = "Bogdan dev docs";
let contiene = texto.includes("dev");
console.log(contiene); // true
  1. indexOf - Devuelve el índice de la primera aparición de una string dentro de otra string:
let texto = "Bogdan dev docs";
let indice = texto.indexOf("dev");
console.log(indice); // 7
  1. replace - Reemplaza una parte de una string por otra string:
let texto = "Bogdan dev docs";
let nuevoTexto = texto.replace("dev", "developer");
console.log(nuevoTexto); // "Bogdan developer docs"
  1. split - Divide una string en un array de substrings:
let texto = "Bogdan dev docs";
let partes = texto.split(" ");
console.log(partes); // ["Bogdan", "dev", "docs"]
  1. substring - Extrae una parte de una string entre dos índices especificados:
let texto = "Bogdan dev docs";
let subcadena = texto.substring(0, 6);
console.log(subcadena); // "Bogdan"
  1. toLowerCase - Convierte una string a minúsculas:
let texto = "Bogdan DEV DOCS";
let minusculas = texto.toLowerCase();
console.log(minusculas); // "bogdan dev docs"
  1. toUpperCase - Convierte una string a mayúsculas:
let texto = "Bogdan dev docs";
let mayusculas = texto.toUpperCase();
console.log(mayusculas); // "BOGDAN DEV DOCS"
  1. trim - Elimina los espacios en blanco al principio y al final de una string:
let texto = "   Bogdan dev docs   ";
let textoLimpio = texto.trim();
console.log(textoLimpio); // "Bogdan dev docs"

TRIVIAL:

// Preguntas Almacenadas
let preguntas = [
    { categoria: "Geografia", pregunta: "¿Cuál es el río más largo del mundo?", respuesta: "Nilo" },
    { categoria: "Arte", pregunta: "¿Quién pintó la Mona Lisa?", respuesta: "Leonardo da Vinci" },
    { categoria: "Espectáculos", pregunta: "¿En qué año se estrenó la primera película de Star Wars?", respuesta: "1977" },
    { categoria: "Historia", pregunta: "¿Quién fue el primer presidente de los Estados Unidos?", respuesta: "George Washington" },
    { categoria: "Ciencias", pregunta: "¿Qué planeta es conocido como el 'Planeta Rojo'?", respuesta: "Marte" },
    { categoria: "Deportes", pregunta: "¿Cuántos jugadores tiene un equipo de fútbol en el campo?", respuesta: "11" }
];

// Estadísticas Partida
let falladas = 0;
let correctas = 0;

while(falladas < 3 && correctas < 4) {
    let categorias = "";
    preguntas.forEach(pregunta => categorias += "•" + pregunta.categoria + "\n");

    let categoria_eligida = prompt(`Aciertos: ${correctas} Fallos: ${falladas} \n¿Qué categoría quieres elegir? \n` + categorias);

    for(let x in preguntas) {
        if(preguntas[x].categoria == categoria_eligida) {
            let respuesta = prompt(preguntas[x].pregunta);
            comprobar(respuesta, preguntas[x].respuesta);
            preguntas.splice(x, 1);
        }
    }
}

function comprobar(respuesta, respuesta_correcta) {
    if (respuesta === respuesta_correcta) {
        correctas++;
    } else {
        falladas++;
    }

    if(falladas === 3) alert("Has perdido");
    if(correctas === 4) alert("Has ganado");
}

GENERAR USUARIO:

// Pepe Perez Sanchez 1990 == pperezs90

let datos = "Pepe Perez Sanchez 1990";
datos = datos.toLowerCase().split(" "); 
let nombre = datos[0];
let apellido1 = datos[1];
let apellido2 = datos[2];
let fnac = datos[3];
let usuario = nombre.charAt(0) + apellido1 + apellido2.charAt(0) + fnac.slice(-2);
alert(usuario);

CRONOMETRO:

<h2 id="cronometro"></h2>
<button id="iniciar">Iniciar</button>
<button id="reiniciar">Reiniciar</button>
<button id="parar">Parar</button>

<script>
var cronometro = document.getElementById('cronometro');
var iniciar = document.getElementById('iniciar');
var reiniciar = document.getElementById('reiniciar');
var parar = document.getElementById('parar');
var intervalo;
var segundos = 0;
var minutos = 0;
var horas = 0;

// lógica del cronómetro
function actualizarCronometro() {
    segundos++;
    if (segundos == 60) {
        segundos = 0;
        minutos++;
        if (minutos == 60) {
            minutos = 0;
            horas++;
        }
    }

    // Doy formato al tiempo
    let segcad = segundos.toString().padStart(2, "0");
    let mincad = minutos.toString().padStart(2, "0");
    let horcad = horas.toString().padStart(2, "0");

    cronometro.textContent = horcad + ":" + mincad + ":" + segcad;
}

iniciar.addEventListener('click', function() {
    if (!intervalo) {
        intervalo = setInterval(actualizarCronometro, 1000);
    }
});

parar.addEventListener('click', function() {
    clearInterval(intervalo);
    intervalo = null;
});

reiniciar.addEventListener('click', function() {
    clearInterval(intervalo);
    intervalo = null;
    segundos = 0;
    minutos = 0;
    horas = 0;
    cronometro.textContent = "00:00:00";
});
</script>

4. Objeto Math

GENERAR LOTERÍA Y NÚMEROS QUE NO SE REPITAN:

function decimo() {

    let array = [];
    let numero;
    
    ​while(array.length != 10) {
    
        numero = aleatorio(0,50);
        if(array.includes(numero)) {
        continue;
        } else {
        array.push(numero);
        }
    }
    return array;
}
}
SACAR NÚMEROS ALEATORIOS EN UN RANGO:
function aleatorio(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
}

CONVERSIÓN A BINARIO,DECIMAL,OCTAL,HEXADECIMAL:

binario = parseInt(numero,2);

decimal = parseInt(numero,10);

octal = parseInt(numero,8);

hexadecimal = parseInt(numero,16)

5. Objeto Array

  1. push - Agrega uno o más elementos al final de un array:
let frutas = ["manzana", "plátano"];
frutas.push("naranja");
console.log(frutas); // ["manzana", "plátano", "naranja"]
  1. pop - Elimina el último elemento de un array:
let frutas = ["manzana", "plátano", "naranja"];
frutas.pop();
console.log(frutas); // ["manzana", "plátano"]
  1. shift - Elimina el primer elemento de un array:
let frutas = ["manzana", "plátano", "naranja"];
frutas.shift();
console.log(frutas); // ["plátano", "naranja"]
  1. unshift - Agrega uno o más elementos al principio de un array:
let frutas = ["manzana", "plátano"];
frutas.unshift("naranja");
console.log(frutas); // ["naranja", "manzana", "plátano"]
  1. splice - Cambia el contenido de un array eliminando, sustituyendo o añadiendo nuevos elementos:
let frutas = ["manzana", "plátano", "naranja"];
frutas.splice(1, 1, "fresa");
console.log(frutas); // ["manzana", "fresa", "naranja"]
  1. slice - Devuelve una copia de una parte del array dentro de un nuevo array:
let frutas = ["manzana", "plátano", "naranja"];
let algunasFrutas = frutas.slice(1, 3);
console.log(algunasFrutas); // ["plátano", "naranja"]
  1. forEach - Ejecuta una función dada en cada elemento del array:
let frutas = ["manzana", "plátano", "naranja"];
frutas.forEach(function(fruta) {
    console.log(fruta);
});
// Salida: 
// manzana
// plátano
// naranja
  1. map - Crea un nuevo array con los resultados de aplicar una función a cada elemento del array:
let numeros = [1, 2, 3];
let dobles = numeros.map(function(numero) {
    return numero * 2;
});
console.log(dobles); // [2, 4, 6]
  1. filter - Crea un nuevo array con todos los elementos que cumplan la condición de una función dada:
let numeros = [1, 2, 3, 4, 5];
let pares = numeros.filter(function(numero) {
    return numero % 2 === 0;
});
console.log(pares); // [2, 4]
  1. reduce - Aplica una función a un acumulador y a cada elemento del array (de izquierda a derecha) para reducirlo a un único valor:
let numeros = [1, 2, 3, 4];
let suma = numeros.reduce(function(acumulador, numero) {
    return acumulador + numero;
}, 0);
console.log(suma); // 10

Ejemplo limpieza de Cadenas de Texto

document.addEventListener("DOMContentLoaded", function () {
    const Usuarios = [
        "Manolo$Lama Sánchez$999000000$lama@cope.es$28200$04/03/1969",
        "Manu$Carreño López$666000000$carreno@ser.es$12001$04/12/1975",
        "Maria Teresa$Molina Fernández$666000000$mteresa@extra.es$12001$21/08/1982",
        "Sammy$Diaz Dian$699660666$sammydev@psoe.es$28200$10/02/1829"
    ];

    // Limpia los datos y los transforma en arrays con información separada
    let Usuarios_limpiados = limpiarUsuarios(Usuarios);

    // Crea instancias de la clase Usuario
    let usuarios = crearUsuarios(Usuarios_limpiados);

    // Recorre el array de usuarios y genera claves y nombres de usuario
    usuarios.forEach(usuario => {
        usuario.clave = generarClave(usuario.nombre);
        usuario.nombre_usuario = crearNombre(usuario.nombre, usuario.apellido1);
        imprimir(usuario.mostrar());
    });
});

Las funciones:

function limpiarUsuarios(array) {
    return array.map(usuario => {
        let datos = usuario.split("$"); 

        let apellidos = datos[1].split(" ");
        let apellido1 = apellidos[0];
        let apellido2 = apellidos.length > 1 ? apellidos.slice(1).join(" ") : ""; // Evita undefined en caso de que solo este un apellido


        let nombres = datos[0].split(" ");
        let nombre1 = nombres[0];
        let nombre2 = nombres.length > 1 ? nombres.slice(1).join(" ") : ""; // Evita undefined en caso de que solo este un nombre

        return [
            nombre1,  //nombre
            nombre2,  // nombre2 (opcional)
            apellido1, // Primer apellido
            apellido2, // Segundo apellido (opcional)
            datos[2],  // Teléfono
            datos[3],  // Email
            datos[4],  // Código Postal
            datos[5]   // Fecha de nacimiento
        ];
    });
}
function crearUsuarios(usuarios) {
    if (!Array.isArray(usuarios)) {
        throw new Error("Debes pasar un array con usuarios.");
    }

    if (!usuarios.every(u => Array.isArray(u))) {
        throw new Error("Cada usuario debe ser un array de datos.");
    }

    return usuarios.map(datos => new Usuario(...datos));
}

function crearNombre(nombre, apellido) {
    if (typeof nombre !== "string" || typeof apellido !== "string") {
        throw new Error("Ambos parametros deben ser cadenas de texto.");
    }

    nombre = nombre.toLowerCase();
    apellido = apellido.toLowerCase();
    let primeraLetra = nombre.charAt(0);
    let tresUltimas = apellido.slice(-3);
    let longitudTotal = (nombre + apellido).replace(/\s/g, "").length;

    return `${primeraLetra}${tresUltimas}${longitudTotal}`;
}

function generarClave(nombre) {
    if (typeof nombre !== "string") {
        throw new Error("Debes pasar un nombre valido.");
    }

    return nombre.toUpperCase() + generarNumAlet(1000, 9999);
}

function generarNumAlet(min, max) {
    if (typeof min !== "number" || typeof max !== "number") {
        throw new Error("Debes pasar numeros validos.");
    }

    return Math.floor(Math.random() * (max - min + 1)) + min;
}

class Usuario {
    #nombre;
    #nombre2;
    #apellido1;
    #apellido2;
    #telefono;
    #email;
    #cp;
    #fecha_nacimiento;
    #clave;
    #nombre_usuario;

    constructor(nombre,nombre2 = "", apellido1,apellido2, telefono, email, cp, fecha_nacimiento) {
        this.#nombre = nombre;
        this.#nombre2 = nombre2;
        this.#apellido1 = apellido1;
        this.#apellido2 = apellido2;
        this.#telefono = telefono;
        this.#email = email;
        this.#cp = cp;
        this.#fecha_nacimiento = fecha_nacimiento;
        this.#clave = "";
        this.#nombre_usuario = "";
    }

    set clave(nuevaClave) {
        if (nuevaClave.length > 0) {
            this.#clave = nuevaClave; 
        } else {
            console.log("La clave no cumple con los requisitos.");
        }
    }

    get clave() {
        return this.#clave; 
    }

    set nombre_usuario(nuevoNombre) {
        if (nuevoNombre.length > 0) {
            this.#nombre_usuario = nuevoNombre; 
        } else {
            console.log("El nombre no cumple con los requisitos.");
        }
    }

    get nombre_usuario() {
        return this.#nombre_usuario; 
    }

    get nombre() {
        return this.#nombre;
    }

    get apellido1() {
        return this.#apellido1;
    }

    get telefono() {
        return this.#telefono;
    }

    get email() {
        return this.#email;
    }

    get cp() {
        return this.#cp;
    }

    get fecha_nacimiento() {
        return this.#fecha_nacimiento;
    }

    mostrar() {
        return "Nombre: " + this.#nombre + " " + this.#nombre2 +  " " + this.#apellido1 + " " + this.#apellido2 + "<br>" +
               "Telefono: " + this.#telefono + "<br>" +
               "Email: " + this.#email + "<br>" +
               "Codigo Postal: " + this.#cp + "<br>" +
               "Fecha de nacimiento: " + this.#fecha_nacimiento + "<br>" +
               "Nombre de usuario: " + this.#nombre_usuario + "<br>" +
               "Clave: " + this.#clave;
    }
    
}


function imprimir(texto) {
    const mostrador = document.createElement("div");
    mostrador.innerHTML = texto
    document.body.appendChild(mostrador);

}

1. Document Object Model (DOM)

1.2. Funciones JavaScript para Localizar Elementos

1.3. Manipulación de Atributos

Funciones para Crear/Eliminar Nodos

Ejemplo Navegación en el DOM

window.addEventListener("load", inicio);

function inicio() {
    let encabezados = document.getElementsByTagName("h2");

    for (let i = 0; i < encabezados.length; i++) {
        encabezados[i].addEventListener("click", recorrerAdelante);
    }
}

function recorrerAdelante(e) {
    let texto = "";
    let h2 = e.target;
    texto += `Has elegido ${h2.textContent}`;

    // Seleccionar el padre
    let padre = h2.parentElement;
    texto += ` que está situado en el ${padre.id}<br/>`;

    // Seleccionar el hermano
    let ul = h2.nextElementSibling;

    // Mostrar el número de hijos
    // ¡OJO! .childNodes incluye texto y comentarios; children no.
    texto += `El número de provincias es ${ul.children.length}: `;

    let hijo = ul.firstElementChild;
    // Si quisiéramos seleccionar el último hijo, pondríamos .lastElementChild.

    while (hijo !== null) {
        texto += ` ${hijo.textContent}`;
        hijo = hijo.nextElementSibling;
        // Si quisiéramos seleccionar el hermano anterior, pondríamos .previousElementSibling.
    }

    // Mostrar el texto
    document.getElementById("texto").innerHTML = texto;
    // Si usamos .textContent, mostraríamos solo texto plano sin etiquetas HTML.
}

Ejemplo Acceso Elementos DOM

window.addEventListener("load", inicio);

function inicio() {
    document.getElementById("cambiarTexto").addEventListener("click", cambiarTextos);
    document.getElementById("cambiarClase").addEventListener("click", cambiarClase);
    document.getElementById("quitarClase").addEventListener("click", quitarClase);
}

function cambiarTextos() {
    document.getElementById("parrafo1").innerHTML = "Cambio en el párrafo 1";
    document.getElementsByTagName("p")[1].innerHTML = "Cambio en el párrafo 2";
    document.getElementsByClassName("claseParrafo")[0].innerHTML = "Cambio en el párrafo 3";
}

function cambiarClase() {
    document.getElementById("parrafo1").setAttribute("class", "claseParrafo");
    document.getElementById("parrafo2").className = "claseParrafo";
}

function quitarClase() {
    let elementos = document.getElementsByTagName("p");
    for (let i = 0; i < elementos.length; i++) {
        elementos[i].className = "";
    }
}

Ejemplo Creación elementos con DOM

window.addEventListener("load", inicio);

function inicio() {
  document.getElementById("crearP").addEventListener("click", crearParrafo);
  document.getElementById("crearI").addEventListener("click", crearImagen);
  document.getElementById("borrarP").addEventListener("click", borrarParrafo);
}

function crearParrafo() {
  let parrafo = document.createElement("p");
  let texto = document.createTextNode(document.getElementById("texto").value);
  parrafo.appendChild(texto);

  let contenido = document.getElementById("div1");
  contenido.appendChild(parrafo);
}

function crearImagen() {
  let imagen = document.createElement("img");
  imagen.src = "goku.jpg";

  let contenido = document.getElementById("div3");
  contenido.appendChild(imagen);
}

function borrarParrafo() {
  let contenido = document.getElementById("div3");
  let hijo = contenido.lastChild;

  if (hijo) {
      contenido.removeChild(hijo);
  }
}

2. Formularios

2.2. Acceso a Elementos de Formularios

2.3. Validación de Formularios: Evento onsubmit

2.4. Deshabilitar Envío Doble

2.5. Enviar Formulario Desde Código


3. Validación de Formularios: Expresiones Regulares

3.1. Validación con Atributo pattern

3.2. Funciones JavaScript para Expresiones Regulares

Ejemplo de Validacion de formulario

document.addEventListener("DOMContentLoaded", function () {
  const form = document.querySelector("form");

  form.addEventListener("submit", validateForm);
  form.addEventListener("reset", confirmReset);

  document.getElementById("usuario").addEventListener("blur", validateUsername);
  document.getElementById("pwd").addEventListener("blur", validatePwd);
  document.getElementById("dni").addEventListener("blur", validateDni);
  document.getElementById("nacimiento").addEventListener("blur", validateNacimiento);
  document.getElementById("rama").addEventListener("change", validateRama);

  document.getElementsByName("horas").forEach(radio => {
      radio.addEventListener("change", validateHoras);
  });

  document.getElementById("condiciones").addEventListener("change", validateCondiciones);
});

function validaDNI(dni) {
  const partes = dni.split("-");
  if (partes.length !== 2) return false;

  const [num, letra] = partes;
  if (!/^\d{8}$/.test(num)) return false;

  const letrasValidas = "TRWAGMYFPDXBNJZSQVHLCKET";
  const letraEsperada = letrasValidas.charAt(parseInt(num, 10) % 23);
  
  return letra === letraEsperada;
}

function showError(campo, mensaje) {
  const container = document.getElementById("info" + campo.id);
  if (container) container.innerHTML = mensaje;
  campo.classList.add("error");
}

function clearError(campo) {
  const container = document.getElementById("info" + campo.id);
  if (container) container.innerHTML = "";
  campo.classList.remove("error");
}

function validateUsername() {
  const userField = document.getElementById("usuario");
  const value = userField.value.trim();

  if (value === "") {
      showError(userField, "El usuario no puede estar vacío.");
      return false;
  }

  if (!/^[a-z0-9]+$/.test(value)) {
      showError(userField, "El usuario debe contener solo minúsculas y números.");
      return false;
  }

  clearError(userField);
  return true;
}

function validatePwd() {
  const pwdField = document.getElementById("pwd");
  const value = pwdField.value;
  const errores = [];

  if (value.trim() === "") errores.push("La contraseña no puede estar vacía.");
  if (value.length <= 8) errores.push("Debe tener más de 8 caracteres.");
  if (!/[A-Z]/.test(value)) errores.push("Debe contener al menos una mayúscula.");
  if (!/[a-z]/.test(value)) errores.push("Debe contener al menos una minúscula.");
  if (!/\d/.test(value)) errores.push("Debe contener al menos un número.");
  if (!/[!@#$%^&*(),.?":{}|<>]/.test(value)) errores.push("Debe contener al menos un carácter especial.");

  if (errores.length > 0) {
      showError(pwdField, errores.join("<br>"));
      return false;
  }

  clearError(pwdField);
  return true;
}

function validateDni() {
  const dniField = document.getElementById("dni");
  let value = dniField.value.trim().toUpperCase();

  if (value === "") {
      showError(dniField, "El DNI no puede estar vacío.");
      return false;
  }

  if (!value.includes("-") && value.length === 9) {
      value = `${value.substring(0, 8)}-${value.substring(8)}`;
      dniField.value = value;
  }

  if (!/^\d{8}-[A-Z]$/.test(value)) {
      showError(dniField, "El DNI debe tener el formato NNNNNNNN-L.");
      return false;
  }

  if (!validaDNI(value)) {
      showError(dniField, "La letra del DNI no es correcta.");
      return false;
  }

  clearError(dniField);
  return true;
}

function validateNacimiento() {
  const nacimientoField = document.getElementById("nacimiento");
  const value = nacimientoField.value.trim();

  if (value === "") {
      showError(nacimientoField, "La fecha de nacimiento no puede estar vacía.");
      return false;
  }

  const fecha = new Date(value);
  if (isNaN(fecha.getTime())) {
      showError(nacimientoField, "La fecha de nacimiento no es válida.");
      return false;
  }

  const hoy = new Date();
  let edad = hoy.getFullYear() - fecha.getFullYear();
  const mes = hoy.getMonth() - fecha.getMonth();
  
  if (mes < 0 || (mes === 0 && hoy.getDate() < fecha.getDate())) edad--;

  if (edad < 18) {
      showError(nacimientoField, "Debes ser mayor de edad.");
      return false;
  }

  clearError(nacimientoField);
  return true;
}

function validateRama() {
  const ramaField = document.getElementById("rama");

  if (ramaField.value === "") {
      showError(ramaField, "Debes seleccionar una rama.");
      return false;
  }

  clearError(ramaField);
  return true;
}

function validateHoras() {
  const radios = document.getElementsByName("horas");
  const seleccionado = Array.from(radios).some(radio => radio.checked);

  const container = document.getElementById("infohoras");
  if (!seleccionado) {
      container.innerHTML = "Debes seleccionar las horas de programación.";
      return false;
  }

  container.innerHTML = "";
  return true;
}

function validateCondiciones() {
  const condField = document.getElementById("condiciones");

  if (!condField.checked) {
      showError(condField, "Debes aceptar enviar este formulario.");
      return false;
  }

  clearError(condField);
  return true;
}

function validateForm(event) {
  document.getElementById("mensajeError").innerText = "";
  let isValid = true;

  if (!validateUsername()) isValid = false;
  if (!validatePwd()) isValid = false;
  if (!validateDni()) isValid = false;
  if (!validateNacimiento()) isValid = false;
  if (!validateRama()) isValid = false;
  if (!validateHoras()) isValid = false;
  if (!validateCondiciones()) isValid = false;

  if (!isValid) {
      document.getElementById("mensajeError").innerText = "Por favor, corrija los errores indicados.";
      event.preventDefault();
      return false;
  }

  if (!confirm("¿Está seguro de enviar el formulario?")) {
      event.preventDefault();
      return false;
  }

  return true;
}

function confirmReset(event) {
  if (!confirm("¿Está seguro de borrar el formulario?")) {
      event.preventDefault();
      return false;
  }

  return true;
}

4. Expresiones Regulares (Referencia Rápida)

regexp.webp

Ejemplo de Funciones que validan campos con regexp:

Nombre de Usuario:

function validateUsername() {
  var userField = document.getElementById("usuario");
  var value = userField.value.trim();
  
  if (value === "") {
    showError(userField, "El usuario no puede estar vacio.");
    return false;
  }
  
  var regex = /^[a-z0-9]+$/;
  if (!regex.test(value)) {
    showError(userField, "El usuario debe contener solo minusculas y numeros.");
    return false;
  }
  
  clearError(userField);
  return true;
}

El formato de DNI:

function validateDni() {
  var dniField = document.getElementById("dni");
  var value = dniField.value.trim().toUpperCase();
  
  if (value === "") {
    showError(dniField, "El DNI no puede estar vacio.");
    return false;
  }
  
  if (value.indexOf("-") === -1 && value.length === 9) {
    value = value.substring(0, 8) + "-" + value.substring(8);
    dniField.value = value;
  }
  
  var patron = /^\d{8}-[A-Z]$/;
  if (!patron.test(value)) {
    showError(dniField, "El DNI debe tener el formato NNNNNNNN-L.");
    return false;
  }
  
  if (!validaDNI(value)) {
    showError(dniField, "La letra del DNI no es correcta.");
    return false;
  }
  
  clearError(dniField);
  return true;
}

Validación de Contraseña:

function validatePwd() {
  var pwdField = document.getElementById("pwd");
  var value = pwdField.value;
  var errores = [];
  
  if (value.trim() === "") errores.push("La contraseña no puede estar vacia.");
  if (value.length <= 8) errores.push("Debe tener mas de 8 caracteres.");
  if (!/[A-Z]/.test(value)) errores.push("Debe contener al menos una mayuscula.");
  if (!/[a-z]/.test(value)) errores.push("Debe contener al menos una minuscula.");
  if (!/\d/.test(value)) errores.push("Debe contener al menos un numero.");
  if (!/[!@#$%^&*(),.?":{}|<>]/.test(value)) errores.push("Debe contener al menos un caracter especial.");
  
  if (errores.length > 0) {
    showError(pwdField, errores.join("<br>"));
    return false;
  }
  
  clearError(pwdField);
  return true;
}

Validación de Fecha de nacimiento +18

function validateNacimiento() {
  var nacimientoField = document.getElementById("nacimiento");
  var value = nacimientoField.value.trim();
  
  if (value === "") {
    showError(nacimientoField, "La fecha de nacimiento no puede estar vacia.");
    return false;
  }
  
  var fecha = new Date(value);
  if (isNaN(fecha.getTime())) {
    showError(nacimientoField, "La fecha de nacimiento no es valida.");
    return false;
  }
  
  var hoy = new Date();
  var edad = hoy.getFullYear() - fecha.getFullYear();
  var mes = hoy.getMonth() - fecha.getMonth();
  if (mes < 0 || (mes === 0 && hoy.getDate() < fecha.getDate())) edad--;
  
  if (edad < 18) {
    showError(nacimientoField, "Debes ser mayor de edad.");
    return false;
  }
  
  clearError(nacimientoField);
  return true;
}

5. Peticiones Asíncronas: Fetch API

5.1. Introducción

5.2. Uso del Método fetch()

5.3. Manejo de Promesas

5.4. Opciones de fetch()

Procesamiento de la Respuesta y Manejo de Errores


Ejemplo de cancelación petición Fetch

<script>
    // Crear una instancia del controlador de aborto
    const controller = new AbortController();
    const signal = controller.signal;
    /*
    // Registrar un listener para detectar la cancelación
    signal.addEventListener("abort", () => {
        console.log("¡Petición abortada!");
    });
    */
    function beginFetching() {
        console.log("Iniciando la solicitud...");
        let urlToFetch = "https://httpbin.org/delay/3";

        fetch(urlToFetch, {
            method: "GET",
            signal: signal
        })
        .then(response => {
            console.log("Solicitud completada (No abortada).");
        })
        .catch(err => {
            console.error(`Error: ${err}`);
        });
    }

    function abortFetching() {
        console.log("Abortando la solicitud...");
        // Cancelar la petición
        controller.abort();
    }
</script>

<h1>Ejemplo de cancelación de fetch</h1>
<hr>
<button onclick="beginFetching();">Iniciar</button>
<button onclick="abortFetching();">Cancelar</button>

Ejemplo Petición Fetch JSON y respuesta JSON con botón de cancelación

//Tras la carga empieza el Script
window.addEventListener("load", function () {
    let resultado = document.getElementById("resultado");

    // Variables señal de cancelación del envío
    let controller;
    let signal;

    document.getElementById("cancelar").addEventListener("click", function () {
        console.log("Petición cancelada");
        controller.abort();
        resultado.innerHTML = "Petición Cancelada";
    });

    // Al hacer clic en enviar, envío los datos al servidor
    document.getElementById("enviar").addEventListener("click", function () {
        resultado.innerHTML = "Enviando...";

        // Creación del controlador de señal de cancelación (debe crearse una nueva en cada petición)
        controller = new AbortController();
        signal = controller.signal;

        // Preparo el JSON que se enviará con cada campo
        const jsonData = {
            nombre: document.getElementById("nombre").value
        };

        // Preparo las opciones de la petición
        const options = {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            signal: signal,
            body: JSON.stringify(jsonData)
        };

        // Lanzo la petición
        fetch("respuesta.php", options)
            // Proceso la respuesta
            .then(response => {
                if (response.ok) return response.text();
                throw new Error(response.status);
            })
            // Proceso los datos
            .then(data => {
                console.log(data);
                resultado.innerHTML = "Petición Correcta";
                resultado.innerHTML += "<br>Respuesta: " + data;
            })
            // En caso de error en la petición, lo gestiono
            .catch(err => {
                console.error("ERROR: ", err.message);
                resultado.innerHTML = "ERROR: " + err.message;
            });
    });
});

Tenemos un controlador en php que si recibe un json con la variable numero, devuelve esta cantidad de posts de la bbdd y sino devuelve corchetes.

if (!empty($obj['numero'])) {
    $numero = $obj['numero'];
    $posts = json_decode($json);
    $output = array_slice($posts, 0, $numero);
    echo json_encode($output);
    die();
} else {
    echo "[]";
    die();
}

Tenemos un html con input para introducir el numero de posts que queremos solicitar y el boton de enviar. Se ejecutara una animacion de carga mientras que se resuelven las promesas del fetch. luego los datos se dibujaran en el dom, cada post tendra un id que se usara para borrarlos del html eligiendo id de un select y dando al boton de borrar:

document.addEventListener("DOMContentLoaded", function() {
    const input_numero = document.getElementById("numero");
    const solicitar = document.getElementById("solicitar");
    const borrar = document.getElementById("eliminar");

    solicitar.addEventListener("click", function() {
        getData(input_numero.value);
    });

    borrar.addEventListener("click", function() {
        const select = document.getElementById("eliminados");
        const divposts = document.getElementById("posts");
        const todosposts = divposts.querySelectorAll("*");

        todosposts.forEach(postdiv => {
            if(postdiv.id === select.value) {
                console.log(postdiv);
                divposts.removeChild(postdiv);
            }
        });
    });
});
//Carga los datos con fetch
async function getData(valor) {
    const divposts = document.getElementById("posts");
    const divnumeroposts = document.getElementById("numeroPosts");
    const img = document.createElement("img");
    const p = document.createElement("p");
    divposts.innerHTML = "";
    p.textContent = "Cargando usuarios...";
    img.src = "loading.gif";
    divnumeroposts.appendChild(img);
    divnumeroposts.appendChild(p);

    const mensaje = { numero: valor };
    const url = "http://localhost:3000/ajax_dom/posts.php";
    const options = {
        body: JSON.stringify(mensaje),
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
    };

    try {
        const response = await fetch(url, options);
        if (!response.ok) {
            throw new Error(`Error: ${response.status}`);
        }
        const data = await response.json();
        console.log(data);

        divnumeroposts.removeChild(img);
        divnumeroposts.removeChild(p);

        showData(data);
    } catch (error) {
        console.error("Hubo un problema con la petición:", error);
    }
}

function showData(array) {
    const divposts = document.getElementById("posts");
    array.forEach(post => {
        const elementoprincipal = document.createElement("article");
        const titulo = document.createElement("h2");
        const bodypost = document.createElement("p");
        const userid = document.createElement("p");

        elementoprincipal.classList.add("post");
        elementoprincipal.id = post.id;
        titulo.textContent = post.title;
        bodypost.textContent = post.body;
        userid.textContent = "Usuario: " + post.id;

        elementoprincipal.appendChild(titulo);
        elementoprincipal.appendChild(bodypost);
        elementoprincipal.appendChild(userid);
        divposts.appendChild(elementoprincipal);
    });
}