alchemy-widget 0.1.5 → 0.2.0

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 (36) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/assets/stylesheets/alchemy_widgets.scss +426 -0
  3. package/bootstrap.js +6 -0
  4. package/controller/alchemy_widgets_controller.js +85 -9
  5. package/element/00-widget_base_element.js +154 -6
  6. package/element/05-widget_element.js +112 -19
  7. package/element/10-container_elements.js +15 -15
  8. package/element/11-alchemy_widgets_list_element.js +2 -2
  9. package/element/20-add_area_element.js +23 -23
  10. package/element/table_of_contents_element.js +104 -8
  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 +300 -38
  14. package/helper/widget_action.js +19 -18
  15. package/helper/widgets/00-widget.js +160 -37
  16. package/helper/widgets/01-container.js +12 -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 +195 -0
  22. package/helper/widgets/header.js +4 -4
  23. package/helper/widgets/markdown.js +17 -10
  24. package/helper/widgets/partial.js +215 -0
  25. package/helper/widgets/sourcecode.js +4 -4
  26. package/helper/widgets/table_of_contents.js +2 -2
  27. package/helper/widgets/text.js +14 -4
  28. package/helper/widgets_helper.js +26 -0
  29. package/package.json +4 -3
  30. package/view/elements/table_of_contents.hwk +23 -9
  31. package/view/form/inputs/edit/widget.hwk +2 -2
  32. package/view/form/inputs/edit/widgets.hwk +2 -2
  33. package/view/widget/elements/al_widget_toolbar.hwk +49 -0
  34. package/view/widget/widget_config.hwk +7 -4
  35. package/assets/stylesheets/alchemy-widget-symbols.scss +0 -191
  36. package/assets/stylesheets/alchemy-widgets.scss +0 -258
@@ -1,75 +1,337 @@
1
1
  /**
2
- * The alchemy-widget-toolbar element
2
+ * The al-widget-toolbar element
3
3
  *
4
4
  * @author Jelle De Loecker <jelle@elevenways.be>
5
- * @since 0.1.0
6
- * @version 0.1.0
5
+ * @since 0.2.0
6
+ * @version 0.2.0
7
7
  */
8
- let Toolbar = Function.inherits('Alchemy.Element.Widget.Base', function AlchemyWidgetToolbar() {
9
- AlchemyWidgetToolbar.super.call(this);
10
- this.hidden = true;
11
- });
8
+ let Toolbar = Function.inherits('Alchemy.Element.Form.Stateful', 'Alchemy.Element.Widget', 'WidgetToolbar');
9
+
10
+ /**
11
+ * The stylesheet to load for this element
12
+ *
13
+ * @author Jelle De Loecker <jelle@elevenways.be>
14
+ * @since 0.2.0
15
+ * @version 0.2.0
16
+ */
17
+ Toolbar.setStylesheetFile('alchemy_widgets');
18
+
19
+ /**
20
+ * Set the custom element prefix
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.2.0
24
+ * @version 0.2.0
25
+ */
26
+ Toolbar.setStatic('custom_element_prefix', 'al');
27
+
28
+ /**
29
+ * The template to use for the content of this element
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.2.0
33
+ * @version 0.2.0
34
+ */
35
+ Toolbar.setTemplateFile('widget/elements/al_widget_toolbar');
36
+
37
+ /**
38
+ * The start-edit button
39
+ *
40
+ * @author Jelle De Loecker <jelle@elevenways.be>
41
+ * @since 0.2.0
42
+ * @version 0.2.0
43
+ */
44
+ Toolbar.addElementGetter('button_start', 'al-button.start-edit');
45
+
46
+ /**
47
+ * The stop-edit button
48
+ *
49
+ * @author Jelle De Loecker <jelle@elevenways.be>
50
+ * @since 0.2.0
51
+ * @version 0.2.0
52
+ */
53
+ Toolbar.addElementGetter('button_stop', 'al-button.stop-edit');
12
54
 
13
55
  /**
14
- * Show the actions for the given widget
56
+ * The stop-and-save button
15
57
  *
16
58
  * @author Jelle De Loecker <jelle@elevenways.be>
17
- * @since 0.1.0
18
- * @version 0.1.0
59
+ * @since 0.2.0
60
+ * @version 0.2.0
61
+ */
62
+ Toolbar.addElementGetter('button_stop_and_save', 'al-button.stop-and-save');
63
+
64
+ /**
65
+ * The save-all button
19
66
  *
20
- * @param {HTMLElement} widget
67
+ * @author Jelle De Loecker <jelle@elevenways.be>
68
+ * @since 0.2.0
69
+ * @version 0.2.0
21
70
  */
