W3docs

Ventanas emergentes en JavaScript y window.open()

Aprende a abrir, controlar y cerrar ventanas del navegador en JavaScript con window.open(), window.close(), eventos focus/blur y postMessage, más restricciones de seguridad y buenas prácticas.

Entre las capacidades de JavaScript, abrir y controlar ventanas separadas del navegador te permite crear flujos de inicio de sesión, handshakes OAuth, vistas previas de impresión y superficies de notificación enriquecidas. Este capítulo cubre todo lo que necesitas: abrir una ventana con window.open(), dimensionarla y posicionarla, intercambiar mensajes con ella, reaccionar a eventos de foco y descarga, y cerrarla correctamente — junto con las restricciones de seguridad modernas que determinan cómo los navegadores tratan todo esto.

Para los diálogos simples de una sola línea (alert, prompt y confirm), consulta JavaScript alert, prompt y confirm. Esta página trata sobre ventanas completas del navegador.

Entendiendo las ventanas emergentes de JavaScript

Una ventana emergente es una ventana de navegador de nivel superior independiente que tu script abre. A diferencia de un alert() modal, tiene su propio documento, su propia URL y permanece abierta hasta que el usuario (o tu código) la cierra. Las ventanas emergentes son útiles para contenido que debe vivir fuera de la página actual: la pantalla de inicio de sesión de un proveedor OAuth, un widget de pago o un informe imprimible. El único punto de entrada para todo esto es el método window.open().

Cómo funciona window.open()

window.open() acepta tres argumentos y devuelve una referencia a la nueva ventana (o null si el navegador la bloqueó):

let win = window.open(url, name, features);
ArgumentoSignificado
urlLa página que se cargará. Pasa una cadena vacía "" para abrir una ventana en blanco que rellenas con script.
nameUn nombre de destino. Reutilizar el mismo nombre reutiliza la misma ventana en lugar de abrir una nueva. Valores especiales como _blank siempre abren una nueva ventana.
featuresUna string de opciones separadas por comas como width=400,height=300,left=100,top=100. Omítela para heredar los valores predeterminados.

warning Los navegadores solo permiten que window.open() tenga éxito cuando se ejecuta directamente dentro de un gesto del usuario como un clic. Llamarla al cargar la página o dentro de un setTimeout se trata como una ventana emergente no solicitada y se bloquea — win devuelve null. Siempre activa las ventanas emergentes desde un controlador de eventos real y verifica el valor de retorno.

Creando una ventana emergente básica

Para crear una ventana emergente simple, llama a window.open() desde un controlador de clic. El método abre una nueva ventana del navegador y devuelve una referencia a ella, que puedes usar para manipular la ventana más adelante.

<p>Click the button to trigger the popup!</p>
<button onclick="openPopup()">Open Popup</button>

<script>

// Function to open a new popup with a message
function openPopup() {
    let newWindow = window.open("", "Example", "width=400,height=400");
    // Use innerHTML for safer dynamic content injection
    newWindow.document.body.innerHTML = "<h1>Welcome to our popup!</h1>";
}
</script>

warning Nota: document.write puede sobreescribir el documento completo si se llama después de que la página se haya cargado. La práctica moderna prefiere innerHTML o métodos de manipulación del DOM para una inyección de contenido dinámico más segura.

Este fragmento de código crea un botón en la página web. Al hacer clic en él, se abre una nueva ventana emergente con dimensiones de 400x400 píxeles y muestra un mensaje de bienvenida.

Controlando el contenido y comportamiento de las ventanas emergentes

Controlar el contenido y el comportamiento de las ventanas emergentes es fundamental para garantizar que contribuyan positivamente a la experiencia del usuario sin ser intrusivas.

<p>Click the button to trigger the popup!</p>
<button onclick="openInteractivePopup()">Learn More</button>

<script>
// Function to open a popup and control its content and behavior
function openInteractivePopup() {
    // Open a new window with specific dimensions
    let popup = window.open("", "InteractivePopupExample", "width=400,height=400");
    // Use innerHTML to inject content safely
    popup.document.body.innerHTML = `
        <h1>Interactive Popup</h1>
        <p>Click the button to change this message.</p>
        <button onclick='document.body.innerHTML = "<h1>Content Updated!</h1><p>Thanks for interacting.</p>";'>Update Content</button>
    `;
}
</script>

Para comunicarse de forma segura entre la ventana padre y la ventana emergente, usa la propiedad window.opener para hacer referencia al padre, y postMessage() para el intercambio de datos entre orígenes o de forma más segura. Para un tratamiento más profundo de este tema, consulta Comunicación entre ventanas.

<!-- In parent window -->
<script>
let popup = window.open("popup.html", "Popup", "width=400,height=400");
popup.postMessage("Hello from parent!", "*");
</script>

<!-- In popup window -->
<script>
window.addEventListener("message", (event) => {
    console.log("Received:", event.data);
    // Respond back if needed
    window.opener.postMessage("Hello back!", event.origin);
});
</script>

Aspectos clave:

  • Esta función no solo abre una ventana emergente, sino que también incorpora elementos interactivos (como un botón dentro de la ventana emergente).
  • Demuestra cómo controlar el contenido de la ventana emergente de forma dinámica después de su creación, lo que es más interactivo y se puede adaptar para reaccionar a las entradas del usuario u otros eventos.

Métodos y eventos avanzados de Window

Más allá de las ventanas emergentes básicas, JavaScript ofrece una variedad de métodos para interactuar con las ventanas del navegador, mejorando la funcionalidad y la interactividad del usuario.

Redimensionar y mover elementos

JavaScript permite redimensionar y reposicionar elementos de la página de forma dinámica, lo que puede ser especialmente útil para crear aplicaciones web responsivas y fáciles de usar. (Nota: window.resizeTo() y window.moveTo() existen para pruebas heredadas o en entornos restringidos, pero los navegadores modernos los restringen en gran medida por razones de seguridad. Este ejemplo simula el comportamiento usando un div con estilos. Para elementos de interfaz arrastrables o redimensionables, position: absolute se prefiere a menudo sobre relative para garantizar cálculos de coordenadas predecibles.)

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Simulate Window Adjustments</title>
    <style>
        #simulatedWindow {
            width: 300px;
            height: 300px;
            position: absolute;
            background-color: #f3f3f3;
            border: 2px solid #ccc;
            margin: 20px;
            padding: 10px;
            transition: all 0.5s ease; /* Smooth transition for size and position changes */
        }
    </style>
</head>
<body>
    <button onclick="adjustSimulatedWindow()">Adjust Window</button>
    <div id="simulatedWindow">This is a simulated window. Click the button to adjust its size and position.</div>

    <script>
        function adjustSimulatedWindow() {
            const elem = document.getElementById('simulatedWindow');
            // Toggle size and position to demonstrate the effect
            if (elem.style.width === '500px') {
                elem.style.width = '300px';
                elem.style.height = '300px';
                elem.style.top = '0px';
                elem.style.left = '0px';
            } else {
                elem.style.width = '500px';
                elem.style.height = '500px';
                elem.style.top = '100px';
                elem.style.left = '100px';
            }
        }
    </script>
</body>
</html>

Aspectos clave:

  1. Estructura HTML: Incluye un botón y un elemento div con estilos para parecerse a una ventana. El div representa la ventana que "redimensionaremos" y "moveremos".
  2. Estilos CSS: Define el tamaño y la posición iniciales de la ventana simulada, con transiciones suaves para el efecto visual.
  3. Función JavaScript: Cuando se hace clic en el botón, la función adjustSimulatedWindow alterna el tamaño y la posición de la ventana simulada. El cambio de posición se gestiona alterando las propiedades CSS top y left, simulando el movimiento de una ventana por la pantalla.

Manejo de eventos de Window

