obsidian#DropdownComponent TypeScript Examples

The following examples show how to use obsidian#DropdownComponent. 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: settings.ts    From folder-note-core with MIT License 6 votes vote down vote up
constructor(public plugin: FNCore) {
    super(plugin.app);

    // Dropdowns
    this.fromOptsEl = new DropdownComponent(
      this.titleEl.createDiv({ text: "From:  " }),
    ).addOptions(LocDescMap);
    this.toOptsEl = new DropdownComponent(
      this.titleEl.createDiv({ text: "To:  " }),
    ).addOptions(LocDescMap);

    // Console output
    this.outputEl = new TextAreaComponent(this.contentEl)
      .setValue("Hello world")
      .setDisabled(true)
      .then((cb) => {
        cb.inputEl.style.width = "100%";
        cb.inputEl.rows = 10;
      });

    // Buttons
    this.buttonContainerEl = this.modalEl.createDiv({
      cls: "modal-button-container",
    });
    this.addButton((cb) =>
      cb.setButtonText("Check Conflicts").onClick(() => this.Convert(true)),
    );
    this.addButton((cb) =>
      cb
        .setButtonText("Convert")
        .setWarning()
        .onClick(() => this.Convert()),
    );
    this.addButton((cb) =>
      cb.setButtonText("Cancel").onClick(this.close.bind(this)),
    );
  }
Example #2
Source File: valueSelectModal.ts    From obsidian_supercharged_links with MIT License 6 votes vote down vote up
buildInputEl(inputDiv: HTMLDivElement): void{
        const selectEl = new DropdownComponent(inputDiv)
        selectEl.selectEl.addClass("frontmatter-select")
        const values = this.settings.values
        selectEl.addOption("","--Empty--")
        Object.keys(values).forEach(key => {
            selectEl.addOption(values[key], values[key])
        });
        if(Object.values(values).includes(this.value)){
            selectEl.setValue(this.value)
        }
        FieldSetting.getValuesListFromNote(this.settings.valuesListNotePath, this.app).then(listNoteValues => {
            listNoteValues.forEach(value => selectEl.addOption(value, value))
            if(listNoteValues.includes(this.value)){
                selectEl.setValue(this.value)
            }
            selectEl.onChange(value => this.newValue = value != "--Empty--" ? value : "")
            const submitButton = new ButtonComponent(inputDiv)
            submitButton.setTooltip("Save")
            .setIcon("checkmark")
            .onClick(async () => {
                if(this.lineNumber == -1){
                    if(this.newValue || this.newValue == ""){
                        replaceValues(this.app, this.file, this.name, this.newValue)
                    }
                } else {
                    this.app.vault.read(this.file).then(result => {
                        let newContent: string[] = []
                        if(this.top){
                            newContent.push(`${this.name}${this.inFrontmatter ? ":" : "::"} ${selectEl.getValue()}`)
                            result.split("\n").forEach((line, _lineNumber) => newContent.push(line))
                        } else {
                            result.split("\n").forEach((line, _lineNumber) => {
                                newContent.push(line)
                                if(_lineNumber == this.lineNumber){
                                    newContent.push(`${this.name}${this.inFrontmatter ? ":" : "::"} ${selectEl.getValue()}`)
                                }
                            })
                        }
                        this.app.vault.modify(this.file, newContent.join('\n'))
                        this.close()
                    })
                }
                this.close()
            })
        })
        
    }
Example #3
Source File: macroChoiceBuilder.ts    From quickadd with MIT License 6 votes vote down vote up
private addSelectMacroSearch() {
        const selectMacroDropdownContainer: HTMLDivElement = this.contentEl.createDiv('selectMacroDropdownContainer');
        const dropdown: DropdownComponent = new DropdownComponent(selectMacroDropdownContainer);

        let macroOptions: Record<string, string> = {};

        this.macros.forEach(macro => {
            macroOptions[macro.name] = macro.name;
        });

        dropdown.addOptions(macroOptions);
        dropdown.onChange(value => {
            this.selectMacro(value);
        });

        const selectedMacro: IMacro = this.macros.find(m => m.id === this.choice.macroId);
        if (selectedMacro) {
            dropdown.setValue(selectedMacro.name);
        } else {
            const value = dropdown.getValue();
            if (value) {
                this.selectMacro(value);
            }
        }
    }
Example #4
Source File: sectionContentModal.ts    From obsidian_supercharged_links with MIT License 6 votes vote down vote up
onOpen(){
        this.titleEl.setText('Select the line before the field to add')
        const contentDiv = this.contentEl.createDiv()
        const inputDiv = contentDiv.createDiv()
        const inputEl = new TextAreaComponent(inputDiv)
        inputEl.inputEl.setAttr("cols", "50")
        inputEl.inputEl.setAttr("rows", "5")
        const footerDiv = contentDiv.createDiv({
            cls: "frontmatter-textarea-buttons"
        })
        const positionSelectorContainer = footerDiv.createDiv({
            cls: "position-selector-container"
        })
        const positionDropdown = new DropdownComponent(positionSelectorContainer)
        positionDropdown.addOption("1", "begining")
        positionDropdown.addOption("2", "end")
        positionDropdown.setValue("2")
        const saveButton = new ButtonComponent(footerDiv)
        saveButton
        .setIcon("checkmark")
        .onClick(() => {
            this.app.vault.read(this.file).then(result => {
                let newContent: string[] = []
                result.split("\n").forEach((line, lineNumber) =>{
                    newContent.push(line)
                    if(lineNumber == this.startLine && positionDropdown.getValue() == "1"){
                        newContent.push(inputEl.getValue())
                    }
                    if(lineNumber == this.startLine && positionDropdown.getValue() == "1"){
                        newContent.push(inputEl.getValue())
                    }
                })
            })
        })
        const cancelButton = new ExtraButtonComponent(footerDiv)
        cancelButton
        .setIcon("cross")
        .onClick(() => this.close())
    }
Example #5
Source File: fieldSelectModal.ts    From obsidian_supercharged_links with MIT License 6 votes vote down vote up
onOpen(){
        this.titleEl.setText(`Insert field after > ${this.line.substring(0, 20)}${this.line.length>20 ? "..." : ""}`)
        const container = this.contentEl.createDiv()
        const settingsDropdownContainer = container.createDiv()
        const settingsSelector = new DropdownComponent(settingsDropdownContainer)
        settingsSelector.addOption("---", "Choose Field")
        settingsSelector.addOption("++New", "New")
        this.plugin.settings.presetFields.forEach(setting => {
            settingsSelector.addOption(setting.name, setting.name)
        })
        settingsSelector.onChange(value => {
            if(value == "++New"){
                const newFieldModal = new addNewFieldModal(this.plugin, this.lineNumber, this.file, this.inFrontmatter, this.top)
                newFieldModal.open()
                this.close()
            } else {
                const field = this.plugin.settings.presetFields.filter(_field => _field.name == value)[0]
                if(field.valuesListNotePath || (field.values && Object.keys(field.values).length > 0)){
                    if(field.isMulti){
                        const fieldModal = new valueMultiSelectModal(this.app, this.file, field.name, "", field, this.lineNumber, this.inFrontmatter, this.top)
                        fieldModal.titleEl.setText(`Select values for ${value}`)
                        fieldModal.open()
                    } else {
                        const fieldModal = new valueSelectModal(this.app, this.file, field.name, "", field, this.lineNumber, this.inFrontmatter, this.top)
                        fieldModal.titleEl.setText(`Select value for ${value}`)
                        fieldModal.open()
                    }
                } else {
                    const fieldModal = new valueTextInputModal(this.app, this.file, value, "", this.lineNumber, this.inFrontmatter, this.top)
                    fieldModal.titleEl.setText(`Enter value for ${value}`)
                    fieldModal.open()
                }
                this.close()
            }
        })
    }
