diff --git a/main.ts b/main.ts index 7b4db4a..dec359b 100644 --- a/main.ts +++ b/main.ts @@ -1,13 +1,14 @@ import { Plugin } from 'obsidian'; -import { Generator } from '@types/core-js'; - +import { TableSortSettings, TableSortSettingsTab, DEFAULT_SETTINGS} from "./src/settings"; import { Table } from "./src/table"; -import { Column } from "./src/column"; +import { getMousedownHandler } from "./src/mouseHandler" + export default class TableSort extends Plugin { + static settings: TableSortSettings; storage: Table[] = []; - gen: Generator; + gen: any; * autoIncrement() { let index = 0; @@ -16,16 +17,16 @@ export default class TableSort extends Plugin { } } - private getTableElement(th: HTMLElement): HTMLTableElement | undefined { + getTableElement(th: HTMLElement): HTMLTableElement | undefined { return th.closest("table") || undefined; } - private getTableID(table: HTMLElement): number { - const id = table.getAttribute("id")?.replace("table-", ""); + getTableID(table: HTMLElement): number { + const id = table.getAttribute("id") ?.replace("table-", ""); return (id) ? parseInt(id) : this.gen.next().value; } - private hasCustomClasses(table: HTMLElement): boolean { + hasCustomClasses(table: HTMLElement): boolean { const classes = table.getAttribute("class") || ""; if (classes.length > 0) { return true; @@ -33,56 +34,42 @@ export default class TableSort extends Plugin { return false; } - private isNewTable(id: number): boolean { + isNewTable(id: number): boolean { // Return true if the user has selected a new table return (this.storage.length - 1 >= id) ? false : true; } - async onload() { - // If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin) - // Using this function will automatically remove the event listener when this plugin is disabled. - this.gen = this.autoIncrement(); - this.storage = []; - - this.registerDomEvent(document, 'click', (evt: MouseEvent) => { - if (evt.target == null) { - return; - } - const element: HTMLElement = evt.target as HTMLElement; - - if (element.tagName !== "TH") { - return; - } - - evt.preventDefault(); - - const tableElement: HTMLTableElement | undefined = this.getTableElement(element); - if (!tableElement || this.hasCustomClasses(tableElement)) { - return; - } + async loadSettings() { + TableSort.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); + } + + static log(out?: any, ...optionalParams: any[]): void { + if (this.settings.isDevmodeEnabled === false) { + return; + } + console.log(out, optionalParams); + } - const tableID: number = this.getTableID(tableElement); + async saveSettings() { + await this.saveData(TableSort.settings); + } - let table; - if (this.isNewTable(tableID)) { - table = new Table(tableID, tableElement); - this.storage.push(table); - } else { - table = this.storage[tableID]; - } + async onload() { + await this.loadSettings(); + this.addSettingTab(new TableSortSettingsTab(this.app, this)); - const columnIndex = table.getColumnIndex(element); - const column: Column = table.getColumnDataAt(columnIndex); + this.gen = this.autoIncrement(); + this.storage = []; - table.handleClick(column, evt.ctrlKey == true); - table.sort(); - }, { capture: true }); + const mousedownHandler = getMousedownHandler(this); + this.registerDomEvent(document, 'click', mousedownHandler, { + capture: true + }); - // When registering intervals, this function will automatically clear the interval when the plugin is disabled. - // this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); + console.log("( obsidian-table-sorting ) Plugin has finished loading."); } onunload() { - + this.storage = []; } } diff --git a/manifest.json b/manifest.json index b611c9d..4d8fb4f 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "table-sorting", "name": "Table Sorting", - "version": "1.2.0", + "version": "1.3.0", "minAppVersion": "0.15.0", "description": "This plugin allows you to sort tables by clicking on the respective table head.", "author": "kraibse", diff --git a/package.json b/package.json index 77a6711..6eb1e1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "table-sorting", - "version": "1.2.0", + "version": "1.3.0", "description": "This is a sample plugin for Obsidian (https://obsidian.md)", "main": "main.js", "scripts": { @@ -12,17 +12,15 @@ "author": "", "license": "MIT", "devDependencies": { + "@types/core-js": "^2.5.5", "@types/node": "^16.11.6", "@typescript-eslint/eslint-plugin": "5.29.0", "@typescript-eslint/parser": "5.29.0", "builtin-modules": "3.3.0", + "core-js": "^3.30.2", "esbuild": "0.14.47", "obsidian": "latest", "tslib": "2.4.0", "typescript": "4.7.4" - }, - "dependencies": { - "@types/core-js": "^2.5.5", - "core-js": "^3.28.0" } } diff --git a/src/column.ts b/src/column.ts index c2483dd..7f63173 100644 --- a/src/column.ts +++ b/src/column.ts @@ -1,3 +1,5 @@ +import TableSort from "../main"; + export class Column { id: number; order: string; @@ -33,7 +35,7 @@ export class Column { } setLabel (label: string) { - console.log("Setting '" + this.getName() + "' to " + label, this.order); + TableSort.log("Setting '" + this.getName() + "' to " + label, this.order); this.element.setAttribute('data-content', label); } diff --git a/src/mouseHandler.ts b/src/mouseHandler.ts new file mode 100644 index 0000000..3ea4f27 --- /dev/null +++ b/src/mouseHandler.ts @@ -0,0 +1,39 @@ +import TableSort from "../main"; +import { Table } from "./table"; +import { Column } from "./column"; + + +export function getMousedownHandler(plugin: TableSort) { + return async (evt: MouseEvent) => { + + if (evt.target == null) { + return; + } + const element: HTMLElement = evt.target as HTMLElement; + if (element.tagName !== "TH") { + return; + } + const tableElement: HTMLTableElement | undefined = plugin.getTableElement(element); + if (!tableElement || plugin.hasCustomClasses(tableElement)) { + return; + } + + evt.preventDefault(); + + const tableID: number = plugin.getTableID(tableElement); + + let table; + if (plugin.isNewTable(tableID)) { + table = new Table(tableID, tableElement, plugin); + plugin.storage.push(table); + } else { + table = plugin.storage[tableID]; + } + + const columnIndex = table.getColumnIndex(element); + const column: Column = table.getColumnDataAt(columnIndex); + + table.handleClick(column, evt.ctrlKey == true); + table.sort(); + } +} diff --git a/src/settings.ts b/src/settings.ts new file mode 100644 index 0000000..a19e92f --- /dev/null +++ b/src/settings.ts @@ -0,0 +1,60 @@ +import TableSort from "main"; +import { App, PluginSettingTab, Setting } from "obsidian"; + + +export interface TableSortSettings { + isEnabled: boolean; + isDevmodeEnabled: boolean; +} + +export const DEFAULT_SETTINGS: Partial = { + isEnabled: true, + isDevmodeEnabled: false, +} + + +export class TableSortSettingsTab extends PluginSettingTab { + plugin: TableSort; + + constructor(app: App, plugin: TableSort) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + const { containerEl } = this; + containerEl.empty(); + + const general_heading = containerEl.createEl("div"); + general_heading.createEl("h2", { text: "General Settings" }); + + new Setting(containerEl) + .setName("Toggle table sorting") + .setDesc("This toggles the activation state of this plugin.") + .addToggle((toggle) => { + toggle + .setDisabled(false) + .setValue(TableSort.settings.isEnabled) + .onChange(async (value) => { + TableSort.settings.isEnabled = value; + await this.plugin.saveSettings(); + }) + }); + + const developer_heading = containerEl.createEl("div"); + developer_heading.createEl("h2", { text: "Developer Settings" }); + + new Setting(containerEl) + .setName("Developer mode") + .setDesc("This enables development logging in the console.") + .addToggle((toggle) => { + toggle + .setDisabled(false) + .setValue(TableSort.settings.isDevmodeEnabled) + .onChange(async (value) => { + TableSort.settings.isDevmodeEnabled = value; + await this.plugin.saveSettings(); + }) + }); + } +} \ No newline at end of file diff --git a/src/table.ts b/src/table.ts index 3f503ad..07ce5fb 100644 --- a/src/table.ts +++ b/src/table.ts @@ -1,18 +1,24 @@ +import TableSort from "../main"; import { Column } from "./column"; export class Table { id: number; column: number; + plugin: TableSort; + filters: Column[]; element: HTMLElement; currentOrder: HTMLElement[]; originalOrder: HTMLElement[]; - columns: Column[] = []; + columns: Column[]; - constructor(id: number, element: HTMLTableElement) { + constructor(id: number, element: HTMLTableElement, plugin: TableSort) { this.id = id || 0; this.element = element; + this.plugin = plugin; + this.filters = []; + this.columns = []; this.column = -1; this.filters = []; element.setAttribute("id", id.toString()); @@ -71,9 +77,9 @@ export class Table { this._updateLabels(); } - fillTable(table: HTMLElement, rows: HTMLElement[]): void { - rows.forEach((row) => { - table.querySelector("tbody")?.appendChild(row); + fillTable(): void { + this.currentOrder.forEach((row) => { + this.element.querySelector("tbody")?.appendChild(row); }); } @@ -136,17 +142,18 @@ export class Table { } return 0; }; - + if (this.filters.length == 0) { this.currentOrder = this.originalOrder; } else { this.currentOrder = Array.from(this.currentOrder).sort((rowA, rowB) => { return compareRows(rowA, rowB); }); + TableSort.log("[obsidian-table-sorting] sort() - Finished sorting trows.") } // this.removeRows(); - this.fillTable(this.element, this.currentOrder); + this.fillTable(); } updateElement() { diff --git a/styles.css b/styles.css index d501569..57968cd 100644 --- a/styles.css +++ b/styles.css @@ -11,6 +11,11 @@ If your plugin does not need CSS, delete this file. --text-color: #fff; } +/* @media (hover: hover) */ +.markdown-source-view.mod-cm6 .cm-embed-block:hover { + /* box-shadow: none; */ +} + tbody tr:hover { background-color: #444654 !important; color: white; @@ -31,11 +36,14 @@ th::after { /* : 0.8rem; */ } +table:not([class]) th { + background-color: #1a1e24 !important; + padding: 0.4rem 0.8rempx; +} + table:not([class]) th::before, table th.neutral::before { - width: 24; - height: 24; - - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='gray' stroke='gray' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='11 17 7 21 3 17'%3E%3C/polyline%3E%3Cline x1='7' y1='21' x2='7' y2='9'%3E%3C/line%3E%3Cpolyline points='21 7 17 3 13 7'%3E%3C/polyline%3E%3Cline x1='17' y1='15' x2='17' y2='3'%3E%3C/line%3E%3C/svg%3E"); + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 19' fill='gray' stroke='gray' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='11 17 7 21 3 17'%3E%3C/polyline%3E%3Cline x1='7' y1='21' x2='7' y2='9'%3E%3C/line%3E%3Cpolyline points='21 7 17 3 13 7'%3E%3C/polyline%3E%3Cline x1='17' y1='15' x2='17' y2='3'%3E%3C/line%3E%3C/svg%3E"); + color: gray !important; } table:not([class]) th.ascending::before { @@ -59,14 +67,15 @@ table:not([class]) th.neutral::before, table:not([class]) th.descending::before, table:not([class]) th.ascending::before { cursor: pointer; - /* color: white; */ fill: white; + vertical-align: middle; } -table:not([class]) th, +/* table:not([class]) th, */ table:not([class]) th.neutral::after, table:not([class]) th.descending::after, table:not([class]) th.ascending::after { margin-left: 0.8rem; - content: attr(data-content) + content: attr(data-content); + color: var(--text-muted); } \ No newline at end of file diff --git a/versions.json b/versions.json index 8846fba..d00e8c3 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,6 @@ { "1.0.0": "0.15.0", "1.1.0": "0.15.0", - "1.2.0": "0.15.0" + "1.2.0": "0.15.0", + "1.3.0": "0.15.0" } \ No newline at end of file