Skip to content

Commit

Permalink
fix editing issues in Firefox
Browse files Browse the repository at this point in the history
  • Loading branch information
zamfofex authored and antonmedv committed Jun 26, 2021
1 parent b037e29 commit 6ed8223
Showing 1 changed file with 41 additions and 19 deletions.
60 changes: 41 additions & 19 deletions codejar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,20 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
let focus = false
let callback: (code: string) => void | undefined
let prev: string // code content prior keydown event
let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1

editor.setAttribute('contentEditable', isFirefox ? 'true' : 'plaintext-only')
editor.setAttribute('contenteditable', 'plaintext-only')
editor.setAttribute('spellcheck', options.spellcheck ? 'true' : 'false')
editor.style.outline = 'none'
editor.style.overflowWrap = 'break-word'
editor.style.overflowY = 'auto'
editor.style.resize = 'vertical'
editor.style.whiteSpace = 'pre-wrap'

let isLegacy = false // true if plaintext-only is not supported

highlight(editor)
if (editor.contentEditable !== "plaintext-only") isLegacy = true
if (isLegacy) editor.setAttribute('contenteditable', 'true')

const debounceHighlight = debounce(() => {
const pos = save()
Expand Down Expand Up @@ -89,7 +92,7 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P

prev = toString()
if (options.preserveIdent) handleNewLine(event)
else firefoxNewLineFix(event)
else legacyNewLineFix(event)
if (options.catchTab) handleTabCharacters(event)
if (options.addClosing) handleSelfClosingCharacters(event)
if (options.history) {
Expand All @@ -99,6 +102,8 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
recording = true
}
}

restore(save())
})

on('keyup', event => {
Expand Down Expand Up @@ -129,23 +134,38 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
const s = getSelection()
const pos: Position = {start: 0, end: 0, dir: undefined}

let {anchorNode, anchorOffset, focusNode, focusOffset} = s
// selection anchor and focus are expected to be text nodes, so normalize them
if (anchorNode.nodeType === Node.ELEMENT_NODE) {
const node = document.createTextNode("")
anchorNode.insertBefore(node, anchorNode.childNodes[anchorOffset])
anchorNode = node
anchorOffset = 0
}
if (focusNode.nodeType === Node.ELEMENT_NODE) {
const node = document.createTextNode("")
focusNode.insertBefore(node, focusNode.childNodes[focusOffset])
focusNode = node
focusOffset = 0
}

visit(editor, el => {
if (el === s.anchorNode && el === s.focusNode) {
pos.start += s.anchorOffset
pos.end += s.focusOffset
pos.dir = s.anchorOffset <= s.focusOffset ? '->' : '<-'
if (el === anchorNode && el === focusNode) {
pos.start += anchorOffset
pos.end += focusOffset
pos.dir = anchorOffset <= focusOffset ? '->' : '<-'
return 'stop'
}

if (el === s.anchorNode) {
pos.start += s.anchorOffset
if (el === anchorNode) {
pos.start += anchorOffset
if (!pos.dir) {
pos.dir = '->'
} else {
return 'stop'
}
} else if (el === s.focusNode) {
pos.end += s.focusOffset
} else if (el === focusNode) {
pos.end += focusOffset
if (!pos.dir) {
pos.dir = '<-'
} else {
Expand All @@ -159,6 +179,9 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
}
})

// collapse empty text nodes
editor.normalize()

return pos
}

Expand All @@ -184,12 +207,12 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
if (el.nodeType !== Node.TEXT_NODE) return

const len = (el.nodeValue || '').length
if (current + len >= pos.start) {
if (current + len > pos.start) {
if (!startNode) {
startNode = el
startOffset = pos.start - current
}
if (current + len >= pos.end) {
if (current + len > pos.end) {
endNode = el
endOffset = pos.end - current
return 'stop'
Expand All @@ -198,9 +221,8 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
current += len
})

// If everything deleted place cursor at editor
if (!startNode) startNode = editor
if (!endNode) endNode = editor
if (!startNode) startNode = editor, startOffset = editor.childNodes.length
if (!endNode) endNode = editor, endOffset = editor.childNodes.length

// Flip back the selection
if (pos.dir == '<-') {
Expand Down Expand Up @@ -248,7 +270,7 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
event.stopPropagation()
insert('\n' + newLinePadding)
} else {
firefoxNewLineFix(event)
legacyNewLineFix(event)
}

// Place adjacent "}" on next line
Expand All @@ -260,10 +282,10 @@ export function CodeJar(editor: HTMLElement, highlight: (e: HTMLElement, pos?: P
}
}

function firefoxNewLineFix(event: KeyboardEvent) {
function legacyNewLineFix(event: KeyboardEvent) {
// Firefox does not support plaintext-only mode
// and puts <div><br></div> on Enter. Let's help.
if (isFirefox && event.key === 'Enter') {
if (isLegacy && event.key === 'Enter') {
preventDefault(event)
event.stopPropagation()
if (afterCursor() == '') {
Expand Down

0 comments on commit 6ed8223

Please sign in to comment.