El manejo de eventos es fundamental para crear aplicaciones interactivas. JavaScript proporciona varios eventos relacionados con las acciones de la ventana, como onbeforeunload y onunload, que se pueden usar para ejecutar código en momentos estratégicos.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>JavaScript Window Events Demo</title>
    <style>
        #message {
            padding: 20px;
            margin: 20px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <p>Watch how the message updates based on window events. Initially, it changes upon loading. If you attempt to exit or click the mock exit link below, a prompt will appear asking if you want to leave the page. Cancelling the action will update the message.</p>
    <div id="message">Wait for it...</div>
    <!-- Mock link for simulating page leave -->
    <a href="#" onclick="simulatePageLeave(); return false;">Mock Page Leave</a>
    <script>
        window.onload = function() {
            document.getElementById('message').innerHTML = '<strong>Window loaded successfully!</strong>';
        };

        // Function to simulate page leave
        function simulatePageLeave() {
            // Show dialog asking if the user really wants to leave
            var confirmLeave = confirm('Are you sure you want to simulate leaving the page?');
            if (confirmLeave) {
                // If confirmed, update message as if leaving
                document.getElementById('message').innerHTML = '<strong>Leaving the page...</strong>';
            } else {
                // If cancelled, update message accordingly
                document.getElementById('message').innerHTML = '<strong>Decided to stay on the page!</strong>';
            }
        }

        window.onbeforeunload = function() {
            document.getElementById('message').innerHTML = '<strong>Preparing to leave the page...</strong>';
            return 'Are you sure you want to leave?';
        };
    </script>
</body>
</html>

Aspectos clave:

  1. Enlace simulado para simular la salida de página: El enlace con href="#" y un controlador onclick que llama a simulatePageLeave(); return false; simula el efecto de intentar salir de la página. El return false; evita la acción predeterminada del enlace, manteniendo al usuario en la página actual.
  2. Diálogo de confirmación: La función simulatePageLeave presenta un diálogo de confirmación similar a lo que podría ocurrir con un intento real de descarga de página. Permite a los usuarios decidir si desean "salir" o no.
  3. Actualizaciones de mensajes: Según la elección del usuario en el diálogo de confirmación, el mensaje en el div se actualiza para reflejar la elección, imitando el comportamiento que cabría esperar al intentar realmente salir de la página.
  4. Nota sobre el comportamiento del navegador: Los navegadores modernos ignoran las cadenas personalizadas devueltas por onbeforeunload y solo muestran un diálogo de confirmación predeterminado. El ejemplo demuestra el activador del evento, pero el texto exacto del mensaje está controlado por el navegador.
Información

Cambiar el innerHTML de un elemento hace que las interacciones del usuario sean más fluidas y menos disruptivas. Este enfoque funciona muy bien para sitios web interactivos y herramientas educativas.

Cerrar una ventana emergente

Es importante proporcionar un mecanismo para que los usuarios puedan cerrar fácilmente las ventanas emergentes que creas. Esto mejora la experiencia del usuario al permitirles controlar su propia interacción con tu aplicación.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Popup Example</title>
    <script>
        var myPopup = null; // Initialize the popup variable.

        // Function to open a popup
        function openPopup() {
            // Check if the popup already exists and is not closed
            if (myPopup === null || myPopup.closed) {
                myPopup = window.open("", "PopupWindow", "width=400,height=400");
                // Set the content of the popup using innerHTML
                myPopup.document.body.innerHTML = `
                    <html>
                    <head><title>Popup Content</title></head>
                    <body>
                        <h1>Welcome!</h1>
                        <p>This is your popup window.</p>
                        <button onclick="window.close()">Close Window</button>
                    </body>
                    </html>
                `;
                // Ensure the popup gets focus
                myPopup.focus();
            } else {
                // Bring the already opened popup to the front
                myPopup.focus();
            }
        }

        // Function to close the popup
        function closePopup() {
            if (myPopup && !myPopup.closed) {
                myPopup.close();
                myPopup = null; // Reset the popup variable after closing it.
            }
        }
    </script>
</head>
<body>
    <button onclick="openPopup()">Open Popup</button>
    <button onclick="closePopup()">Close Popup</button>
</body>
</html>

Aspectos clave:

  1. Gestión del estado: La variable myPopup se establece inicialmente en null y se verifica para ver si es null o ha sido cerrada (myPopup.closed). Esto ayuda a decidir si crear una nueva ventana emergente o enfocar la existente.
  2. Duplicación de contenido: Al asegurarse de que la ventana emergente está correctamente inicializada o cerrada, se evita el problema de duplicar el contenido. Cada apertura de la ventana emergente comienza desde cero.
  3. Gestión del foco: Usar myPopup.focus() garantiza que, si la ventana emergente ya está abierta, pasará al primer plano cuando se haga clic en "Open Popup" nuevamente.
Información

Siempre prueba el comportamiento de las ventanas emergentes y los métodos de window en diferentes navegadores y dispositivos para garantizar la compatibilidad y la capacidad de respuesta.

Focus y Blur en una ventana