Example #6
Source File: FileClassAttributeSelectModal.ts    From obsidian_supercharged_links with MIT License 6 votes vote down vote up
onOpen(){
        this.titleEl.setText(`Select the field to update`)
        createFileClass(this.plugin, this.file.basename).then(fileClass => {
            this.titleEl.setText(`Select the field to update in ${fileClass.name}`)
            const selectContainer = this.contentEl.createDiv()
            const select = new DropdownComponent(selectContainer)
            select.addOption("select an attribute", "--select an attribute--")
            fileClass.attributes.forEach(attr => {
                select.addOption(attr.name, attr.name)
            })

            select.addOption("++newAttr++", "++Add a new attribute++")
            select.onChange((attrName) => {
                if(attrName == "++newAttr"){
                    const modal = new FileClassAttributeModal(this.plugin.app, fileClass)
                    modal.open()
                    this.close()
                } else {
                    const modal = new FileClassAttributeModal(this.plugin.app, fileClass, fileClass.attributes.filter(attr => attr.name == attrName)[0])
                    modal.open()
                    this.close()
                }
            })
        })
    }
Example #7
Source File: settings.ts    From obsidian-citation-plugin with MIT License 6 votes vote down vote up
addValueChangeCallback<T extends HTMLTextAreaElement | HTMLInputElement>(
    component: AbstractTextComponent<T> | DropdownComponent,
    settingsKey: string,
    cb?: (value: string) => void,
  ): void {
    component.onChange(async (value) => {
      (this.plugin.settings as IIndexable)[settingsKey] = value;
      this.plugin.saveSettings().then(() => {
        if (cb) {
          cb(value);
        }
      });
    });
  }
Example #8
Source File: view.ts    From obsidian-fantasy-calendar with MIT License 6 votes vote down vote up
async display() {
        this.contentEl.empty();
        this.contentEl.createEl("h4", { text: "Switch Calendars" });
        const dropdownEl = this.contentEl.createDiv(
            "fantasy-calendar-dropdown"
        );
        dropdownEl.createEl("label", {
            text: "Choose a Calendar"
        });
        const dropdown = new DropdownComponent(dropdownEl).onChange((v) => {
            this.calendar = this.plugin.data.calendars.find((c) => c.id == v);
        });
        dropdown
            .addOptions(
                Object.fromEntries(
                    this.plugin.data.calendars.map((c) => [c.id, c.name])
                )
            )
            .setValue(this.calendar ? this.calendar.id : null);
        const buttonEl = this.contentEl.createDiv(
            "fantasy-calendar-confirm-buttons"
        );
        new ButtonComponent(buttonEl)
            .setButtonText("Switch")
            .setCta()
            .onClick(() => {
                this.confirmed = true;
                this.close();
            });
        new ButtonComponent(buttonEl).setButtonText("Cancel").onClick(() => {
            this.close();
        });
    }
Example #9
Source File: settings.ts    From folder-note-core with MIT License 5 votes vote down vote up
fromOptsEl: DropdownComponent;
Example #10
Source File: chooseSectionModal.ts    From obsidian_supercharged_links with MIT License 5 votes vote down vote up
onOpen(){
        this.titleEl.setText("Add a field in this note after:")
        const inputDiv = this.contentEl.createDiv({
            cls: "frontmatter-modal-value"
        })
        const selectEl = new DropdownComponent(inputDiv)
        selectEl.selectEl.addClass("frontmatter-select")
        selectEl.addOption("","Select line")
        selectEl.addOption("top_0","top")
        this.app.vault.read(this.file).then(result => {
			let foreHeadText = false
			let frontmatterStart = false
			let frontmatterEnd = false
			let inFrontmatter = false
            result.split("\n").forEach((line, lineNumber) => {
                if(line!="---" && !foreHeadText && !frontmatterStart){
					foreHeadText = true
				}
				if(line == "---" && !foreHeadText){
					if(!frontmatterStart){
						frontmatterStart = true
						inFrontmatter = true
					} else if(!frontmatterEnd){
						frontmatterEnd = true
						inFrontmatter = false
					}
				}
				if(inFrontmatter){
                    selectEl.addOption(`frontmatter_${lineNumber}`, `${line.substring(0, 30)}${line.length > 30 ? "..." : ""}`)
                }else{
                    selectEl.addOption(`body_${lineNumber}`, `${line.substring(0, 30)}${line.length > 30 ? "..." : ""}`)
                }
            })
            selectEl.onChange(value => {
                const valueArray = selectEl.getValue().match(/(\w+)_(\d+)/)
                const position = valueArray[1]
                const lineNumber = Number(valueArray[2])
                const inFrontmatter = position == "frontmatter" ? true : false
                const top = position == "top" ? true : false
                const modal = new fieldSelectModal(this.plugin, this.file, lineNumber, result.split('\n')[lineNumber], inFrontmatter, top)
                this.close()
                modal.open()
            })
        })
    }
Example #11
Source File: SelectModal.ts    From obsidian_supercharged_links with MIT License 5 votes vote down vote up
export default class SelectModal extends DropdownComponent {
    modals: Record<string, any>

