Last active
July 7, 2023 15:51
-
-
Save bjones1/6eb4381cb2c9b687caab7c1a8edf7381 to your computer and use it in GitHub Desktop.
CodeMirror problem with focusin handlers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="codemirror-test.js" type="module"></script> | |
</head> | |
<body></body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// To bundle: node_modules\.bin\esbuild src/codemirror-test.mts --bundle --outdir=./static/bundled --sourcemap --format=esm | |
import { basicSetup } from "codemirror"; | |
import { | |
Decoration, | |
DecorationSet, | |
EditorView, | |
ViewPlugin, | |
ViewUpdate, | |
WidgetType, | |
} from "@codemirror/view"; | |
import { | |
EditorState, | |
EditorSelection, | |
StateField, | |
Transaction, | |
} from "@codemirror/state"; | |
// Define a simple widget which contains a contenteditable div. | |
class EditableDivWidget extends WidgetType { | |
constructor(readonly contents: string) { | |
super(); | |
} | |
toDOM() { | |
let wrap = document.createElement("div"); | |
wrap.className = "editable-div"; | |
wrap.innerHTML = `<div contenteditable style='font-family: auto; white-space: normal; outline-width: 0px;'>${this.contents}</div>`; | |
return wrap; | |
} | |
// We want to handle all events for this widget. | |
ignoreEvent(event: Event) { | |
if (event.type === "focusin") { | |
return false; | |
} else { | |
return true; | |
} | |
} | |
} | |
// Define a state field to contain a DecorationSet of EditableDivWidgets. | |
const editableDivField = StateField.define<DecorationSet>({ | |
create(state: EditorState) { | |
return Decoration.none; | |
}, | |
update(editableDivs: DecorationSet, tr: Transaction) { | |
return editableDivs.map(tr.changes); | |
}, | |
provide: (field: StateField<DecorationSet>) => | |
EditorView.decorations.from(field), | |
fromJSON: (json: any, state: EditorState) => | |
Decoration.set( | |
json.map(([from, to, contents]: [number, number, string]) => | |
Decoration.replace({ | |
widget: new EditableDivWidget(contents), | |
block: true, | |
}).range(from, to) | |
) | |
), | |
}); | |
// Define a simple view plugin to forward events correctly. | |
const testPlugin = ViewPlugin.fromClass(class {}, { | |
eventHandlers: { | |
focusin: (e: Event, view) => { | |
console.log(e.type); | |
console.log(e.target); | |
if ((e.target as HTMLElement).closest(".editable-div") !== null) { | |
console.log( | |
"Success! Handling focusin for contenteditable div." | |
); | |
return false; | |
} else { | |
console.log("Not our contentedtiable div."); | |
return false; | |
} | |
}, | |
}, | |
}); | |
// Follow the standard steps to create the CodeMirror editor. Use fromJSON to create | |
// a pre-loaded setup with our widget already embedded. | |
let state = EditorState.fromJSON( | |
{ | |
doc: "\nChecking on focusin routing...", | |
selection: EditorSelection.single(0).toJSON(), | |
editable_div: [[0, 0, "Testing"]], | |
}, | |
{ | |
extensions: [testPlugin, basicSetup], | |
}, | |
{ | |
editable_div: editableDivField, | |
} | |
); | |
let view = new EditorView({ | |
state, | |
parent: document.body, | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "codemirror-focusin", | |
"version": "1.0.0", | |
"type": "module", | |
"scripts": { | |
"build": "run-script-os", | |
"build:win32": "node_modules\\.bin\\esbuild codemirror-test.mts --bundle --outdir=. --sourcemap --format=esm", | |
"build:default": "node_modules/.bin/esbuild codemirror-test.mts --bundle --outdir=. --sourcemap --format=esm", | |
"serve": "npx http-server" | |
}, | |
"devDependencies": { | |
"esbuild": "^0.18", | |
"run-script-os": "^1", | |
"typescript": "^4" | |
}, | |
"dependencies": { | |
"@codemirror/view": "=6.14.0", | |
"codemirror": "^6" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
// <details> | |
// <summary>License</summary> | |
// <p>Copyright (C) 2022 Bryan A. Jones.</p> | |
// <p>This file is part of the CodeChat Editor.</p> | |
// <p>The CodeChat Editor is free software: you can redistribute it and/or | |
// modify it under the terms of the GNU General Public License as | |
// published by the Free Software Foundation, either version 3 of the | |
// License, or (at your option) any later version.</p> | |
// <p>The CodeChat Editor is distributed in the hope that it will be useful, | |
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
// General Public License for more details.</p> | |
// <p>You should have received a copy of the GNU General Public License | |
// along with the CodeChat Editor. If not, see <a | |
// href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>. | |
// </p> | |
// </details> | |
// <h1>.tsconfig.json - TypeScript configuration</h1> | |
{ | |
"compilerOptions": { | |
"allowJs": true, | |
// <p>Required by ESBuild per their <a | |
// href="https://esbuild.github.io/content-types/#es-module-interop">docs</a>; | |
// see also <a | |
// href="https://www.typescriptlang.org/tsconfig#esModuleInterop">the | |
// TypeScript docs</a>.</p> | |
"esModuleInterop": true, | |
// <p>Required by ESBuild per their <a | |
// href="https://esbuild.github.io/content-types/#isolated-modules">docs</a>; | |
// see also <a | |
// href="https://www.typescriptlang.org/tsconfig#isolatedModules">the | |
// TypeScript docs</a>.</p> | |
"isolatedModules": true, | |
"module": "ES2022", | |
"moduleResolution": "nodenext", | |
"outDir": "out", | |
"rootDir": "src", | |
"strict": true, | |
"target": "ES2022" | |
}, | |
"exclude": ["node_modules", "static"] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment