Skip to content

Commit edebfec

Browse files
authored
Merge branch 'master' into replace-gapi
2 parents 09a3c6c + ac5474f commit edebfec

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

src/commons/editor/Editor.tsx

+83
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Ace, require as acequire, createEditSession } from 'ace-builds';
33
import 'ace-builds/src-noconflict/ext-language_tools';
44
import 'ace-builds/src-noconflict/ext-searchbox';
5+
import 'ace-builds/src-noconflict/ext-settings_menu';
56
import 'js-slang/dist/editors/ace/theme/source';
67

78
import * as AceBuilds from 'ace-builds';
@@ -559,6 +560,88 @@ const EditorBase = React.memo((props: EditorProps & LocalStateProps) => {
559560
}
560561
});
561562

563+
// Override the overlayPage function to add an id to the overlay div.
564+
// This allows the overlay div to be referenced and removed when the editor is unmounted.
565+
// See https://github.com/source-academy/frontend/pull/2832
566+
acequire('ace/ext/menu_tools/overlay_page').overlayPage = function (
567+
editor: any,
568+
contentElement: HTMLElement,
569+
callback: any
570+
) {
571+
let closer: HTMLElement | null = document.createElement('div');
572+
// Add id to the overlay div
573+
closer.id = 'overlay';
574+
let ignoreFocusOut = false;
575+
576+
function documentEscListener(e: KeyboardEvent) {
577+
if (e.keyCode === 27) {
578+
close();
579+
}
580+
}
581+
582+
function close() {
583+
if (!closer) return;
584+
document.removeEventListener('keydown', documentEscListener);
585+
closer?.parentNode?.removeChild(closer);
586+
if (editor) {
587+
editor.focus();
588+
}
589+
closer = null;
590+
callback && callback();
591+
}
592+
593+
/**
594+
* Defines whether overlay is closed when user clicks outside of it.
595+
*
596+
* @param {Boolean} ignore If set to true overlay stays open when focus moves to another part of the editor.
597+
*/
598+
function setIgnoreFocusOut(ignore: boolean) {
599+
ignoreFocusOut = ignore;
600+
if (ignore) {
601+
closer!.style.pointerEvents = 'none';
602+
contentElement.style.pointerEvents = 'auto';
603+
}
604+
}
605+
606+
closer.style.cssText =
607+
'margin: 0; padding: 0; ' +
608+
'position: fixed; top:0; bottom:0; left:0; right:0;' +
609+
'z-index: 9990; ' +
610+
(editor ? 'background-color: rgba(0, 0, 0, 0.3);' : '');
611+
closer.addEventListener('click', function (e: Event) {
612+
if (!ignoreFocusOut) {
613+
close();
614+
}
615+
});
616+
617+
// click closer if esc key is pressed
618+
document.addEventListener('keydown', documentEscListener);
619+
620+
contentElement.addEventListener('click', function (e: Event) {
621+
e.stopPropagation();
622+
});
623+
624+
closer.appendChild(contentElement);
625+
document.body.appendChild(closer);
626+
if (editor) {
627+
editor.blur();
628+
}
629+
return {
630+
close: close,
631+
setIgnoreFocusOut: setIgnoreFocusOut
632+
};
633+
};
634+
635+
// Remove the overlay div when the editor is unmounted
636+
React.useEffect(() => {
637+
return () => {
638+
const div = document.getElementById('overlay');
639+
if (div) {
640+
div.parentNode?.removeChild(div);
641+
}
642+
};
643+
}, []);
644+
562645
return (
563646
<HotKeys className="Editor bp4-card bp4-elevation-0" handlers={handlers}>
564647
<div className="row editor-react-ace" data-testid="Editor">

0 commit comments

Comments
 (0)