mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-04 08:38:41 +08:00
99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
import { App, ISuggestOwner, Scope } from "obsidian";
|
|
|
|
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes
|
|
|
|
const wrapAround = (value: number, size: number): number => {
|
|
return ((value % size) + size) % size;
|
|
};
|
|
|
|
export default class Suggest<T> {
|
|
private owner: ISuggestOwner<T>;
|
|
private values: T[];
|
|
private suggestions: HTMLDivElement[];
|
|
private selectedItem: number;
|
|
private containerEl: HTMLElement;
|
|
|
|
constructor(owner: ISuggestOwner<T>, containerEl: HTMLElement, scope: Scope) {
|
|
this.owner = owner;
|
|
this.containerEl = containerEl;
|
|
|
|
containerEl.on("click", ".suggestion-item", this.onSuggestionClick.bind(this));
|
|
containerEl.on(
|
|
"mousemove",
|
|
".suggestion-item",
|
|
this.onSuggestionMouseover.bind(this)
|
|
);
|
|
|
|
scope.register([], "ArrowUp", (event) => {
|
|
if (!event.isComposing) {
|
|
this.setSelectedItem(this.selectedItem - 1, true);
|
|
return false;
|
|
}
|
|
});
|
|
|
|
scope.register([], "ArrowDown", (event) => {
|
|
if (!event.isComposing) {
|
|
this.setSelectedItem(this.selectedItem + 1, true);
|
|
return false;
|
|
}
|
|
});
|
|
|
|
scope.register([], "Enter", (event) => {
|
|
if (!event.isComposing) {
|
|
this.useSelectedItem(event);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
onSuggestionClick(event: MouseEvent, el: HTMLDivElement): void {
|
|
event.preventDefault();
|
|
|
|
const item = this.suggestions.indexOf(el);
|
|
this.setSelectedItem(item, false);
|
|
this.useSelectedItem(event);
|
|
}
|
|
|
|
onSuggestionMouseover(_event: MouseEvent, el: HTMLDivElement): void {
|
|
const item = this.suggestions.indexOf(el);
|
|
this.setSelectedItem(item, false);
|
|
}
|
|
|
|
setSuggestions(values: T[]) {
|
|
this.containerEl.empty();
|
|
const suggestionEls: HTMLDivElement[] = [];
|
|
|
|
values.forEach((value) => {
|
|
const suggestionEl = this.containerEl.createDiv("suggestion-item");
|
|
this.owner.renderSuggestion(value, suggestionEl);
|
|
suggestionEls.push(suggestionEl);
|
|
});
|
|
|
|
this.values = values;
|
|
this.suggestions = suggestionEls;
|
|
this.setSelectedItem(0, false);
|
|
}
|
|
|
|
useSelectedItem(event: MouseEvent | KeyboardEvent) {
|
|
const currentValue = this.values[this.selectedItem];
|
|
if (currentValue) {
|
|
this.owner.selectSuggestion(currentValue, event);
|
|
}
|
|
}
|
|
|
|
setSelectedItem(selectedIndex: number, scrollIntoView: boolean) {
|
|
const normalizedIndex = wrapAround(selectedIndex, this.suggestions.length);
|
|
const prevSelectedSuggestion = this.suggestions[this.selectedItem];
|
|
const selectedSuggestion = this.suggestions[normalizedIndex];
|
|
|
|
prevSelectedSuggestion?.removeClass("is-selected");
|
|
selectedSuggestion?.addClass("is-selected");
|
|
|
|
this.selectedItem = normalizedIndex;
|
|
|
|
if (scrollIntoView) {
|
|
selectedSuggestion.scrollIntoView(false);
|
|
}
|
|
}
|
|
}
|