Módulo 3: Introducción a JavaScript

Proyecto Final: Portafolio Interactivo

Lección 16 de 33 del Curso Roadmap Learning Laravel

Duración: 2 horas
Nivel: Principiante (requiere conocimientos de HTML, CSS, y JavaScript: variables, funciones, eventos, DOM, validación de formularios)
Objetivo: Mejorar el portafolio personal del Módulo 2 añadiendo al menos dos interacciones dinámicas con JavaScript (por ejemplo, validación de formulario y menú que se oculte/muestre), para crear una página web interactiva y profesional, como base para aplicaciones Laravel.
Materiales necesarios:

  • Computadora con un editor de texto (recomendado: VS Code, descarga gratuita desde code.visualstudio.com).
  • Navegador web (Chrome, Firefox, etc.) con consola de desarrollo (F12 o clic derecho > Inspeccionar > Console).
  • Alternativa: Usa un editor online como CodePen (codepen.io) para prototipos rápidos.
  • Código base: El portafolio del Módulo 2 (Lección 6: index.html, opcionalmente estilos.css).
    Entregable: Una página web (index.html y opcionalmente estilos.css, script.js) que sea responsive, use HTML semántico, CSS estilizado, y contenga al menos 2 interacciones dinámicas con JavaScript.
    Contexto: Este proyecto integra HTML, CSS, y JavaScript para simular una aplicación web interactiva, similar a las vistas Blade dinámicas en Laravel, donde las interacciones mejoran la experiencia del usuario.

Introducción al proyecto (15 minutos)

Explicación:

El proyecto final consiste en mejorar el portafolio personal creado en la Lección 6 del Módulo 2, que incluye secciones de Inicio, Sobre mí, y Contacto (con un formulario). Ahora, añadiremos interacciones dinámicas usando JavaScript para hacerlo más funcional y atractivo.

Interacciones sugeridas:

  1. Validación del formulario: Verificar que los campos (nombre, email, mensaje) no estén vacíos y que el email tenga un "@".
  2. Menú que se oculte/muestre: Un botón para alternar la visibilidad del menú de navegación, ideal para móviles.

Conceptos a usar:

  • HTML semántico (Módulo 2): <header>, <nav>, <main>, <form>, etc.
  • CSS estilizado y responsive (Módulo 2): Flexbox, media queries, unidades relativas.
  • JavaScript (Módulo 3):
    • Variables (let, const) y funciones (Lección 1).
    • Manipulación del DOM (getElementById, querySelector, style) (Lección 2).
    • Eventos (onclick, submit, preventDefault) y validación (Lección 3).

