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);| Argumento | Significado |
|---|---|
url | La página que se cargará. Pasa una cadena vacía "" para abrir una ventana en blanco que rellenas con script. |
name | Un 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. |
features | Una 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 unsetTimeoutse trata como una ventana emergente no solicitada y se bloquea —windevuelvenull. 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.writepuede sobreescribir el documento completo si se llama después de que la página se haya cargado. La práctica moderna prefiereinnerHTMLo 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:
- Estructura HTML: Incluye un botón y un elemento
divcon estilos para parecerse a una ventana. Eldivrepresenta la ventana que "redimensionaremos" y "moveremos". - Estilos CSS: Define el tamaño y la posición iniciales de la ventana simulada, con transiciones suaves para el efecto visual.
- Función JavaScript: Cuando se hace clic en el botón, la función
adjustSimulatedWindowalterna el tamaño y la posición de la ventana simulada. El cambio de posición se gestiona alterando las propiedades CSStopyleft, 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:
- Enlace simulado para simular la salida de página: El enlace con
href="#"y un controladoronclickque llama asimulatePageLeave(); return false;simula el efecto de intentar salir de la página. Elreturn false;evita la acción predeterminada del enlace, manteniendo al usuario en la página actual. - Diálogo de confirmación: La función
simulatePageLeavepresenta 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. - Actualizaciones de mensajes: Según la elección del usuario en el diálogo de confirmación, el mensaje en el
divse actualiza para reflejar la elección, imitando el comportamiento que cabría esperar al intentar realmente salir de la página. - Nota sobre el comportamiento del navegador: Los navegadores modernos ignoran las cadenas personalizadas devueltas por
onbeforeunloady 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.
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:
- Gestión del estado: La variable
myPopupse establece inicialmente ennully se verifica para ver si esnullo ha sido cerrada (myPopup.closed). Esto ayuda a decidir si crear una nueva ventana emergente o enfocar la existente. - 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.
- 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.
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()yhandleBlur()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
awaito unsetTimeout, el gesto está "agotado" y la llamada se bloquea. window.openerynoopener. Cuando abres una ventana, la nueva página puede leer e incluso navegar por el abridor a través dewindow.opener. Para enlaces a sitios no confiables esto supone un riesgo de phishing, por lo que agregarel="noopener"a los anclajes o pasanoopeneren 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
- 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.
- 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.
- 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
- JavaScript alert, prompt y confirm — los diálogos integrados más simples.
- Comunicación entre ventanas —
postMessage,window.openery la política del mismo origen en profundidad. - Tamaños de ventana y desplazamiento — cómo leer y controlar la geometría de una ventana.