alchemy-widget 0.1.0 → 0.1.3

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 0.1.3 (2022-03-21)
2
+
3
+ * Catch and print errors when appending a widget to a container
4
+
5
+ ## 0.1.2 (2022-02-20)
6
+
7
+ * Add `table-of-contents` element and widget
8
+
9
+ ## 0.1.1 (2022-01-28)
10
+
11
+ * Hide context button when clicking out of widget
12
+ * Update context button position on scroll
13
+ * Fix row children becoming too wide
14
+
1
15
  ## 0.1.0 (2021-09-12)
2
16
 
3
17
  * Initial release
@@ -11,7 +11,7 @@ alchemy-widgets-column {
11
11
  }
12
12
 
13
13
  > * {
14
- flex: 1 auto;
14
+ flex: 1;
15
15
  }
16
16
  }
17
17
 
@@ -251,4 +251,8 @@ alchemy-widget[type="header"] {
251
251
  font-weight: bold;
252
252
  height: 1.3em;
253
253
  }
254
+ }
255
+
256
+ table-of-contents {
257
+ display: block;
254
258
  }
@@ -179,15 +179,26 @@ AlchemyWidgets.setMethod(function clear() {
179
179
  *
180
180
  * @author Jelle De Loecker <jelle@elevenways.be>
181
181
  * @since 0.1.0
182
- * @version 0.1.0
182
+ * @version 0.1.3
183
183
  *
184
184
  * @param {String} type
185
185
  * @param {Object} config
186
186
  */
187
187
  AlchemyWidgets.setMethod(function addWidget(type, config) {
188
188
 
189
+ let instance;
190
+
189
191
  // Create the instance of the widget
190
- let instance = this.instance.createChildWidget(type, config);
192
+ try {
193
+ instance = this.instance.createChildWidget(type, config);
194
+ } catch (err) {
195
+ config = {
196
+ original_config : config,
197
+ html : '<pre>' + err.message + '\n' + err.stack + '</pre>',
198
+ };
199
+
200
+ instance = this.instance.createChildWidget('html', config);
201
+ }
191
202
 
192
203
  // Attach the renderer
193
204
  instance.hawkejs_renderer = this.hawkejs_renderer;
@@ -0,0 +1,193 @@
1
+ /**
2
+ * The table-of-contents element
3
+ *
4
+ * @author Jelle De Loecker <jelle@elevenways.be>
5
+ * @since 0.1.2
6
+ * @version 0.1.2
7
+ */
8
+ const TableOfContents = Function.inherits('Alchemy.Element.App', 'TableOfContents');
9
+
10
+ /**
11
+ * The template to use for the content of this element
12
+ *
13
+ * @author Jelle De Loecker <jelle@elevenways.be>
14
+ * @since 0.1.2
15
+ * @version 0.1.2
16
+ */
17
+ TableOfContents.setTemplateFile('elements/table_of_contents');
18
+
19
+ /**
20
+ * Set the content
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.1.2
24
+ * @version 0.1.2
25
+ */
26
+ TableOfContents.setAssignedProperty('content');
27
+
28
+ /**
29
+ * The role of this element
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.1.2
33
+ * @version 0.1.2
34
+ */
35
+ TableOfContents.setRole('navigation');
36
+
37
+ /**
38
+ * The parent query
39
+ *
40
+ * @author Jelle De Loecker <jelle@elevenways.be>
41
+ * @since 0.1.2
42
+ * @version 0.1.2
43
+ */
44
+ TableOfContents.setAttribute('parent-selector');
45
+
46
+ /**
47
+ * The children query
48
+ *
49
+ * @author Jelle De Loecker <jelle@elevenways.be>
50
+ * @since 0.1.2
51
+ * @version 0.1.2
52
+ */
53
+ TableOfContents.setAttribute('children-selector');
54
+
55
+ /**
56
+ * The elements query
57
+ *
58
+ * @author Jelle De Loecker <jelle@elevenways.be>
59
+ * @since 0.1.2
60
+ * @version 0.1.2
61
+ */
62
+ TableOfContents.setAttribute('elements-selector');
63
+
64
+ /**
65
+ * The elements query
66
+ *
67
+ * @author Jelle De Loecker <jelle@elevenways.be>
68
+ * @since 0.1.2
69
+ * @version 0.1.2
70
+ */
71
+ TableOfContents.setAttribute('title-selector');
72
+
73
+ /**
74
+ * The class to add when intersecting (visible)
75
+ *
76
+ * @author Jelle De Loecker <jelle@elevenways.be>
77
+ * @since 0.1.2
78
+ * @version 0.1.2
79
+ */
80
+ TableOfContents.setAttribute('intersection-class');
81
+
82
+ /**
83
+ * Get the entries
84
+ *
85
+ * @author Jelle De Loecker <jelle@elevenways.be>
86
+ * @since 0.1.2
87
+ * @version 0.1.2
88
+ */
89
+ TableOfContents.setProperty(function entries() {
90
+
91
+ let result = [],
92
+ parent = this.parentElement,
93
+ wrapper;
94
+
95
+ if (this.parent_selector) {
96
+ parent = this.queryParents(this.parent_selector);
97
+ }
98
+
99
+ if (parent) {
100
+ wrapper = parent;
101
+ }
102
+
103
+ if (wrapper && this.children_selector) {
104
+ wrapper = wrapper.querySelector(this.children_selector);
105
+ }
106
+
107
+ if (wrapper) {
108
+ let elements = wrapper.querySelectorAll(this.elements_selector || 'h1,h2'),
109
+ element,
110
+ title,
111
+ i;
112
+
113
+ for (i = 0; i < elements.length; i++) {
114
+ element = elements[i];
115
+
116
+ if (!element.id) {
117
+
118
+ if (element.hawkejs_id) {
119
+ element.id = element.hawkejs_id;
120
+ }
121
+
122
+ if (!element.id) {
123
+ continue;
124
+ }
125
+ }
126
+
127
+ let title_element;
128
+
129
+ if (this.title_selector) {
130
+ title_element = element.querySelector(this.title_selector);
131
+ }
132
+
133
+ if (!title_element) {
134
+ title_element = element;
135
+ }
136
+
137
+ title = (title_element.toc_title || title_element.textContent || '').trim();
138
+
139
+ title = title.truncate(30);
140
+
141
+ // Don't add empty titles
142
+ if (!title) {
143
+ continue;
144
+ }
145
+
146
+ result.push({
147
+ id : element.id,
148
+ title : title,
149
+ element : element,
150
+ });
151
+ }
152
+ }
153
+
154
+ return result;
155
+ });
156
+
157
+ /**
158
+ * Added to the dom for the first time
159
+ *
160
+ * @author Jelle De Loecker <jelle@elevenways.be>
161
+ * @since 0.1.2
162
+ * @version 0.1.2
163
+ */
164
+ TableOfContents.setMethod(async function introduced() {
165
+
166
+ await this.rerender();
167
+
168
+ const observer = new IntersectionObserver(entries => {
169
+
170
+ let class_name = this.intersection_class || 'visible';
171
+
172
+ for (let entry of entries) {
173
+ const id = entry.target.getAttribute('id');
174
+
175
+ let query = `a[href="#${id}"]`,
176
+ element = this.querySelector(query);
177
+
178
+ if (!element) {
179
+ return;
180
+ }
181
+
182
+ if (entry.intersectionRatio > 0) {
183
+ element.classList.add(class_name);
184
+ } else {
185
+ element.classList.remove(class_name);
186
+ }
187
+ };
188
+ });
189
+
190
+ for (let entry of this.entries) {
191
+ observer.observe(entry.element);
192
+ }
193
+ });
@@ -112,4 +112,43 @@ Awc.setMethod(function introduced() {
112
112
 
113
113
  that.toggleToolbar();
114
114
  });
115
+
116
+ document.addEventListener('click', e => {
117
+
118
+ if (!this.active_widget) {
119
+ return;
120
+ }
121
+
122
+ // Ignore clicks on the context element button itself!
123
+ if (e.target == this || this.contains(e.target)) {
124
+ return;
125
+ }
126
+
127
+ // Ignore clicks in the active widget
128
+ if (e.target == this.active_widget || this.active_widget.contains(e.target)) {
129
+ return;
130
+ }
131
+
132
+ return this.unselectedWidget();
133
+ });
134
+
135
+ let update_scroll = () => {
136
+ animation_request = null;
137
+ this.moveToWidget(this.active_widget);
138
+ }
139
+
140
+ let animation_request;
141
+
142
+ document.addEventListener('scroll', e => {
143
+
144
+ if (!this.active_widget) {
145
+ return;
146
+ }
147
+
148
+ if (animation_request != null) {
149
+ cancelAnimationFrame(animation_request);
150
+ }
151
+
152
+ animation_request = requestAnimationFrame(update_scroll);
153
+ }, {passive: true});
115
154
  });
@@ -408,7 +408,7 @@ Widget.setMethod(function _createPopulatedWidgetElement() {
408
408
  *
409
409
  * @author Jelle De Loecker <jelle@elevenways.be>
410
410
  * @since 0.1.0
411
- * @version 0.1.0
411
+ * @version 0.1.2
412
412
  */
413
413
  Widget.setMethod(function populateWidget() {
414
414
 
@@ -416,8 +416,10 @@ Widget.setMethod(function populateWidget() {
416
416
  let name,
417
417
  i;
418
418
 
419
- for (i = 0; i < this.config.wrapper_class_names.length; i++) {
420
- name = this.config.wrapper_class_names[i];
419
+ let class_names = Array.cast(this.config.wrapper_class_names);
420
+
421
+ for (i = 0; i < class_names.length; i++) {
422
+ name = class_names[i];
421
423
  this.widget.classList.add(name);
422
424
  }
423
425
  }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The TOC Widget class
3
+ *
4
+ * @constructor
5
+ *
6
+ * @author Jelle De Loecker <jelle@elevenways.be>
7
+ * @since 0.1.2
8
+ * @version 0.1.2
9
+ *
10
+ * @param {Object} data
11
+ */
12
+ const Toc = Function.inherits('Alchemy.Widget', 'TableOfContents');
13
+
14
+ /**
15
+ * Populate the widget
16
+ *
17
+ * @author Jelle De Loecker <jelle@elevenways.be>
18
+ * @since 0.1.2
19
+ * @version 0.1.2
20
+ */
21
+ Toc.setMethod(function populateWidget() {
22
+
23
+ populateWidget.super.call(this);
24
+
25
+ let toc = this.createElement('table-of-contents');
26
+
27
+ if (this.config.parent_selector) {
28
+ toc.parent_selector = this.config.parent_selector;
29
+ }
30
+
31
+ if (this.config.elements_selector) {
32
+ toc.elements_selector = this.config.elements_selector;
33
+ }
34
+
35
+ if (this.config.child_selector) {
36
+ toc.child_selector = this.config.child_selector;
37
+ }
38
+
39
+ if (this.config.title_selector) {
40
+ toc.title_selector = this.config.title_selector;
41
+ }
42
+
43
+ this.widget.append(toc);
44
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemy-widget",
3
3
  "description": "The widget plugin for the AlchemyMVC",
4
- "version": "0.1.0",
4
+ "version": "0.1.3",
5
5
  "author": "Jelle De Loecker <jelle@elevenways.be>",
6
6
  "keywords": [
7
7
  "alchemy",
@@ -10,11 +10,11 @@
10
10
  "widget"
11
11
  ],
12
12
  "peerDependencies": {
13
- "alchemymvc" : "~1.1.0"
13
+ "alchemymvc" : ">=1.1.0"
14
14
  },
15
15
  "repository": "11ways/alchemy-widget",
16
16
  "license": "MIT",
17
17
  "engines": {
18
- "node" : ">=10.0.0"
18
+ "node" : ">=12.0.0"
19
19
  }
20
20
  }
@@ -0,0 +1,9 @@
1
+ <ol>
2
+ {% each self.entries as entry %}
3
+ <li>
4
+ <a href="#{% entry.id %}">
5
+ {{ entry.title }}
6
+ </a>
7
+ </li>
8
+ {% /each %}
9
+ </ol>