Estructura del portafolio base (recordatorio del Módulo 2):

  • Inicio: Título y bienvenida.
  • Sobre mí: Información personal, imagen, lista de habilidades.
  • Contacto: Formulario con nombre, email, mensaje.
  • Menú de navegación: Enlaces a las secciones (#inicio, #sobre-mi, #contacto).
  • Responsive: Ajustado para móviles con media queries.

Punto clave: Las interacciones dinámicas hacen que el portafolio sea más profesional, similar a una aplicación Laravel donde las vistas responden a las acciones del usuario.

Actividad rápida (5 minutos):

Revisa tu portafolio del Módulo 2 (index.html). En papel o VS Code, escribe 2 interacciones que te gustaría añadir además de las sugeridas. Ejemplo:

  • Mostrar un mensaje de éxito tras enviar el formulario.
  • Cambiar el fondo al hacer clic en un botón.

Planificación de las interacciones (20 minutos)

Explicación:

Antes de programar, planifiquemos las dos interacciones dinámicas principales: validación del formulario y menú que se oculte/muestre.

Interacción 1: Validación del formulario

  • Objetivo: Asegurar que nombre, email, y mensaje no estén vacíos, y que el email contenga "@".
  • Cómo hacerlo:
    • Usar el evento submit con preventDefault() para validar antes de enviar.
    • Seleccionar campos con getElementById.
    • Verificar .value para campos vacíos y includes("@") para el email.
    • Mostrar errores con <p> o alert, y un mensaje de éxito si es válido.
  • Ejemplo de lógica:
    let nombre = document.getElementById("nombre").value;
    if (nombre === "") {
        document.getElementById("errorNombre").textContent = "Nombre vacío";
    }

Interacción 2: Menú que se oculte/muestre

  • Objetivo: Un botón que alterne la visibilidad del menú (<nav>), útil en móviles.
  • Cómo hacerlo:
    • Añadir un botón con onclick para llamar a una función.
    • Usar style.display ("none" para ocultar, "block" para mostrar).
    • Alternar con una condición (if).
  • Ejemplo de lógica:
    function toggleMenu() {
        let menu = document.getElementById("menu");
        menu.style.display = menu.style.display === "none" ? "block" : "none";
    }

Requisitos del proyecto:

  • Mantener el HTML semántico y CSS responsive del portafolio original.
  • Añadir JavaScript en <script> o un archivo externo (script.js).
  • Garantizar accesibilidad: Mensajes de error claros, navegación por teclado.
  • Probar en móviles (usar herramientas de desarrollo para simular pantallas pequeñas).

Punto clave: Planificar las interacciones asegura que el código sea organizado, una práctica que usarás en Laravel para estructurar vistas y lógica.

Actividad rápida (5 minutos):

En papel o VS Code, escribe el HTML y JavaScript básico para un botón que llame a una función toggleMenu(). Solución sugerida:

<button onclick="toggleMenu()">Menú</button>
<script>
    function toggleMenu() {
        console.log("Menú alternado");
    }
</script>

Implementación del portafolio interactivo (1 hora 15 minutos)

Explicación:

Ahora mejoraremos el portafolio añadiendo las interacciones. Usaremos el código base del Módulo 2 y lo extenderemos con JavaScript. Dividiremos el trabajo en: actualizar el HTML/CSS, implementar la validación del formulario, e implementar el menú interactivo.

Paso 1: Código base actualizado
Tomemos el portafolio del Módulo 2 y añadamos elementos para las interacciones:

<!DOCTYPE html>
<html lang="es">
<head>
    <title>Mi Portafolio Interactivo</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            color: #333;
        }
        header {
            background-color: #2c3e50;
            color: white;
            padding: 1rem;
            text-align: center;
        }
        #menuToggle {
            display: none; /* Oculto en escritorio */
            background-color: #34495e;
            color: white;
            padding: 10px;
            border: none;
            cursor: pointer;
        }
        nav {
            margin-top: 1rem;
        }
        nav a {
            color: white;
            text-decoration: none;
            margin: 0 1rem;
        }
        nav a:hover {
            text-decoration: underline;
        }
        main {
            max-width: 800px;
            margin: 0 auto;
            padding: 1rem;
        }
        section {
            margin-bottom: 2rem;
            padding: 2rem;
            background-color: #f9f9f9;
            border-radius: 8px;
        }
        #sobre-mi img {
            max-width: 150px;
            border-radius: 50%;
        }
        form {
            display: flex;
            flex-direction: column;
        }
        .campo {
            margin-bottom: 1rem;
        }
        label {
            font-weight: bold;
            margin-bottom: 0.3rem;
        }
        input, textarea {
            padding: 0.5rem;
            border: 2px solid #ccc;
            border-radius: 4px;
            font-size: 1rem;
        }
        button {
            background-color: #2c3e50;
            color: white;
            padding: 0.7rem;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            background-color: #34495e;
        }
        .error {
            color: red;
            font-size: 0.9rem;
            margin-top: 0.2rem;
        }
        footer {
            background-color: #2c3e50;
            color: white;
            text-align: center;
            padding: 1rem;
            margin-top: 2rem;
        }
        /* Responsive */
        @media (max-width: 600px) {
            #menuToggle {
                display: block; /* Visible en móvil */
            }
            nav {
                display: none; /* Oculto por defecto en móvil */
            }
            nav.mostrar {
                display: block; /* Mostrar cuando se activa */
            }
            nav a {
                display: block;
                margin: 0.5rem 0;
            }
            section {
                padding: 1rem;
            }
        }
    </style>