    constructor(containerEl: HTMLElement){
        super(containerEl)
        this.modals = {}
    }
}
Example #12
Source File: SettingsTab.ts    From obsidian-rss with GNU General Public License v3.0 5 votes vote down vote up
display(): void {
        const {containerEl} = this;

        containerEl.empty();

        containerEl.createEl('h2', {text: t("RSS_Reader") + " " + t("settings")});

        containerEl.createEl('h3', {text: t("file_creation")});

        const templateDesc = new DocumentFragment();
        templateDesc.createDiv().innerHTML = t("template_new_help") + "<br>" + t("available_variables") + `<br>` +
            `<strong>{{title}}</strong> → ${t("article_title")}<br>` +
            `<strong>{{link}}</strong> → ${t("article_link")}<br>` +
            `<strong>{{author}}</strong> → ${t("article_author")}<br>` +
            `<strong>{{published}}</strong> → ${t("article_published")}<br>` +
            `<strong>{{created}}</strong> → ${t("note_created")}<br>` +
            `<strong>{{description}}</strong> → ${t("article_description")}<br>` +
            `<strong>{{content}}</strong> → ${t("article_content")}<br>` +
            `<strong>{{folder}}</strong> → ${t("feed_folder")}<br>` +
            `<strong>{{feed}}</strong> → ${t("feed_title")}<br>` +
            `<strong>{{filename}}</strong> → ${t("filename")}<br>` +
            `<strong>{{tags}}</strong> → ${t("article_tags")}<br>` +
            `<strong>{{media}}</strong> → ${t("article_media")}<br>` +
            `<strong>{{highlights}}</strong> → ${t("highlights")}`;

        new Setting(containerEl)
            .setName(t("template_new"))
            .setDesc(templateDesc)
            .addTextArea((textArea: TextAreaComponent) => {
                textArea
                    .setValue(this.plugin.settings.template)
                    .setPlaceholder(DEFAULT_SETTINGS.template)
                    .onChange(async (value) => {
                        await this.plugin.writeSettings(() => ({
                            template: value
                        }));
                    });
                textArea.inputEl.setAttr("rows", 15);
                textArea.inputEl.setAttr("cols", 50);
            });

        const pasteTemplateDesc = new DocumentFragment();
        pasteTemplateDesc.createDiv().innerHTML = t("template_new_help") + "<br>" + t("available_variables") + `<br>` +
            `<strong>{{title}}</strong> → ${t("article_title")}<br>` +
            `<strong>{{link}}</strong> → ${t("article_link")}<br>` +
            `<strong>{{author}}</strong> → ${t("article_author")}<br>` +
            `<strong>{{published}}</strong> → ${t("article_published")}<br>` +
            `<strong>{{created}}</strong> → ${t("note_created")}<br>` +
            `<strong>{{description}}</strong> → ${t("article_description")}<br>` +
            `<strong>{{content}}</strong> → ${t("article_content")}<br>` +
            `<strong>{{folder}}</strong> → ${t("feed_folder")}<br>` +
            `<strong>{{feed}}</strong> → ${t("feed_title")}<br>` +
            `<strong>{{tags}}</strong> → ${t("article_tags")}<br>` +
            `<strong>{{media}}</strong> → ${t("article_media")}<br>` +
            `<strong>{{highlights}}</strong> → ${t("highlights")}`;

        new Setting(containerEl)
            .setName(t("template_paste"))
            .setDesc(pasteTemplateDesc)
            .addTextArea((textArea: TextAreaComponent) => {
                textArea
                    .setValue(this.plugin.settings.pasteTemplate)
                    .setPlaceholder(DEFAULT_SETTINGS.pasteTemplate)
                    .onChange(async (value) => {
                        await this.plugin.writeSettings(() => ({
                            pasteTemplate: value
                        }));
                    });
                textArea.inputEl.setAttr("rows", 15);
                textArea.inputEl.setAttr("cols", 50);
            });

        new Setting(containerEl)
            .setName(t("file_location"))
            .setDesc(t("file_location_help"))
            .addDropdown(async (dropdown: DropdownComponent) => {
                dropdown
                    .addOption("default", t("file_location_default"))
                    .addOption("custom", t("file_location_custom"))
                    .setValue(this.plugin.settings.saveLocation)
                    .onChange(async (value: string) => {
                        await this.plugin.writeSettings(() => (
                            {saveLocation: value}
                        ));
                        this.display();
                    });
            });

        if (this.plugin.settings.saveLocation == "custom") {
            new Setting(containerEl)
                .setName(t("file_location_folder"))
                .setDesc(t("file_location_folder_help"))
                .addSearch(async (search: SearchComponent) => {
                    new FolderSuggest(this.app, search.inputEl);
                    search
                        .setValue(this.plugin.settings.saveLocationFolder)
                        .setPlaceholder(DEFAULT_SETTINGS.saveLocationFolder)
                        .onChange(async (value: string) => {
                            await this.plugin.writeSettings(() => (
                                {saveLocationFolder: value}
                            ));
                        });
                });
        }

        let dateFormatSampleEl: MomentFormatComponent;
        const dateFormat = new Setting(containerEl)
            .setName(t("date_format"))
            .addMomentFormat((format: MomentFormatComponent) => {
                dateFormatSampleEl = format
                    .setDefaultFormat(DEFAULT_SETTINGS.dateFormat)
                    .setPlaceholder(DEFAULT_SETTINGS.dateFormat)
                    .setValue(this.plugin.settings.dateFormat)
                    .onChange(async (value) => {
                        await this.plugin.writeSettings(() => (
                            {dateFormat: value}
                        ));
                    });
            });
        const referenceLink = dateFormat.descEl.createEl("a");
        referenceLink.setAttr("href", "https://momentjs.com/docs/#/displaying/format/");
        referenceLink.setText(t("syntax_reference"));
        const text = dateFormat.descEl.createDiv("text");
        text.setText(t("syntax_looks"));
        const sampleEl = text.createSpan("sample");
        dateFormatSampleEl.setSampleEl(sampleEl);
        dateFormat.addExtraButton((button) => {
            button
                .setIcon('reset')
                .setTooltip(t("reset"))
                .onClick(async () => {
                    await this.plugin.writeSettings(() => ({
                        dateFormat: DEFAULT_SETTINGS.dateFormat
                    }));
                    this.display();
                });
        });

        new Setting(containerEl)
            .setName(t("ask_filename"))
            .setDesc(t("ask_filename_help"))
            .addToggle((toggle: ToggleComponent) => {
                toggle
                    .setValue(this.plugin.settings.askForFilename)
                    .onChange(async (value) => {
                        await this.plugin.writeSettings(() => ({
                            askForFilename: value
                        }));
                    });
            });

        new Setting(containerEl)
            .setName(t("default_filename"))
            .setDesc(t("default_filename_help"))
            .addText((text) => {
                text
                    .setPlaceholder(DEFAULT_SETTINGS.defaultFilename)
                    .setValue(this.plugin.settings.defaultFilename)
                    .onChange(async (value) => {
                        if (value.length > 0) {
                            await this.plugin.writeSettings(() => ({
                                defaultFilename: value
                            }));
                        } else {
                            new Notice(t("fix_errors"));
                        }
                    });
            });

        containerEl.createEl("hr", {attr: {style: "border-top: 5px solid var(--background-modifier-border);"}});
        containerEl.createEl("h3", {text: "Misc"});

        const refresh = new Setting(containerEl)
            .setName(t("refresh_time"))
            .setDesc(t("refresh_time_help"))
            .addText((text: TextComponent) => {
                text
                    .setPlaceholder(String(DEFAULT_SETTINGS.updateTime))
                    .setValue(String(this.plugin.settings.updateTime))
                    .onChange(async (value) => {
                        if (value.length === 0) {
                            new Notice(t("specify_positive_number"));
                            return;
                        }
                        if (Number(value) < 0) {
                            new Notice(t("specify_positive_number"));
                            return;
                        }

                        await this.plugin.writeSettings(() => (
                            {updateTime: Number(value)}
                        ));
                    });
                text.inputEl.setAttr("type", "number");
                text.inputEl.setAttr("min", "1");
                //we don't want decimal numbers.
                text.inputEl.setAttr("onkeypress", "return event.charCode >= 48 && event.charCode <= 57");
            });
        refresh.addExtraButton((button) => {
            button
                .setIcon('reset')
                .setTooltip('restore default')
                .onClick(async () => {
                    await this.plugin.writeSettings(() => ({
                        updateTime: DEFAULT_SETTINGS.updateTime
                    }));
                    this.display();
                });
        });

        new Setting(containerEl)
            .setName(t("multi_device_usage"))
            .setDesc(t("multi_device_usage_help"))
            .addToggle((toggle: ToggleComponent) => {
                return toggle
                    .setValue(this.plugin.settings.autoSync)
                    .onChange(async (value) => {
                        await this.plugin.writeSettings(() => ({
                            autoSync: value
                        }));
                    });
            });

        new Setting(containerEl)
            .setName(t("display_style"))
            .addDropdown(dropdown => {
                return dropdown
                    .addOption("list", t("list"))
                    .addOption("cards", t("cards"))
                    .setValue(this.plugin.settings.displayStyle)
                    .onChange(async (value) => {
                        await this.plugin.writeSettings(() => ({
                            displayStyle: value
                        }));
                    });
            });

        containerEl.createEl("h2", {text: t("content")});

        const filterContainer = containerEl.createDiv("filter-container");
        displayFilterSettings(this.plugin, filterContainer);

        const feedsContainer = containerEl.createDiv(
            "feed-container"
        );
        displayFeedSettings(this.plugin, feedsContainer);

        containerEl.createEl("hr", {attr: {style: "border-top: 5px solid var(--background-modifier-border);"}});

        const hotkeyContainer = containerEl.createDiv("hotkey-container");
        displayHotkeys(this.plugin, hotkeyContainer);

        containerEl.createEl("hr", {attr: {style: "border-top: 5px solid var(--background-modifier-border);"}});

        const details = containerEl.createEl("details");
        const summary = details.createEl("summary");
        summary.setText(t("advanced"));
        const advanced = details.createDiv("advanced");

        advanced.createEl("h3", {text: t("customize_terms")});
        advanced.createSpan({text: "Change a few selected terms here. You can help translating the plugin "});
        advanced.createEl("a", {text: "here", href: "https://github.com/joethei/obsidian-rss/tree/master/src/l10n"});

        new Setting(advanced)
            .setName(t("folders"))
            .addText(text => {
                text
                    .setPlaceholder(t("folders"))
                    .setValue(this.plugin.settings.renamedText.folders)
                    .onChange(async value => {
                        await this.plugin.writeSettings(() => ({
                            renamedText: {
                                ...this.plugin.settings.renamedText,
                                folders: value
                            }
                        }));
                    });
            });

        new Setting(advanced)
            .setName(t("filtered_folders"))
            .addText(text => {
                text
                    .setPlaceholder(t("filtered_folders"))
                    .setValue(this.plugin.settings.renamedText.filtered_folders)
                    .onChange(async value => {
                        await this.plugin.writeSettings(() => ({
                            renamedText: {
                                ...this.plugin.settings.renamedText,
                                filtered_folders: value
                            }
                        }));
                    });
            });

        new Setting(advanced)
            .setName(t("no_folder"))
            .addText(text => {
                text
                    .setPlaceholder(t("no_folder"))
                    .setValue(this.plugin.settings.renamedText.no_folder)
                    .onChange(async value => {
                        await this.plugin.writeSettings(() => ({
                            renamedText: {
                                ...this.plugin.settings.renamedText,
                                no_folder: value
                            }
                        }));
                    });
            });

        advanced.createEl("hr", {attr: {style: "border-top: 5px solid var(--background-modifier-border);"}});

        new Setting(advanced)
            .setName(t("display_media"))
            .addToggle(toggle => {
               toggle
                   .setValue(this.plugin.settings.displayMedia)
                   .onChange(async value => {
                       await this.plugin.writeSettings(() => ({
                           displayMedia: value
                       }));
                   });
            });
    }
