Last active
May 14, 2024 18:53
-
-
Save davestewart/ae16e30091f457e3f4ddeeac569b8f2a to your computer and use it in GitHub Desktop.
Example of using BroadcastChannel to communicate with pages in the same domain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Instructions (updated to use BroadcastChannel) | |
* | |
* - open the JS console and run this code | |
* - if nothing happens, enable popups in the browser URL bar | |
* - wait for windows to load | |
* - click on any of the open windows to see them all change color | |
* - hit Esc to close all windows | |
* | |
* My stuff: | |
* | |
* - https://davestewart.co.uk | |
* - https://controlspace.app | |
*/ | |
/** | |
* Helper class to get / set colors | |
*/ | |
const Colors = { | |
get () { | |
return '#' + Math.floor(Math.random() * Math.pow(255, 3)).toString(16).padStart(6, 0) | |
}, | |
set (win, color) { | |
Object.assign(win.document.body.style, { | |
background: color, | |
color: 'black', | |
}) | |
}, | |
} | |
/** | |
* Setup broadcast channel on each window | |
*/ | |
function initWindow (win) { | |
// set up channel | |
const channel = new BroadcastChannel('colors') | |
// handle user interaction | |
const exec = async () => { | |
// get color | |
const color = Colors.get() | |
// send data to other pages | |
await channel.postMessage({ color }) // supports objects! | |
// update local ui | |
win.document.querySelector('pre').innerHTML += `<div style="color:${color}">${color}<div>` | |
} | |
// wire up user interaction | |
win.addEventListener('focus', exec) | |
win.addEventListener('mousedown', exec) | |
// receive channel events + utilize data | |
channel.addEventListener('message', (event) => { | |
Colors.set(win, event.data.color) | |
}) | |
} | |
/** | |
* Setup window layout | |
*/ | |
function setup (cx = 6, cy = 3, gap = 30) { | |
// screen bounds | |
const s = { | |
w: screen.availWidth, | |
h: screen.availHeight, | |
l: screen.availLeft, | |
t: screen.availTop, | |
} | |
// window layout | |
const gx = (cx + 1) * gap | |
const gy = (cy + 1) * gap | |
const w = Math.floor((s.w - gx) / cx) | |
const h = Math.floor((s.h - gy) / cy) | |
// create windows | |
const windows = [] | |
for (let y = 0; y < cy; y++) { | |
for (let x = 0; x < cx; x++) { | |
// create window | |
const win = window.open('', `window_${x}_${y}`, [ | |
`width=${w}`, | |
`height=${h - 60}`, | |
`left=${s.l + (w * x) + (gap * x) + gap}`, | |
`top=${s.t + (h * y) + (gap * y) + gap}`, | |
`scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no`, | |
].join(',')) | |
// implement functionality on load | |
win.addEventListener('load', () => { | |
// setup broadcast channel | |
initWindow(win) | |
// set window text | |
win.document.body.innerHTML = '<pre style="padding: .5rem; line-height: 1.7; user-select: none">Click: Change color<br>Esc: Close windows</pre>' | |
// setup window closing | |
windows.push(win) | |
win.document.addEventListener('keydown', (event) => { | |
if (event.key.toLowerCase().includes('esc')) { | |
windows.forEach(win => { | |
win.close() | |
}) | |
} | |
}) | |
}) | |
} | |
} | |
} | |
// create windows | |
setup() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment