alchemy-widget 0.1.6 → 0.2.1

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/assets/stylesheets/{alchemy-widgets.scss → alchemy_widgets.scss} +169 -54
  3. package/bootstrap.js +101 -2
  4. package/controller/alchemy_widgets_controller.js +64 -0
  5. package/element/00-widget_base_element.js +105 -4
  6. package/element/05-widget_element.js +33 -21
  7. package/element/10-container_elements.js +27 -32
  8. package/element/11-alchemy_widgets_list_element.js +2 -2
  9. package/element/20-add_area_element.js +22 -22
  10. package/element/table_of_contents_element.js +144 -11
  11. package/element/widget_actionbar_element.js +92 -0
  12. package/element/widget_context_element.js +39 -23
  13. package/element/widget_toolbar_element.js +295 -50
  14. package/helper/widget_action.js +10 -10
  15. package/helper/widgets/00-widget.js +244 -27
  16. package/helper/widgets/01-container.js +29 -7
  17. package/helper/widgets/05-list.js +1 -1
  18. package/helper/widgets/alchemy_field_widget.js +112 -0
  19. package/helper/widgets/alchemy_form_widget.js +183 -0
  20. package/helper/widgets/alchemy_table_widget.js +71 -0
  21. package/helper/widgets/alchemy_tabs_widget.js +193 -0
  22. package/helper/widgets/hawkejs_template.js +60 -0
  23. package/helper/widgets/header.js +8 -10
  24. package/helper/widgets/html.js +52 -3
  25. package/helper/widgets/markdown.js +18 -13
  26. package/helper/widgets/partial.js +1 -3
  27. package/helper/widgets/sourcecode.js +5 -7
  28. package/helper/widgets/table_of_contents.js +2 -4
  29. package/helper/widgets/text.js +15 -15
  30. package/helper/widgets_helper.js +26 -0
  31. package/package.json +3 -2
  32. package/view/elements/table_of_contents.hwk +33 -9
  33. package/view/form/inputs/edit/widget.hwk +2 -2
  34. package/view/form/inputs/edit/widgets.hwk +2 -2
  35. package/view/widget/elements/al_widget_toolbar.hwk +49 -0
  36. package/view/widget/widget_config.hwk +7 -4
  37. package/assets/stylesheets/alchemy-widget-symbols.scss +0 -191
