obsidian#SuggestModal TypeScript Examples

The following examples show how to use obsidian#SuggestModal. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: sharedTypes.ts    From obsidian-switcher-plus with GNU General Public License v3.0 6 votes vote down vote up
export declare class SystemSwitcher extends SuggestModal<AnySuggestion> {
  shouldShowAlias: boolean;
  protected isOpen: boolean;
  protected chooser: Chooser<AnySuggestion>;
  constructor(app: App);
  protected onInput(): void;
  protected updateSuggestions(): void;
  getSuggestions(query: string): AnySuggestion[];
  renderSuggestion(value: AnySuggestion, el: HTMLElement): void;
  onChooseSuggestion(item: AnySuggestion, evt: MouseEvent | KeyboardEvent): void;
}
Example #2
Source File: suggester.ts    From obsidian-fantasy-calendar with MIT License 6 votes vote down vote up
constructor(
        owner: SuggestModal<T>,
        containerEl: HTMLElement,
        scope: Scope
    ) {
        this.containerEl = containerEl;
        this.owner = owner;
        containerEl.on(
            "click",
            ".suggestion-item",
            this.onSuggestionClick.bind(this)
        );
        containerEl.on(
            "mousemove",
            ".suggestion-item",
            this.onSuggestionMouseover.bind(this)
        );

        scope.register([], "ArrowUp", () => {
            this.setSelectedItem(this.selectedItem - 1, true);
            return false;
        });

        scope.register([], "ArrowDown", () => {
            this.setSelectedItem(this.selectedItem + 1, true);
            return false;
        });

        scope.register([], "Enter", (evt) => {
            this.useSelectedItem(evt);
            return false;
        });

        scope.register([], "Tab", (evt) => {
            this.chooseSuggestion(evt);
            return false;
        });
    }
Example #3
Source File: ArticleSuggestModal.ts    From obsidian-rss with GNU General Public License v3.0 6 votes vote down vote up
export class ArticleSuggestModal extends SuggestModal<RssFeedItem> {

    plugin: RssReaderPlugin;
    items: RssFeedItem[];

    constructor(plugin: RssReaderPlugin, items: RssFeedItem[]) {
        super(plugin.app);
        this.plugin = plugin;
        this.items = items;
    }

    getItems(): RssFeedItem[] {
        return this.items;
    }

    onChooseSuggestion(item: RssFeedItem, _: MouseEvent | KeyboardEvent): void {
        this.close();
        new ItemModal(this.plugin, item, this.items, false).open();
    }

    getSuggestions(query: string): RssFeedItem[] {
        return this.items.filter((item) => {
           return item.title.toLowerCase().includes(query.toLowerCase()) || item.content.toLowerCase().includes(query.toLowerCase());
        });
    }

    renderSuggestion(item: RssFeedItem, el: HTMLElement) : void {
        el.createEl("div", { text: item.title });
        el.createEl("small", { text: moment(item.pubDate).format(this.plugin.settings.dateFormat) + " " + item.creator });
    }

}
Example #4
Source File: index.ts    From obsidian-admonition with MIT License 6 votes vote down vote up
constructor(
        owner: SuggestModal<T>,
        containerEl: HTMLElement,
        scope: Scope
    ) {
        this.containerEl = containerEl;
        this.owner = owner;
        containerEl.on(
            "click",
            ".suggestion-item",
            this.onSuggestionClick.bind(this)
        );
        containerEl.on(
            "mousemove",
            ".suggestion-item",
            this.onSuggestionMouseover.bind(this)
        );

        scope.register([], "ArrowUp", () => {
            this.setSelectedItem(this.selectedItem - 1, true);
            return false;
        });

        scope.register([], "ArrowDown", () => {
            this.setSelectedItem(this.selectedItem + 1, true);
            return false;
        });

        scope.register([], "Enter", (evt) => {
            this.useSelectedItem(evt);
            return false;
        });

        scope.register([], "Tab", (evt) => {
            this.useSelectedItem(evt);
            return false;
        });
    }
Example #5
Source File: suggester.ts    From obsidian-initiative-tracker with GNU General Public License v3.0 6 votes vote down vote up
constructor(
        owner: SuggestModal<T>,
        containerEl: HTMLElement,
        scope: Scope
    ) {
        this.containerEl = containerEl;
        this.owner = owner;
        containerEl.on(
            "click",
            ".suggestion-item",
            this.onSuggestionClick.bind(this)
        );
        containerEl.on(
            "mousemove",
            ".suggestion-item",
            this.onSuggestionMouseover.bind(this)
        );

        scope.register([], "ArrowUp", () => {
            this.setSelectedItem(this.selectedItem - 1, true);
            return false;
        });

        scope.register([], "ArrowDown", () => {
            this.setSelectedItem(this.selectedItem + 1, true);
            return false;
        });

        scope.register([], "Enter", (evt) => {
            this.useSelectedItem(evt);
            return false;
        });

        scope.register([], "Tab", (evt) => {
            this.useSelectedItem(evt);
            return false;
        });
    }
