improve autocomplete working
This commit is contained in:
@@ -65,6 +65,7 @@ export default defineComponent({
|
|||||||
'update:modelValue',
|
'update:modelValue',
|
||||||
'click',
|
'click',
|
||||||
'contextedLinkAutocomplete',
|
'contextedLinkAutocomplete',
|
||||||
|
'contextedKeypress',
|
||||||
],
|
],
|
||||||
|
|
||||||
data(): CKEditorComponentData {
|
data(): CKEditorComponentData {
|
||||||
@@ -227,6 +228,9 @@ export default defineComponent({
|
|||||||
editor.model.document.on('contextedLinkAutocomplete', (_, data) => {
|
editor.model.document.on('contextedLinkAutocomplete', (_, data) => {
|
||||||
this.$emit('contextedLinkAutocomplete', data)
|
this.$emit('contextedLinkAutocomplete', data)
|
||||||
})
|
})
|
||||||
|
editor.model.document.on('contextedKeypress', (_, eventData) => {
|
||||||
|
this.$emit('contextedKeypress', eventData)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export default class ContextedLinkEditing extends Plugin {
|
|||||||
init() {
|
init() {
|
||||||
this._defineSchema() // ADDED
|
this._defineSchema() // ADDED
|
||||||
this._defineConverters() // ADDED
|
this._defineConverters() // ADDED
|
||||||
|
this._addContextedKeyHandler()
|
||||||
const twoStepCaretMovementPlugin = this.editor.plugins.get(TwoStepCaretMovement)
|
const twoStepCaretMovementPlugin = this.editor.plugins.get(TwoStepCaretMovement)
|
||||||
twoStepCaretMovementPlugin.registerAttribute('contextedLink')
|
twoStepCaretMovementPlugin.registerAttribute('contextedLink')
|
||||||
inlineHighlight(this.editor, 'contextedLink', 'a', HIGHLIGHT_CLASS)
|
inlineHighlight(this.editor, 'contextedLink', 'a', HIGHLIGHT_CLASS)
|
||||||
@@ -18,14 +19,6 @@ export default class ContextedLinkEditing extends Plugin {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
afterInit() {
|
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()
|
this._addAutocomplete()
|
||||||
}
|
}
|
||||||
_defineSchema() {
|
_defineSchema() {
|
||||||
@@ -98,7 +91,9 @@ export default class ContextedLinkEditing extends Plugin {
|
|||||||
const autocompleteText = (inputText as string).match(/(?<=\[\[).*/g)
|
const autocompleteText = (inputText as string).match(/(?<=\[\[).*/g)
|
||||||
const cursorNodes = [focus.textNode, focus.nodeBefore, focus.nodeAfter]
|
const cursorNodes = [focus.textNode, focus.nodeBefore, focus.nodeAfter]
|
||||||
const autocompleteNode: any = cursorNodes.find((node) =>
|
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)) {
|
||||||
@@ -112,35 +107,47 @@ export default class ContextedLinkEditing extends Plugin {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showAutocomplete = true
|
showAutocomplete = true
|
||||||
const view = editor.editing.view
|
fireAutocompleteEvent(editor, true, autocompleteNode)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!autocompleteNode && showAutocomplete) {
|
if (!autocompleteNode && showAutocomplete) {
|
||||||
showAutocomplete = false
|
showAutocomplete = false
|
||||||
editor.model.document.fire('contextedLinkAutocomplete', {
|
fireAutocompleteEvent(editor, false)
|
||||||
show: showAutocomplete,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
_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) {
|
function getNodePosition(editor: any, modelPosition: any) {
|
||||||
@@ -181,3 +188,32 @@ function getTextAfterCode(range: any, model: any) {
|
|||||||
}, '')
|
}, '')
|
||||||
return { text, range: model.createRange(start, range.end) }
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,21 @@ const results = computed<Note[]>(() => {
|
|||||||
props.autocompleteText ? findNotesByByTitle(props.autocompleteText) : notes.value
|
props.autocompleteText ? findNotesByByTitle(props.autocompleteText) : notes.value
|
||||||
).filter((note) => note.id !== activeNote.value?.id)
|
).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>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<ul
|
<ul
|
||||||
|
|||||||
@@ -64,9 +64,11 @@ const handleClick = ({ data }: { data: any }) => {
|
|||||||
if (note) activeNote.value = note
|
if (note) activeNote.value = note
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const autocompleteRef = ref<InstanceType<typeof Autocomplete> | null>(null)
|
||||||
const showAutocomplete = ref(false)
|
const showAutocomplete = ref(false)
|
||||||
const autocompleteStyle = ref({})
|
const autocompleteStyle = ref({})
|
||||||
const autocompleteText = ref('')
|
const autocompleteText = ref('')
|
||||||
|
|
||||||
const handleAutocomplete = (event: AutocompleteEvent) => {
|
const handleAutocomplete = (event: AutocompleteEvent) => {
|
||||||
const position = event.position
|
const position = event.position
|
||||||
if (position && editorElement.value) {
|
if (position && editorElement.value) {
|
||||||
@@ -82,6 +84,10 @@ const handleAutocomplete = (event: AutocompleteEvent) => {
|
|||||||
autocompleteText.value = event.autocompleteText || ''
|
autocompleteText.value = event.autocompleteText || ''
|
||||||
showAutocomplete.value = event.show
|
showAutocomplete.value = event.show
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleContextedKeypress = (event: any) => {
|
||||||
|
if (autocompleteRef.value) autocompleteRef.value.handleKeypress(event)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="relative" ref="editorElement">
|
<div class="relative" ref="editorElement">
|
||||||
@@ -92,9 +98,11 @@ const handleAutocomplete = (event: AutocompleteEvent) => {
|
|||||||
:config="editorConfig"
|
:config="editorConfig"
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
@contexted-link-autocomplete="handleAutocomplete"
|
@contexted-link-autocomplete="handleAutocomplete"
|
||||||
|
@contexted-keypress="handleContextedKeypress"
|
||||||
></CKEditor>
|
></CKEditor>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
v-if="showAutocomplete"
|
v-if="showAutocomplete"
|
||||||
|
ref="autocompleteRef"
|
||||||
:autocomplete-text="autocompleteText"
|
:autocomplete-text="autocompleteText"
|
||||||
:style="autocompleteStyle"
|
:style="autocompleteStyle"
|
||||||
class="absolute w-[250px]"
|
class="absolute w-[250px]"
|
||||||
|
|||||||
Reference in New Issue
Block a user