Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(NcRichContenteditable): past content to an empty field fails #6241

Merged
merged 3 commits into from
Nov 20, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 5 additions & 77 deletions src/components/NcRichContenteditable/NcRichContenteditable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ export default {
@input="onInput"
@compositionstart="isComposing = true"
@compositionend="isComposing = false"
@keydown.delete="onDelete"
@keydown.esc.capture="onKeyEsc"
@keydown.enter.exact="onEnter"
@keydown.ctrl.enter.exact.stop.prevent="onCtrlEnter"
Expand Down Expand Up @@ -484,15 +483,6 @@ export default {
return !this.localValue || this.localValue.trim() === ''
},

/**
* Is this Firefox? 🙄
*
* @return {boolean}
*/
isFF() {
return !!navigator.userAgent.match(/firefox/i)
},

/**
* Is the current value over maxlength?
*
Expand Down Expand Up @@ -792,23 +782,13 @@ export default {
const text = clipboardData.getData('text')
const selection = window.getSelection()

// If no selection, replace the whole data
if (!selection.rangeCount) {
this.updateValue(text)
return
}

// Generate text and insert
const range = selection.getRangeAt(0)
selection.deleteFromDocument()
range.deleteContents()
range.insertNode(document.createTextNode(text))

// Put cursor at the end of the selection
const newRange = document.createRange()
newRange.setStart(event.target, range.endOffset)
newRange.collapse(true)
selection.removeAllRanges()
selection.addRange(newRange)
// Collapse the range to the end position
range.collapse(false)

// Propagate data
this.updateValue(this.$refs.contenteditable.innerHTML)
Expand All @@ -820,7 +800,8 @@ export default {
* @param {string} htmlOrText the html content (or raw text with @mentions)
*/
updateValue(htmlOrText) {
const text = this.parseContent(htmlOrText)
// Browsers keep <br> after erasing contenteditable
const text = this.parseContent(htmlOrText).replace(/^\n$/, '')
this.localValue = text
this.model = text
},
Expand All @@ -836,59 +817,6 @@ export default {
this.localValue = value
},

/**
* Because FF have a decade old bug preventing contenteditable=false
* to properly be deleted on backspace, we have to hack 👀
* https://stackoverflow.com/a/59383394/3885878
* https://stackoverflow.com/a/30574622
*
* @param {Event} event the delete keydown event
*/
onDelete(event) {
if (!this.isFF || !window.getSelection) {
return
}
Comment on lines -848 to -850
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you remove this method, isFF is also not needed anymore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to pasting issue, but noticed:
if input is started or ended with embedded HTML (mention) "@Test01 anyword @Test01":

  • 🐞 in FF cursor isn't moving to the very start or end with ⬅️ ➡️ keys (⬆️ ⬇️ are working)
  • 🐞 in Safari cursor jumps to the very beginning
  • ✅ in Chrome everything is fine


// Either disabled or edit deactivated
if (!this.canEdit) {
return
}

// fix backspace bug in FF
// https://bugzilla.mozilla.org/show_bug.cgi?id=685445
// https://bugzilla.mozilla.org/show_bug.cgi?id=1665167
const selection = window.getSelection()
const node = event.target
if (!selection.isCollapsed || !selection.rangeCount) {
return
}

const curRange = selection.getRangeAt(selection.rangeCount - 1)
if (curRange.commonAncestorContainer.nodeType === 3 && curRange.startOffset > 0) {
// we are in child selection. The characters of the text node is being deleted
return
}

const range = document.createRange()
if (selection.anchorNode !== node) {
// selection is in character mode. expand it to the whole editable field
range.selectNodeContents(node)
range.setEndBefore(selection.anchorNode)
} else if (selection.anchorOffset > 0) {
range.setEnd(node, selection.anchorOffset)
} else {
// reached the beginning of editable field
return
}
range.setStart(node, range.endOffset - 1)

const previousNode = range.cloneContents().lastChild
if (previousNode && previousNode.contentEditable === 'false') {
// this is some rich content, e.g. smile. We should help the user to delete it
range.deleteContents()
event.preventDefault()
}
},
/**
* Enter key pressed. Submits if not multiline
*
Expand Down
Loading