]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/framework/toolbars.ts
Opensearch: Fixed XML declaration when php short tags enabled
[bookstack] / resources / js / wysiwyg / ui / framework / toolbars.ts
1 import {EditorContainerUiElement, EditorUiElement} from "./core";
2
3 import {el} from "../../utils/dom";
4
5 export type EditorContextToolbarDefinition = {
6     selector: string;
7     content: EditorUiElement[],
8     displayTargetLocator?: (originalTarget: HTMLElement) => HTMLElement;
9 };
10
11 export class EditorContextToolbar extends EditorContainerUiElement {
12
13     protected target: HTMLElement;
14
15     constructor(target: HTMLElement, children: EditorUiElement[]) {
16         super(children);
17         this.target = target;
18     }
19
20     protected buildDOM(): HTMLElement {
21         return el('div', {
22             class: 'editor-context-toolbar',
23         }, this.getChildren().map(child => child.getDOMElement()));
24     }
25
26     updatePosition() {
27         const editorBounds = this.getContext().scrollDOM.getBoundingClientRect();
28         const targetBounds = this.target.getBoundingClientRect();
29         const dom = this.getDOMElement();
30         const domBounds = dom.getBoundingClientRect();
31
32         const showing = targetBounds.bottom > editorBounds.top
33             && targetBounds.top < editorBounds.bottom;
34
35         dom.hidden = !showing;
36
37         if (!this.target.isConnected) {
38             // If our target is no longer in the DOM, tell the manager an update is needed.
39             this.getContext().manager.triggerFutureStateRefresh();
40             return;
41         } else if (!showing) {
42             return;
43         }
44
45         const showAbove: boolean = targetBounds.bottom + 6 + domBounds.height > editorBounds.bottom;
46         dom.classList.toggle('is-above', showAbove);
47
48         const targetMid = targetBounds.left + (targetBounds.width / 2);
49         const targetLeft = targetMid - (domBounds.width / 2);
50         if (showAbove) {
51             dom.style.top = (targetBounds.top - 6 - domBounds.height) + 'px';
52         } else {
53             dom.style.top = (targetBounds.bottom + 6) + 'px';
54         }
55         dom.style.left = targetLeft + 'px';
56     }
57
58     insert(children: EditorUiElement[]) {
59         this.addChildren(...children);
60         const dom = this.getDOMElement();
61         dom.append(...children.map(child => child.getDOMElement()));
62     }
63
64     protected empty() {
65         const children = this.getChildren();
66         for (const child of children) {
67             child.getDOMElement().remove();
68         }
69         this.removeChildren(...children);
70     }
71
72     destroy() {
73         this.empty();
74         this.getDOMElement().remove();
75     }
76 }