alchemy-widget 0.2.0 → 0.2.2
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 +24 -0
- package/assets/stylesheets/alchemy_widgets.scss +13 -8
- package/bootstrap.js +97 -0
- package/controller/alchemy_widgets_controller.js +64 -0
- package/element/00-widget_base_element.js +13 -4
- package/element/05-widget_element.js +31 -10
- package/element/10-container_elements.js +12 -17
- package/element/table_of_contents_element.js +44 -7
- package/helper/widgets/00-widget.js +223 -16
- package/helper/widgets/01-container.js +23 -3
- package/helper/widgets/alchemy_tabs_widget.js +2 -4
- package/helper/widgets/hawkejs_template.js +60 -0
- package/helper/widgets/header.js +5 -7
- package/helper/widgets/html.js +52 -3
- package/helper/widgets/markdown.js +3 -5
- package/helper/widgets/partial.js +3 -5
- package/helper/widgets/sourcecode.js +3 -5
- package/helper/widgets/table_of_contents.js +1 -3
- package/helper/widgets/text.js +15 -15
- package/package.json +2 -2
- package/view/elements/table_of_contents.hwk +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 0.2.2 (2022-12-23)
|
|
2
|
+
|
|
3
|
+
* Fix widgets not being populated properly
|
|
4
|
+
|
|
5
|
+
## 0.2.1 (2022-12-23)
|
|
6
|
+
|
|
7
|
+
* Add a `-first` modifier class to the first visible entry of a table-of-contents element
|
|
8
|
+
* Make HTML widget editable
|
|
9
|
+
* Also store and retrieve copied widget config from localStorage
|
|
10
|
+
* Move `Container` widget init logic from the custom-element to the main widget instance
|
|
11
|
+
* Disable most `backdrop-filter` properties, they caused too many FPS issues
|
|
12
|
+
* Add the ability to hide widgets from the public
|
|
13
|
+
* Allow overriding the language (`lang` attribute) of a widget
|
|
14
|
+
* Fix config of container widgets not being saved
|
|
15
|
+
* Only add minium dimensions when editing
|
|
16
|
+
* Add `child-role` attribute & use it to set the default role of child widgets
|
|
17
|
+
* Add the `toc-has-content` or `toc-is-empty` class to `al-toc` elements
|
|
18
|
+
* Fix issue where `Text` widget would break when edited with LanguageTool extension
|
|
19
|
+
* Do not truncate titles in table-of-contents automatically
|
|
20
|
+
* Fix nesting levels in `al-toc`
|
|
21
|
+
* Only allow text inside header widgets
|
|
22
|
+
* Move default `Widget#populateWidget()` code to `Widget#finalizePopulatedWidget()`
|
|
23
|
+
* Add `HawkejsTemplate` widget
|
|
24
|
+
|
|
1
25
|
## 0.2.0 (2022-11-02)
|
|
2
26
|
|
|
3
27
|
* Use `al-` prefix for all custom elements
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
al-widget-toolbar {
|
|
3
3
|
display: none;
|
|
4
4
|
}
|
|
5
|
+
|
|
6
|
+
[hidden] {
|
|
7
|
+
display: none !important;
|
|
8
|
+
}
|
|
5
9
|
}
|
|
6
10
|
|
|
7
11
|
html.logged-in {
|
|
@@ -110,6 +114,7 @@ al-widgets-column {
|
|
|
110
114
|
&.aw-editing {
|
|
111
115
|
position: relative;
|
|
112
116
|
min-height: 3rem;
|
|
117
|
+
min-width: 10rem;
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
> * {
|
|
@@ -127,7 +132,7 @@ al-widget {
|
|
|
127
132
|
background: white;
|
|
128
133
|
border: 2px dashed rgba(0, 0, 0, 0.4);
|
|
129
134
|
pointer-events: none;
|
|
130
|
-
backdrop-filter: invert(80%);
|
|
135
|
+
//backdrop-filter: invert(80%);
|
|
131
136
|
clip-path: polygon(0% 0%, 0% 100%, 2px 100%, 2px 2px, calc(100% - 2px) 2px, calc(100% - 2px) calc(100% - 2px), 0 calc(100% - 2px), 0 100%, 100% 100%, 100% 0)
|
|
132
137
|
}
|
|
133
138
|
}
|
|
@@ -159,11 +164,6 @@ al-widgets-column {
|
|
|
159
164
|
}
|
|
160
165
|
}
|
|
161
166
|
|
|
162
|
-
al-widgets {
|
|
163
|
-
min-width: 10rem;
|
|
164
|
-
min-height: 10rem;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
167
|
al-widgets-row {
|
|
168
168
|
flex-flow: row;
|
|
169
169
|
flex: 10 10 auto;
|
|
@@ -287,12 +287,13 @@ al-widget {
|
|
|
287
287
|
|
|
288
288
|
&.aw-editing {
|
|
289
289
|
min-height: 2rem;
|
|
290
|
+
min-width: 2rem;
|
|
290
291
|
|
|
291
292
|
&:hover {
|
|
292
293
|
background: rgba(60, 60, 120, 0.2);
|
|
293
294
|
|
|
294
|
-
// This actually causes some glitches on Firefox :/
|
|
295
|
-
backdrop-filter: blur(4px);
|
|
295
|
+
// This actually causes some glitches on Firefox and chrome too :/
|
|
296
|
+
//backdrop-filter: blur(4px);
|
|
296
297
|
}
|
|
297
298
|
}
|
|
298
299
|
|
|
@@ -423,4 +424,8 @@ al-toc {
|
|
|
423
424
|
display: block;
|
|
424
425
|
}
|
|
425
426
|
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.aw-hidden {
|
|
430
|
+
opacity: 0.8;
|
|
426
431
|
}
|
package/bootstrap.js
CHANGED
|
@@ -4,9 +4,106 @@ if (!alchemy.plugins.form) {
|
|
|
4
4
|
throw new Error('The alchemy-form plugin has to be loaded BEFORE alchemy-widget');
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
/* Ckeditor 5 available toolbar buttons (from styleboost build)
|
|
8
|
+
[
|
|
9
|
+
"blockQuote",
|
|
10
|
+
"bold",
|
|
11
|
+
"code",
|
|
12
|
+
"codeBlock",
|
|
13
|
+
"selectAll",
|
|
14
|
+
"undo",
|
|
15
|
+
"redo",
|
|
16
|
+
"heading",
|
|
17
|
+
"horizontalLine",
|
|
18
|
+
"imageTextAlternative",
|
|
19
|
+
"toggleImageCaption",
|
|
20
|
+
"imageStyle:inline",
|
|
21
|
+
"imageStyle:alignLeft",
|
|
22
|
+
"imageStyle:alignRight",
|
|
23
|
+
"imageStyle:alignCenter",
|
|
24
|
+
"imageStyle:alignBlockLeft",
|
|
25
|
+
"imageStyle:alignBlockRight",
|
|
26
|
+
"imageStyle:block",
|
|
27
|
+
"imageStyle:side",
|
|
28
|
+
"imageStyle:wrapText",
|
|
29
|
+
"imageStyle:breakText",
|
|
30
|
+
"uploadImage",
|
|
31
|
+
"imageUpload",
|
|
32
|
+
"indent",
|
|
33
|
+
"outdent",
|
|
34
|
+
"italic",
|
|
35
|
+
"link",
|
|
36
|
+
"linkImage",
|
|
37
|
+
"numberedList",
|
|
38
|
+
"bulletedList",
|
|
39
|
+
"mediaEmbed",
|
|
40
|
+
"removeFormat",
|
|
41
|
+
"sourceEditing",
|
|
42
|
+
"strikethrough",
|
|
43
|
+
"insertTable",
|
|
44
|
+
"tableColumn",
|
|
45
|
+
"tableRow",
|
|
46
|
+
"mergeTableCells",
|
|
47
|
+
"toggleTableCaption",
|
|
48
|
+
"tableCellProperties",
|
|
49
|
+
"tableProperties",
|
|
50
|
+
"todoList"
|
|
51
|
+
]
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
let options = {
|
|
55
|
+
ckeditor_path: null,
|
|
56
|
+
ckeditor_toolbar: [
|
|
57
|
+
'heading',
|
|
58
|
+
'|',
|
|
59
|
+
'bold', 'italic', 'link', 'bulletedList', 'numberedList',
|
|
60
|
+
'|',
|
|
61
|
+
'indent',
|
|
62
|
+
'outdent',
|
|
63
|
+
'horizontalLine',
|
|
64
|
+
'|',
|
|
65
|
+
'blockQuote',
|
|
66
|
+
'code',
|
|
67
|
+
'codeBlock',
|
|
68
|
+
'|',
|
|
69
|
+
'imageUpload',
|
|
70
|
+
'insertTable',
|
|
71
|
+
'|',
|
|
72
|
+
'undo', 'redo',
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Inject the user-overridden options
|
|
77
|
+
alchemy.plugins.widget = Object.assign(options, alchemy.plugins.widget);
|
|
78
|
+
|
|
79
|
+
if (!options.ckeditor_path) {
|
|
80
|
+
if (alchemy.plugins.styleboost) {
|
|
81
|
+
options.ckeditor_path = '/public/ckeditor/5/ckeditor.js';
|
|
82
|
+
} else {
|
|
83
|
+
options.ckeditor_path = 'https://cdn.ckeditor.com/ckeditor5/35.3.2/inline/ckeditor.js';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (options.ckeditor_path) {
|
|
88
|
+
alchemy.exposeStatic('ckeditor_path', options.ckeditor_path);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (options.ckeditor_toolbar) {
|
|
92
|
+
alchemy.exposeStatic('ckeditor_toolbar', options.ckeditor_toolbar);
|
|
93
|
+
}
|
|
94
|
+
|
|
7
95
|
Router.add({
|
|
8
96
|
name : 'AlchemyWidgets#save',
|
|
9
97
|
methods : 'post',
|
|
10
98
|
paths : '/api/alchemywidgets/save',
|
|
11
99
|
policy : 'logged_in',
|
|
100
|
+
permission : 'alchemy.widgets.save',
|
|
12
101
|
});
|
|
102
|
+
|
|
103
|
+
Router.add({
|
|
104
|
+
name : 'AlchemyWidgets#uploadImage',
|
|
105
|
+
methods : 'post',
|
|
106
|
+
paths : '/api/alchemywidgets/upload',
|
|
107
|
+
policy : 'logged_in',
|
|
108
|
+
permission : 'alchemy.widgets.image.upload',
|
|
109
|
+
});
|
|
@@ -184,4 +184,68 @@ AlchemyWidgets.setAction(async function save(conduit) {
|
|
|
184
184
|
};
|
|
185
185
|
|
|
186
186
|
conduit.end(result);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Handle an image upload from within CKeditor
|
|
191
|
+
*
|
|
192
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
193
|
+
* @since 0.2.1
|
|
194
|
+
* @version 0.2.1
|
|
195
|
+
*/
|
|
196
|
+
AlchemyWidgets.setAction(async function uploadImage(conduit) {
|
|
197
|
+
|
|
198
|
+
let file = conduit.files.upload;
|
|
199
|
+
|
|
200
|
+
const MediaFile = this.getModel('MediaFile');
|
|
201
|
+
|
|
202
|
+
let name = file.name.split('.');
|
|
203
|
+
|
|
204
|
+
// Remove the last piece if there are more than 1
|
|
205
|
+
if (name.length > 1) {
|
|
206
|
+
name.pop();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Join them again
|
|
210
|
+
name = name.join('.');
|
|
211
|
+
|
|
212
|
+
const options = {
|
|
213
|
+
move : true,
|
|
214
|
+
filename : file.name,
|
|
215
|
+
name : name,
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
MediaFile.addFile(file.path, options, (err, result) => {
|
|
219
|
+
|
|
220
|
+
if (err) {
|
|
221
|
+
return conduit.error(err);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const params = {
|
|
225
|
+
id : result._id,
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
let default_path = alchemy.routeUrl('Media::image', params);
|
|
229
|
+
let url = RURL.parse(default_path);
|
|
230
|
+
|
|
231
|
+
let path_800 = url.clone();
|
|
232
|
+
path_800.param('width', '800');
|
|
233
|
+
|
|
234
|
+
let path_1024 = url.clone();
|
|
235
|
+
path_1024.param('height', '1024');
|
|
236
|
+
|
|
237
|
+
let path_1920 = url.clone();
|
|
238
|
+
path_1920.param('width', '1920');
|
|
239
|
+
|
|
240
|
+
let response = {
|
|
241
|
+
urls: {
|
|
242
|
+
default : default_path,
|
|
243
|
+
'800' : path_800+'',
|
|
244
|
+
'1024' : path_1024+'',
|
|
245
|
+
'1920' : path_1920+''
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
conduit.end(response);
|
|
250
|
+
});
|
|
187
251
|
});
|
|
@@ -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.1
|
|
368
368
|
*/
|
|
369
369
|
Base.setMethod(async function copyConfigToClipboard() {
|
|
370
370
|
|
|
@@ -377,11 +377,15 @@ Base.setMethod(async function copyConfigToClipboard() {
|
|
|
377
377
|
value._altype = 'widget';
|
|
378
378
|
value.type = this.type;
|
|
379
379
|
|
|
380
|
+
let dried = JSON.dry(value, null, '\t');
|
|
381
|
+
|
|
380
382
|
try {
|
|
381
|
-
await navigator.clipboard.writeText(
|
|
383
|
+
await navigator.clipboard.writeText(dried);
|
|
382
384
|
} catch (err) {
|
|
383
385
|
console.error('Failed to copy:', err);
|
|
384
386
|
}
|
|
387
|
+
|
|
388
|
+
localStorage._copied_widget_config = dried;
|
|
385
389
|
});
|
|
386
390
|
|
|
387
391
|
/**
|
|
@@ -389,7 +393,7 @@ Base.setMethod(async function copyConfigToClipboard() {
|
|
|
389
393
|
*
|
|
390
394
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
391
395
|
* @since 0.2.0
|
|
392
|
-
* @version 0.2.
|
|
396
|
+
* @version 0.2.1
|
|
393
397
|
*/
|
|
394
398
|
Base.setMethod(async function getConfigFromClipboard() {
|
|
395
399
|
|
|
@@ -398,7 +402,12 @@ Base.setMethod(async function getConfigFromClipboard() {
|
|
|
398
402
|
try {
|
|
399
403
|
result = await navigator.clipboard.readText();
|
|
400
404
|
} catch (err) {
|
|
401
|
-
|
|
405
|
+
|
|
406
|
+
if (!localStorage._copied_widget_config) {
|
|
407
|
+
return false;
|
|
408
|
+
} else {
|
|
409
|
+
result = localStorage._copied_widget_config;
|
|
410
|
+
}
|
|
402
411
|
}
|
|
403
412
|
|
|
404
413
|
if (result) {
|
|
@@ -79,6 +79,15 @@ Widget.setAssignedProperty('filter_value');
|
|
|
79
79
|
*/
|
|
80
80
|
Widget.setAttribute('child-class');
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* A role to give to each child widgets
|
|
84
|
+
*
|
|
85
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
86
|
+
* @since 0.2.1
|
|
87
|
+
* @version 0.2.1
|
|
88
|
+
*/
|
|
89
|
+
Widget.setAttribute('child-role');
|
|
90
|
+
|
|
82
91
|
/**
|
|
83
92
|
* Is this widget being edited?
|
|
84
93
|
*
|
|
@@ -206,7 +215,7 @@ Widget.setMethod(function getValueFromRecord(record) {
|
|
|
206
215
|
*
|
|
207
216
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
208
217
|
* @since 0.1.5
|
|
209
|
-
* @version 0.1
|
|
218
|
+
* @version 0.2.1
|
|
210
219
|
*/
|
|
211
220
|
Widget.setMethod(function applyValue(value) {
|
|
212
221
|
|
|
@@ -246,7 +255,7 @@ Widget.setMethod(function applyValue(value) {
|
|
|
246
255
|
}
|
|
247
256
|
|
|
248
257
|
this.instance.config = config;
|
|
249
|
-
let promise = this.instance.
|
|
258
|
+
let promise = this.instance.loadWidget();
|
|
250
259
|
|
|
251
260
|
if (promise) {
|
|
252
261
|
this.delayAssemble(promise);
|
|
@@ -269,13 +278,11 @@ Widget.setMethod(function syncConfig() {
|
|
|
269
278
|
*
|
|
270
279
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
271
280
|
* @since 0.1.0
|
|
272
|
-
* @version 0.1
|
|
281
|
+
* @version 0.2.1
|
|
273
282
|
*/
|
|
274
283
|
Widget.setMethod(function startEditor() {
|
|
275
284
|
|
|
276
|
-
|
|
277
|
-
throw new Error('Unable to start the editor: this widget element has no accompanying instance');
|
|
278
|
-
}
|
|
285
|
+
this.assertWidgetInstance();
|
|
279
286
|
|
|
280
287
|
this.instance.startEditor();
|
|
281
288
|
this.addEditEventListeners();
|
|
@@ -286,19 +293,33 @@ Widget.setMethod(function startEditor() {
|
|
|
286
293
|
*
|
|
287
294
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
288
295
|
* @since 0.1.0
|
|
289
|
-
* @version 0.1
|
|
296
|
+
* @version 0.2.1
|
|
290
297
|
*/
|
|
291
298
|
Widget.setMethod(function stopEditor() {
|
|
292
299
|
|
|
293
|
-
|
|
294
|
-
throw new Error('Unable to stop the editor: this widget element has no accompanying instance');
|
|
295
|
-
}
|
|
300
|
+
this.assertWidgetInstance();
|
|
296
301
|
|
|
297
302
|
this.unselectWidget();
|
|
298
303
|
this.instance.stopEditor();
|
|
299
304
|
this.removeEditEventListeners();
|
|
300
305
|
});
|
|
301
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Make sure there is an instance
|
|
309
|
+
*
|
|
310
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
311
|
+
* @since 0.2.1
|
|
312
|
+
* @version 0.2.1
|
|
313
|
+
*/
|
|
314
|
+
Widget.setMethod(function assertWidgetInstance() {
|
|
315
|
+
|
|
316
|
+
if (!this.instance) {
|
|
317
|
+
console.error('Problem with widget element:', this);
|
|
318
|
+
throw new Error('Unable to stop the editor: this ' + this.tagName + ' element has no accompanying instance');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
});
|
|
322
|
+
|
|
302
323
|
/**
|
|
303
324
|
* Mouse click
|
|
304
325
|
*
|
|
@@ -62,21 +62,22 @@ AlchemyWidgets.setAssignedProperty('context_variables', function getContextData(
|
|
|
62
62
|
*
|
|
63
63
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
64
64
|
* @since 0.1.0
|
|
65
|
-
* @version 0.1
|
|
65
|
+
* @version 0.2.1
|
|
66
66
|
*/
|
|
67
67
|
AlchemyWidgets.setProperty(function value() {
|
|
68
68
|
|
|
69
|
-
let
|
|
69
|
+
let config = this.instance.config,
|
|
70
|
+
widgets = this.getWidgetsConfig(),
|
|
70
71
|
result;
|
|
72
|
+
|
|
73
|
+
config = Object.assign({}, config, {widgets});
|
|
71
74
|
|
|
72
75
|
if (this.nodeName == 'AL-WIDGETS') {
|
|
73
|
-
result =
|
|
76
|
+
result = config;
|
|
74
77
|
} else {
|
|
75
78
|
result = {
|
|
76
79
|
type : this.instance.constructor.type_name,
|
|
77
|
-
config :
|
|
78
|
-
widgets : widgets
|
|
79
|
-
}
|
|
80
|
+
config : config,
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -91,7 +92,7 @@ AlchemyWidgets.setProperty(function value() {
|
|
|
91
92
|
*
|
|
92
93
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
93
94
|
* @since 0.1.5
|
|
94
|
-
* @version 0.1
|
|
95
|
+
* @version 0.2.1
|
|
95
96
|
*/
|
|
96
97
|
AlchemyWidgets.setMethod(function applyValue(value) {
|
|
97
98
|
|
|
@@ -119,24 +120,18 @@ AlchemyWidgets.setMethod(function applyValue(value) {
|
|
|
119
120
|
if (config.class_names) {
|
|
120
121
|
Hawkejs.addClasses(this, config.class_names);
|
|
121
122
|
}
|
|
123
|
+
} else {
|
|
124
|
+
config = this.instance?.config || {};
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
if (!this.instance) {
|
|
125
128
|
return;
|
|
126
129
|
}
|
|
127
130
|
|
|
131
|
+
config.widgets = widgets;
|
|
132
|
+
|
|
128
133
|
this.instance.config = config;
|
|
129
134
|
this.instance.initContainer();
|
|
130
|
-
|
|
131
|
-
if (!widgets || !widgets.length) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
let widget;
|
|
136
|
-
|
|
137
|
-
for (widget of widgets) {
|
|
138
|
-
this.addWidget(widget.type, widget.config);
|
|
139
|
-
}
|
|
140
135
|
});
|
|
141
136
|
|
|
142
137
|
/**
|
|
@@ -88,12 +88,21 @@ TableOfContents.setAttribute('title-selector');
|
|
|
88
88
|
*/
|
|
89
89
|
TableOfContents.setAttribute('intersection-class');
|
|
90
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
|
+
|
|
91
100
|
/**
|
|
92
101
|
* Get the entries
|
|
93
102
|
*
|
|
94
103
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
95
104
|
* @since 0.1.2
|
|
96
|
-
* @version 0.2.
|
|
105
|
+
* @version 0.2.1
|
|
97
106
|
*/
|
|
98
107
|
TableOfContents.setProperty(function entries() {
|
|
99
108
|
|
|
@@ -138,7 +147,7 @@ TableOfContents.setProperty(function entries() {
|
|
|
138
147
|
|
|
139
148
|
let title_element,
|
|
140
149
|
starts_level,
|
|
141
|
-
|
|
150
|
+
ends_level;
|
|
142
151
|
|
|
143
152
|
if (this.title_selector) {
|
|
144
153
|
title_element = element.querySelector(this.title_selector);
|
|
@@ -155,7 +164,10 @@ TableOfContents.setProperty(function entries() {
|
|
|
155
164
|
current_level = heading_level;
|
|
156
165
|
} else if (heading_level > current_level) {
|
|
157
166
|
current_level++;
|
|
158
|
-
|
|
167
|
+
|
|
168
|
+
if (last_entry) {
|
|
169
|
+
last_entry.starts_level = true;
|
|
170
|
+
}
|
|
159
171
|
} else if (heading_level == current_level && last_entry) {
|
|
160
172
|
last_entry.starts_level = false;
|
|
161
173
|
} else if (heading_level < current_level) {
|
|
@@ -169,7 +181,9 @@ TableOfContents.setProperty(function entries() {
|
|
|
169
181
|
|
|
170
182
|
title = (title_element.toc_title || title_element.textContent || '').trim();
|
|
171
183
|
|
|
172
|
-
|
|
184
|
+
if (this.truncate_length) {
|
|
185
|
+
title = title.truncate(this.truncate_length);
|
|
186
|
+
}
|
|
173
187
|
|
|
174
188
|
// Don't add empty titles
|
|
175
189
|
if (!title) {
|
|
@@ -191,7 +205,7 @@ TableOfContents.setProperty(function entries() {
|
|
|
191
205
|
let ended_level = false,
|
|
192
206
|
entries = result,
|
|
193
207
|
current_branch,
|
|
194
|
-
|
|
208
|
+
current_nodes = [];
|
|
195
209
|
|
|
196
210
|
result = current_nodes;
|
|
197
211
|
last_entry = null;
|
|
@@ -255,7 +269,7 @@ TableOfContents.setProperty(function entries() {
|
|
|
255
269
|
*
|
|
256
270
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
257
271
|
* @since 0.1.2
|
|
258
|
-
* @version 0.1
|
|
272
|
+
* @version 0.2.1
|
|
259
273
|
*/
|
|
260
274
|
TableOfContents.setMethod(async function introduced() {
|
|
261
275
|
|
|
@@ -263,7 +277,8 @@ TableOfContents.setMethod(async function introduced() {
|
|
|
263
277
|
|
|
264
278
|
const observer = new IntersectionObserver(entries => {
|
|
265
279
|
|
|
266
|
-
let class_name = this.intersection_class || 'visible'
|
|
280
|
+
let class_name = this.intersection_class || 'visible',
|
|
281
|
+
first_name = class_name + '-first';
|
|
267
282
|
|
|
268
283
|
for (let entry of entries) {
|
|
269
284
|
const id = entry.target.getAttribute('id');
|
|
@@ -281,6 +296,28 @@ TableOfContents.setMethod(async function introduced() {
|
|
|
281
296
|
element.classList.remove(class_name);
|
|
282
297
|
}
|
|
283
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
|
+
|
|
284
321
|
});
|
|
285
322
|
|
|
286
323
|
for (let entry of this.entries) {
|