alchemy-widget 0.2.4 → 0.2.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.
- package/CHANGELOG.md +13 -0
- package/assets/stylesheets/alchemy_widgets.scss +16 -0
- package/element/00-widget_base_element.js +72 -8
- package/element/05-widget_element.js +9 -2
- package/element/10-container_elements.js +4 -0
- package/element/table_of_contents_element.js +314 -314
- package/helper/widgets/00-widget.js +93 -9
- package/helper/widgets/html.js +20 -4
- package/helper/widgets/markdown.js +33 -12
- package/helper/widgets/sourcecode.js +15 -3
- package/helper_field/widget.js +53 -2
- package/helper_field/widgets.js +24 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## 0.2.6 (2023-02-26)
|
|
2
|
+
|
|
3
|
+
* Replace *EasyMDE* markdown editor with *Toast editor*
|
|
4
|
+
* Implement the `valueHasContent` method
|
|
5
|
+
* Make sure widgets keep a link to the `conduit` instance
|
|
6
|
+
|
|
7
|
+
## 0.2.5 (2023-02-11)
|
|
8
|
+
|
|
9
|
+
* Add `code_type` field to the `Sourcecode` widget
|
|
10
|
+
* Allow setting the source of an `HTML` widget via its config dialog
|
|
11
|
+
* Make `paste` widget action only append copied widgets to a container
|
|
12
|
+
* Add `replace` widget action to replace a widget with anything in the current clipboard
|
|
13
|
+
|
|
1
14
|
## 0.2.4 (2023-01-30)
|
|
2
15
|
|
|
3
16
|
* Fix the tree structure generation of the `al-toc` element
|
|
@@ -428,4 +428,20 @@ al-toc {
|
|
|
428
428
|
|
|
429
429
|
.aw-hidden {
|
|
430
430
|
opacity: 0.8;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
al-widget[type="markdown"] {
|
|
434
|
+
.markdown-editor-container {
|
|
435
|
+
background: white;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.ProseMirror {
|
|
439
|
+
font-size: 1.1rem;
|
|
440
|
+
--default-font-family: "Roboto", sans-serif;
|
|
441
|
+
font-family: var(--font-family, var(--default-font-family));
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.toastui-editor-toolbar .toastui-editor-md-tab-container .toastui-editor-tabs {
|
|
445
|
+
display: none;
|
|
446
|
+
}
|
|
431
447
|
}
|
|
@@ -364,7 +364,7 @@ Base.setMethod(async function save() {
|
|
|
364
364
|
*
|
|
365
365
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
366
366
|
* @since 0.2.0
|
|
367
|
-
* @version 0.2.
|
|
367
|
+
* @version 0.2.5
|
|
368
368
|
*/
|
|
369
369
|
Base.setMethod(async function copyConfigToClipboard() {
|
|
370
370
|
|
|
@@ -375,7 +375,10 @@ Base.setMethod(async function copyConfigToClipboard() {
|
|
|
375
375
|
}
|
|
376
376
|
|
|
377
377
|
value._altype = 'widget';
|
|
378
|
-
|
|
378
|
+
|
|
379
|
+
if (this.type) {
|
|
380
|
+
value.type = this.type;
|
|
381
|
+
}
|
|
379
382
|
|
|
380
383
|
let dried = JSON.dry(value, null, '\t');
|
|
381
384
|
|
|
@@ -389,11 +392,11 @@ Base.setMethod(async function copyConfigToClipboard() {
|
|
|
389
392
|
});
|
|
390
393
|
|
|
391
394
|
/**
|
|
392
|
-
* Get configuration from the clipboard
|
|
395
|
+
* Get any current configuration from the clipboard
|
|
393
396
|
*
|
|
394
397
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
395
398
|
* @since 0.2.0
|
|
396
|
-
* @version 0.2.
|
|
399
|
+
* @version 0.2.5
|
|
397
400
|
*/
|
|
398
401
|
Base.setMethod(async function getConfigFromClipboard() {
|
|
399
402
|
|
|
@@ -428,7 +431,35 @@ Base.setMethod(async function getConfigFromClipboard() {
|
|
|
428
431
|
return false;
|
|
429
432
|
}
|
|
430
433
|
|
|
431
|
-
|
|
434
|
+
return result;
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Get configuration from the clipboard and return it if it's valid
|
|
439
|
+
*
|
|
440
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
441
|
+
* @since 0.2.5
|
|
442
|
+
* @version 0.2.5
|
|
443
|
+
*/
|
|
444
|
+
Base.setMethod(async function getReplaceableConfigFromClipboard() {
|
|
445
|
+
|
|
446
|
+
let result = await this.getConfigFromClipboard();
|
|
447
|
+
|
|
448
|
+
if (result.type == this.type) {
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (result.type == 'container') {
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (!this.can_be_removed) {
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
let parent_widget = this.parent_container;
|
|
461
|
+
|
|
462
|
+
if (!parent_widget || !parent_widget.editing || !parent_widget.addWidget) {
|
|
432
463
|
return false;
|
|
433
464
|
}
|
|
434
465
|
|
|
@@ -440,13 +471,46 @@ Base.setMethod(async function getConfigFromClipboard() {
|
|
|
440
471
|
*
|
|
441
472
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
442
473
|
* @since 0.2.0
|
|
443
|
-
* @version 0.2.
|
|
474
|
+
* @version 0.2.5
|
|
444
475
|
*/
|
|
445
476
|
Base.setMethod(async function pasteConfigFromClipboard() {
|
|
446
477
|
|
|
447
|
-
let result = await this.
|
|
478
|
+
let result = await this.getReplaceableConfigFromClipboard();
|
|
448
479
|
|
|
449
480
|
if (result) {
|
|
450
|
-
this.
|
|
481
|
+
this.replaceWithConfig(config);
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Apply the given config
|
|
487
|
+
*
|
|
488
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
489
|
+
* @since 0.2.0
|
|
490
|
+
* @version 0.2.5
|
|
491
|
+
*/
|
|
492
|
+
Base.setMethod(async function replaceWithConfig(config) {
|
|
493
|
+
|
|
494
|
+
if (!config?.type) {
|
|
495
|
+
throw new Error('Unable to replace, config type is empty');
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (this.type == config.type) {
|
|
499
|
+
this.value = config;
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
let parent_widget = this.parent_container;
|
|
504
|
+
|
|
505
|
+
// If this isn't in an editable widget, it can't be replaced.
|
|
506
|
+
// (Might be a hard-coded widget type)
|
|
507
|
+
if (!parent_widget || !parent_widget.editing || !parent_widget.addWidget) {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
let new_widget = parent_widget.addWidget(config.type, config.config);
|
|
512
|
+
|
|
513
|
+
if (new_widget) {
|
|
514
|
+
this.replaceWith(new_widget);
|
|
451
515
|
}
|
|
452
516
|
});
|
|
@@ -12,9 +12,16 @@ let Widget = Function.inherits('Alchemy.Element.Widget.Base', 'Widget');
|
|
|
12
12
|
*
|
|
13
13
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
14
14
|
* @since 0.1.0
|
|
15
|
-
* @version 0.
|
|
15
|
+
* @version 0.2.5
|
|
16
16
|
*/
|
|
17
|
-
Widget.setAttribute('type')
|
|
17
|
+
Widget.setAttribute('type', function getType(type) {
|
|
18
|
+
|
|
19
|
+
if (!type) {
|
|
20
|
+
type = this.instance.constructor.type_name;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return type;
|
|
24
|
+
});
|
|
18
25
|
|
|
19
26
|
/**
|
|
20
27
|
* Mark this as a widget
|
|
@@ -199,6 +199,8 @@ AlchemyWidgets.setMethod(function clear() {
|
|
|
199
199
|
*
|
|
200
200
|
* @param {String} type
|
|
201
201
|
* @param {Object} config
|
|
202
|
+
*
|
|
203
|
+
* @return {HTMLElement}
|
|
202
204
|
*/
|
|
203
205
|
AlchemyWidgets.setMethod(function addWidget(type, config) {
|
|
204
206
|
|
|
@@ -229,6 +231,8 @@ AlchemyWidgets.setMethod(function addWidget(type, config) {
|
|
|
229
231
|
if (this.editing) {
|
|
230
232
|
element.startEditor();
|
|
231
233
|
}
|
|
234
|
+
|
|
235
|
+
return element;
|
|
232
236
|
});
|
|
233
237
|
|
|
234
238
|
/**
|
|
@@ -1,315 +1,315 @@
|
|
|
1
|
-
const RELATED_HEADING = Symbol('related_heading'),
|
|
2
|
-
RELATED_SIBLINGS = Symbol('related_siblings');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The table-of-contents element
|
|
6
|
-
*
|
|
7
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
8
|
-
* @since 0.1.2
|
|
9
|
-
* @version 0.1.2
|
|
10
|
-
*/
|
|
11
|
-
const TableOfContents = Function.inherits('Alchemy.Element.App', 'TableOfContents');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The template to use for the content of this element
|
|
15
|
-
*
|
|
16
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
17
|
-
* @since 0.1.2
|
|
18
|
-
* @version 0.1.2
|
|
19
|
-
*/
|
|
20
|
-
TableOfContents.setTemplateFile('elements/table_of_contents');
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Set the actual tag name
|
|
24
|
-
*
|
|
25
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
26
|
-
* @since 0.2.0
|
|
27
|
-
* @version 0.2.0
|
|
28
|
-
*/
|
|
29
|
-
TableOfContents.setTagName('AL-TOC');
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Set the content
|
|
33
|
-
*
|
|
34
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
35
|
-
* @since 0.1.2
|
|
36
|
-
* @version 0.1.2
|
|
37
|
-
*/
|
|
38
|
-
TableOfContents.setAssignedProperty('content');
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The role of this element
|
|
42
|
-
*
|
|
43
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
44
|
-
* @since 0.1.2
|
|
45
|
-
* @version 0.1.2
|
|
46
|
-
*/
|
|
47
|
-
TableOfContents.setRole('navigation');
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* The parent query
|
|
51
|
-
*
|
|
52
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
53
|
-
* @since 0.1.2
|
|
54
|
-
* @version 0.1.2
|
|
55
|
-
*/
|
|
56
|
-
TableOfContents.setAttribute('parent-selector');
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* The children query
|
|
60
|
-
*
|
|
61
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
62
|
-
* @since 0.1.2
|
|
63
|
-
* @version 0.1.2
|
|
64
|
-
*/
|
|
65
|
-
TableOfContents.setAttribute('children-selector');
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* The elements query
|
|
69
|
-
*
|
|
70
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
71
|
-
* @since 0.1.2
|
|
72
|
-
* @version 0.1.2
|
|
73
|
-
*/
|
|
74
|
-
TableOfContents.setAttribute('elements-selector');
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* The elements query
|
|
78
|
-
*
|
|
79
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
80
|
-
* @since 0.1.2
|
|
81
|
-
* @version 0.1.2
|
|
82
|
-
*/
|
|
83
|
-
TableOfContents.setAttribute('title-selector');
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* The class to add when intersecting (visible)
|
|
87
|
-
*
|
|
88
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
89
|
-
* @since 0.1.2
|
|
90
|
-
* @version 0.1.2
|
|
91
|
-
*/
|
|
92
|
-
TableOfContents.setAttribute('intersection-class');
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Should titles be truncated?
|
|
96
|
-
*
|
|
97
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
98
|
-
* @since 0.2.1
|
|
99
|
-
* @version 0.2.1
|
|
100
|
-
*/
|
|
101
|
-
TableOfContents.setAttribute('truncate-length', {type: 'number'});
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Get the entries
|
|
105
|
-
*
|
|
106
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
107
|
-
* @since 0.1.2
|
|
108
|
-
* @version 0.2.4
|
|
109
|
-
*/
|
|
110
|
-
TableOfContents.setProperty(function entries() {
|
|
111
|
-
|
|
112
|
-
let result = [],
|
|
113
|
-
parent = this.parentElement,
|
|
114
|
-
wrapper;
|
|
115
|
-
|
|
116
|
-
if (this.parent_selector) {
|
|
117
|
-
parent = this.queryParents(this.parent_selector);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (parent) {
|
|
121
|
-
wrapper = parent;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (wrapper && this.children_selector) {
|
|
125
|
-
wrapper = wrapper.querySelector(this.children_selector);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (wrapper) {
|
|
129
|
-
|
|
130
|
-
let heading_level = 0,
|
|
131
|
-
heading,
|
|
132
|
-
i;
|
|
133
|
-
|
|
134
|
-
let headings = wrapper.querySelectorAll(this.elements_selector || 'h1, h2, h3, h4, h5, h6'),
|
|
135
|
-
nodes = [];
|
|
136
|
-
|
|
137
|
-
for (i = 0; i < headings.length; i++) {
|
|
138
|
-
heading = headings[i];
|
|
139
|
-
|
|
140
|
-
if (!heading.id) {
|
|
141
|
-
|
|
142
|
-
if (heading.hawkejs_id) {
|
|
143
|
-
heading.id = heading.hawkejs_id;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (!heading.id) {
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
let title_element,
|
|
152
|
-
title;
|
|
153
|
-
|
|
154
|
-
if (this.title_selector) {
|
|
155
|
-
title_element = heading.querySelector(this.title_selector);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (!title_element) {
|
|
159
|
-
title_element = heading;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (title_element.nodeName[0] == 'H' && isFinite(title_element.nodeName[1])) {
|
|
163
|
-
heading_level = +title_element.nodeName[1];
|
|
164
|
-
} else if (!heading_level) {
|
|
165
|
-
heading_level = 1;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
title = (title_element.toc_title || title_element.textContent || '').trim();
|
|
169
|
-
|
|
170
|
-
if (this.truncate_length) {
|
|
171
|
-
title = title.truncate(this.truncate_length);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Don't add empty titles
|
|
175
|
-
if (!title) {
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
let node = {
|
|
180
|
-
id : heading.id,
|
|
181
|
-
level : heading_level,
|
|
182
|
-
title : title,
|
|
183
|
-
element : heading,
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
nodes.push(node);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
result = nodes;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return result;
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Get the entries tree
|
|
197
|
-
*
|
|
198
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
199
|
-
* @since 0.2.4
|
|
200
|
-
* @version 0.2.4
|
|
201
|
-
*/
|
|
202
|
-
TableOfContents.setProperty(function tree() {
|
|
203
|
-
return Blast.listToTree(this.entries);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Added to the dom for the first time
|
|
208
|
-
*
|
|
209
|
-
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
210
|
-
* @since 0.1.2
|
|
211
|
-
* @version 0.2.4
|
|
212
|
-
*/
|
|
213
|
-
TableOfContents.setMethod(async function introduced() {
|
|
214
|
-
|
|
215
|
-
await this.rerender();
|
|
216
|
-
|
|
217
|
-
const observer = new IntersectionObserver(entries => {
|
|
218
|
-
|
|
219
|
-
let class_name = this.intersection_class || 'visible',
|
|
220
|
-
first_name = class_name + '-first';
|
|
221
|
-
|
|
222
|
-
let intersect_map = new Map();
|
|
223
|
-
|
|
224
|
-
for (let entry of entries) {
|
|
225
|
-
const heading = entry.target[RELATED_HEADING] || entry.target;
|
|
226
|
-
const id = heading.getAttribute('id');
|
|
227
|
-
|
|
228
|
-
if (!id) {
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
let query = `a[href="#${id}"]`,
|
|
233
|
-
element = this.querySelector(query);
|
|
234
|
-
|
|
235
|
-
if (!element) {
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
let value = intersect_map.get(element) || 0;
|
|
240
|
-
|
|
241
|
-
if (entry.intersectionRatio > 0) {
|
|
242
|
-
value++;
|
|
243
|
-
} else {
|
|
244
|
-
let siblings = heading[RELATED_SIBLINGS];
|
|
245
|
-
|
|
246
|
-
if (siblings?.length) {
|
|
247
|
-
for (let sibling of siblings) {
|
|
248
|
-
if (sibling.isVisible(-150)) {
|
|
249
|
-
value++;
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
intersect_map.set(element, value);
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
for (let [element, value] of intersect_map) {
|
|
260
|
-
|
|
261
|
-
if (value > 0) {
|
|
262
|
-
element.classList.add(class_name);
|
|
263
|
-
} else {
|
|
264
|
-
element.classList.remove(class_name);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
let is_visible,
|
|
269
|
-
all_marked = this.querySelectorAll('.' + class_name + ', .' + first_name),
|
|
270
|
-
element,
|
|
271
|
-
seen = 0,
|
|
272
|
-
i;
|
|
273
|
-
|
|
274
|
-
for (i = 0; i < all_marked.length; i++) {
|
|
275
|
-
element = all_marked[i];
|
|
276
|
-
is_visible = element.classList.contains(class_name);
|
|
277
|
-
|
|
278
|
-
if (is_visible && seen == 0) {
|
|
279
|
-
element.classList.add(first_name);
|
|
280
|
-
} else {
|
|
281
|
-
element.classList.remove(first_name);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (is_visible) {
|
|
285
|
-
seen++;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
let entries = this.entries,
|
|
291
|
-
elements = [];
|
|
292
|
-
|
|
293
|
-
for (let entry of entries) {
|
|
294
|
-
observer.observe(entry.element);
|
|
295
|
-
elements.push(entry.element);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
for (let element of elements) {
|
|
299
|
-
|
|
300
|
-
element[RELATED_SIBLINGS] = [];
|
|
301
|
-
let sibling = element.nextElementSibling;
|
|
302
|
-
|
|
303
|
-
while (sibling) {
|
|
304
|
-
|
|
305
|
-
if (elements.includes(sibling)) {
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
element[RELATED_SIBLINGS].push(sibling);
|
|
310
|
-
sibling[RELATED_HEADING] = element;
|
|
311
|
-
observer.observe(sibling);
|
|
312
|
-
sibling = sibling.nextElementSibling;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
1
|
+
const RELATED_HEADING = Symbol('related_heading'),
|
|
2
|
+
RELATED_SIBLINGS = Symbol('related_siblings');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The table-of-contents element
|
|
6
|
+
*
|
|
7
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
8
|
+
* @since 0.1.2
|
|
9
|
+
* @version 0.1.2
|
|
10
|
+
*/
|
|
11
|
+
const TableOfContents = Function.inherits('Alchemy.Element.App', 'TableOfContents');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The template to use for the content of this element
|
|
15
|
+
*
|
|
16
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
17
|
+
* @since 0.1.2
|
|
18
|
+
* @version 0.1.2
|
|
19
|
+
*/
|
|
20
|
+
TableOfContents.setTemplateFile('elements/table_of_contents');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Set the actual tag name
|
|
24
|
+
*
|
|
25
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
26
|
+
* @since 0.2.0
|
|
27
|
+
* @version 0.2.0
|
|
28
|
+
*/
|
|
29
|
+
TableOfContents.setTagName('AL-TOC');
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set the content
|
|
33
|
+
*
|
|
34
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
35
|
+
* @since 0.1.2
|
|
36
|
+
* @version 0.1.2
|
|
37
|
+
*/
|
|
38
|
+
TableOfContents.setAssignedProperty('content');
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The role of this element
|
|
42
|
+
*
|
|
43
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
44
|
+
* @since 0.1.2
|
|
45
|
+
* @version 0.1.2
|
|
46
|
+
*/
|
|
47
|
+
TableOfContents.setRole('navigation');
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The parent query
|
|
51
|
+
*
|
|
52
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
53
|
+
* @since 0.1.2
|
|
54
|
+
* @version 0.1.2
|
|
55
|
+
*/
|
|
56
|
+
TableOfContents.setAttribute('parent-selector');
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The children query
|
|
60
|
+
*
|
|
61
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
62
|
+
* @since 0.1.2
|
|
63
|
+
* @version 0.1.2
|
|
64
|
+
*/
|
|
65
|
+
TableOfContents.setAttribute('children-selector');
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The elements query
|
|
69
|
+
*
|
|
70
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
71
|
+
* @since 0.1.2
|
|
72
|
+
* @version 0.1.2
|
|
73
|
+
*/
|
|
74
|
+
TableOfContents.setAttribute('elements-selector');
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The elements query
|
|
78
|
+
*
|
|
79
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
80
|
+
* @since 0.1.2
|
|
81
|
+
* @version 0.1.2
|
|
82
|
+
*/
|
|
83
|
+
TableOfContents.setAttribute('title-selector');
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The class to add when intersecting (visible)
|
|
87
|
+
*
|
|
88
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
89
|
+
* @since 0.1.2
|
|
90
|
+
* @version 0.1.2
|
|
91
|
+
*/
|
|
92
|
+
TableOfContents.setAttribute('intersection-class');
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Should titles be truncated?
|
|
96
|
+
*
|
|
97
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
98
|
+
* @since 0.2.1
|
|
99
|
+
* @version 0.2.1
|
|
100
|
+
*/
|
|
101
|
+
TableOfContents.setAttribute('truncate-length', {type: 'number'});
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get the entries
|
|
105
|
+
*
|
|
106
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
107
|
+
* @since 0.1.2
|
|
108
|
+
* @version 0.2.4
|
|
109
|
+
*/
|
|
110
|
+
TableOfContents.setProperty(function entries() {
|
|
111
|
+
|
|
112
|
+
let result = [],
|
|
113
|
+
parent = this.parentElement,
|
|
114
|
+
wrapper;
|
|
115
|
+
|
|
116
|
+
if (this.parent_selector) {
|
|
117
|
+
parent = this.queryParents(this.parent_selector);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (parent) {
|
|
121
|
+
wrapper = parent;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (wrapper && this.children_selector) {
|
|
125
|
+
wrapper = wrapper.querySelector(this.children_selector);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (wrapper) {
|
|
129
|
+
|
|
130
|
+
let heading_level = 0,
|
|
131
|
+
heading,
|
|
132
|
+
i;
|
|
133
|
+
|
|
134
|
+
let headings = wrapper.querySelectorAll(this.elements_selector || 'h1, h2, h3, h4, h5, h6'),
|
|
135
|
+
nodes = [];
|
|
136
|
+
|
|
137
|
+
for (i = 0; i < headings.length; i++) {
|
|
138
|
+
heading = headings[i];
|
|
139
|
+
|
|
140
|
+
if (!heading.id) {
|
|
141
|
+
|
|
142
|
+
if (heading.hawkejs_id) {
|
|
143
|
+
heading.id = heading.hawkejs_id;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!heading.id) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let title_element,
|
|
152
|
+
title;
|
|
153
|
+
|
|
154
|
+
if (this.title_selector) {
|
|
155
|
+
title_element = heading.querySelector(this.title_selector);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!title_element) {
|
|
159
|
+
title_element = heading;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (title_element.nodeName[0] == 'H' && isFinite(title_element.nodeName[1])) {
|
|
163
|
+
heading_level = +title_element.nodeName[1];
|
|
164
|
+
} else if (!heading_level) {
|
|
165
|
+
heading_level = 1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
title = (title_element.toc_title || title_element.textContent || '').trim();
|
|
169
|
+
|
|
170
|
+
if (this.truncate_length) {
|
|
171
|
+
title = title.truncate(this.truncate_length);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Don't add empty titles
|
|
175
|
+
if (!title) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
let node = {
|
|
180
|
+
id : heading.id,
|
|
181
|
+
level : heading_level,
|
|
182
|
+
title : title,
|
|
183
|
+
element : heading,
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
nodes.push(node);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
result = nodes;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return result;
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get the entries tree
|
|
197
|
+
*
|
|
198
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
199
|
+
* @since 0.2.4
|
|
200
|
+
* @version 0.2.4
|
|
201
|
+
*/
|
|
202
|
+
TableOfContents.setProperty(function tree() {
|
|
203
|
+
return Blast.listToTree(this.entries);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Added to the dom for the first time
|
|
208
|
+
*
|
|
209
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
210
|
+
* @since 0.1.2
|
|
211
|
+
* @version 0.2.4
|
|
212
|
+
*/
|
|
213
|
+
TableOfContents.setMethod(async function introduced() {
|
|
214
|
+
|
|
215
|
+
await this.rerender();
|
|
216
|
+
|
|
217
|
+
const observer = new IntersectionObserver(entries => {
|
|
218
|
+
|
|
219
|
+
let class_name = this.intersection_class || 'visible',
|
|
220
|
+
first_name = class_name + '-first';
|
|
221
|
+
|
|
222
|
+
let intersect_map = new Map();
|
|
223
|
+
|
|
224
|
+
for (let entry of entries) {
|
|
225
|
+
const heading = entry.target[RELATED_HEADING] || entry.target;
|
|
226
|
+
const id = heading.getAttribute('id');
|
|
227
|
+
|
|
228
|
+
if (!id) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let query = `a[href="#${id}"]`,
|
|
233
|
+
element = this.querySelector(query);
|
|
234
|
+
|
|
235
|
+
if (!element) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
let value = intersect_map.get(element) || 0;
|
|
240
|
+
|
|
241
|
+
if (entry.intersectionRatio > 0) {
|
|
242
|
+
value++;
|
|
243
|
+
} else {
|
|
244
|
+
let siblings = heading[RELATED_SIBLINGS];
|
|
245
|
+
|
|
246
|
+
if (siblings?.length) {
|
|
247
|
+
for (let sibling of siblings) {
|
|
248
|
+
if (sibling.isVisible(-150)) {
|
|
249
|
+
value++;
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
intersect_map.set(element, value);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
for (let [element, value] of intersect_map) {
|
|
260
|
+
|
|
261
|
+
if (value > 0) {
|
|
262
|
+
element.classList.add(class_name);
|
|
263
|
+
} else {
|
|
264
|
+
element.classList.remove(class_name);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
let is_visible,
|
|
269
|
+
all_marked = this.querySelectorAll('.' + class_name + ', .' + first_name),
|
|
270
|
+
element,
|
|
271
|
+
seen = 0,
|
|
272
|
+
i;
|
|
273
|
+
|
|
274
|
+
for (i = 0; i < all_marked.length; i++) {
|
|
275
|
+
element = all_marked[i];
|
|
276
|
+
is_visible = element.classList.contains(class_name);
|
|
277
|
+
|
|
278
|
+
if (is_visible && seen == 0) {
|
|
279
|
+
element.classList.add(first_name);
|
|
280
|
+
} else {
|
|
281
|
+
element.classList.remove(first_name);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (is_visible) {
|
|
285
|
+
seen++;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
let entries = this.entries,
|
|
291
|
+
elements = [];
|
|
292
|
+
|
|
293
|
+
for (let entry of entries) {
|
|
294
|
+
observer.observe(entry.element);
|
|
295
|
+
elements.push(entry.element);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
for (let element of elements) {
|
|
299
|
+
|
|
300
|
+
element[RELATED_SIBLINGS] = [];
|
|
301
|
+
let sibling = element.nextElementSibling;
|
|
302
|
+
|
|
303
|
+
while (sibling) {
|
|
304
|
+
|
|
305
|
+
if (elements.includes(sibling)) {
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
element[RELATED_SIBLINGS].push(sibling);
|
|
310
|
+
sibling[RELATED_HEADING] = element;
|
|
311
|
+
observer.observe(sibling);
|
|
312
|
+
sibling = sibling.nextElementSibling;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
315
|
});
|
|
@@ -148,7 +148,7 @@ Widget.enforceProperty(function is_hidden(new_value) {
|
|
|
148
148
|
*
|
|
149
149
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
150
150
|
* @since 0.1.0
|
|
151
|
-
* @version 0.2.
|
|
151
|
+
* @version 0.2.5
|
|
152
152
|
*/
|
|
153
153
|
Widget.constitute(function prepareSchema() {
|
|
154
154
|
|
|
@@ -197,18 +197,57 @@ Widget.constitute(function prepareSchema() {
|
|
|
197
197
|
return true;
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
-
copy.setIcon('
|
|
200
|
+
copy.setIcon('copy');
|
|
201
201
|
copy.close_actionbar = true;
|
|
202
202
|
|
|
203
|
+
// Add the "replace from clipboard" action
|
|
204
|
+
let replace = this.createAction('replace', 'Replace from clipboard');
|
|
205
|
+
|
|
206
|
+
replace.setHandler(async function replaceAction(widget_el, handle) {
|
|
207
|
+
|
|
208
|
+
let config = await widget_el.getReplaceableConfigFromClipboard();
|
|
209
|
+
|
|
210
|
+
if (!config) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
widget_el.replaceWithConfig(config);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
replace.setTester(function replaceActionTester(widget_el, handle) {
|
|
218
|
+
return widget_el.getReplaceableConfigFromClipboard();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
replace.setIcon('repeat');
|
|
222
|
+
replace.close_actionbar = true;
|
|
223
|
+
|
|
203
224
|
// Add the "paste from clipboard" action
|
|
204
|
-
let paste = this.createAction('paste', '
|
|
225
|
+
let paste = this.createAction('paste', 'Paste from clipboard');
|
|
226
|
+
|
|
227
|
+
paste.setHandler(async function pasteAction(widget_el, handle) {
|
|
205
228
|
|
|
206
|
-
|
|
207
|
-
|
|
229
|
+
let config = await widget_el.getConfigFromClipboard();
|
|
230
|
+
|
|
231
|
+
if (!config) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
widget_el.addWidget(config.type, config.config);
|
|
208
236
|
});
|
|
209
237
|
|
|
210
|
-
paste.setTester(function
|
|
211
|
-
|
|
238
|
+
paste.setTester(async function pasteActionTester(widget_el, handle) {
|
|
239
|
+
|
|
240
|
+
if (!widget_el.addWidget) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let config = await widget_el.getConfigFromClipboard();
|
|
245
|
+
|
|
246
|
+
if (!config || config.type == 'container') {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return true;
|
|
212
251
|
});
|
|
213
252
|
|
|
214
253
|
paste.setIcon('paste');
|
|
@@ -489,7 +528,7 @@ Widget.setStatic(function unDry(obj, custom_method, whenDone) {
|
|
|
489
528
|
*
|
|
490
529
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
491
530
|
* @since 0.1.0
|
|
492
|
-
* @version 0.
|
|
531
|
+
* @version 0.2.6
|
|
493
532
|
*
|
|
494
533
|
* @param {String} type The typeof widget to create
|
|
495
534
|
* @param {Object} config The optional config object
|
|
@@ -507,6 +546,10 @@ Widget.setMethod(function createChildWidget(type, config) {
|
|
|
507
546
|
// Create the instance
|
|
508
547
|
let instance = new WidgetClass(config);
|
|
509
548
|
|
|
549
|
+
if (this.conduit) {
|
|
550
|
+
instance.conduit = this.conduit;
|
|
551
|
+
}
|
|
552
|
+
|
|
510
553
|
// Set the parent instance!
|
|
511
554
|
instance.parent_instance = this;
|
|
512
555
|
|
|
@@ -543,12 +586,16 @@ Widget.setMethod(function toDry() {
|
|
|
543
586
|
*
|
|
544
587
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
545
588
|
* @since 0.1.0
|
|
546
|
-
* @version 0.2.
|
|
589
|
+
* @version 0.2.6
|
|
547
590
|
*
|
|
548
591
|
* @return {Array}
|
|
549
592
|
*/
|
|
550
593
|
Widget.setMethod(async function getActionbarActions() {
|
|
551
594
|
|
|
595
|
+
if (!this.constructor.actions) {
|
|
596
|
+
return [];
|
|
597
|
+
}
|
|
598
|
+
|
|
552
599
|
let sorted = this.constructor.actions.getSorted(),
|
|
553
600
|
result = [],
|
|
554
601
|
action;
|
|
@@ -969,4 +1016,41 @@ Widget.setMethod(function getHandle() {
|
|
|
969
1016
|
}
|
|
970
1017
|
|
|
971
1018
|
return element;
|
|
1019
|
+
});
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* See if the given value is considered not-empty for this widget
|
|
1023
|
+
*
|
|
1024
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1025
|
+
* @since 0.2.6
|
|
1026
|
+
* @version 0.2.6
|
|
1027
|
+
*
|
|
1028
|
+
* @return {Boolean}
|
|
1029
|
+
*/
|
|
1030
|
+
Widget.setMethod(function valueHasContent(value) {
|
|
1031
|
+
|
|
1032
|
+
if (!value || typeof value != 'object') {
|
|
1033
|
+
return false;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
let entry,
|
|
1037
|
+
key;
|
|
1038
|
+
|
|
1039
|
+
for (key in value) {
|
|
1040
|
+
entry = value[key];
|
|
1041
|
+
|
|
1042
|
+
if (entry) {
|
|
1043
|
+
if (Array.isArray(entry) && entry.length) {
|
|
1044
|
+
return true;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
if (entry === '') {
|
|
1048
|
+
continue;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
return false;
|
|
972
1056
|
});
|
package/helper/widgets/html.js
CHANGED
|
@@ -17,11 +17,15 @@ const Html = Function.inherits('Alchemy.Widget', 'Html');
|
|
|
17
17
|
*
|
|
18
18
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
19
19
|
* @since 0.1.0
|
|
20
|
-
* @version 0.
|
|
20
|
+
* @version 0.2.5
|
|
21
21
|
*/
|
|
22
22
|
Html.constitute(function prepareSchema() {
|
|
23
23
|
// The actual HTML contents
|
|
24
|
-
this.schema.addField('html', 'Html'
|
|
24
|
+
this.schema.addField('html', 'Html', {
|
|
25
|
+
title : 'HTML',
|
|
26
|
+
description : 'The HTML sourcecode',
|
|
27
|
+
widget_config_editable : true,
|
|
28
|
+
});
|
|
25
29
|
});
|
|
26
30
|
|
|
27
31
|
/**
|
|
@@ -79,12 +83,24 @@ Html.setMethod(function _stopEditor() {
|
|
|
79
83
|
*
|
|
80
84
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
81
85
|
* @since 0.1.0
|
|
82
|
-
* @version 0.2.
|
|
86
|
+
* @version 0.2.5
|
|
83
87
|
*
|
|
84
88
|
* @param {HTMLElement} widget
|
|
85
89
|
*/
|
|
86
90
|
Html.setMethod(function populateWidget() {
|
|
87
|
-
|
|
91
|
+
|
|
92
|
+
let html = this.config.html;
|
|
93
|
+
|
|
94
|
+
if (html == null) {
|
|
95
|
+
html = '';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (this.ckeditor) {
|
|
99
|
+
|
|
100
|
+
this.ckeditor.setData(html);
|
|
101
|
+
} else {
|
|
102
|
+
this.widget.innerHTML = html;
|
|
103
|
+
}
|
|
88
104
|
});
|
|
89
105
|
|
|
90
106
|
/**
|
|
@@ -52,21 +52,35 @@ Markdown.setMethod(function populateWidget() {
|
|
|
52
52
|
*
|
|
53
53
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
54
54
|
* @since 0.1.0
|
|
55
|
-
* @version 0.2.
|
|
55
|
+
* @version 0.2.6
|
|
56
56
|
*/
|
|
57
57
|
Markdown.setMethod(async function _startEditor() {
|
|
58
58
|
|
|
59
59
|
Hawkejs.removeChildren(this.widget);
|
|
60
60
|
|
|
61
|
-
hawkejs.scene.enableStyle('https://
|
|
62
|
-
await hawkejs.require('https://
|
|
61
|
+
hawkejs.scene.enableStyle('https://uicdn.toast.com/editor/latest/toastui-editor.min.css');
|
|
62
|
+
await hawkejs.require('https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js');
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
const Editor = toastui.Editor
|
|
65
|
+
|
|
66
|
+
let element = this.createElement('div');
|
|
67
|
+
element.classList.add('markdown-editor-container');
|
|
65
68
|
this.widget.append(element);
|
|
66
|
-
element.value = this.config.markdown || '';
|
|
67
69
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
+
const editor = new Editor({
|
|
71
|
+
el : element,
|
|
72
|
+
height : '900px',
|
|
73
|
+
initialEditType : 'markdown',
|
|
74
|
+
previewStyle : 'vertical',
|
|
75
|
+
usageStatistics : false,
|
|
76
|
+
autofocus : false,
|
|
77
|
+
previewStyle : 'global',
|
|
78
|
+
hideModeSwitch : true,
|
|
79
|
+
initialEditType : 'markdown',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
this.toast_editor = editor;
|
|
83
|
+
editor.setMarkdown(this.config.markdown || '');
|
|
70
84
|
});
|
|
71
85
|
|
|
72
86
|
/**
|
|
@@ -74,12 +88,19 @@ Markdown.setMethod(async function _startEditor() {
|
|
|
74
88
|
*
|
|
75
89
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
76
90
|
* @since 0.1.0
|
|
77
|
-
* @version 0.2.
|
|
91
|
+
* @version 0.2.6
|
|
78
92
|
*/
|
|
79
93
|
Markdown.setMethod(function _stopEditor() {
|
|
80
94
|
|
|
81
95
|
Hawkejs.removeChildren(this.widget);
|
|
82
|
-
|
|
96
|
+
|
|
97
|
+
if (this.toast_editor) {
|
|
98
|
+
try {
|
|
99
|
+
this.toast_editor.destroy();
|
|
100
|
+
} catch (err) {}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.toast_editor = null;
|
|
83
104
|
|
|
84
105
|
return this.loadWidget();
|
|
85
106
|
});
|
|
@@ -89,7 +110,7 @@ Markdown.setMethod(function _stopEditor() {
|
|
|
89
110
|
*
|
|
90
111
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
91
112
|
* @since 0.1.0
|
|
92
|
-
* @version 0.2.
|
|
113
|
+
* @version 0.2.6
|
|
93
114
|
*
|
|
94
115
|
* @return {Object}
|
|
95
116
|
*/
|
|
@@ -97,8 +118,8 @@ Markdown.setMethod(function syncConfig() {
|
|
|
97
118
|
|
|
98
119
|
let value = '';
|
|
99
120
|
|
|
100
|
-
if (this.
|
|
101
|
-
value = this.
|
|
121
|
+
if (this.toast_editor) {
|
|
122
|
+
value = this.toast_editor.getMarkdown();
|
|
102
123
|
}
|
|
103
124
|
|
|
104
125
|
this.config.markdown = value;
|
|
@@ -16,11 +16,18 @@ const Sourcecode = Function.inherits('Alchemy.Widget', 'Sourcecode');
|
|
|
16
16
|
*
|
|
17
17
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
18
18
|
* @since 0.1.0
|
|
19
|
-
* @version 0.
|
|
19
|
+
* @version 0.2.5
|
|
20
20
|
*/
|
|
21
21
|
Sourcecode.constitute(function prepareSchema() {
|
|
22
22
|
// The actual sourcecode contents
|
|
23
23
|
this.schema.addField('sourcecode', 'Text');
|
|
24
|
+
|
|
25
|
+
// The type of sourcecode
|
|
26
|
+
this.schema.addField('code_type', 'String', {
|
|
27
|
+
title : 'Code type',
|
|
28
|
+
description : 'The type of sourcecode',
|
|
29
|
+
widget_config_editable : true,
|
|
30
|
+
});
|
|
24
31
|
});
|
|
25
32
|
|
|
26
33
|
/**
|
|
@@ -37,7 +44,7 @@ Sourcecode.setProperty('sourcecode_field', 'sourcecode');
|
|
|
37
44
|
*
|
|
38
45
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
39
46
|
* @since 0.1.0
|
|
40
|
-
* @version 0.2.
|
|
47
|
+
* @version 0.2.5
|
|
41
48
|
*
|
|
42
49
|
* @param {HTMLElement} widget
|
|
43
50
|
*/
|
|
@@ -53,7 +60,12 @@ Sourcecode.setMethod(function populateWidget() {
|
|
|
53
60
|
pre = this.createElement('pre');
|
|
54
61
|
|
|
55
62
|
pre.append(code);
|
|
56
|
-
code.
|
|
63
|
+
code.textContent = source;
|
|
64
|
+
|
|
65
|
+
if (this.config.code_type) {
|
|
66
|
+
code.classList.add('language-' + this.config.code_type);
|
|
67
|
+
pre.classList.add('language-' + this.config.code_type);
|
|
68
|
+
}
|
|
57
69
|
|
|
58
70
|
this.widget.append(pre);
|
|
59
71
|
});
|
package/helper_field/widget.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
7
7
|
* @since 0.1.0
|
|
8
|
-
* @version 0.
|
|
8
|
+
* @version 0.2.6
|
|
9
9
|
*/
|
|
10
10
|
const WidgetField = Function.inherits('Alchemy.Field.Schema', function Widget(schema, name, options) {
|
|
11
11
|
|
|
@@ -17,12 +17,15 @@ const WidgetField = Function.inherits('Alchemy.Field.Schema', function Widget(sc
|
|
|
17
17
|
options.type = 'text';
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// Already set the options (they'll be changed by the super call too though)
|
|
21
|
+
this.options = options;
|
|
22
|
+
|
|
20
23
|
// A custom schema should NOT be passed to this class, this class uses
|
|
21
24
|
// a fixed schema that should not be altered.
|
|
22
25
|
// But because that's exactly what happens when cloning (like preparing
|
|
23
26
|
// the data to be sent to Hawkejs) we have to allow it anyway
|
|
24
27
|
if (!options.schema) {
|
|
25
|
-
let WidgetClass =
|
|
28
|
+
let WidgetClass = this.widget_class,
|
|
26
29
|
sub_schema = WidgetClass.schema.clone();
|
|
27
30
|
|
|
28
31
|
options.schema = sub_schema;
|
|
@@ -31,6 +34,24 @@ const WidgetField = Function.inherits('Alchemy.Field.Schema', function Widget(sc
|
|
|
31
34
|
Widget.super.call(this, schema, name, options);
|
|
32
35
|
});
|
|
33
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Get the constructor of the widget class
|
|
39
|
+
*
|
|
40
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
41
|
+
* @since 0.2.6
|
|
42
|
+
* @version 0.2.6
|
|
43
|
+
*
|
|
44
|
+
* @type {Function}
|
|
45
|
+
*/
|
|
46
|
+
WidgetField.setProperty(function widget_class() {
|
|
47
|
+
|
|
48
|
+
if (!this.options?.type) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return Classes.Alchemy.Widget.Widget.getMember(this.options.type)
|
|
53
|
+
});
|
|
54
|
+
|
|
34
55
|
/**
|
|
35
56
|
* Cast the given value to this field's type
|
|
36
57
|
*
|
|
@@ -75,3 +96,33 @@ WidgetField.setMethod(function toDry() {
|
|
|
75
96
|
|
|
76
97
|
return {value};
|
|
77
98
|
});
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* See if the given value is considered not-empty for this field
|
|
102
|
+
*
|
|
103
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
104
|
+
* @since 0.2.6
|
|
105
|
+
* @version 0.2.6
|
|
106
|
+
*
|
|
107
|
+
* @param {Mixed} value
|
|
108
|
+
*
|
|
109
|
+
* @return {Boolean}
|
|
110
|
+
*/
|
|
111
|
+
WidgetField.setMethod(function valueHasContent(value) {
|
|
112
|
+
|
|
113
|
+
if (!value) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let constructor = this.widget_class;
|
|
118
|
+
|
|
119
|
+
if (!constructor) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
value = this.cast(value);
|
|
124
|
+
|
|
125
|
+
let instance = new constructor();
|
|
126
|
+
|
|
127
|
+
return instance.valueHasContent(value);
|
|
128
|
+
});
|
package/helper_field/widgets.js
CHANGED
|
@@ -36,4 +36,28 @@ const WidgetsField = Function.inherits('Alchemy.Field.Schema', function Widgets(
|
|
|
36
36
|
WidgetsField.setMethod(function getOptionsForDrying() {
|
|
37
37
|
let {schema, ...options} = this.options;
|
|
38
38
|
return options;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* See if the given value is considered not-empty for this field
|
|
43
|
+
*
|
|
44
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
45
|
+
* @since 0.2.6
|
|
46
|
+
* @version 0.2.6
|
|
47
|
+
*
|
|
48
|
+
* @param {Mixed} value
|
|
49
|
+
*
|
|
50
|
+
* @return {Boolean}
|
|
51
|
+
*/
|
|
52
|
+
WidgetsField.setMethod(function valueHasContent(value) {
|
|
53
|
+
|
|
54
|
+
if (!value) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!value.widgets?.length) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return true;
|
|
39
63
|
});
|
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.2.
|
|
4
|
+
"version": "0.2.6",
|
|
5
5
|
"author": "Jelle De Loecker <jelle@elevenways.be>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"alchemy",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"alchemymvc" : ">=1.2.0",
|
|
14
|
-
"alchemy-form": "~0.2.
|
|
14
|
+
"alchemy-form": "~0.2.4"
|
|
15
15
|
},
|
|
16
16
|
"repository": "11ways/alchemy-widget",
|
|
17
17
|
"license": "MIT",
|