Unlisted
Edited
Aug 28, 2021
Paused
Insert cell
Insert cell
// Chrome (macOS 10.13):
// - width: min 152
// - height: min 99; -1
Insert cell
Insert cell
button('Click', e => {
const autoClose = w => {invalidation.then(() => w.close())};
const T = 1/3;
const positions = [
[0, 0, T, .5],
[T, 0, T, .5],
[T*2, 0, T, .5],
];

const sw = screen.availWidth,
sh = screen.availHeight;

for(const [x, y, w, h] of positions) {
const win = openWindow({features: {left: x*sw, top:y*sh, width: sw*w, height:sh*h}});
position(win, x, y, w, h);
autoClose(win);
win.document.body.appendChild(html`<p>${win.outerWidth}x${win.outerHeight}`);
setTimeout(() => {
win.document.body.appendChild(html`<p>${win.innerWidth}x${win.innerHeight}`);
}, 100);
}
})
Insert cell
Insert cell
htl.html`<button onclick=${async e => {
const btn = e.target;
const win = btn.win ??= openWindow({features: {width:200,height:200}});
const status = html`<div>Window`;
status.onclick = () => win.focus();
btn.replaceWith(status);
// win.resizeTo(200, 200);
win.onunload = () => {
status.replaceWith(btn);
};
await Promises.delay(500);
win.close();
win.open(); // Cannot reopen a closed window
}}>Click`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
resized, `${window.outerWidth}x${window.outerHeight}`
Insert cell
resized, `${window.innerWidth}x${window.innerHeight}`
Insert cell
resized, `${screen.width}x${screen.height}`
Insert cell
resized, `${screen.availWidth}x${screen.availHeight}`
Insert cell
defaultFeatures = ({
menubar: 0,
toolbar: 0,
location: 0,
status: 0,
resizable: 1,
scrollbars: 0,
width: null,
height: null,
left: null,
top: null,
})
Insert cell
Insert cell
features = ['menubar', 'toolbar', 'location', 'status', 'resizable', 'scrollbars']
Insert cell
featureTable = (window, features) => {
const tests = {
menubar: w => w.menubar.visible,
toolbar: w => w.toolbar.visible,
location: w => w.locationbar.visible,
status: w => w.statusbar.visible,
resizable: w => null,
scrollbars: w => scrollbars.visible,
left: w => w.screenX,
top: w => w.screenY,
width: w => w.innerWidth,
height: w => w.innerHeight,
};
}
Insert cell
featureFormatters = ((bool = v => v ? 1 : 0) => ({
menubar: bool,
toolbar: bool,
location: bool,
status: bool,
resizable: bool,
scrollbars: bool,
left: v => +v,
top: v => +v,
width: v => Math.max(100, v),
height: v => Math.max(100, v),
}))()
Insert cell
featureTests = ({
menubar: w => w.menubar.visible,
toolbar: w => w.toolbar.visible,
location: w => w.locationbar.visible,
status: w => w.statusbar.visible,
resizable: w => null,
scrollbars: w => scrollbars.visible,
left: w => w.screenX,
top: w => w.screenY,
width: w => w.innerWidth,
height: w => w.innerHeight,
})
Insert cell
function openWindow({target = '_blank', features = null, invalidation: invalidated = invalidation}) {
const w = window.open('', target, serializeFeatures(features));
invalidated.then(() => w.close());
return w;
}
Insert cell
function serializeFeatures(features) {
if(features == null) return undefined;
return Object.entries({...defaultFeatures, ...features})
.filter(([k, v]) => v != null)
.map(([k, v]) => `${k}=${featureFormatters[k](v)}`)
.join(',');
}
Insert cell
serializeFeatures({toolbar: 1})
Insert cell
function position(window, left, top, width, height) {
const w = screen.availWidth,
h = screen.availHeight;
window.resizeTo(Math.round(width * w), Math.round(height * h));
window.moveTo(Math.round(left * w), Math.round(top * h));
}
Insert cell
function button(label, onclick) {
return htl.html`<button onclick=${onclick}>${label}`;
}
Insert cell
json = JSON.stringify
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more