Add firefox compability for autocomplete

This commit is contained in:
kwaroran
2024-09-24 00:05:21 +09:00
parent e676623a4e
commit c1903c5b56

View File

@@ -38,7 +38,7 @@
hideAutoComplete() hideAutoComplete()
}} }}
> >
{#if !highlight || !CSS.highlights || isFirefox} {#if !highlight}
<textarea <textarea
class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-10 overflow-y-auto" class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-10 overflow-y-auto"
class:px-4={padding} class:px-4={padding}
@@ -67,6 +67,28 @@
} }
}} }}
/> />
{:else if isFirefox}
<div
class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-10 overflow-y-auto px-4 py-2 break-words whitespace-pre-wrap"
contenteditable="true"
bind:innerText={value}
on:keydown={(e) => {
handleKeyDown(e)
onInput()
}}
on:input={(e) => {
autoComplete()
}}
on:paste={(e) => {
e.preventDefault()
const text = e.clipboardData.getData('text/plain')
if(text){
insertContent(text, 'paste')
}
}}
bind:this={inputDom}
translate="no"
>{value ?? ''}</div>
{:else} {:else}
<div <div
class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-10 overflow-y-auto px-4 py-2 break-words whitespace-pre-wrap" class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-10 overflow-y-auto px-4 py-2 break-words whitespace-pre-wrap"
@@ -79,13 +101,14 @@
on:input={(e) => { on:input={(e) => {
autoComplete() autoComplete()
}} }}
bind:this={inputDom}
translate="no" translate="no"
>{value ?? ''}</div> >{value ?? ''}</div>
{/if} {/if}
<div class="hidden absolute z-100 bg-bgcolor border border-darkborderc p-2 flex-col" bind:this={autoCompleteDom}> <div class="hidden absolute z-100 bg-bgcolor border border-darkborderc p-2 flex-col" bind:this={autoCompleteDom}>
{#each autocompleteContents as content, i} {#each autocompleteContents as content, i}
<button class="w-full text-left py-1 px-2 bg-bgcolor" class:text-blue-500={selectingAutoComplete === i} on:click={() => { <button class="w-full text-left py-1 px-2 bg-bgcolor" class:text-blue-500={selectingAutoComplete === i} on:click={() => {
insertAutoComplete(content) insertContent(content)
}}>{content}</button> }}>{content}</button>
{/each} {/each}
</div> </div>
@@ -116,6 +139,7 @@
let optiValue = value let optiValue = value
let autoCompleteDom: HTMLDivElement let autoCompleteDom: HTMLDivElement
let autocompleteContents:string[] = [] let autocompleteContents:string[] = []
let inputDom: HTMLDivElement
const autoComplete = () => { const autoComplete = () => {
if(isMobile){ if(isMobile){
@@ -160,27 +184,38 @@
autoCompleteDom.style.display = 'flex' autoCompleteDom.style.display = 'flex'
} }
const insertAutoComplete = (insertContent:string) => { const insertContent = (insertContent:string, type:'autoComplete'|'paste' = 'autoComplete') => {
const sel = window.getSelection() const sel = window.getSelection()
if(sel){ if(sel){
const range = sel.getRangeAt(0) const range = sel.getRangeAt(0)
let content = (range.startContainer).textContent let content = (range.startContainer).textContent
let contentStart = content.substring(0, range.startOffset) let contentStart = content.substring(0, range.startOffset)
let contentEnd = content.substring(range.startOffset) let contentEnd = content.substring(range.startOffset)
contentStart = contentStart.substring(0, contentStart.lastIndexOf('{{')) if(type === 'autoComplete'){
contentStart = contentStart.substring(0, contentStart.lastIndexOf('{{'))
if(insertContent.endsWith(':')){ if(insertContent.endsWith(':')){
insertContent = `{{${insertContent}:` insertContent = `{{${insertContent}:`
} }
else{ else if(insertContent.startsWith('#')){
insertContent = `{{${insertContent}}}` insertContent = `{{${insertContent} `
}
else{
insertContent = `{{${insertContent}}}`
}
} }
const cons = contentStart + insertContent + contentEnd const cons = contentStart + insertContent + contentEnd
range.startContainer.textContent = cons range.startContainer.textContent = cons
sel.collapse(range.startContainer, contentStart.length + insertContent.length)
hideAutoComplete() hideAutoComplete()
try {
sel.collapse(range.startContainer, contentStart.length + insertContent.length)
} catch (error) {
inputDom.dispatchEvent(new Event('input'))
inputDom.dispatchEvent(new Event('change'))
}
//invoke onInput
} }
} }
@@ -218,7 +253,7 @@
case 'Tab': case 'Tab':
e.preventDefault() e.preventDefault()
if(selectingAutoComplete !== -1){ if(selectingAutoComplete !== -1){
insertAutoComplete(autocompleteContents[selectingAutoComplete]) insertContent(autocompleteContents[selectingAutoComplete])
} }
break break
case 'Escape': case 'Escape':