22
- Toolbar.setMethod(function showWidgetActions(widget) {
71
+ Toolbar.addElementGetter('button_save_all', 'al-button.save-all');
23
72
 
24
- if (!widget || !widget.instance) {
73
+ /**
74
+ * Make sure the toolbar is visible
75
+ *
76
+ * @author Jelle De Loecker <jelle@elevenways.be>
77
+ * @since 0.2.0
78
+ * @version 0.2.0
79
+ */
80
+ Toolbar.setStatic(function show() {
81
+
82
+ if (!alchemy.hasPermission('alchemy.widgets.toolbar')) {
83
+ return;
84
+ }
85
+
86
+ let toolbar = document.querySelector('al-widget-toolbar');
87
+
88
+ if (toolbar) {
25
89
  return;
26
90
  }
27
91
 
28
- const that = this;
92
+ toolbar = hawkejs.createElement('al-widget-toolbar');
93
+
94
+ hawkejs.scene.bottom_element.append(toolbar);
95
+ });
96
+
97
+ /**
98
+ * Get all the root widgets
99
+ *
100
+ * @author Jelle De Loecker <jelle@elevenways.be>
101
+ * @since 0.2.0
102
+ * @version 0.2.0
103
+ */
104
+ Toolbar.setMethod(function getAllRootWidgets() {
105
+
106
+ let elements = document.body.queryAllNotNested('al-widgets'),
107
+ result = [],
108
+ i;
109
+
110
+ for (i = 0; i < elements.length; i++) {
111
+ result.push(elements[i]);
112
+ }
113
+
114
+ elements = document.body.queryAllNotNested('al-widget');
115
+
116
+ for (i = 0; i < elements.length; i++) {
117
+
118
+ if (elements[i].is_root_widget) {
119
+ result.push(elements[i]);
120
+ }
121
+ }
122
+
123
+ return result;
124
+ });
125
+
126
+ /**
127
+ * Start editing all the widgets
128
+ *
129
+ * @author Jelle De Loecker <jelle@elevenways.be>
130
+ * @since 0.2.0
131
+ * @version 0.2.0
132
+ */
133
+ Toolbar.setMethod(function startEditing() {
134
+
135
+ let i;
136
+
137
+ Blast.editing = true;
138
+ document.body.classList.add('editing-blocks');
139
+
140
+ let elements = this.getAllRootWidgets();
141
+
142
+ for (i = 0; i < elements.length; i++) {
143
+ elements[i].startEditor();
144
+ }
145
+
146
+ this.setState('editing');
147
+ });
148
+
149
+ /**
150
+ * Stop editing all the widgets
151
+ *
152
+ * @author Jelle De Loecker <jelle@elevenways.be>
153
+ * @since 0.2.0
154
+ * @version 0.2.0
155
+ */
156
+ Toolbar.setMethod(function stopEditing() {
157
+
158
+ if (!Blast.editing) {
159
+ return;
160
+ }
29
161
 
30
- let actions = widget.instance.getToolbarActions();
162
+ let i;
31
163
 
32
- // Clear all the old buttons
33
- Hawkejs.removeChildren(this);
164
+ Blast.editing = false;
165
+ document.body.classList.remove('editing-blocks');
34
166
 
35
- for (let action of actions) {
167
+ let elements = this.getAllRootWidgets();
36
168
 
37
- let button = this.createElement('button');
38
- button.classList.add('aw-toolbar-button');
169
+ for (i = 0; i < elements.length; i++) {
170
+ elements[i].stopEditor();
171
+ }
39
172
 
40
- button.innerHTML = action.getButtonHTML();
41
- button.setAttribute('title', action.title);
173
+ this.setState('ready');
174
+ });
42
175
 
43
- let is_selected = action.isAlreadySelected(widget);
176
+ /**
177
+ * Save all the widgets
178
+ *
179
+ * @author Jelle De Loecker <jelle@elevenways.be>
180
+ * @since 0.2.0
181
+ * @version 0.2.0
182
+ */
183
+ Toolbar.setMethod(async function saveAll() {
44
184
 
45
- if (is_selected) {
46
- button.classList.add('aw-button-selected');
185
+ if (this._saving) {
186
+ try {
187
+ await this._saving;
188
+ } catch (err) {
189
+ // Ignore;
47
190
  }
191
+ }
192
+
193
+ this._saving = null;
48
194
 
49
- button.addEventListener('click', function onClick(e) {
195
+ let elements = this.getAllRootWidgets();
196
+ let widget_data = [];
197
+ let pledge;
50
198
 
51
- e.preventDefault();
199
+ for (let element of elements) {
200
+ let entry = element.gatherSaveData();
52
201
 
53
- action.applyOnWidget(widget, that);
54
- });
202
+ if (entry) {
203
+ widget_data.push(entry);
204
+ }
205
+ }
55
206
 
56
- this.append(button);
207
+ if (widget_data.length) {
208
+ let config = {
209
+ href : alchemy.routeUrl('AlchemyWidgets#save'),
210
+ post : {
211
+ widgets: widget_data
212
+ }
213
+ };
214
+
215
+ pledge = alchemy.fetch(config);
216
+ this._saving = pledge;
57
217
  }
218
+
219
+ return pledge;
58
220
  });
59
221
 
60
222
  /**
61
- * Close the toolbar
223
+ * Save all and update the states
62
224
  *
63
225
  * @author Jelle De Loecker <jelle@elevenways.be>
64
- * @since 0.1.0
65
- * @version 0.1.0
226
+ * @since 0.2.0
227
+ * @version 0.2.0
228
+ *
229
+ * @param {Boolean} before_stop
66
230
  */
67
- Toolbar.setMethod(function close() {
68
- this.hidden = true;
231
+ Toolbar.setMethod(async function saveAllAndUpdateButtonStates(before_stop) {
232
+
233
+ let state = 'saving',
234
+ button;
69
235
 
70
- if (this.context_element && this.context_element.active_widget) {
71
- this.context_element.active_widget.selectWidget();
236
+ if (before_stop) {
237
+ button = this.button_stop_and_save;
238
+ state += '-before-stop';
239
+ } else {
240
+ button = this.button_save_all;
72
241
  }
73
242
 
74
- this.context_element = null;
243
+ this.setState(state);
244
+ button.setState(state);
245
+
246
+ let save_error = null;
247
+
248
+ let restore_toolbar_state = this.wrapForCurrentState(() => {
249
+ if (save_error) {
250
+ this.setState('error');
251
+ } else {
252
+ this.setState('editing')
253
+ }
254
+ });
255
+
256
+ let restore_button_state = button.wrapForCurrentState(() => {
257
+
258
+ if (save_error) {
259
+ button.setState('error');
260
+ } else {
261
+ button.setState('saved', 2500, 'ready');
262
+ }
263
+ });
264
+
265
+ try {
266
+ await this.saveAll();
267
+ } catch (err) {
268
+ save_error = err;
269
+ }
270
+
271
+ restore_toolbar_state();
272
+ restore_button_state();
273
+
274
+ if (save_error) {
275
+ return false;
276
+ }
277
+
278
+ return true;
279
+ });
280
+
281
+ /**
282
+ * This element has been added to the DOM for the first time
283
+ *
284
+ * @author Jelle De Loecker <jelle@elevenways.be>
285
+ * @since 0.2.0
286
+ * @version 0.2.0
287
+ */
288
+ Toolbar.setMethod(function introduced() {
289
+
290
+ this.button_start.addEventListener('activate', async e => {
291
+ this.startEditing();
292
+ });
293
+
294
+ this.button_stop.addEventListener('activate', async e => {
295
+ this.stopEditing();
296
+ });
297
+
298
+ this.button_save_all.addEventListener('activate', e => {
299
+ this.saveAllAndUpdateButtonStates(false);
300
+ });
301
+
302
+ this.button_stop_and_save.addEventListener('activate', async e => {
303
+ let saved = await this.saveAllAndUpdateButtonStates(true);
304
+
305
+ if (saved) {
306
+ this.stopEditing();
307
+ }
308
+ });
309
+
310
+ hawkejs.scene.on('opening_url', e => {
311
+ this.stopEditing();
312
+ });
313
+ });
314
+
315
+ /**
316
+ * The element has been added to the dom
317
+ *
318
+ * @author Jelle De Loecker <jelle@elevenways.be>
319
+ * @since 0.2.0
320
+ * @version 0.2.0
321
+ */
322
+ Toolbar.setMethod(function connected() {
323
+ let html = document.querySelector('html');
324
+ html.classList.add('with-al-widget-toolbar');
325
+ });
326
+
327
+ /**
328
+ * The element has been removed from the dom
329
+ *
330
+ * @author Jelle De Loecker <jelle@elevenways.be>
331
+ * @since 0.2.0
332
+ * @version 0.2.0
333
+ */
334
+ Toolbar.setMethod(function disconnected() {
335
+ let html = document.querySelector('html');
336
+ html.classList.remove('with-al-widget-toolbar');
75
337
  });
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @author Jelle De Loecker <jelle@elevenways.be>
7
7
  * @since 0.1.0
8
- * @version 0.1.0
8
+ * @version 0.2.0
9
9
  *
10
10
  * @param {String} name
11
11
  */
@@ -29,8 +29,8 @@ const Action = Function.inherits('Alchemy.Base', 'Alchemy.Widget', function Acti
29
29
  // The icon to use for this action
30
30
  this.icon = null;
31
31
 
32
- // Close the toolbar after clicking?
33
- this.close_toolbar = false;
32
+ // Close the actionbar after clicking?
33
+ this.close_actionbar = false;
34
34
  });
35
35
 
36
36
  /**
@@ -90,11 +90,11 @@ Action.setMethod(function setIcon(icon) {
90
90
  *
91
91
  * @author Jelle De Loecker <jelle@elevenways.be>
92
92
  * @since 0.1.0
93
- * @version 0.1.0
93
+ * @version 0.2.0
94
94
  *
95
95
  * @param {HTMLElement} widget
96
96
  */
97
- Action.setMethod(function applyOnWidget(widget, toolbar) {
97
+ Action.setMethod(function applyOnWidget(widget, actionbar) {
98
98
 
99
99
  if (!this.handler) {
100
100
  throw new Error('Failed to apply action "' + this.name + '" on widget, no handler found');
@@ -103,10 +103,10 @@ Action.setMethod(function applyOnWidget(widget, toolbar) {
103
103
  let instance = widget.instance,
104
104
  handle = instance.getHandle();
105
105
 
106
- this.handler(widget, handle, toolbar);
106
+ this.handler(widget, handle, actionbar);
107
107
 
108
- if (this.close_toolbar) {
109
- toolbar.close();
108
+ if (this.close_actionbar) {
109
+ actionbar.close();
110
110
  }
111
111
  });
112
112
 
@@ -119,7 +119,7 @@ Action.setMethod(function applyOnWidget(widget, toolbar) {
119
119
  *
120
120
  * @param {HTMLElement} widget
121
121
  *
122
- * @return {Boolean}
122
+ * @return {Boolean|Promise}
123
123
  */
124
124
  Action.setMethod(function test(widget) {
125
125
 
@@ -141,30 +141,31 @@ Action.setMethod(function test(widget) {
141
141
  *
142
142
  * @author Jelle De Loecker <jelle@elevenways.be>
143
143
  * @since 0.1.0
144
- * @version 0.1.0
144
+ * @version 0.1.6
145
145
  *
146
- * @return {String}
146
+ * @return {HTMLElement|String}
147
147
  */
148
- Action.setMethod(function getButtonHTML() {
148
+ Action.setMethod(function getButtonContent() {
149
149
 
150
- let html;
150
+ let result;
151
151
 
152
152
  if (this.icon) {
153
153
 
154
154
  let icon = this.icon;
155
155
 
156
156
  if (typeof icon == 'string') {
157
- html = '<i class="' + icon + '"></i>';
157
+ result = Blast.Classes.Hawkejs.Hawkejs.createElement('al-icon');
158
+ result.setIcon(icon);
158
159
  } else if (icon.html) {
159
- html = icon.html;
160
+ result = Blast.Classes.Hawkejs.parseHTML(icon.html);
160
161
  }
161
162
  }
162
163
 
163
- if (!html) {
164
- html = this.name;
164
+ if (!result) {
165
+ result = this.name;
165
166
  }
166
167
 
167
- return html;
168
+ return result;
168
169
  });
169
170
 
170
171
  /**