Example #13
Source File: settings.ts    From obsidian-citation-plugin with MIT License 5 votes vote down vote up
buildValueInput<T extends HTMLTextAreaElement | HTMLInputElement>(
    component: AbstractTextComponent<T> | DropdownComponent,
    settingsKey: string,
    cb?: (value: string) => void,
  ): void {
    component.setValue((this.plugin.settings as IIndexable)[settingsKey]);
    this.addValueChangeCallback(component, settingsKey, cb);
  }
Example #14
Source File: event.ts    From obsidian-fantasy-calendar with MIT License 5 votes vote down vote up
buildDateFields(el: HTMLElement, field = this.event.date) {
        el.empty();
        const dayEl = el.createDiv("fantasy-calendar-date-field");
        dayEl.createEl("label", { text: "Day" });
        const day = new TextComponent(dayEl)
            .setPlaceholder("Day")
            .setValue(`${field.day}`)
            .onChange((v) => {
                field.day = Number(v);
                this.buildDateString();
            });
        day.inputEl.setAttr("type", "number");

        const monthEl = el.createDiv("fantasy-calendar-date-field");
        monthEl.createEl("label", { text: "Month" });
        new DropdownComponent(monthEl)
            .addOptions(
                Object.fromEntries([
                    ["select", "Select Month"],
                    ...this.calendar.static.months.map((month) => [
                        month.name,
                        month.name
                    ])
                ])
            )
            .setValue(
                field.month != undefined
                    ? this.calendar.static.months[field.month].name
                    : "select"
            )
            .onChange((v) => {
                if (v === "select") field.month = null;
                const index = this.calendar.static.months.find(
                    (m) => m.name == v
                );
                field.month = this.calendar.static.months.indexOf(index);
                this.buildDateString();
            });

        const yearEl = el.createDiv("fantasy-calendar-date-field");
        yearEl.createEl("label", { text: "Year" });
        const year = new TextComponent(yearEl)
            .setPlaceholder("Year")
            .setValue(`${field.year}`)
            .onChange((v) => {
                if (!v || v == undefined) {
                    field.year = undefined;
                } else {
                    field.year = Number(v);
                }
                this.buildDateString();
            });
        year.inputEl.setAttr("type", "number");
    }
Example #15
Source File: viewControls.ts    From obsidian-map-view with GNU General Public License v3.0 5 votes vote down vote up
private presetsBox: DropdownComponent;
Example #16
Source File: viewControls.ts    From obsidian-map-view with GNU General Public License v3.0 5 votes vote down vote up
private sourceMode: DropdownComponent;
Example #17
Source File: viewControls.ts    From obsidian-map-view with GNU General Public License v3.0 5 votes vote down vote up
private mapSourceBox: DropdownComponent;
Example #18
Source File: viewControls.ts    From obsidian-map-view with GNU General Public License v3.0 5 votes vote down vote up
refreshPresets() {
        if (this.presetsDivContent) this.presetsDivContent.remove();
        this.presetsDivContent = this.presetsDiv.createDiv({
            cls: 'graph-control-content',
        });
        this.presetsBox = new DropdownComponent(this.presetsDivContent);
        const states = [
            this.settings.defaultState,
            ...(this.settings.savedStates || []),
        ];
        this.presetsBox.addOption('-1', '');
        for (const [index, preset] of states.entries()) {
            this.presetsBox.addOption(index.toString(), preset.name);
        }
        if (
            this.lastSelectedPresetIndex &&
            this.lastSelectedPresetIndex < states.length &&
            areStatesEqual(this.getCurrentState(), this.lastSelectedPreset)
        )
            this.presetsBox.setValue(this.lastSelectedPreset.toString());
        this.presetsBox.onChange(async (value: string) => {
            const chosenPresetNumber = parseInt(value);
            if (chosenPresetNumber == -1) return;
            await this.choosePresetAndUpdateState(chosenPresetNumber);
        });
        let savePreset = new ButtonComponent(this.presetsDivContent);
        savePreset
            .setButtonText('Save as...')
            .setTooltip('Save the current view as a preset.')
            .onClick(() => {
                const dialog = new NewPresetDialog(
                    this.app,
                    this.getCurrentState(),
                    this.plugin,
                    this.settings,
                    (index: string) => {
                        // If a new preset was added, this small function makes sure it's selected afterwards
                        this.refreshPresets();
                        if (index) this.presetsBox.setValue(index);
                    }
                );
                dialog.open();
            });
        let deletePreset = new ButtonComponent(this.presetsDivContent);
        deletePreset
            .setButtonText('Delete')
            .setTooltip('Delete the currently-selected preset.')
            .onClick(async () => {
                const selectionIndex = parseInt(this.presetsBox.getValue());
                if (selectionIndex > 0) {
                    this.settings.savedStates.splice(selectionIndex - 1, 1);
                    await this.plugin.saveSettings();
                    this.refreshPresets();
                }
            });
        let saveAsDefault = new ButtonComponent(this.presetsDivContent);
        saveAsDefault
            .setButtonText('Save as Default')
            .setTooltip('Save the current view as the default one.')
            .onClick(async () => {
                this.settings.defaultState = {
                    ...this.getCurrentState(),
                    name: 'Default',
                };
                await this.plugin.saveSettings();
                this.presetsBox.setValue('0');
            });
        new ButtonComponent(this.presetsDivContent)
            .setButtonText('Copy URL')
            .setTooltip('Copy the current view as a URL.')
            .onClick(async () => {
                this.view.copyStateUrl();
            });
    }
