Skip to content

Commit 9c9656b

Browse files
tomoamdummdidumm
andauthored
[fix] focus management between editor and iframe (sveltejs#168)
Fixes sveltejs#167 Co-authored-by: Simon H <[email protected]>
1 parent ad9173d commit 9c9656b

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

content/tutorial/common/src/__client.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,18 @@ if (import.meta.hot) {
8989
);
9090
});
9191
}
92+
93+
/**
94+
* The iframe sometimes takes focus control in ways we can't prevent
95+
* while the editor is focussed. Refocus the editor in these cases.
96+
*/
97+
window.addEventListener('focusin', (e) => {
98+
if (e.target.tagName === 'BODY') {
99+
parent.postMessage(
100+
{
101+
type: 'focus_on_editor'
102+
},
103+
'*'
104+
);
105+
}
106+
});

src/routes/tutorial/[slug]/Editor.svelte

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
* This boolean tracks whether or not the editor should be refocused.
4242
*/
4343
let preserve_focus = true;
44+
/** @type {any} */
45+
let remove_focus_timeout;
4446
4547
onMount(() => {
4648
let destroyed = false;
@@ -241,34 +243,27 @@
241243
</script>
242244
243245
<svelte:window
244-
on:pointerdown={(e) => {
245-
if (!container.contains(/** @type {HTMLElement} */ (e.target))) {
246-
preserve_focus = false;
246+
on:message={(e) => {
247+
if (preserve_focus && e.data.type === 'focus_on_editor') {
248+
instance?.editor.focus();
247249
}
248250
}}
249251
/>
250252
251253
<div bind:clientWidth={w} bind:clientHeight={h}>
252254
<div
253255
bind:this={container}
254-
on:keydown={(e) => {
255-
if (e.key === 'Tab') {
256-
preserve_focus = false;
257-
258-
setTimeout(() => {
259-
preserve_focus = true;
260-
}, 0);
261-
}
262-
}}
263256
on:focusin={() => {
257+
clearTimeout(remove_focus_timeout);
264258
preserve_focus = true;
265259
}}
266260
on:focusout={() => {
267-
if (preserve_focus) {
268-
setTimeout(() => {
269-
instance?.editor.focus();
270-
}, 0);
271-
}
261+
// Heuristic: user did refocus themmselves if focus_on_editor
262+
// doesn't happen in the next few miliseconds. Needed
263+
// because else navigations inside the iframe refocus the editor.
264+
remove_focus_timeout = setTimeout(() => {
265+
preserve_focus = false;
266+
}, 500)
272267
}}
273268
/>
274269
</div>

0 commit comments

Comments
 (0)