improve autocomplete working

This commit is contained in:
2023-05-08 22:51:18 +02:00
parent e4b373a940
commit 9e06781e32
4 changed files with 96 additions and 33 deletions

View File

@@ -65,6 +65,7 @@ export default defineComponent({
'update:modelValue',
'click',
'contextedLinkAutocomplete',
'contextedKeypress',
],
data(): CKEditorComponentData {
@@ -227,6 +228,9 @@ export default defineComponent({
editor.model.document.on('contextedLinkAutocomplete', (_, data) => {
this.$emit('contextedLinkAutocomplete', data)
})
editor.model.document.on('contextedKeypress', (_, eventData) => {
this.$emit('contextedKeypress', eventData)
})
},
},

View File

@@ -9,6 +9,7 @@ export default class ContextedLinkEditing extends Plugin {
init() {
this._defineSchema() // ADDED
this._defineConverters() // ADDED
this._addContextedKeyHandler()
const twoStepCaretMovementPlugin = this.editor.plugins.get(TwoStepCaretMovement)
twoStepCaretMovementPlugin.registerAttribute('contextedLink')
inlineHighlight(this.editor, 'contextedLink', 'a', HIGHLIGHT_CLASS)
@@ -18,14 +19,6 @@ export default class ContextedLinkEditing extends Plugin {
)
}
afterInit() {
// const editor = this.editor
// editor.model.document.on('change', (eventInfo, batch) => {
// const model = editor.model
// const selection = model.document.selection
// const collapsed = selection.isCollapsed // should be true
// if (!collapsed) return
// console.log(eventInfo, batch)
// })
this._addAutocomplete()
}
_defineSchema() {
@@ -98,9 +91,11 @@ export default class ContextedLinkEditing extends Plugin {
const autocompleteText = (inputText as string).match(/(?<=\[\[).*/g)
const cursorNodes = [focus.textNode, focus.nodeBefore, focus.nodeAfter]
const autocompleteNode: any = cursorNodes.find((node) =>
node?.hasAttribute('autocomplete')
['contextedLink', 'autocomplete'].some((attribute) =>
node?.hasAttribute(attribute)
)
)
if (Boolean(autocompleteText) || Boolean(autocompleteNode)) {
if (Boolean(autocompleteText) !== Boolean(autocompleteNode)) {
editor.execute('autocomplete')
@@ -112,35 +107,47 @@ export default class ContextedLinkEditing extends Plugin {
}
} else {
showAutocomplete = true
const view = editor.editing.view
const viewPosition = view.document.selection.focus
const viewNode = viewPosition?.parent.parent
const domElement = viewNode
? (view.domConverter.mapViewToDom(viewNode) as HTMLElement)
: undefined
const event: AutocompleteEvent = {
position: getNodePosition(
editor,
editor.model.createPositionFromPath(
autocompleteNode.root,
autocompleteNode.getPath()
)
),
autocompleteText: autocompleteNode.data,
domElement,
show: showAutocomplete,
}
editor.model.document.fire('contextedLinkAutocomplete', event)
fireAutocompleteEvent(editor, true, autocompleteNode)
}
}
if (!autocompleteNode && showAutocomplete) {
showAutocomplete = false
editor.model.document.fire('contextedLinkAutocomplete', {
show: showAutocomplete,
})
fireAutocompleteEvent(editor, false)
}
})
}
_addContextedKeyHandler() {
const editor = this.editor
const viewDocument = editor.editing.view.document
viewDocument.on(
'keydown',
(evt, data) => {
const { keyCode } = data
const keyCodesCycle = [38, 40] // Up, Down
const keyCodesConfirm = [13] // Enter
const keyCodesCancel = [27] // Escape
if (keyCodesCancel.includes(keyCode)) {
fireAutocompleteEvent(editor, false)
}
const keyCodes = [...keyCodesConfirm, ...keyCodesCycle]
const selection = editor.model.document.selection
const selectionInContextedLink = ['contextedLink', 'autocomplete'].some(
(attribute) => selection.hasAttribute(attribute)
)
if (selectionInContextedLink && keyCodes.includes(keyCode)) {
if (selection.hasAttribute('contextedLink')) {
const autocompleteNode = editor.model.document.selection.focus
?.textNode as any
fireAutocompleteEvent(editor, true, autocompleteNode)
}
console.log(keyCode)
this.editor.model.document.fire('contextedKeypress', { keyCode })
data.preventDefault(evt.stop())
}
},
{ priority: 'highest' }
)
}
}
function getNodePosition(editor: any, modelPosition: any) {
@@ -150,7 +157,7 @@ function getNodePosition(editor: any, modelPosition: any) {
const viewRange = editor.editing.view.createRange(viewPosition)
const domConverter = editor.editing.view.domConverter
const rangeRects = Rect.getDomRangeRects(
domConverter.viewRangeToDom(viewRange)
domConverter.viewRangeToDom(viewRange)
).pop()
return rangeRects
} catch (e) {
@@ -181,3 +188,32 @@ function getTextAfterCode(range: any, model: any) {
}, '')
return { text, range: model.createRange(start, range.end) }
}
function fireAutocompleteEvent(editor: any, show: boolean, autocompleteNode?: any) {
let event: AutocompleteEvent
if (show) {
const view = editor.editing.view
const viewPosition = view.document.selection.focus
const viewNode = viewPosition?.parent.parent
const domElement = viewNode
? (view.domConverter.mapViewToDom(viewNode) as HTMLElement)
: undefined
event = {
position: getNodePosition(
editor,
editor.model.createPositionFromPath(
autocompleteNode.root,
autocompleteNode.getPath()
)
),
autocompleteText: autocompleteNode.data,
domElement,
show: true,
}
} else {
event = {
show: false,
}
}
editor.model.document.fire('contextedLinkAutocomplete', event)
}

View File

@@ -12,6 +12,21 @@ const results = computed<Note[]>(() => {
props.autocompleteText ? findNotesByByTitle(props.autocompleteText) : notes.value
).filter((note) => note.id !== activeNote.value?.id)
})
const handleKeypress = (event: { [key: string]: number }) => {
const keyCode = event.keyCode
const keyCodes = {
cycle: [38, 40],
confirm: [13],
}
if (keyCodes.cycle.includes(keyCode)) {
const direction = keyCode === 38 ? -1 : 1
// console.log(direction)
} else if (keyCodes.confirm.includes(keyCode)) {
// console.log('confirm')
}
}
defineExpose({ handleKeypress })
</script>
<template>
<ul

View File

@@ -64,9 +64,11 @@ const handleClick = ({ data }: { data: any }) => {
if (note) activeNote.value = note
}
const autocompleteRef = ref<InstanceType<typeof Autocomplete> | null>(null)
const showAutocomplete = ref(false)
const autocompleteStyle = ref({})
const autocompleteText = ref('')
const handleAutocomplete = (event: AutocompleteEvent) => {
const position = event.position
if (position && editorElement.value) {
@@ -82,6 +84,10 @@ const handleAutocomplete = (event: AutocompleteEvent) => {
autocompleteText.value = event.autocompleteText || ''
showAutocomplete.value = event.show
}
const handleContextedKeypress = (event: any) => {
if (autocompleteRef.value) autocompleteRef.value.handleKeypress(event)
}
</script>
<template>
<div class="relative" ref="editorElement">
@@ -92,9 +98,11 @@ const handleAutocomplete = (event: AutocompleteEvent) => {
:config="editorConfig"
@click="handleClick"
@contexted-link-autocomplete="handleAutocomplete"
@contexted-keypress="handleContextedKeypress"
></CKEditor>
<Autocomplete
v-if="showAutocomplete"
ref="autocompleteRef"
:autocomplete-text="autocompleteText"
:style="autocompleteStyle"
class="absolute w-[250px]"