Example #19
Source File: viewControls.ts    From obsidian-map-view with GNU General Public License v3.0 5 votes vote down vote up
createControls() {
        this.controlsDiv = createDiv({
            cls: 'graph-controls',
        });
        let filtersDiv = this.controlsDiv.createDiv({
            cls: 'graph-control-div',
        });
        filtersDiv.innerHTML = `
			<input id="filtersCollapsible" class="controls-toggle" type="checkbox">
			<label for="filtersCollapsible" class="lbl-triangle">â–¸</label>
			<label for="filtersCollapsible" class="lbl-toggle">Filters</label>
			`;
        const filtersButton = filtersDiv.getElementsByClassName(
            'controls-toggle'
        )[0] as HTMLInputElement;
        filtersButton.checked = this.settings.mapControls.filtersDisplayed;
        filtersButton.onclick = async () => {
            this.settings.mapControls.filtersDisplayed = filtersButton.checked;
            this.plugin.saveSettings();
        };
        let filtersContent = filtersDiv.createDiv({
            cls: 'graph-control-content',
        });
        // Wrapping the query box in a div so we can place a button in the right-middle of it
        const queryDiv = filtersContent.createDiv('search-input-container');
        queryDiv.style.margin = '0';
        this.queryBox = new TextComponent(queryDiv);
        this.queryBox.setPlaceholder('Query');
        this.queryBox.onChange((query: string) => {
            this.setStateByQueryString(query);
        });
        let suggestor: QuerySuggest = null;
        this.queryBox.inputEl.addEventListener('focus', (ev: FocusEvent) => {
            if (!suggestor) {
                suggestor = new QuerySuggest(this.app, this.queryBox);
                suggestor.open();
            }
        });
        this.queryBox.inputEl.addEventListener('focusout', (ev: FocusEvent) => {
            if (suggestor) {
                suggestor.close();
                suggestor = null;
            }
        });
        let clearButton = queryDiv.createDiv('search-input-clear-button');
        clearButton.onClickEvent((ev) => {
            this.queryBox.setValue('');
            this.setStateByQueryString('');
        });

        let viewDiv = this.controlsDiv.createDiv({ cls: 'graph-control-div' });
        viewDiv.innerHTML = `
			<input id="viewCollapsible" class="controls-toggle" type="checkbox">
			<label for="viewCollapsible" class="lbl-triangle">â–¸</label>
			<label for="viewCollapsible" class="lbl-toggle">View</label>
			`;
        const viewButton = viewDiv.getElementsByClassName(
            'controls-toggle'
        )[0] as HTMLInputElement;
        viewButton.checked = this.settings.mapControls.viewDisplayed;
        viewButton.onclick = async () => {
            this.settings.mapControls.viewDisplayed = viewButton.checked;
            this.plugin.saveSettings();
        };
        let viewDivContent = viewDiv.createDiv({
            cls: 'graph-control-content',
        });
        this.mapSourceBox = new DropdownComponent(viewDivContent);
        for (const [index, source] of this.settings.mapSources.entries()) {
            this.mapSourceBox.addOption(index.toString(), source.name);
        }
        this.mapSourceBox.onChange(async (value: string) => {
            this.setStateByNewMapSource(parseInt(value));
        });
        this.setMapSourceBoxByState();
        this.sourceMode = new DropdownComponent(viewDivContent);
        this.sourceMode
            .addOptions({ auto: 'Auto', light: 'Light', dark: 'Dark' })
            .setValue(this.settings.chosenMapMode ?? 'auto')
            .onChange(async (value) => {
                this.settings.chosenMapMode = value as MapLightDark;
                await this.plugin.saveSettings();
                this.view.refreshMap();
            });
        let goDefault = new ButtonComponent(viewDivContent);
        goDefault
            .setButtonText('Reset')
            .setTooltip('Reset the view to the defined default.')
            .onClick(async () => {
                this.presetsBox.setValue('0');
                await this.choosePresetAndUpdateState(0);
                this.updateControlsToState();
            });
        let fitButton = new ButtonComponent(viewDivContent);
        fitButton
            .setButtonText('Fit')
            .setTooltip(
                'Set the map view to fit all currently-displayed markers.'
            )
            .onClick(() => this.view.autoFitMapToMarkers());
        const followDiv = viewDivContent.createDiv({
            cls: 'graph-control-follow-div',
        });
        this.followActiveNoteToggle = new ToggleComponent(followDiv);
        const followLabel = followDiv.createEl('label');
        followLabel.className = 'graph-control-follow-label';
        followLabel.addEventListener('click', () =>
            this.followActiveNoteToggle.onClick()
        );
        followLabel.innerHTML = 'Follow active note';
        this.followActiveNoteToggle.onChange((value) => {
            this.setStateByFollowActiveNote(value);
        });

        this.presetsDiv = this.controlsDiv.createDiv({
            cls: 'graph-control-div',
        });
        this.presetsDiv.innerHTML = `
			<input id="presetsCollapsible" class="controls-toggle" type="checkbox">
			<label for="presetsCollapsible" class="lbl-triangle">â–¸</label>
			<label for="presetsCollapsible" class="lbl-toggle">Presets</label>
			`;
        const presetsButton = this.presetsDiv.getElementsByClassName(
            'controls-toggle'
        )[0] as HTMLInputElement;
        presetsButton.checked = this.settings.mapControls.presetsDisplayed;
        presetsButton.onclick = async () => {
            this.settings.mapControls.presetsDisplayed = presetsButton.checked;
            this.plugin.saveSettings();
        };
        this.refreshPresets();

        this.parentElement.append(this.controlsDiv);
    }
Example #20
Source File: MacroBuilder.ts    From quickadd with MIT License 5 votes vote down vote up
private addAddEditorCommandsSetting() {
        let dropdownComponent: DropdownComponent;

        const addEditorCommandFromDropdown = () => {
            const type: EditorCommandType = dropdownComponent.getValue() as EditorCommandType;
            let command: IEditorCommand;

            switch (type) {
                case EditorCommandType.Copy:
                    command = new CopyCommand();
                    break;
                case EditorCommandType.Cut:
                    command = new CutCommand();
                    break;
                case EditorCommandType.Paste:
                    command = new PasteCommand();
                    break;
                case EditorCommandType.SelectActiveLine:
                    command = new SelectActiveLineCommand();
                    break;
                case EditorCommandType.SelectLinkOnActiveLine:
                    command = new SelectLinkOnActiveLineCommand();
                    break;
                default:
                    log.logError("invalid editor command type");
            }

            this.addCommandToMacro(command);
        }

        new Setting(this.contentEl)
            .setName("Editor commands")
            .setDesc("Add editor command")
            .addDropdown(dropdown => {
                dropdownComponent = dropdown;
                dropdown.selectEl.style.marginRight = "1em";
                dropdown.addOption(EditorCommandType.Copy, EditorCommandType.Copy)
                    .addOption(EditorCommandType.Cut, EditorCommandType.Cut)
                    .addOption(EditorCommandType.Paste, EditorCommandType.Paste)
                    .addOption(EditorCommandType.SelectActiveLine, EditorCommandType.SelectActiveLine)
                    .addOption(EditorCommandType.SelectLinkOnActiveLine, EditorCommandType.SelectLinkOnActiveLine);
            })
            .addButton(button => button.setCta().setButtonText("Add").onClick(addEditorCommandFromDropdown));
    }
Example #21
Source File: settings.ts    From folder-note-core with MIT License 5 votes vote down vote up
toOptsEl: DropdownComponent;
Example #22
Source File: view.ts    From obsidian-fantasy-calendar with MIT License 4 votes vote down vote up
buildDateFields() {
        this.dateFieldEl.empty();
        if (
            this.tempCurrentDays != undefined &&
            this.date.month != undefined &&
            this.tempCurrentDays >
                this.calendar.static.months[this.date.month]?.length
        ) {
            this.tempCurrentDays =
                this.calendar.static.months[this.date.month]?.length;
        }
        const dayEl = this.dateFieldEl.createDiv("fantasy-calendar-date-field");
        dayEl.createEl("label", { text: "Day" });
        const day = new TextComponent(dayEl)
            .setPlaceholder("Day")
            .setValue(`${this.tempCurrentDays}`)
            .setDisabled(this.date.month == undefined)
            .onChange((v) => {
                if (
                    Number(v) < 1 ||
                    (Number(v) >
                        this.calendar.static.months[this.date.month]?.length ??
                        Infinity)
                ) {
                    new Notice(
                        `The current day must be between 1 and ${
                            this.calendar.static.months[this.date.month].length
                        }`
                    );
                    this.tempCurrentDays = this.date.day;
                    this.buildDateFields();
                    return;
                }
                this.tempCurrentDays = Number(v);
            });
        day.inputEl.setAttr("type", "number");

        const monthEl = this.dateFieldEl.createDiv(
            "fantasy-calendar-date-field"
        );
        monthEl.createEl("label", { text: "Month" });
        new DropdownComponent(monthEl)
            .addOptions(
                Object.fromEntries([
                    ["select", "Select Month"],
                    ...this.calendar.static.months.map((month) => [
                        month.name,
                        month.name
                    ])
                ])
            )
            .setValue(
                this.date.month != undefined
                    ? this.calendar.static.months[this.date.month].name
                    : "select"
            )
            .onChange((v) => {
                if (v === "select") this.date.month = null;
                const index = this.calendar.static.months.find(
                    (m) => m.name == v
                );
                this.date.month = this.calendar.static.months.indexOf(index);
                this.buildDateFields();
            });

        const yearEl = this.dateFieldEl.createDiv(
            "fantasy-calendar-date-field"
        );
        yearEl.createEl("label", { text: "Year" });
        if (this.calendar.static.useCustomYears) {
            const yearDrop = new DropdownComponent(yearEl);
            (this.calendar.static.years ?? []).forEach((year) => {
                yearDrop.addOption(year.id, year.name);
            });
            if (this.date.year > this.calendar.static.years?.length) {
                this.date.year = this.calendar.static.years
                    ? this.calendar.static.years.length
                    : null;
            }
            yearDrop
                .setValue(this.calendar.static.years?.[this.date.year - 1]?.id)
                .onChange((v) => {
                    this.date.year =
                        this.calendar.static.years.findIndex((y) => y.id == v) +
                        1;
                });
        } else {
            const year = new TextComponent(yearEl)
                .setPlaceholder("Year")
                .setValue(`${this.date.year}`)
                .onChange((v) => {
                    this.date.year = Number(v);
                });
            year.inputEl.setAttr("type", "number");
        }
    }