Los eventos focus y blur se pueden usar para detectar cuándo una ventana o página gana o pierde el foco. Esto puede ser útil para pausar actividades cuando el usuario cambia de pestaña o ventana.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Focus and Blur Events Demo</title>
    <style>
        body { transition: background-color 0.5s ease; } /* Smooth transition for background color */
    </style>
    <script>
        // Function to handle focus event
        function handleFocus() {
            document.getElementById('status').innerHTML = 'Window is focused';
            document.body.style.backgroundColor = '#DFF0D8'; // Light green background
        }

        // Function to handle blur event
        function handleBlur() {
            document.getElementById('status').innerHTML = 'Window is not focused';
            document.body.style.backgroundColor = '#F2DEDE'; // Light red background
        }

        window.addEventListener('focus', handleFocus);
        window.addEventListener('blur', handleBlur);
    </script>
</head>
<body>
    <h1>Focus and Blur Events on Window</h1>
    <p>Status: <span id="status">Window is focused</span></p>
    <p><strong>Instructions:</strong> To test this functionality, click inside this window to focus, then click away to another window or tab to trigger the blur effect. Notice the background color change and status update.</p>
</body>
</html>

Aspectos clave:

  • Controladores de eventos: handleFocus() y handleBlur() actualizan el contenido de la página y el color de fondo según el estado de foco de la ventana.
  • Retroalimentación visual: Los cambios en el color de fondo proporcionan retroalimentación visual inmediata y clara sobre el estado de foco, mejorando la experiencia interactiva.

Seguridad y bloqueadores de ventanas emergentes

Dado que las ventanas emergentes han sido históricamente abusadas, los navegadores modernos aplican reglas estrictas. Conocerlas ahorra horas de depuración del tipo "¿por qué mi ventana es null?".

  • Requisito de gesto. Una ventana emergente solo se abre durante una acción síncrona del usuario (clic, pulsación de tecla, toque). Después de un await o un setTimeout, el gesto está "agotado" y la llamada se bloquea.
  • window.opener y noopener. Cuando abres una ventana, la nueva página puede leer e incluso navegar por el abridor a través de window.opener. Para enlaces a sitios no confiables esto supone un riesgo de phishing, por lo que agrega rel="noopener" a los anclajes o pasa noopener en la string de características:
// Anchor form — the new tab cannot touch this page
// <a href="https://example.com" target="_blank" rel="noopener noreferrer">Open</a>

// Scripted form — returns null because the link is severed
window.open("https://example.com", "_blank", "noopener");
  • Detectar una ventana emergente bloqueada. Siempre verifica el valor de retorno, ya que una llamada bloqueada devuelve null:
const win = window.open("/report", "report", "width=600,height=800");
if (!win || win.closed || typeof win.closed === "undefined") {
  // Popup was blocked — fall back to navigating in the same tab
  location.href = "/report";
}

Buenas prácticas para usar ventanas emergentes y métodos de Window

  1. Consentimiento y control del usuario: Siempre asegúrate de que las ventanas emergentes no interrumpan la experiencia del usuario. Proporciona suficiente control para que los usuarios puedan cerrar las ventanas emergentes no deseadas.
  2. Consideraciones de seguridad: Ten en cuenta las implicaciones de seguridad del contenido externo en las ventanas emergentes. Usa fuentes de confianza y conexiones seguras para proteger los datos del usuario.
  3. Optimización del rendimiento: Usa las ventanas emergentes y los métodos de window con moderación, ya que pueden afectar el rendimiento de tu aplicación web. Optimiza el uso para equilibrar la funcionalidad y la eficiencia de recursos.

Conclusión

Usar eficazmente las ventanas emergentes de JavaScript y los métodos de window puede mejorar significativamente la funcionalidad y la experiencia del usuario en las aplicaciones web. Siguiendo los ejemplos y las buenas prácticas proporcionados, los desarrolladores pueden implementar estas funcionalidades de manera eficiente y responsable. Recuerda priorizar la experiencia del usuario y la seguridad en todas las implementaciones para mantener la integridad y la eficacia de tus aplicaciones web.

Capítulos relacionados

Práctica

Práctica
¿Cuáles de los siguientes son métodos para mostrar ventanas emergentes en JavaScript?
¿Cuáles de los siguientes son métodos para mostrar ventanas emergentes en JavaScript?
Was this page helpful?