microsoft / monaco-editor

A browser based code editor
https://microsoft.github.io/monaco-editor/
MIT License
40.43k stars 3.6k forks source link

e.preventDefault() does not work on 'Tab' keydown event #2759

Closed Cobertos closed 3 years ago

Cobertos commented 3 years ago

When using e.preventDefault() on an event from Editor#onKeyDown, it doesn't seem to work when the key was a Tab key.

Example (prevents both Tab and 'S', while 'S' never prints, it does indent on Tab): https://codepen.io/cobertos/pen/qBXKLpO?editors=0010

Code:

require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@0.30.1/min/vs' }});
window.MonacoEnvironment = { getWorkerUrl: () => proxy };

let proxy = URL.createObjectURL(new Blob([`
    self.MonacoEnvironment = {
        baseUrl: 'https://unpkg.com/monaco-editor@0.30.1/min/'
    };
    importScripts('https://unpkg.com/monaco-editor@0.30.1/min/vs/base/worker/workerMain.js');
`], { type: 'text/javascript' }));

require(["vs/editor/editor.main"], function () {
    let editor = monaco.editor.create(document.getElementById('container'), {
        value: [
            'function x() {',
            '\tconsole.log("Hello world!");',
            '}'
        ].join('\n'),
        language: 'javascript',
        theme: 'vs-light' 
    });

console.log(editor);
editor.onKeyDown((e) => {
  console.log("key down", e);
  if (e.code === "Tab" || e.code === 'KeyS') {
    e.preventDefault();
    console.log('prevented');
  }
});

});
alexdima commented 3 years ago

e.preventDefault(); prevents the default browser action. In the case of S, the default browser action is to create an input event for S and type it in the <textarea> we use for input. So preventing default on S leads to nothing being typed in the <textarea>, thus we don't receive an input event, thus nothing happens.

In the case of Tab, the default browser action is to move the focus to the next HTML element. This is prevented by your code, but all our keybindings that also run on Tab are not prevented. This is because e.preventDefault() is a browser concept, and not a Monaco Editor concept. Here is an example that shows how you can override Tab. The sample is more complicated, it also shows how you can dynamically turn on/off this override --> https://microsoft.github.io/monaco-editor/playground.html#interacting-with-the-editor-adding-a-command-to-an-editor-instance