@trebco/treb 27.5.2 → 27.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,113 @@
1
+
2
+ import { Editor, type NodeDescriptor } from './editor';
3
+
4
+ export class ExternalEditor extends Editor {
5
+
6
+ public get active() {
7
+ return this.nodes.length > 0;
8
+ }
9
+
10
+ public Reset() {
11
+ this.AttachNodes();
12
+ }
13
+
14
+ /**
15
+ * attach to a set of nodes (one is fine).
16
+ *
17
+ * FIXME: since this is not used in subclasses for ICE and formula bar,
18
+ * perhaps we should move it into a new subclass specifically for
19
+ * external editor. we can add some flags as well. TODO/FIXME
20
+ *
21
+ * update modifying how this works. we will now watch focus ourselves.
22
+ */
23
+ public AttachNodes(nodes: HTMLElement[] = [], assume_formula = true) {
24
+
25
+ this.assume_formula = assume_formula;
26
+
27
+ // try to preserve any nodes/descriptors we've already "cooked",
28
+ // since this may get called multiple times when you switch between
29
+ // fields.
30
+
31
+ // (that's less true than before, but still might happen).
32
+
33
+ let descriptors: NodeDescriptor[] = [];
34
+
35
+ descriptors = nodes.map(node => {
36
+ for (const compare of this.nodes) {
37
+ if (compare.node === node) {
38
+ return compare;
39
+ }
40
+ }
41
+ return { node }; // not found, return a new one
42
+ });
43
+
44
+ // we should probably clean up here. if there's overlap we will just
45
+ // add a new one. note that we're looping over the *old* set here,
46
+ // so don't try to optimize by moving this into another loop.
47
+
48
+ for (const descriptor of this.nodes) {
49
+ if (descriptor.listeners) {
50
+ for (const [key, value] of descriptor.listeners.entries()) {
51
+ descriptor.node.removeEventListener(key, value);
52
+ }
53
+ descriptor.listeners.clear();
54
+ }
55
+ }
56
+
57
+ this.nodes = descriptors;
58
+
59
+
60
+ for (const descriptor of this.nodes) {
61
+
62
+ // check if we need to flush the cached text
63
+
64
+ if (descriptor.formatted_text === descriptor.node.textContent) {
65
+ const test = descriptor.node.innerHTML.length;
66
+ if (descriptor.check !== test) {
67
+ descriptor.formatted_text = undefined; // flush
68
+ }
69
+ }
70
+
71
+ // if it's already focused, set as active
72
+
73
+ if (document.activeElement === descriptor.node) {
74
+ this.active_editor = descriptor;
75
+ }
76
+
77
+ // format
78
+
79
+ this.UpdateText(descriptor, { toll_events: true });
80
+
81
+ // add listeners
82
+
83
+ this.RegisterListener(descriptor, 'focusin', () => {
84
+ // console.info('focusin');
85
+ this.active_editor = descriptor;
86
+ });
87
+
88
+ this.RegisterListener(descriptor, 'focusout', () => {
89
+ // console.info('focusout');
90
+ this.active_editor = undefined;
91
+ });
92
+
93
+ this.RegisterListener(descriptor, 'input', (event: Event) => {
94
+
95
+ // we're filtering on trusted here because we send an event.
96
+ // but when we send that event we also trigger an update.
97
+ // so... why not just run through the event handler?
98
+
99
+ if (event.isTrusted) {
100
+ this.UpdateText(descriptor);
101
+ this.UpdateColors(); // will send a local event
102
+ }
103
+
104
+ });
105
+
106
+
107
+ }
108
+
109
+ this.UpdateColors(true); // always send an event, just in case
110
+
111
+ }
112
+
113
+ }