@@ -16,6 +16,15 @@ const TableOfContents = Function.inherits('Alchemy.Element.App', 'TableOfContent
16
16
  */
17
17
  TableOfContents.setTemplateFile('elements/table_of_contents');
18
18
 
19
+ /**
20
+ * Set the actual tag name
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.2.0
24
+ * @version 0.2.0
25
+ */
26
+ TableOfContents.setTagName('AL-TOC');
27
+
19
28
  /**
20
29
  * Set the content
21
30
  *
@@ -79,12 +88,21 @@ TableOfContents.setAttribute('title-selector');
79
88
  */
80
89
  TableOfContents.setAttribute('intersection-class');
81
90
 
91
+ /**
92
+ * Should titles be truncated?
93
+ *
94
+ * @author Jelle De Loecker <jelle@elevenways.be>
95
+ * @since 0.2.1
96
+ * @version 0.2.1
97
+ */
98
+ TableOfContents.setAttribute('truncate-length', {type: 'number'});
99
+
82
100
  /**
83
101
  * Get the entries
84
102
  *
85
103
  * @author Jelle De Loecker <jelle@elevenways.be>
86
104
  * @since 0.1.2
87
- * @version 0.1.2
105
+ * @version 0.2.1
88
106
  */
89
107
  TableOfContents.setProperty(function entries() {
90
108
 
@@ -105,7 +123,10 @@ TableOfContents.setProperty(function entries() {
105
123
  }
106
124
 
107
125
  if (wrapper) {
108
- let elements = wrapper.querySelectorAll(this.elements_selector || 'h1,h2'),
126
+
127
+ let current_level = null,
128
+ last_entry,
129
+ elements = wrapper.querySelectorAll(this.elements_selector || 'h1,h2'),
109
130
  element,
110
131
  title,
111
132
  i;
@@ -124,7 +145,9 @@ TableOfContents.setProperty(function entries() {
124
145
  }
125
146
  }
126
147
 
127
- let title_element;
148
+ let title_element,
149
+ starts_level,
150
+ ends_level;
128
151
 
129
152
  if (this.title_selector) {
130
153
  title_element = element.querySelector(this.title_selector);
@@ -134,20 +157,107 @@ TableOfContents.setProperty(function entries() {
134
157
  title_element = element;
135
158
  }
136
159
 
160
+ if (element.nodeName[0] == 'H' && isFinite(element.nodeName[1])) {
161
+ let heading_level = +element.nodeName[1];
162
+
163
+ if (current_level == null) {
164
+ current_level = heading_level;
165
+ } else if (heading_level > current_level) {
166
+ current_level++;
167
+
168
+ if (last_entry) {
169
+ last_entry.starts_level = true;
170
+ }
171
+ } else if (heading_level == current_level && last_entry) {
172
+ last_entry.starts_level = false;
173
+ } else if (heading_level < current_level) {
174
+ current_level--;
175
+
176
+ if (last_entry) {
177
+ last_entry.ends_level = true;
178
+ }
179
+ }
180
+ }
181
+
137
182
  title = (title_element.toc_title || title_element.textContent || '').trim();
138
183
 
139
- title = title.truncate(30);
184
+ if (this.truncate_length) {
185
+ title = title.truncate(this.truncate_length);
186
+ }
140
187
 
141
188
  // Don't add empty titles
142
189
  if (!title) {
143
190
  continue;
144
191
  }
145
192
 
146
- result.push({
147
- id : element.id,
148
- title : title,
149
- element : element,
150
- });
193
+ last_entry = {
194
+ id : element.id,
195
+ level : current_level,
196
+ title : title,
197
+ element : element,
198
+ starts_level : starts_level,
199
+ ends_level : ends_level,
200
+ };
201
+
202
+ result.push(last_entry);
203
+ }
204
+
205
+ let ended_level = false,
206
+ entries = result,
207
+ current_branch,
208
+ current_nodes = [];
209
+
210
+ result = current_nodes;
211
+ last_entry = null;
212
+
213
+ for (let entry of entries) {
214
+
215
+ if (ended_level) {
216
+
217
+ while (entry.level >= current_branch.level) {
218
+ current_branch = current_branch.parent;
219
+ current_nodes = current_branch?.children || result;
220
+
221
+ if (!current_branch) {
222
+ current_branch = result[result.length - 1];
223
+ break;
224
+ }
225
+ }
226
+
227
+ ended_level = false;
228
+ }
229
+
230
+ if (!current_branch) {
231
+ current_branch = entry;
232
+ } else {
233
+ entry.parent = current_branch;
234
+ }
235
+
236
+ if (entry.starts_level) {
237
+
238
+ current_branch = last_entry;
239
+
240
+ if (!current_branch.children) {
241
+ current_branch.children = [];
242
+ }
243
+
244
+ current_nodes = current_branch.children;
245
+ }
246
+
247
+ current_nodes.push(entry);
248
+
249
+ if (entry.ends_level) {
250
+ ended_level = true;
251
+ current_branch = entry.parent;
252
+ current_nodes = current_branch.children || result;
253
+
254
+ if (!current_branch) {
255
+ current_branch = result[result.length - 1];
256
+ break;
257
+ }
258
+ }
259
+
260
+ last_entry = entry;
151
261
  }
152
262
  }
153
263
 
@@ -159,7 +269,7 @@ TableOfContents.setProperty(function entries() {
159
269
  *
160
270
  * @author Jelle De Loecker <jelle@elevenways.be>
161
271
  * @since 0.1.2
162
- * @version 0.1.2
272
+ * @version 0.2.1
163
273
  */
164
274
  TableOfContents.setMethod(async function introduced() {
165
275
 
@@ -167,7 +277,8 @@ TableOfContents.setMethod(async function introduced() {
167
277
 
168
278
  const observer = new IntersectionObserver(entries => {
169
279
 
170
- let class_name = this.intersection_class || 'visible';
280
+ let class_name = this.intersection_class || 'visible',
281
+ first_name = class_name + '-first';
171
282
 
172
283
  for (let entry of entries) {
173
284
  const id = entry.target.getAttribute('id');
@@ -185,6 +296,28 @@ TableOfContents.setMethod(async function introduced() {
185
296
  element.classList.remove(class_name);
186
297
  }
187
298
  };
299
+
300
+ let is_visible,
301
+ all_marked = this.querySelectorAll('.' + class_name + ', .' + first_name),
302
+ element,
303
+ seen = 0,
304
+ i;
305
+
306
+ for (i = 0; i < all_marked.length; i++) {
307
+ element = all_marked[i];
308
+ is_visible = element.classList.contains(class_name);
309
+
310
+ if (is_visible && seen == 0) {
311
+ element.classList.add(first_name);
312
+ } else {
313
+ element.classList.remove(first_name);
314
+ }
315
+
316
+ if (is_visible) {
317
+ seen++;
318
+ }
319
+ }
320
+
188
321
  });
189
322
 
190
323
  for (let entry of this.entries) {
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The al-widget-actionbar element
3
+ *
4
+ * @author Jelle De Loecker <jelle@elevenways.be>
5
+ * @since 0.1.0
6
+ * @version 0.2.0
7
+ */
8
+ let Actionbar = Function.inherits('Alchemy.Element.Widget.Base', function WidgetActionbar() {
9
+ WidgetActionbar.super.call(this);
10
+ this.hidden = true;
11
+ });
12
+
13
+ /**
14
+ * Show the actions for the given widget
15
+ *
16
+ * @author Jelle De Loecker <jelle@elevenways.be>
17
+ * @since 0.1.0
18
+ * @version 0.2.0
19
+ *
20
+ * @param {HTMLElement} widget
21
+ */
22
+ Actionbar.setMethod(async function showWidgetActions(widget) {
23
+
24
+ if (!widget || !widget.instance) {
25
+ return;
26
+ }
27
+
28
+ const that = this;
29
+
30
+ let actions = await widget.instance.getActionbarActions();
31
+
32
+ // Clear all the old buttons
33
+ Hawkejs.removeChildren(this);
34
+
35
+ for (let action of actions) {
36
+
37
+ let button = this.createElement('button');
38
+ button.classList.add('aw-actionbar-button');
39
+
40
+ let content = action.getButtonContent();
41
+
42
+ if (!content) {
43
+ content = action.title;
44
+ }
45
+
46
+ if (typeof content == 'string') {
47
+ button.innerText = content;
48
+ } else if (content) {
49
+ if (Array.isArray(content)) {
50
+ for (let entry of content) {
51
+ button.append(entry);
52
+ }
53
+ } else {
54
+ button.append(content);
55
+ }
56
+ }
57
+
58
+ button.setAttribute('title', action.title);
59
+
60
+ let is_selected = action.isAlreadySelected(widget);
61
+
62
+ if (is_selected) {
63
+ button.classList.add('aw-button-selected');
64
+ }
65
+
66
+ button.addEventListener('click', function onClick(e) {
67
+
68
+ e.preventDefault();
69
+
70
+ action.applyOnWidget(widget, that);
71
+ });
72
+
73
+ this.append(button);
74
+ }
75
+ });
76
+
77
+ /**
78
+ * Close the actionbar
79
+ *
80
+ * @author Jelle De Loecker <jelle@elevenways.be>
81
+ * @since 0.1.0
82
+ * @version 0.1.0
83
+ */
84
+ Actionbar.setMethod(function close() {
85
+ this.hidden = true;
86
+
87
+ if (this.context_element && this.context_element.active_widget) {
88
+ this.context_element.active_widget.selectWidget();
89
+ }
90
+
91
+ this.context_element = null;
92
+ });
@@ -1,14 +1,14 @@
1
1
  /**
2
- * The alchemy-widget-context element
2
+ * The al-widget-context element
3
3
  *
4
4
  * @author Jelle De Loecker <jelle@elevenways.be>
5
5
  * @since 0.1.0
6
- * @version 0.1.0
6
+ * @version 0.2.0
7
7
  */
8
- let Awc = Function.inherits('Alchemy.Element.Widget.Base', function AlchemyWidgetContext() {
9
- AlchemyWidgetContext.super.call(this);
8
+ let Awc = Function.inherits('Alchemy.Element.Widget.Base', function WidgetContext() {
9
+ WidgetContext.super.call(this);
10
10
 
11
- this.innerHTML = `<button class="menu-button widget-button" title="Menu"><i class="gg-menu-grid-o"></i></button>`;
11
+ this.innerHTML = `<button class="menu-button widget-button" title="Menu"><al-icon icon-name="grid"></al-icon></button>`;
12
12
  this.hidden = true;
13
13
  });
14
14
 
@@ -45,48 +45,64 @@ Awc.setMethod(function moveToWidget(widget) {
45
45
  });
46
46
 
47
47
  /**
48
- * Exiting the given widget
48
+ * The given widget has been unselected
49
49
  *
50
50
  * @author Jelle De Loecker <jelle@elevenways.be>
51
51
  * @since 0.1.0
52
- * @version 0.1.0
52
+ * @version 0.2.0
53
53
  */
54
54
  Awc.setMethod(function unselectedWidget(widget) {
55
55
 
56
56
  this.hidden = true;
57
57
  this.active_widget = null;
58
58
 
59
- if (this.toolbar) {
60
- this.toolbar.hidden = true;
59
+ if (this.actionbar) {
60
+ this.actionbar.hidden = true;
61
61
  }
62
62
  });
63
63
 
64
64
  /**
65
- * Show the toolbar
65
+ * Force unselecting any widget
66
+ *
67
+ * @author Jelle De Loecker <jelle@elevenways.be>
68
+ * @since 0.2.0
69
+ * @version 0.2.0
70
+ */
71
+ Awc.setMethod(function forceUnselection() {
72
+
73
+ if (this.active_widget) {
74
+ this.active_widget.unselectWidget();
75
+ } else {
76
+ this.unselectedWidget();
77
+ }
78
+ });
79
+
80
+ /**
81
+ * Show the actionbar
66
82
  *
67
83
  * @author Jelle De Loecker <jelle@elevenways.be>
68
84
  * @since 0.1.0
69
- * @version 0.1.0
85
+ * @version 0.2.0
70
86
  */
71
- Awc.setMethod(function toggleToolbar() {
87
+ Awc.setMethod(function toggleActionbar() {
72
88
 
73
89
  if (!this.active_widget) {
74
90
  return;
75
91
  }
76
92
 
77
- if (!this.toolbar) {
78
- this.toolbar = document.createElement('alchemy-widget-toolbar');
79
- this.append(this.toolbar);
93
+ if (!this.actionbar) {
94
+ this.actionbar = document.createElement('al-widget-actionbar');
95
+ this.append(this.actionbar);
80
96
  }
81
97
 
82
- if (this.toolbar.context_element == this && !this.toolbar.hidden) {
83
- this.toolbar.close();
98
+ if (this.actionbar.context_element == this && !this.actionbar.hidden) {
99
+ this.actionbar.close();
84
100
  return;
85
101
  }
86
102
 
87
- this.toolbar.hidden = false;
88
- this.toolbar.context_element = this;
89
- this.toolbar.showWidgetActions(this.active_widget);
103
+ this.actionbar.hidden = false;
104
+ this.actionbar.context_element = this;
105
+ this.actionbar.showWidgetActions(this.active_widget);
90
106
  });
91
107
 
92
108
  /**
@@ -94,7 +110,7 @@ Awc.setMethod(function toggleToolbar() {
94
110
  *
95
111
  * @author Jelle De Loecker <jelle@elevenways.be>
96
112
  * @since 0.1.0
97
- * @version 0.1.0
113
+ * @version 0.2.0
98
114
  */
99
115
  Awc.setMethod(function introduced() {
100
116
 
@@ -110,7 +126,7 @@ Awc.setMethod(function introduced() {
110
126
  return that.exitingWidget();
111
127
  }
112
128
 
113
- that.toggleToolbar();
129
+ that.toggleActionbar();
114
130
  });
115
131
 
116
132
  document.addEventListener('click', e => {
@@ -129,7 +145,7 @@ Awc.setMethod(function introduced() {
129
145
  return;
130
146
  }
131
147
 
132
- return this.unselectedWidget();
148
+ return this.forceUnselection();
133
149
  });
134
150
 
135
151
  let update_scroll = () => {