Skip to content

Commit 0574cc7

Browse files
authored
prevent iframe from stealing focus from editor (sveltejs#1258)
* prevent iframe from stealing focus from editor * dual mechanism
1 parent 00cdeb1 commit 0574cc7

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

packages/repl/src/lib/Output/srcdoc/index.html

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@
4343
}
4444

4545
(0, eval)(data.args.script);
46+
47+
// hand focus back to the editor if it's taken in an effect
48+
// that runs immediately (for focuses in effects, this is
49+
// more effective than listening for the focusin event)
50+
Promise.resolve().then(() => {
51+
if (document.activeElement !== null && document.activeElement !== document.body) {
52+
send({ type: 'iframe_took_focus' });
53+
}
54+
});
4655
}
4756

4857
if (action === 'catch_clicks') {
@@ -244,6 +253,26 @@
244253
original(...args);
245254
};
246255
}
256+
257+
// Focus management
258+
let can_focus = false;
259+
260+
window.addEventListener('pointerdown', (e) => (can_focus = true));
261+
window.addEventListener('pointerup', (e) => (can_focus = false));
262+
window.addEventListener('keydown', (e) => (can_focus = true));
263+
window.addEventListener('keyup', (e) => (can_focus = false));
264+
265+
window.addEventListener('focusin', (e) => {
266+
// if focusin happened as a result of a mouse/keyboard event, allow it
267+
if (can_focus) return;
268+
269+
// if `e.target` is the `<body>` and there's a `relatedTarget`,
270+
// assume the focusin was the result of a user navigation — allow it
271+
if (e.target.tagName === 'BODY' && e.relatedTarget) return;
272+
273+
// otherwise, broadcast an event that causes the editor to reclaim focus
274+
send({ type: 'iframe_took_focus' });
275+
});
247276
})();
248277
</script>
249278
</head>

0 commit comments

Comments
 (0)