Example #23
Source File: FilteredFolderModal.ts    From obsidian-rss with GNU General Public License v3.0 4 votes vote down vote up
async display() : Promise<void> {
        const { contentEl } = this;

        contentEl.empty();

        let nameText: TextComponent;
        const name = new Setting(contentEl)
            .setName(t("name"))
            .setDesc(t("filter_name_help"))
            .addText((text) => {
                nameText = text;
                text.setValue(this.name)
                    .onChange((value) => {
                        this.removeValidationError(text);
                        this.name = value;
                    });
            });
        name.controlEl.addClass("rss-setting-input");

        new Setting(contentEl)
            .setName(t("only_favorites"))
            .addToggle(toggle => {
                toggle
                    .setValue(this.favorites)
                    .onChange(value => {
                        this.favorites = value;
                    });
            });

        new Setting(contentEl)
            .setName(t("show_read"))
            .addToggle(toggle => {
                toggle
                    .setValue(this.read)
                    .onChange(value => {
                        this.read = value;
                    });
            });

        new Setting(contentEl)
            .setName(t("show_unread"))
            .addToggle(toggle => {
                toggle
                    .setValue(this.unread)
                    .onChange(value => {
                        this.unread = value;
                    });
            });

        const sorting = new Setting(contentEl)
            .setName(t("sort"))
            .addDropdown((dropdown: DropdownComponent) => {
                for(const order in SortOrder) {
                    if(order.length > 1) {
                        // @ts-ignore
                        dropdown.addOption(order, t("sort_" + order.toLowerCase()));
                    }
                }

                dropdown
                    .setValue(this.sortOrder)
                    .onChange(async (value: string) => {
                        this.sortOrder = value;
                    });
            });
        sorting.controlEl.addClass("rss-setting-input");

        //folders
        const foldersDiv = contentEl.createDiv("folders");
        foldersDiv.createEl("h2", {text: t("folders")});
        foldersDiv.createEl("p", {text: t("filter_folder_help")});

        for (const folder in this.filterFolders) {
            new Setting(foldersDiv)
                .addSearch(async (search: SearchComponent) => {
                    new ArraySuggest(this.app, search.inputEl, get(folderStore));
                    search
                        .setValue(this.filterFolders[folder])
                        .onChange(async (value: string) => {
                            this.removeValidationError(search);
                            this.filterFolders = this.filterFolders.filter(e => e !== this.filterFolders[folder]);
                            this.filterFolders.push(value);
                        });
                })
                .addExtraButton((button) => {
                    button
                        .setTooltip(t("delete"))
                        .setIcon("feather-trash")
                        .onClick(() => {
                            this.filterFolders = this.filterFolders.filter(e => e !== this.filterFolders[folder]);
                            this.display();
                        });

                });
        }

        let folderValue = "";
        const newFolder = new Setting(foldersDiv)
            .addSearch(async (search: SearchComponent) => {
                new ArraySuggest(this.app, search.inputEl, get(folderStore));
                search
                    .onChange(async (value: string) => {
                        folderValue = value;
                    });
            }).addExtraButton(button => {
                button
                    .setTooltip(t("add"))
                    .setIcon("plus")
                    .onClick(() => {
                        this.filterFolders.push(folderValue);
                        this.display();
                    });
            });
        newFolder.controlEl.addClass("rss-setting-input");

        foldersDiv.createEl("p", {text: t("filter_folder_ignore_help")});

        //ignore folders
        for (const folder in this.ignoreFolders) {
            new Setting(foldersDiv)
                .addSearch(async (search: SearchComponent) => {
                    new ArraySuggest(this.app, search.inputEl, get(folderStore));
                    search
                        .setValue(this.ignoreFolders[folder])
                        .onChange(async (value: string) => {
                            this.removeValidationError(search);
                            this.ignoreFolders = this.ignoreFolders.filter(e => e !== this.ignoreFolders[folder]);
                            this.ignoreFolders.push(value);
                        });
                })
                .addExtraButton((button) => {
                    button
                        .setTooltip(t("delete"))
                        .setIcon("trash")
                        .onClick(() => {
                            this.ignoreFolders = this.ignoreFolders.filter(e => e !== this.ignoreFolders[folder]);
                            this.display();
                        });

                });
        }

        let folderIgnoreValue = "";
        const newIgnoreFolder = new Setting(foldersDiv)
            .addSearch(async (search: SearchComponent) => {
                new ArraySuggest(this.app, search.inputEl, get(folderStore));
                search
                    .onChange(async (value: string) => {
                        folderIgnoreValue = value;
                    });
            }).addExtraButton(button => {
                button
                    .setTooltip(t("add"))
                    .setIcon("plus")
                    .onClick(() => {
                        this.ignoreFolders.push(folderIgnoreValue);
                        this.display();
                    });
            });
        newIgnoreFolder.controlEl.addClass("rss-setting-input");


        //feeds
        const feedsDiv = contentEl.createDiv("feeds");
        feedsDiv.createEl("h2", {text: t("feeds")});
        feedsDiv.createEl("p", {text: t("filter_feed_help")});

        const feeds = this.plugin.settings.feeds.filter(feed => {
            if(this.filterFolders.length === 0)
                return true;
            return this.filterFolders.contains(feed.folder);
        }).map((feed) => feed.name);

        for (const feed in this.filterFeeds) {
            new Setting(feedsDiv)
                .addSearch(async (search: SearchComponent) => {
                    new ArraySuggest(this.app, search.inputEl, new Set(feeds));
                    search
                        .setValue(this.filterFeeds[feed])
                        .onChange(async (value: string) => {
                            this.removeValidationError(search);
                            this.filterFeeds = this.filterFeeds.filter(e => e !== this.filterFeeds[feed]);
                            this.filterFeeds.push(value);
                        });
                })
                .addExtraButton((button) => {
                    button
                        .setTooltip(t("delete"))
                        .setIcon("trash")
                        .onClick(() => {
                            this.filterFeeds = this.filterFeeds.filter(e => e !== this.filterFeeds[feed]);
                            this.display();
                        });

                });
        }

        let feedValue = "";
        const newFeed = new Setting(feedsDiv)
            .addSearch(async (search: SearchComponent) => {
                new ArraySuggest(this.app, search.inputEl, new Set(feeds));
                search
                    .onChange(async (value: string) => {
                        feedValue = value;
                    });
            }).addExtraButton(button => {
                button
                    .setTooltip(t("add"))
                    .setIcon("plus")
                    .onClick(() => {
                        this.filterFeeds.push(feedValue);
                        this.display();
                    });
            });
        newFeed.controlEl.addClass("rss-setting-input");

        feedsDiv.createEl("p", {text: t("filter_feed_ignore_help")});

        //ignore feeds
        for (const folder in this.ignoreFeeds) {
            new Setting(feedsDiv)
                .addSearch(async (search: SearchComponent) => {
                    new ArraySuggest(this.app, search.inputEl, new Set(feeds));
                    search
                        .setValue(this.ignoreFeeds[folder])
                        .onChange(async (value: string) => {
                            this.removeValidationError(search);
                            this.ignoreFeeds = this.ignoreFeeds.filter(e => e !== this.ignoreFeeds[folder]);
                            this.ignoreFeeds.push(value);
                        });
                })
                .addExtraButton((button) => {
                    button
                        .setTooltip(t("delete"))
                        .setIcon("trash")
                        .onClick(() => {
                            this.ignoreFeeds = this.ignoreFeeds.filter(e => e !== this.ignoreFeeds[folder]);
                            this.display();
                        });

                });
        }

        let feedIgnoreValue = "";
        const newIgnoreFeed = new Setting(feedsDiv)
            .addSearch(async (search: SearchComponent) => {
                new ArraySuggest(this.app, search.inputEl, new Set(feeds));
                search
                    .onChange(async (value: string) => {
                        feedIgnoreValue = value;
                    });
            }).addExtraButton(button => {
                button
                    .setTooltip(t("add"))
                    .setIcon("plus")
                    .onClick(() => {
                        this.ignoreFeeds.push(feedIgnoreValue);
                        this.display();
                    });
            });
        newIgnoreFeed.controlEl.addClass("rss-setting-input");

        //tags
        const tagDiv = contentEl.createDiv("tags");
        tagDiv.createEl("h2", {text: t("tags")});
        tagDiv.createEl("p", {text: t("filter_tags_help")});

        for (const tag in this.filterTags) {
            new Setting(tagDiv)
                .addSearch(async (search: SearchComponent) => {
                    new ArraySuggest(this.app, search.inputEl, get(tagsStore));
                    search
                        .setValue(this.filterTags[tag])
                        .onChange(async (value: string) => {
                            this.removeValidationError(search);
                            if (!value.match(TAG_REGEX) || value.match(NUMBER_REGEX) || value.contains(" ") || value.contains('#')) {
                                this.setValidationError(search, t("invalid_tag"));
                                return;
                            }
                            this.filterTags = this.filterTags.filter(e => e !== this.filterTags[tag]);
                            this.filterTags.push(value);
                        });
                })
                .addExtraButton((button) => {
                    button
                        .setTooltip(t("delete"))
                        .setIcon("trash")
                        .onClick(() => {
                            this.filterTags = this.filterTags.filter(e => e !== this.filterTags[tag]);
                            this.display();
                        });

                });
        }

        let tagValue = "";
        let tagComponent: SearchComponent;
        const newTag = new Setting(tagDiv)
            .addSearch(async (search: SearchComponent) => {
                tagComponent = search;
                new ArraySuggest(this.app, search.inputEl, get(tagsStore));
                search
                    .onChange(async (value: string) => {
                        if (!value.match(TAG_REGEX) || value.match(NUMBER_REGEX) || value.contains(" ") || value.contains('#')) {
                            this.setValidationError(search, t("invalid_tag"));
                            return;
                        }
                        tagValue = value;
                    });
            }).addExtraButton(button => {
                button
                    .setTooltip(t("add"))
                    .setIcon("plus")
                    .onClick(() => {
                        if (!tagValue.match(TAG_REGEX) || tagValue.match(NUMBER_REGEX) || tagValue.contains(" ") || tagValue.contains('#')) {
                            this.setValidationError(tagComponent, t("invalid_tag"));
                            return;
                        }
                        this.filterTags.push(tagValue);
                        this.display();
                    });
            });
        newTag.controlEl.addClass("rss-setting-input");

        tagDiv.createEl("p", {text: t("filter_tags_ignore_help")});

        for (const tag in this.ignoreTags) {
            new Setting(tagDiv)
                .addSearch(async (search: SearchComponent) => {
                    new ArraySuggest(this.app, search.inputEl, get(tagsStore));
                    search
                        .setValue(this.ignoreTags[tag])
                        .onChange(async (value: string) => {
                            this.removeValidationError(search);
                            if (!value.match(TAG_REGEX) || value.match(NUMBER_REGEX) || value.contains(" ") || value.contains('#')) {
                                this.setValidationError(search, t("invalid_tag"));
                                return;
                            }
                            this.ignoreTags = this.ignoreTags.filter(e => e !== this.ignoreTags[tag]);
                            this.ignoreTags.push(value);
                        });
                })
                .addExtraButton((button) => {
                    button
                        .setTooltip(t("delete"))
                        .setIcon("trash")
                        .onClick(() => {
                            this.ignoreTags = this.ignoreTags.filter(e => e !== this.ignoreTags[tag]);
                            this.display();
                        });

                });
        }

        let ignoreTagValue = "";
        let ignoreTagComponent: SearchComponent;
        const newTagIgnore = new Setting(tagDiv)
            .addSearch(async (search: SearchComponent) => {
                ignoreTagComponent = search;
                new ArraySuggest(this.app, search.inputEl, get(tagsStore));
                search
                    .onChange(async (value: string) => {
                        if (!value.match(TAG_REGEX) || value.match(NUMBER_REGEX) || value.contains(" ") || value.contains('#')) {
                            this.setValidationError(search, t("invalid_tag"));
                            return;
                        }
                        ignoreTagValue = value;
                    });
            }).addExtraButton(button => {
                button
                    .setTooltip(t("add"))
                    .setIcon("plus")
                    .onClick(() => {
                        if (!ignoreTagValue.match(TAG_REGEX) || ignoreTagValue.match(NUMBER_REGEX) || ignoreTagValue.contains(" ") || ignoreTagValue.contains('#')) {
                            this.setValidationError(ignoreTagComponent, t("invalid_tag"));
                            return;
                        }
                        this.ignoreTags.push(ignoreTagValue);
                        this.display();
                    });
            });
        newTagIgnore.controlEl.addClass("rss-setting-input");


        //save & cancel

        const footerEl = contentEl.createDiv();
        const footerButtons = new Setting(footerEl);
        footerButtons.addButton((b) => {
            b.setTooltip(t("save"))
                .setIcon("checkmark")
                .onClick(async () => {
                    let error = false;
                    if(!nameText.getValue().length) {
                        this.setValidationError(nameText, t("invalid_name"));
                        error = true;
                    }

                    if(error) {
                        new Notice(t("fix_errors"));
                        return;
                    }
                    this.saved = true;
                    this.close();
                });
            return b;
        });
        footerButtons.addExtraButton((b) => {
            b.setIcon("cross")
                .setTooltip(t("cancel"))
                .onClick(() => {
                    this.saved = false;
                    this.close();
                });
            return b;
        });
    }
Example #24
Source File: settings-tab.ts    From better-word-count with MIT License 4 votes vote down vote up
display(): void {
    let { containerEl } = this;

    containerEl.empty();
    containerEl.createEl("h2", { text: "Better Word Count Settings" });

    // General Settings
    containerEl.createEl("h3", { text: "General Settings" });
    new Setting(containerEl)
      .setName("Collect Statistics")
      .setDesc(
        "Reload Required for change to take effect. Turn on to start collecting daily statistics of your writing. Stored in the .vault-stats file in the root of your vault. This is required for counts of the day."
      )
      .addToggle((cb: ToggleComponent) => {
        cb.setValue(this.plugin.settings.collectStats);
        cb.onChange(async (value: boolean) => {
          this.plugin.settings.collectStats = value;
          await this.plugin.saveSettings();
        });
      });
    new Setting(containerEl)
      .setName("Don't Count Comments")
      .setDesc("Turn on if you don't want markdown comments to be counted.")
      .addToggle((cb: ToggleComponent) => {
        cb.setValue(this.plugin.settings.countComments);
        cb.onChange(async (value: boolean) => {
          this.plugin.settings.countComments = value;
          await this.plugin.saveSettings();
        });
      });

    // Status Bar Settings
    containerEl.createEl("h3", { text: "Status Bar Settings" });
    new Setting(containerEl)
      .setName("Select a Preset")
      .setDesc(
        "Presets are premade status bar expressions. Overides status bar settings."
      )
      .addDropdown((cb: DropdownComponent) => {
        PRESETS.forEach((preset: PresetOption) => {
          cb.addOption(preset.name, preset.name);
        });
        cb.setValue(this.plugin.settings.preset.name);

        cb.onChange(async (value: string) => {
          let newPreset = PRESETS.find((preset) => preset.name === value);
          this.plugin.settings.preset = newPreset;
          this.plugin.settings.statusBarQuery = newPreset.statusBarQuery;
          this.plugin.settings.statusBarAltQuery = newPreset.statusBarAltQuery;
          await this.plugin.saveSettings();
        });
      });
    new Setting(containerEl)
      .setName("Status Bar Text")
      .setDesc("Customize the Status Bar text with this.")
      .addTextArea((cb: TextAreaComponent) => {
        cb.setPlaceholder("Enter an expression...");
        cb.setValue(this.plugin.settings.statusBarQuery);
        cb.onChange((value: string) => {
          let newPreset = PRESETS.find((preset) => preset.name === "custom");
          this.plugin.settings.preset = newPreset;
          this.plugin.settings.statusBarQuery = value;
          this.plugin.saveSettings();
        });
      });
    new Setting(containerEl)
      .setName("Alternative Status Bar Text")
      .setDesc("Customize the Alternative Status Bar text with this.")
      .addTextArea((cb: TextAreaComponent) => {
        cb.setPlaceholder("Enter an expression...");
        cb.setValue(this.plugin.settings.statusBarAltQuery);
        cb.onChange((value: string) => {
          let newPreset = PRESETS.find((preset) => preset.name === "custom");
          this.plugin.settings.preset = newPreset;
          this.plugin.settings.statusBarAltQuery = value;
          this.plugin.saveSettings();
        });
      });

    this.containerEl.createEl("h3", {
      text: "Syntax for the status bars works like this: ",
    });

    this.containerEl.createEl("li", {
      text: "To get a stat input the name of the stat in between `{}` eg. `{word_count}`.",
    });

    this.containerEl.createEl("li", {
      text: "All other words remain.",
    });

    this.containerEl.createEl("br");

    this.containerEl.createEl("h4", {
      text: "Available Stats:",
    });

    this.containerEl.createEl("p", {
      text:
        "word_count, " +
        "character_count, " +
        "sentence_count, " +
        "total_word_count, " +
        "total_character_count, " +
        "total_sentence_count, " +
        "file_count, " +
        "words_today, " +
        "characters_today, " +
        "sentences_today, ",
    });
  }
