Skip to content

Instantly share code, notes, and snippets.

@mzechmeister
Last active January 3, 2022 21:00
Show Gist options
  • Save mzechmeister/d0333d6e46746efc2f06e61547d69047 to your computer and use it in GitHub Desktop.
Save mzechmeister/d0333d6e46746efc2f06e61547d69047 to your computer and use it in GitHub Desktop.
pseudo editable field (code mirror lite)
<!DOCTYPE html>
<html>
<head>
<style>
#cursor {
border-left: 1px solid red;
animation: blink 1s;
margin-left: -1px;
animation-iteration-count: infinite;
}
span {
color: green;
}
span:not(#cursor):before {
content: "5";
vertical-align: super;
font-size: smaller;
}
@keyframes blink {
50% { border-color: #ffffff00; } }}
</style>
</head>
<body>
<textarea id="ta" style="height:150px">The top element is a textarea and the div at the bottom a pseudo editable field. Type to see how the caret follows. Type a dollar character to insert a span. Mouse click in the editable field doen't set the caret properly.</textarea>
<div id="mydiv" onclick="ta.selectionEnd = getSelectionPosition(); ta.selectionStart = ta.selectionEnd; ta.focus(); update()"></div>
<script>
function getSelectionPosition() {
var sel = window.getSelection()
console.log(sel)
return sel.focusOffset
}
function parse(t) {
return t.replaceAll('$', '<span>XX</span>')
}
function update() {
curpos = ta.selectionEnd
mydiv.innerHTML = parse(ta.value.slice(0, curpos)+"<span id='cursor'></span>"+ta.value.slice(curpos))
}
ta.onkeydown = update
ta.oninput = update
ta.onclick = update
ta.onkeyup = update
update()
</script>
</body>
</html>
@mzechmeister
Copy link
Author

mzechmeister commented Nov 14, 2021

preview latest: https://gistpreview.github.io/?d0333d6e46746efc2f06e61547d69047

  • Rev 41 mouseup to focus ta (should be better than Rev 39)
  • Rev 40 Cleaned.
  • Rev 39 fix: text selection with mouse difficult (focus went to ta).
  • Rev 38 feat: Undo/redo button.
  • Rev 37 Cleaned.
  • Rev 36: fix: edge requires clipboard for dataTransfer.
  • Rev 35: fix: Handling of backward selection.
  • Rev 34 refact: Using e.inputType to detect various events.
  • Rev 33 fix: oninput fires again after drop.
  • Rev 32 chore: New variable name insText.
  • Rev 31 chore: New variable names cutA and cut.
  • Rev 30 fix: No pseudocursor for del key.
  • Rev 29 chore: divcutsel renamed to cutpos.
  • Rev 28 Better handling of drop (selection history).
  • Rev 27 Better handling of drop (selection history).
  • Rev 26 Fix drop not working properly anymore.
  • Rev 25 Space formatting.
  • Rev 24 Handle input in editable div.
  • Rev 23 Simplifications; update function removed.
  • Rev 22 Handback textarea selection to div selection.
  • Rev 21 A try to handle drag and drop. Simplier but now textarea and div must have the same content. Undo with ctrl-Z ends up with selection all.
  • Rev 20 Redirect drop from mydiv to textarea.
  • Rev 19 Cleaning + simplification.
  • Rev 18 getClientRects.
  • Rev 17 fix minor caret misbehaviour (jump at pos 0 -> 1, hide caret when focus out).
  • Rev 16 sel.anchorNode returns body not ta in chrome and edge, instead use document.activeElement.
  • Rev 15 range.toString().length instead of node loop.
  • Rev 14: div is contenteditable, but only to simplify position detection.
  • Rev 13: refact: Cursor as relative div. But: textnode dissociates, extended range not marked anymore.
  • Rev 12: fix: caret behaviour at nested span (located at middle start or end).
  • Rev 11: refact: overlay cursor the absolute.
  • Rev 10: last version with inline span for caret;
    fix backward selection (desktop only), double click selection not working
  • Rev 9: fix mouse selection does not work.
  • Rev 8: replaceAll not working on some android, replaced by replace + / /g.
  • Rev 7: mousedown+preventDefault to keep focus on textarea, and rangeParent instead of selection. Now, build-in text selection on mobiles does not popup. There seems to be no redundant selectionchange calls.
  • Rev 6: refact: onselectionchange instead of key events. Now pseudo caret is also moved for spacebar swiping on mobiles. onclick does not set the caret (firefox).
  • Rev 5: feat: Text selection with keyboard.
  • Rev 4: As before, click sets the caret properly (curpos computed with node loop; would allow to corrected of string length changes by parser)
  • Rev 3: Fixed: Click sets now the caret properly. However, text selection are now deleted. Since the parse changes the string length at dollar, this needs to be taken into account.
  • Rev 0 (https://gist.github.com/mzechmeister/d0333d6e46746efc2f06e61547d69047/e4732a0a72b6bea5923081af66e7134dc0ca211a)

Problems of contenteditable:

  • mixes content and layout, we want to edit to content only, the rendering should be done by parsing.
  • edit history tricky, needs obsolete document.execCommand and document.execCommand + insertHTML does not work.
  • different browser behaviour for caret position

@mzechmeister
Copy link
Author

To inspect codemirror search for the textarea element and inspect the attached events.

https://github.com/codemirror/CodeMirror/blob/c1941628cdda92c32977b3a26b0a0b70c9a8f9b5/src/input/TextareaInput.js#L224

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment