window.open('', 'test'); open a new "about:blank" window, instead of focus existing "test" window
I have a web application that open multiple external popup window eg.:
window.open('https://stackoverflow.com/', 'stackoverflow')
The end user, can open multiple window of my application and I want that only one window for target exists. The solution I have adopted is a BroadcastChannel
for share beetween my application instances the information if a target window is already opened.
broadcastChannel.postMessage({ type: 'open', value: 'stackoverflow'});
window.open('https://stackoverflow.com/', 'stackoverflow');
all application instances listen for the message and collect opened target windows
const openWindowsTarget = [];
broadcastChannel.onmessage = (event) => {
if( event.data.type === 'open' ){
openWindowsTarget.push(event.data.value);
}
}
In this way if a target window is opened somewhere, the window is opened without url, just with the target
if (openWindowsTarget.includes('stackoverflow') ) {
window.open('', 'stackoverflow');
}
the window in this way is just focused without reload.
This behavior works in the past, but in the present day the effect is a new "about:blank" window is opened. Probably something is changed in the browser side.
I'm finding a solution for fix then!
For test/help save this snippet into an html file (example.html), open into two separate window and click on the button
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<button onclick="openWindow('https://stackoverflow.com/', 'stackoverflow')">
Open stackoverflow
</button>
<script>
const broadcastChannel = new BroadcastChannel('WindowService');
const openWindowsTarget = [];
broadcastChannel.onmessage = (event) => {
if (event.data.type === 'open') {
openWindowsTarget.push(event.data.value);
console.log({openWindowsTarget})
}
};
function openWindow(url, target) {
if (openWindowsTarget.includes(target)) {
window.open('', target);
} else {
broadcastChannel.postMessage({ type: 'open', value: target });
openWindowsTarget.push(target);
window.open(url, target);
}
}
</script>
</body>
</html>
I have also tried to change approach and send a broadcast message for focus the window, but the focus()
has no effect, if the window is minimized, it remain minimized
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<button onclick="openWindow('https://stackoverflow.com/', 'stackoverflow')">
Open stackoverflow
</button>
<script>
const broadcastChannel = new BroadcastChannel('WindowService');
const openWindowsTarget = [];
const localWindows = {};
broadcastChannel.onmessage = (event) => {
if (event.data.type === 'open') {
openWindowsTarget.push(event.data.value);
console.log({openWindowsTarget})
}
if (event.data.type === 'focus') {
if( localWindows[event.data.value] ){
localWindows[event.data.value].focus();
}
}
};
function openWindow(url, target) {
if (openWindowsTarget.includes(target)) {
broadcastChannel.postMessage({ type: 'focus', value: target });
} else {
broadcastChannel.postMessage({ type: 'open', value: target });
openWindowsTarget.push(target);
localWindows[target] = window.open(url, target);
}
}
</script>
</body>
</html>
Other ideas?
Answer
Perhaps a solution that checks the existence of a window would be suitable. Although your original script did not cause any problems for me.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<script>
let windowObjectReference = null; // global variable
function openWindow(url, windowName) {
if (windowObjectReference === null || windowObjectReference.closed) {
windowObjectReference = window.open(url, windowName);
} else {
windowObjectReference.focus();
}
}
</script>
<body>
<button onclick="openWindow('https://stackoverflow.com/', 'stackoverflow')">
Open or create a window named `stackoverflow`
</button>
</body>
</html>