Example #25
Source File: FileClassAttributeModal.ts    From obsidian_supercharged_links with MIT License 4 votes vote down vote up
onOpen(){
        //title
        this.titleEl.setText(this.attr ? `Manage ${this.attr.name}` : `Create a new attribute for ${this.fileClass.name}`)
        
        //name input
        const nameInputContainer = this.contentEl.createDiv()
        nameInputContainer.setText("name")
        const nameInput = new TextComponent(nameInputContainer)
        this.attr ? nameInput.setValue(this.attr.name) : nameInput.setPlaceholder("Type a name for this attribute")

        //header for select
        const typeSelectHeader = this.contentEl.createDiv()
        const attrLine = typeSelectHeader.createEl("div")
        const attrName = attrLine.createEl("strong")
        attrName.setText(`<${this.name}>`)
        attrLine.append(" fields in files with:")
        String(`---\nfileClass: ${this.fileClass.name}\n...\n---`).split('\n').forEach(line => {
            typeSelectHeader.createEl("div", "yaml-frontmatter-red").setText(line)
        })

        // type select
        const typeSelectContainer = this.contentEl.createDiv({cls: 'frontmatter-value-selector-container'})
        const typeSelectLabel = typeSelectContainer.createDiv({cls: 'frontmatter-value-selector-inline-label'})
        typeSelectLabel.setText("will: ")
        const typeSelectDropDown = typeSelectContainer.createDiv({cls: 'frontmatter-value-selector-toggler'})
        const typeSelect = new DropdownComponent(typeSelectDropDown)
        Object.keys(types).forEach(key => {
            typeSelect.addOption(key, types[key])
        })
        if(this.attr){
            typeSelect.setValue(this.type)
        }

        // options input
        const optionsInputContainer = this.contentEl.createDiv({cls: 'frontmatter-value-selector-container'})
        const optionsInputLabel = optionsInputContainer.createDiv({cls: 'frontmatter-value-selector-inline-label-top'})
        optionsInputLabel.setText("Values")
        const optionsInput = new TextAreaComponent(optionsInputContainer)
        optionsInput.inputEl.rows = 3
        optionsInput.inputEl.cols = 26
        this.attr ? optionsInput.setValue(this.type == "input" ? "" : this.options.join(", ")) : optionsInput.setPlaceholder("insert values, comma separated")
        !this.attr || this.type == "input" ? optionsInputContainer.hide() : optionsInputContainer.show()

        // event handlers
        typeSelect.onChange(type => {
            type == "input" ? optionsInputContainer.hide() : optionsInputContainer.show()
            this.type = type
        })
        optionsInput.onChange(value => this.options = value.split(",").map(item => item.trim()))
        nameInput.onChange(value => {this.name = value; attrName.setText(`<${value}>`)})

        // footer buttons
        const footer = this.contentEl.createDiv({cls: "frontmatter-value-grid-footer"})
        const saveButton = new ButtonComponent(footer)
        saveButton.setIcon("checkmark")
        saveButton.onClick(() => {
            this.fileClass.updateAttribute(this.type, this.options, this.name, this.attr)
            this.close()
        })
        if(this.attr){
            const removeButton = new ButtonComponent(footer)
            removeButton.setIcon("trash")
            removeButton.onClick(() => {
                const confirmModal = new Modal(this.app)
                confirmModal.titleEl.setText("Please confirm")
                confirmModal.contentEl.createDiv().setText(`Do you really want to remove ${this.attr.name} attribute from ${this.fileClass.name}?`)
                const confirmFooter = confirmModal.contentEl.createDiv({cls: "frontmatter-value-grid-footer"})
                const confirmButton = new ButtonComponent(confirmFooter)
                confirmButton.setIcon("checkmark")
                confirmButton.onClick(() => {
                    this.fileClass.removeAttribute(this.attr)
                    confirmModal.close()
                    this.close()
                })
                const dismissButton = new ExtraButtonComponent(confirmFooter)
                dismissButton.setIcon("cross")
                dismissButton.onClick(() => this.close())
                confirmModal.open()
            })
        }
        const cancelButton = new ExtraButtonComponent(footer)
        cancelButton.setIcon("cross")
        cancelButton.onClick(() => this.close())
    }
Example #26
Source File: settingsTab.ts    From obsidian-map-view with GNU General Public License v3.0 4 votes vote down vote up
refreshUrlParsingRules(containerEl: HTMLElement) {
        containerEl.innerHTML = '';
        const parsingRules = this.plugin.settings.urlParsingRules;
        // Make sure that the default settings are included. That's because I'll want to add more parsing
        // rules in the future, and I want existing users to receive them
        for (const defaultSetting of DEFAULT_SETTINGS.urlParsingRules)
            if (
                parsingRules.findIndex(
                    (rule) => rule.name === defaultSetting.name
                ) === -1
            ) {
                parsingRules.push(defaultSetting);
                this.plugin.saveSettings();
            }
        for (const setting of parsingRules) {
            const parsingRuleDiv = containerEl.createDiv('parsing-rule');
            const line1 = parsingRuleDiv.createDiv('parsing-rule-line-1');
            let line2: HTMLDivElement = null;
            let adjustToRuleType = (ruleType: UrlParsingRuleType) => {
                text.setPlaceholder(
                    ruleType === 'fetch'
                        ? 'Regex with 1 capture group'
                        : 'Regex with 2 capture groups'
                );
                if (line2)
                    line2.style.display =
                        ruleType === 'fetch' ? 'block' : 'none';
            };
            const controls = new Setting(line1).addText((component) => {
                component
                    .setPlaceholder('Name')
                    .setValue(setting.name)
                    .onChange(async (value: string) => {
                        setting.name = value;
                        await this.plugin.saveSettings();
                    });
            });
            const text = new TextComponent(controls.controlEl);
            text.setValue(setting.regExp).onChange(async (value: string) => {
                setting.regExp = value;
                await this.plugin.saveSettings();
            });
            controls.addDropdown((component) =>
                component
                    .addOption('latLng', '(lat)(lng)')
                    .addOption('lngLat', '(lng)(lat)')
                    .addOption('fetch', 'fetch')
                    .setValue(setting.ruleType ?? 'latLng')
                    .onChange(async (value: UrlParsingRuleType) => {
                        setting.ruleType = value;
                        adjustToRuleType(value);
                        await this.plugin.saveSettings();
                    })
                    .selectEl.addClass('url-rule-dropdown')
            );
            controls.settingEl.style.padding = '0px';
            controls.settingEl.style.borderTop = 'none';
            if (!setting.preset)
                controls.addButton((component) =>
                    component.setButtonText('Delete').onClick(async () => {
                        this.plugin.settings.urlParsingRules.remove(setting);
                        await this.plugin.saveSettings();
                        this.refreshUrlParsingRules(containerEl);
                    })
                );
            line2 = parsingRuleDiv.createDiv('parsing-rule-line-2');
            adjustToRuleType(setting.ruleType);
            const contentLabel = line2.createEl('label');
            contentLabel.setText('Content parsing expression:');
            contentLabel.style.paddingRight = '10px';
            new TextComponent(line2)
                .setPlaceholder('Regex with 1-2 capture groups')
                .setValue(setting.contentParsingRegExp)
                .onChange(async (value) => {
                    setting.contentParsingRegExp = value;
                    await this.plugin.saveSettings();
                });
            new DropdownComponent(line2)
                .addOption('latLng', '(lat)(lng)')
                .addOption('lngLat', '(lng)(lat)')
                .addOption('googlePlace', '(google-place)')
                .setValue(setting.contentType ?? 'latLng')
                .onChange(async (value) => {
                    setting.contentType = value as UrlParsingContentType;
                    await this.plugin.saveSettings();
                });
        }
    }