</head>
<body>
    <header>
        <h1>Mi Portafolio</h1>
        <button id="menuToggle" onclick="toggleMenu()">☰ Menú</button>
        <nav id="menu">
            <a href="#inicio">Inicio</a>
            <a href="#sobre-mi">Sobre mí</a>
            <a href="#contacto">Contacto</a>
        </nav>
    </header>
    <main>
        <section id="inicio">
            <h2>Hola, soy [Tu Nombre]</h2>
            <p>Bienvenido a mi portafolio interactivo.</p>
        </section>
        <section id="sobre-mi">
            <h2>Sobre mí</h2>
            <img src="https://via.placeholder.com/150" alt="Foto de perfil">
            <p>Soy un apasionado del desarrollo web, con experiencia en HTML, CSS y JavaScript.</p>
            <ul>
                <li>Habilidad: Desarrollo frontend</li>
                <li>Interés: Laravel y JavaScript</li>
            </ul>
        </section>
        <section id="contacto">
            <h2>Contacto</h2>
            <form id="contactoForm" onsubmit="validarFormulario(event)">
                <div class="campo">
                    <label for="nombre">Nombre:</label>
                    <input type="text" id="nombre" name="nombre" placeholder="Tu nombre">
                    <p id="errorNombre" class="error"></p>
                </div>
                <div class="campo">
                    <label for="email">Email:</label>
                    <input type="email" id="email" name="email" placeholder="Tu correo">
                    <p id="errorEmail" class="error"></p>
                </div>
                <div class="campo">
                    <label for="mensaje">Mensaje:</label>
                    <textarea id="mensaje" name="mensaje" placeholder="Tu mensaje" rows="4"></textarea>
                    <p id="errorMensaje" class="error"></p>
                </div>
                <button type="submit">Enviar</button>
            </form>
        </section>
    </main>
    <footer>
        <p>© 2023 [Tu Nombre]. Todos los derechos reservados.</p>
    </footer>
</body>
</html>

