mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-09-10 02:32:02 +09:00
Hello world
First open source release of Campfire 🎉
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import Collection from "lib/autocomplete/collection"
|
||||
import SuggestionController from "lib/autocomplete/suggestion_controller"
|
||||
import { generateUUID } from "lib/autocomplete/helpers"
|
||||
import { Renderer } from "lib/autocomplete/renderer"
|
||||
|
||||
export default class BaseAutocompleteHandler {
|
||||
#autocompletables
|
||||
#url
|
||||
|
||||
constructor(element, url) {
|
||||
this.element = element
|
||||
this.#url = url
|
||||
if (!this.element.id) { this.element.id = `autocomplete_${generateUUID()}` }
|
||||
this.suggestionController = new SuggestionController(this)
|
||||
}
|
||||
|
||||
updateWithContentAndPosition(content, position) {
|
||||
if (this.suggestionController && this.shouldAutocompleteWithContentAndPosition(content, position)) {
|
||||
this.suggestionController.updateWithContentAndPosition(content, position)
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.#closeSuggestionController()
|
||||
}
|
||||
|
||||
// Subclass methods
|
||||
|
||||
get pattern() {
|
||||
return null
|
||||
}
|
||||
|
||||
shouldAutocompleteWithContentAndPosition(content, position) {
|
||||
return true
|
||||
}
|
||||
|
||||
getAutocompletable(value) {
|
||||
return this.#autocompletables.get(value)
|
||||
}
|
||||
|
||||
autocompletablesMatchingQuery(query) {
|
||||
return this.#autocompletables.matchingQuery(query).toArray()
|
||||
}
|
||||
|
||||
loadAutocompletables(query, callback) {
|
||||
const url = query ? this.#autocompletablesUrl(query) : this.#url
|
||||
|
||||
this.#fetchAutocompletables(url).then((autocompletables) => {
|
||||
this.setAutocompletables(autocompletables)
|
||||
callback()
|
||||
})
|
||||
}
|
||||
|
||||
setAutocompletables(autocompletables) {
|
||||
this.#autocompletables = new Collection(autocompletables)
|
||||
}
|
||||
|
||||
// SuggestionController Delegate
|
||||
|
||||
getSuggestionsIdentifier() {
|
||||
return `${this.element.id}_suggestions`
|
||||
}
|
||||
|
||||
matchQueryAndTerminatorForWord(word) {
|
||||
if (!this.pattern) return
|
||||
|
||||
const match = word.match(this.pattern)
|
||||
if (match) {
|
||||
return {
|
||||
query: match[1],
|
||||
terminator: match?.[2] || ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getOffsetsAtPosition(position) {
|
||||
return this.element.getBoundingClientRect()
|
||||
}
|
||||
|
||||
getResultsPlacement() {
|
||||
return this.#suggestionResultsPlacement
|
||||
}
|
||||
|
||||
fetchResultsForQuery(query, callback) {
|
||||
this.loadAutocompletables(query, () => {
|
||||
const autocompletables = this.autocompletablesMatchingQuery(query)
|
||||
const html = new Renderer().renderAutocompletableSuggestions(autocompletables)
|
||||
callback(html)
|
||||
})
|
||||
}
|
||||
|
||||
willCommitValueAtRangeWithTerminator(value, range, terminator) {
|
||||
const autocompletable = this.getAutocompletable(value)
|
||||
this.insertAutocompletable(autocompletable, range, terminator)
|
||||
}
|
||||
|
||||
didShowResults(selectElement) {
|
||||
selectElement.classList.add("rich_text")
|
||||
}
|
||||
|
||||
#autocompletablesUrl(query) {
|
||||
const separator = this.#url.includes('?') ? '&' : '?'
|
||||
return `${this.#url}${separator}query=${query}`
|
||||
}
|
||||
|
||||
get #suggestionResultsPlacement() {
|
||||
return this.element.dataset.suggestionResultsPlacement
|
||||
}
|
||||
|
||||
#closeSuggestionController() {
|
||||
if (!this.suggestionController) return
|
||||
|
||||
if (this.suggestionController.active) {
|
||||
this.suggestionController.hideResults()
|
||||
} else {
|
||||
this.suggestionController.destroy()
|
||||
this.suggestionController = null
|
||||
}
|
||||
}
|
||||
|
||||
#fetchAutocompletables(url) {
|
||||
if (url) {
|
||||
return fetch(url, { as: "json" }).then(response => response.json())
|
||||
} else {
|
||||
return Promise.resolve()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user