Skip to content

Instantly share code, notes, and snippets.

@dragosstancu
Forked from davestewart/broadcast-channel.md
Created December 20, 2023 19:47
Show Gist options
  • Save dragosstancu/468d47a87cf3d01217b9d4b76f2a529b to your computer and use it in GitHub Desktop.
Save dragosstancu/468d47a87cf3d01217b9d4b76f2a529b to your computer and use it in GitHub Desktop.
Example of using BroadcastChannel to communicate with pages in the same domain
/**
* 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