mirror of
https://github.com/onlyworlds/obsidian-plugin.git
synced 2026-07-22 11:00:31 +00:00
94 lines
3.5 KiB
TypeScript
94 lines
3.5 KiB
TypeScript
import { App, Modal, Notice } from 'obsidian';
|
|
import { Category } from '../enums';
|
|
|
|
export class TemplateSelectionModal extends Modal {
|
|
private defaultCategory: string;
|
|
|
|
constructor(app: App, private executeCreation: (category: string) => void, defaultCategory: string | null = null) {
|
|
super(app);
|
|
this.defaultCategory = defaultCategory || '';
|
|
}
|
|
|
|
onOpen() {
|
|
let { contentEl } = this;
|
|
contentEl.createEl('h3', { text: 'Create element of category..' });
|
|
|
|
// Create input field for category selection
|
|
let inputEl = contentEl.createEl('input', {
|
|
type: 'text',
|
|
placeholder: 'Type to select a category...',
|
|
value: this.defaultCategory // Prefill if a default category is available
|
|
});
|
|
|
|
// Assign ID to the input for the datalist association
|
|
const dataListId = 'categories-list';
|
|
inputEl.setAttribute('list', dataListId);
|
|
|
|
// Create a datalist element and set the ID attribute manually
|
|
let dataListEl = contentEl.createEl('datalist');
|
|
dataListEl.id = dataListId;
|
|
|
|
// Populate datalist with categories
|
|
const categories = Object.keys(Category).filter(key => isNaN(Number(key)));
|
|
categories.forEach(category => {
|
|
dataListEl.createEl('option', { value: category });
|
|
});
|
|
|
|
// Handle keydown to select the top suggestion on 'Enter'
|
|
inputEl.addEventListener('keydown', (event) => {
|
|
if (event.key === 'Enter') {
|
|
event.preventDefault(); // Prevent the default form submit behavior
|
|
|
|
this.handleCategorySelection(inputEl.value, dataListEl, categories);
|
|
}
|
|
});
|
|
|
|
// Handle input changes for direct matches
|
|
inputEl.addEventListener('input', () => {
|
|
const value = inputEl.value;
|
|
if (categories.includes(value)) {
|
|
this.executeCreation(value);
|
|
this.close();
|
|
}
|
|
});
|
|
|
|
// Create "OK" button
|
|
const button = contentEl.createEl('button', { text: 'CHOOSE' });
|
|
button.style.marginLeft = '10px'; // Add some spacing between input and button
|
|
|
|
// Handle button click for category selection
|
|
button.addEventListener('click', () => {
|
|
this.handleCategorySelection(inputEl.value, dataListEl, categories);
|
|
});
|
|
|
|
// Focus the input field and select all text
|
|
inputEl.focus();
|
|
if (inputEl.value) {
|
|
inputEl.select(); // This will select all the text in the input
|
|
}
|
|
}
|
|
|
|
handleCategorySelection(inputValue: string, dataListEl: HTMLElement, categories: string[]) {
|
|
const trimmedValue = inputValue.trim();
|
|
|
|
// Try to find the first datalist option that starts with the input value
|
|
const matchedOption = Array.from(dataListEl.querySelectorAll('option'))
|
|
.find(option => option.value.toLowerCase().startsWith(trimmedValue.toLowerCase()));
|
|
|
|
if (matchedOption) {
|
|
this.executeCreation(matchedOption.value);
|
|
this.close();
|
|
} else if (categories.includes(trimmedValue)) {
|
|
// Handle case where user manually types an exact category
|
|
this.executeCreation(trimmedValue);
|
|
this.close();
|
|
} else {
|
|
new Notice('No matching category found.');
|
|
}
|
|
}
|
|
|
|
onClose() {
|
|
let { contentEl } = this;
|
|
contentEl.empty();
|
|
}
|
|
}
|