Files
racket-wiki/static/js/wiki/cmap/cmap-editor-ui-controller.js
T
2026-09-03 17:24:56 +02:00

60 lines
2.8 KiB
JavaScript

"use strict";
/** Connect CMap toolbar actions to an editor and application callbacks. */
export class CmapEditorUiController {
constructor({ root, getEditor, actions = {} }) {
this.root = root;
this.getEditor = getEditor;
this.actions = actions;
this.listeners = [];
}
bind(selector, event, handler) {
const element = this.root.querySelector(selector);
if (!element) return;
const listener = (eventObject) => handler(eventObject, this.getEditor());
element.addEventListener(event, listener);
this.listeners.push(() => element.removeEventListener(event, listener));
}
/**
* Bind every standard CMap toolbar action once.
* result : This controller, so the host may retain the initialized instance.
*/
initialize() {
this.bind("#cmap-save-map", "click", () => this.actions.save?.());
this.bind("#cmap-undo", "click", (_event, editor) => editor?.undo());
this.bind("#cmap-redo", "click", (_event, editor) => editor?.redo());
this.bind("#cmap-select-all", "click", (_event, editor) => editor?.selectAll());
this.bind("#cmap-delete-selected", "click", (_event, editor) => editor?.deleteSelection());
this.bind("#cmap-edit-selected", "click", () => this.actions.edit?.());
this.bind("#cmap-copy-selected", "click", (_event, editor) => editor?.copySelectionReferences());
this.bind("#cmap-cut-selected", "click", (_event, editor) => editor?.cutSelectionReferences());
this.bind("#cmap-paste-concepts", "click", (_event, editor) => editor?.pasteConceptReferences());
this.bind("#cmap-group-selected", "click", () => this.actions.group?.());
this.bind("#cmap-ungroup-selected", "click", (_event, editor) => editor?.ungroupSelection());
this.bind("#cmap-hide-selected", "click", (_event, editor) => editor?.hideSelectionInCurrentContext());
this.bind("#cmap-zoom-out", "click", () => this.actions.zoom?.(-10));
this.bind("#cmap-zoom-in", "click", () => this.actions.zoom?.(10));
this.bind("#cmap-zoom-reset", "click", () => this.actions.zoom?.(100, true));
this.bind("#cmap-zoom-percent", "change", (event) => this.actions.zoom?.(event.target.value, true));
this.bind("#cmap-toggle-page-guides", "click", () => this.actions.togglePageGuides?.());
this.bind("#cmap-selection-toolbar", "click", (event, editor) => {
const button = event.target.closest("button");
if (!button || button.disabled || !editor) return;
if (button.dataset.cmapLayout) {
editor.applySelectionLayout(button.dataset.cmapLayout);
} else {
this.actions.selection?.(button.dataset.cmapSelectionAction, editor);
}
});
return this;
}
/** Remove every listener installed by initialize before the host is disposed. */
destroy() {
for (const remove of this.listeners) remove();
this.listeners = [];
}
}