Example #6
Source File: suggester.ts    From obsidian-fantasy-calendar with MIT License 5 votes vote down vote up
owner: SuggestModal<T>;
Example #7
Source File: index.ts    From obsidian-admonition with MIT License 5 votes vote down vote up
owner: SuggestModal<T>;
Example #8
Source File: suggester.ts    From obsidian-initiative-tracker with GNU General Public License v3.0 5 votes vote down vote up
owner: SuggestModal<T>;
Example #9
Source File: locationSearchDialog.ts    From obsidian-map-view with GNU General Public License v3.0 4 votes vote down vote up
export class LocationSearchDialog extends SuggestModal<SuggestInfo> {
    private settings: PluginSettings;
    private searcher: GeoSearcher;
    private lastSearchTime = 0;
    private delayInMs = 250;
    private lastSearch = '';
    private lastSearchResults: SuggestInfo[] = [];
    private includeResults: SuggestInfo[] = [];
    private hasIcons: boolean = false;

    private dialogAction: DialogAction;
    private editor: Editor = null;

    // If dialogAction is 'custom', this will launch upon selection
    public customOnSelect: (selection: SuggestInfo) => void;

    constructor(
        app: App,
        settings: PluginSettings,
        dialogAction: DialogAction,
        title: string,
        editor: Editor = null,
        includeResults: SuggestInfo[] = null,
        hasIcons: boolean = false
    ) {
        super(app);
        this.settings = settings;
        this.searcher = new GeoSearcher(app, settings);
        this.dialogAction = dialogAction;
        this.editor = editor;
        this.includeResults = includeResults;
        this.hasIcons = hasIcons;

        this.setPlaceholder(
            title + ': type a place name or paste a string to parse'
        );
        this.setInstructions([{ command: 'enter', purpose: 'to use' }]);
    }

    getSuggestions(query: string) {
        let result: SuggestInfo[] = [];
        // Get results from the "to include" list, e.g. existing markers
        let resultsToInclude: SuggestInfo[] = [];
        if (this.includeResults)
            for (const toInclude of this.includeResults) {
                if (
                    query.length == 0 ||
                    toInclude.name.toLowerCase().includes(query.toLowerCase())
                )
                    resultsToInclude.push(toInclude);
                if (resultsToInclude.length >= consts.MAX_MARKER_SUGGESTIONS)
                    break;
            }
        result = result.concat(resultsToInclude);

        // From this point onward, results are added asynchronously.
        // We make sure to add them *after* the synchronuous results, otherwise
        // it will be very annoying for a user who may have already selected something.
        if (query == this.lastSearch) {
            result = result.concat(this.lastSearchResults);
        }
        this.getSearchResultsWithDelay(query);
        return result;
    }

    renderSuggestion(value: SuggestInfo, el: HTMLElement) {
        el.addClass('map-search-suggestion');
        if (this.hasIcons) {
            let iconDiv = el.createDiv('search-icon-div');
            const compiledIcon = getIconFromOptions(
                value.icon ?? consts.SEARCH_RESULT_MARKER
            );
            let iconElement: HTMLElement = compiledIcon.createIcon();
            let style = iconElement.style;
            style.marginLeft = style.marginTop = '0';
            style.position = 'relative';
            iconDiv.append(iconElement);
            let textDiv = el.createDiv('search-text-div');
            textDiv.appendText(value.name);
        } else el.appendText(value.name);
    }

    onChooseSuggestion(value: SuggestInfo, evt: MouseEvent | KeyboardEvent) {
        if (this.dialogAction == 'newNote')
            this.newNote(value.location, evt, value.name);
        else if (this.dialogAction == 'addToNote')
            this.addToNote(value.location, evt, value.name);
        else if (this.dialogAction == 'custom' && this.customOnSelect != null)
            this.customOnSelect(value);
    }

    async newNote(
        location: leaflet.LatLng,
        ev: MouseEvent | KeyboardEvent,
        query: string
    ) {
        const locationString = `${location.lat},${location.lng}`;
        const newFileName = utils.formatWithTemplates(
            this.settings.newNoteNameFormat,
            query
        );
        const file: TFile = await utils.newNote(
            this.app,
            'singleLocation',
            this.settings.newNotePath,
            newFileName,
            locationString,
            this.settings.newNoteTemplate
        );
        // If there is an open map view, use it to decide how and where to open the file.
        // Otherwise, open the file from the active leaf
        const mapView = utils.findOpenMapView(this.app);
        if (mapView) {
            mapView.goToFile(file, ev.ctrlKey, utils.handleNewNoteCursorMarker);
        } else {
            const leaf = this.app.workspace.activeLeaf;
            await leaf.openFile(file);
            const editor = await utils.getEditor(this.app);
            if (editor) await utils.handleNewNoteCursorMarker(editor);
        }
    }

    async addToNote(
        location: leaflet.LatLng,
        ev: MouseEvent | KeyboardEvent,
        query: string
    ) {
        const locationString = `[${location.lat},${location.lng}]`;
        utils.verifyOrAddFrontMatter(this.editor, 'location', locationString);
    }

    async getSearchResultsWithDelay(query: string) {
        if (query === this.lastSearch || query.length < 3) return;
        const timestamp = Date.now();
        this.lastSearchTime = timestamp;
        const Sleep = (ms: number) =>
            new Promise((resolve) => setTimeout(resolve, ms));
        await Sleep(this.delayInMs);
        if (this.lastSearchTime != timestamp) {
            // Search is canceled by a newer search
            return;
        }
        // After the sleep our search is still the last -- so the user stopped and we can go on
        this.lastSearch = query;
        this.lastSearchResults = await this.searcher.search(query);
        (this as any).updateSuggestions();
    }
}