Cambios realizados:

  • HTML:
    • Añadido <button id="menuToggle"> para alternar el menú.
    • <nav id="menu"> con ID para manipularlo.
    • <p class="error"> bajo cada campo del formulario para mensajes de validación.
    • <div class="campo"> para organizar los campos.
  • CSS:
    • Estilo para el botón de menú (#menuToggle), visible solo en móviles.
    • nav.mostrar para mostrar el menú en móviles cuando se activa.
    • Clase .error para mensajes de error en rojo.
    • Mantienen la responsividad y accesibilidad del portafolio original.

Paso 2: Añadir JavaScript para las interacciones
Agregamos el código JavaScript dentro de <script> o en un archivo externo (script.js con <script src="script.js"></script>):

<script>
    // Interacción 1: Validación del formulario
    function validarFormulario(event) {
        event.preventDefault();
        let nombre = document.getElementById("nombre").value;
        let email = document.getElementById("email").value;
        let mensaje = document.getElementById("mensaje").value;
        let errorNombre = document.getElementById("errorNombre");
        let errorEmail = document.getElementById("errorEmail");
        let errorMensaje = document.getElementById("errorMensaje");
        let esValido = true;

        // Limpiar errores previos
        errorNombre.textContent = "";
        errorEmail.textContent = "";
        errorMensaje.textContent = "";

        // Validar nombre
        if (nombre === "") {
            errorNombre.textContent = "El nombre no puede estar vacío";
            esValido = false;
        }

        // Validar email
        if (email === "") {
            errorEmail.textContent = "El email no puede estar vacío";
            esValido = false;
        } else if (!email.includes("@")) {
            errorEmail.textContent = "El email debe contener un @";
            esValido = false;
        }

        // Validar mensaje
        if (mensaje === "") {
            errorMensaje.textContent = "El mensaje no puede estar vacío";
            esValido = false;
        }

        // Mostrar éxito si es válido
        if (esValido) {
            alert("Formulario enviado con éxito: " + nombre + ", " + email);
            document.getElementById("contactoForm").reset(); // Limpiar formulario
        }
    }

    // Interacción 2: Menú que se oculte/muestre
    function toggleMenu() {
        let menu = document.getElementById("menu");
        menu.classList.toggle("mostrar");
    }
</script>

Cómo funciona:

  • Validación del formulario:
    • onsubmit="validarFormulario(event)": Llama a la función al enviar.
    • event.preventDefault(): Evita el envío por defecto.
    • Verifica que nombre, email, y mensaje no estén vacíos.
    • Comprueba que email tenga "@" con includes().
    • Muestra errores en <p class="error"> o una alerta de éxito.
    • reset() limpia el formulario tras un envío válido.
  • Menú que se oculte/muestre:
    • onclick="toggleMenu()": Llama a la función al clic.
    • classList.toggle("mostrar"): Alterna la clase .mostrar para cambiar display en móviles.
    • En escritorio, el menú permanece visible; en móvil, se muestra el botón.

Cómo probarlo:

  1. Crea un archivo portafolio_interactivo.html en VS Code.
  2. Copia el HTML, CSS, y JavaScript (o usa script.js con <script src="script.js">).
  3. Ábrelo en un navegador.
  4. Prueba las interacciones:
    • Formulario:
      • Enviar con campos vacíos → Errores en rojo.
      • Enviar con email sin "@" → Error: "El email debe contener un @".
      • Enviar con datos válidos → Alerta de éxito y formulario limpio.
    • Menú:
      • En móvil (simula con F12 > dispositivo): Clic en "☰ Menú" muestra/oculta los enlaces.
      • En escritorio: Menú siempre visible, botón oculto.
  5. Usa la consola (F12 > Console) para depurar errores.
  6. Alternativa: Pega en CodePen y ajusta la vista previa.

Resultado esperado:

  • Pantallas grandes (>600px): Menú horizontal, formulario funcional con validación, errores en rojo, alerta de éxito.
  • Pantallas móviles (≤600px): Botón "☰ Menú" que alterna la visibilidad del menú vertical, formulario con validación intacta.
  • Accesibilidad: Errores claros, navegación por teclado (Tab para formulario, Enter para enviar).

Punto clave: Estas interacciones simulan funcionalidades de una vista Blade en Laravel, donde JavaScript mejora la experiencia del usuario.


Personalización y pruebas (25 minutos)

Explicación:

Con las interacciones funcionando, dedica tiempo a personalizar y probar:

  • Personalización:
    • Cambia colores del CSS (por ejemplo, #e74c3c para rojo).
    • Añade una imagen personal en Sobre mí (src="perfil.jpg").
    • Modifica los mensajes de error o alerta (por ejemplo, "¡Gracias por contactarme!").
    • Opcional: Añade una tercera interacción (por ejemplo, cambiar el texto de bienvenida al clic).
  • Pruebas:
    • Verifica responsividad en móviles y escritorios (320px, 768px, 1200px).
    • Prueba accesibilidad: Navega con Tab/Enter, verifica mensajes de error claros.
    • Abre en varios navegadores (Chrome, Firefox, Edge) para compatibilidad.
    • Usa la consola para detectar errores (por ejemplo, IDs incorrectos).

Ejemplo de personalización:

Cambiar colores y mensaje de éxito:

<style>
    header, footer, button {
        background-color: #e74c3c; /* Rojo */
    }
</style>
<script>
    if (esValido) {
        alert("¡Gracias, " + nombre + "! Tu mensaje fue enviado.");
        document.getElementById("contactoForm").reset();
    }
</script>

Punto clave: Personalizar y probar son habilidades clave para crear vistas únicas en Laravel, asegurando funcionalidad y calidad.

Actividad rápida (5 minutos):

Añade un mensaje en Sobre mí que cambie al clic (tercera interacción opcional). Solución sugerida:

<p id="bio">Soy desarrollador web.</p>
<button onclick="cambiarBio()">Cambiar Bio</button>
<script>
    function cambiarBio() {
        document.getElementById("bio").textContent = "¡Apasionado por la tecnología!";
    }
</script>

Reflexión y mejoras (10 minutos)

Explicación:

Reflexionemos sobre lo aprendido y posibles mejoras:

  • Logros:
    • Mejoraste el portafolio con HTML semántico, CSS responsive, y JavaScript interactivo.
    • Implementaste validación de formulario (Lección 3) y un menú dinámico (Lección 2).
    • Creaste un proyecto completo, similar a una vista Blade interactiva en Laravel.
  • Mejoras posibles:
    • Añadir validación avanzada (por ejemplo, longitud mínima para el mensaje).
    • Usar addEventListener en lugar de onclick/onsubmit para modernizar el código.
    • Implementar animaciones CSS para el menú (por ejemplo, deslizamiento).
    • Estas mejoras se explorarán en módulos futuros (por ejemplo, frameworks como Vue.js).

Actividad final (5 minutos):

Piensa en una mejora para tu portafolio (por ejemplo, un contador de clics). Escribe en papel o VS Code el código para añadirla. Ejemplo:

<p>Clics: <span id="contador">0</span></p>
<button onclick="contarClic()">Clic</button>
<script>
    let clics = 0;
    function contarClic() {
        clics++;
        document.getElementById("contador").textContent = clics;
    }
</script>

Entregable: Página con al menos 2 interacciones dinámicas

Requisitos:

  • Un archivo portafolio_interactivo.html (y opcionalmente estilos.css, script.js) que contenga:
    • HTML semántico:
      • <header> con menú (<nav>).
      • <main> con secciones Inicio, Sobre mí, Contacto (usando <section>).
      • <form> en Contacto con nombre, email, mensaje.
      • <footer> con información básica.
    • CSS estilizado y responsive:
      • Diseño atractivo (colores, fuentes, márgenes).
      • Media query para móviles (menú colapsable, formulario ajustado).
      • Estilos para errores (color: red).
    • JavaScript con 2 interacciones dinámicas:
      • Validación de formulario: Verifica nombre, email (con "@"), mensaje no vacíos; muestra errores y éxito.
      • Menú que se oculte/muestre: Botón que alterna el menú, activo en móviles.
    • Accesibilidad:
      • Mensajes de error claros.
      • Navegación por teclado funcional (Tab para formulario, Enter para enviar).
      • alt en imágenes.
  • La página debe verse bien en navegadores modernos y simular un portafolio profesional interactivo.

Instrucciones para completar:

  1. Usa el código proporcionado como base o mejora tu portafolio del Módulo 2.
  2. Implementa las interacciones:
    • Validación: Añade <p class="error"> y verifica campos con JavaScript.
    • Menú: Añade un botón y usa classList.toggle o style.display.
  3. Personaliza el contenido:
    • Usa tu nombre, texto real en Sobre mí, colores propios.
    • Opcional: Incluye una imagen personal (alt descriptivo).
  4. Prueba exhaustivamente:
    • Verifica responsividad (móviles y escritorios).
    • Prueba el formulario con datos inválidos/válidos.
    • Confirma que el menú alterna en móviles.
    • Revisa la consola para errores.
  5. Guarda el proyecto en una carpeta (por ejemplo, portafolio_interactivo/) con index.html, y opcionalmente estilos.css, script.js.
  6. Opcional: Añade una tercera interacción (por ejemplo, cambiar texto dinámicamente).

Tiempo estimado: 1.5 horas dentro de la lección (implementación y pruebas) + 30 minutos para personalización o depuración.
Entregable: Archivo portafolio_interactivo.html (y archivos asociados) funcional. Puedes compartir el código o describirlo para que lo revise.

Ejemplo de uso:

  • En navegador: Un portafolio con menú clickable, formulario validado, y errores claros.
  • En móvil: Botón "☰" que muestra el menú, formulario ajustado y funcional.

Consejo: Guarda copias del código (index_v1.html) para experimentar sin riesgos.

Evaluación Final: Conocimientos Clave para Crear Interacciones Dinámicas

¡Es momento de evaluar tus conocimientos sobre interacciones dinámicas en desarrollo web! Este examen consta de 10 preguntas con opciones múltiples que cubren temas clave como validación de formularios, manipulación del DOM y la creación de funcionalidades interactivas. Contesta con atención y demuestra cómo aplicarías estas técnicas en proyectos reales. ¡Éxito!

1. ¿Cuál es el objetivo principal del proyecto final del Módulo 3?

2. ¿Qué interacción dinámica verifica que los campos del formulario no estén vacíos?

3. ¿Qué método JavaScript se usó para evitar el envío del formulario durante la validación?

4. ¿Qué propiedad CSS se alternó para mostrar u ocultar el menú en móviles?

5. ¿Qué elemento HTML contiene los enlaces de navegación en el portafolio?

6. En la validación del formulario, ¿qué se comprobó específicamente en el campo email?

7. ¿Qué método JavaScript se usó para alternar la clase del menú?

8. ¿Qué técnica CSS asegura que el portafolio sea responsive en móviles?

9. ¿Cómo se mostraban los mensajes de error en el formulario?

10. ¿Qué atributo mejora la accesibilidad de la imagen en la sección Sobre mí?

© Copyright Cursos Laravel :: 2025 Términos y condiciones