lexgui 0.2.0 → 0.4.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.
- package/build/components/timeline.js +47 -25
- package/build/lexgui.css +938 -328
- package/build/lexgui.js +1608 -459
- package/build/lexgui.min.css +1 -1
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +1608 -459
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +34 -2
- package/demo.js +2 -5
- package/examples/index.html +0 -3
- package/examples/previews/side_bar.png +0 -0
- package/examples/side_bar.html +43 -11
- package/package.json +1 -1
package/build/lexgui.js
CHANGED
|
@@ -12,11 +12,12 @@ console.warn( 'Script _build/lexgui.js_ is depracated and will be removed soon.
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
var LX = {
|
|
15
|
-
version: "0.
|
|
15
|
+
version: "0.4.0",
|
|
16
16
|
ready: false,
|
|
17
|
-
components: [], //
|
|
18
|
-
signals: {}, //
|
|
19
|
-
extraCommandbarEntries: [] //
|
|
17
|
+
components: [], // Specific pre-build components
|
|
18
|
+
signals: {}, // Events and triggers
|
|
19
|
+
extraCommandbarEntries: [], // User specific entries for command bar
|
|
20
|
+
activeDraggable: null // Watch for the current active draggable
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
LX.MOUSE_LEFT_CLICK = 0;
|
|
@@ -29,6 +30,8 @@ LX.MOUSE_TRIPLE_CLICK = 3;
|
|
|
29
30
|
LX.CURVE_MOVEOUT_CLAMP = 0;
|
|
30
31
|
LX.CURVE_MOVEOUT_DELETE = 1;
|
|
31
32
|
|
|
33
|
+
LX.DRAGGABLE_Z_INDEX = 101;
|
|
34
|
+
|
|
32
35
|
function clamp( num, min, max ) { return Math.min( Math.max( num, min ), max ); }
|
|
33
36
|
function round( number, precision ) { return precision == 0 ? Math.floor( number ) : +(( number ).toFixed( precision ?? 2 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' )); }
|
|
34
37
|
function remapRange( oldValue, oldMin, oldMax, newMin, newMax ) { return ((( oldValue - oldMin ) * ( newMax - newMin )) / ( oldMax - oldMin )) + newMin; }
|
|
@@ -88,7 +91,7 @@ LX.doAsync = doAsync;
|
|
|
88
91
|
*/
|
|
89
92
|
function getSupportedDOMName( text )
|
|
90
93
|
{
|
|
91
|
-
return text.replace(/\s/g, '').replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll('.', '');
|
|
94
|
+
return text.replace( /\s/g, '' ).replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll( '.', '' );
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
LX.getSupportedDOMName = getSupportedDOMName;
|
|
@@ -227,7 +230,8 @@ LX.hexToRgb = hexToRgb;
|
|
|
227
230
|
function rgbToHex( rgb )
|
|
228
231
|
{
|
|
229
232
|
let hex = "#";
|
|
230
|
-
for( let c of rgb )
|
|
233
|
+
for( let c of rgb )
|
|
234
|
+
{
|
|
231
235
|
c = Math.floor( c * 255 );
|
|
232
236
|
hex += c.toString( 16 );
|
|
233
237
|
}
|
|
@@ -302,7 +306,7 @@ LX.buildTextPattern = buildTextPattern;
|
|
|
302
306
|
|
|
303
307
|
/**
|
|
304
308
|
* @method makeDraggable
|
|
305
|
-
* @description
|
|
309
|
+
* @description Allows an element to be dragged
|
|
306
310
|
* @param {Element} domEl
|
|
307
311
|
* @param {Object} options
|
|
308
312
|
* autoAdjust (Bool): Sets in a correct position at the beggining
|
|
@@ -327,6 +331,7 @@ function makeDraggable( domEl, options = { } )
|
|
|
327
331
|
top = top ?? e.clientY - offsetY - parentRect.y;
|
|
328
332
|
domEl.style.left = clamp( left, dragMargin + fixedOffset.x, fixedOffset.x + parentRect.width - domEl.offsetWidth - dragMargin ) + 'px';
|
|
329
333
|
domEl.style.top = clamp( top, dragMargin + fixedOffset.y, fixedOffset.y + parentRect.height - domEl.offsetHeight - dragMargin ) + 'px';
|
|
334
|
+
domEl.style.translate = "none"; // Force remove translation
|
|
330
335
|
};
|
|
331
336
|
|
|
332
337
|
// Initial adjustment
|
|
@@ -371,26 +376,45 @@ function makeDraggable( domEl, options = { } )
|
|
|
371
376
|
e.preventDefault();
|
|
372
377
|
e.stopPropagation();
|
|
373
378
|
e.stopImmediatePropagation();
|
|
374
|
-
|
|
379
|
+
|
|
380
|
+
if( !currentTarget )
|
|
381
|
+
{
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
375
385
|
// Remove image when dragging
|
|
376
386
|
var img = new Image();
|
|
377
387
|
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=';
|
|
378
388
|
e.dataTransfer.setDragImage( img, 0, 0 );
|
|
379
389
|
e.dataTransfer.effectAllowed = "move";
|
|
390
|
+
|
|
380
391
|
const rect = e.target.getBoundingClientRect();
|
|
381
392
|
const parentRect = currentTarget.parentElement.getBoundingClientRect();
|
|
382
393
|
const isFixed = ( currentTarget.style.position == "fixed" );
|
|
383
394
|
const fixedOffset = isFixed ? new LX.vec2( parentRect.x, parentRect.y ) : new LX.vec2();
|
|
384
395
|
offsetX = e.clientX - rect.x - fixedOffset.x;
|
|
385
396
|
offsetY = e.clientY - rect.y - fixedOffset.y;
|
|
397
|
+
|
|
386
398
|
document.addEventListener( "mousemove", onMove );
|
|
399
|
+
|
|
400
|
+
currentTarget._eventCatched = true;
|
|
401
|
+
|
|
402
|
+
// Force active dialog to show on top
|
|
403
|
+
if( LX.activeDraggable )
|
|
404
|
+
{
|
|
405
|
+
LX.activeDraggable.style.zIndex = LX.DRAGGABLE_Z_INDEX;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
LX.activeDraggable = domEl;
|
|
409
|
+
LX.activeDraggable.style.zIndex = LX.DRAGGABLE_Z_INDEX + 1;
|
|
410
|
+
|
|
387
411
|
if( onDragStart )
|
|
388
412
|
{
|
|
389
413
|
onDragStart( currentTarget, e );
|
|
390
414
|
}
|
|
391
415
|
}, false );
|
|
392
416
|
|
|
393
|
-
document.addEventListener( 'mouseup', () => {
|
|
417
|
+
document.addEventListener( 'mouseup', (e) => {
|
|
394
418
|
if( currentTarget )
|
|
395
419
|
{
|
|
396
420
|
currentTarget = null;
|
|
@@ -401,6 +425,48 @@ function makeDraggable( domEl, options = { } )
|
|
|
401
425
|
|
|
402
426
|
LX.makeDraggable = makeDraggable;
|
|
403
427
|
|
|
428
|
+
/**
|
|
429
|
+
* @method makeCollapsible
|
|
430
|
+
* @description Allows an element to be collapsed/expanded
|
|
431
|
+
* @param {Element} domEl: Element to be treated as collapsible
|
|
432
|
+
* @param {Element} content: Content to display/hide on collapse/extend
|
|
433
|
+
* @param {Element} parent: Element where the content will be appended (default is domEl.parent)
|
|
434
|
+
* @param {Object} options
|
|
435
|
+
*/
|
|
436
|
+
function makeCollapsible( domEl, content, parent, options = { } )
|
|
437
|
+
{
|
|
438
|
+
domEl.classList.add( "collapsible" );
|
|
439
|
+
|
|
440
|
+
const collapsed = ( options.collapsed ?? true );
|
|
441
|
+
const actionIcon = LX.makeIcon( "Right" );
|
|
442
|
+
actionIcon.classList.add( "collapser" );
|
|
443
|
+
actionIcon.dataset[ "collapsed" ] = collapsed;
|
|
444
|
+
actionIcon.style.marginLeft = "auto";
|
|
445
|
+
|
|
446
|
+
actionIcon.addEventListener( "click", function(e) {
|
|
447
|
+
e.preventDefault();
|
|
448
|
+
e.stopPropagation();
|
|
449
|
+
if( this.dataset[ "collapsed" ] )
|
|
450
|
+
{
|
|
451
|
+
delete this.dataset[ "collapsed" ];
|
|
452
|
+
content.style.display = "block";
|
|
453
|
+
}
|
|
454
|
+
else
|
|
455
|
+
{
|
|
456
|
+
this.dataset[ "collapsed" ] = true;
|
|
457
|
+
content.style.display = "none";
|
|
458
|
+
}
|
|
459
|
+
} );
|
|
460
|
+
|
|
461
|
+
domEl.appendChild( actionIcon );
|
|
462
|
+
|
|
463
|
+
parent = parent ?? domEl.parentElement;
|
|
464
|
+
|
|
465
|
+
parent.appendChild( content );
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
LX.makeCollapsible = makeCollapsible;
|
|
469
|
+
|
|
404
470
|
/**
|
|
405
471
|
* @method makeCodeSnippet
|
|
406
472
|
* @description Create a code snippet in a specific language
|
|
@@ -503,6 +569,23 @@ function makeCodeSnippet( code, size, options = { } )
|
|
|
503
569
|
|
|
504
570
|
LX.makeCodeSnippet = makeCodeSnippet;
|
|
505
571
|
|
|
572
|
+
/**
|
|
573
|
+
* @method makeIcon
|
|
574
|
+
* @description Gets an SVG element using one of LX.ICONS
|
|
575
|
+
* @param {String} iconName
|
|
576
|
+
* @param {String} iconTitle
|
|
577
|
+
*/
|
|
578
|
+
function makeIcon( iconName, iconTitle )
|
|
579
|
+
{
|
|
580
|
+
const icon = document.createElement( "a" );
|
|
581
|
+
icon.title = iconTitle ?? "";
|
|
582
|
+
icon.className = "lexicon";
|
|
583
|
+
icon.innerHTML = LX.ICONS[ iconName ] ?? "";
|
|
584
|
+
return icon;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
LX.makeIcon = makeIcon;
|
|
588
|
+
|
|
506
589
|
/**
|
|
507
590
|
* @method registerCommandbarEntry
|
|
508
591
|
* @description Adds an extra command bar entry
|
|
@@ -772,12 +855,12 @@ function _createCommandbar( root )
|
|
|
772
855
|
if( LX.has('CodeEditor') )
|
|
773
856
|
{
|
|
774
857
|
const instances = LX.CodeEditor.getInstances();
|
|
775
|
-
if(!instances.length) return;
|
|
858
|
+
if( !instances.length ) return;
|
|
776
859
|
|
|
777
860
|
const languages = instances[ 0 ].languages;
|
|
778
861
|
|
|
779
|
-
for( let l of Object.keys( languages ) )
|
|
780
|
-
|
|
862
|
+
for( let l of Object.keys( languages ) )
|
|
863
|
+
{
|
|
781
864
|
const key = "Language: " + l;
|
|
782
865
|
const icon = instances[ 0 ]._getFileIcon( null, languages[ l ].ext );
|
|
783
866
|
|
|
@@ -785,9 +868,11 @@ function _createCommandbar( root )
|
|
|
785
868
|
"<img src='" + ( "https://raw.githubusercontent.com/jxarco/lexgui.js/master/" + icon ) + "'>";
|
|
786
869
|
|
|
787
870
|
value += key + " <span class='lang-ext'>(" + languages[ l ].ext + ")</span>";
|
|
788
|
-
if( key.toLowerCase().includes( filter ) )
|
|
871
|
+
if( key.toLowerCase().includes( filter ) )
|
|
872
|
+
{
|
|
789
873
|
_addElement( value, () => {
|
|
790
|
-
for( let i of instances )
|
|
874
|
+
for( let i of instances )
|
|
875
|
+
{
|
|
791
876
|
i._changeLanguage( l );
|
|
792
877
|
}
|
|
793
878
|
}, "", {} );
|
|
@@ -860,6 +945,25 @@ function init( options = { } )
|
|
|
860
945
|
this.root = document.body;
|
|
861
946
|
}
|
|
862
947
|
|
|
948
|
+
// Notifications
|
|
949
|
+
{
|
|
950
|
+
const notifSection = document.createElement( "section" );
|
|
951
|
+
notifSection.className = "notifications";
|
|
952
|
+
this.notifications = document.createElement( "ol" );
|
|
953
|
+
this.notifications.className = "";
|
|
954
|
+
this.notifications.iWidth = 0;
|
|
955
|
+
notifSection.appendChild( this.notifications );
|
|
956
|
+
this.container.appendChild( notifSection );
|
|
957
|
+
|
|
958
|
+
this.notifications.addEventListener( "mouseenter", () => {
|
|
959
|
+
this.notifications.classList.add( "list" );
|
|
960
|
+
} );
|
|
961
|
+
|
|
962
|
+
this.notifications.addEventListener( "mouseleave", () => {
|
|
963
|
+
this.notifications.classList.remove( "list" );
|
|
964
|
+
} );
|
|
965
|
+
}
|
|
966
|
+
|
|
863
967
|
// Disable drag icon
|
|
864
968
|
root.addEventListener( 'dragover', function( e ) {
|
|
865
969
|
e.preventDefault();
|
|
@@ -1010,6 +1114,7 @@ LX.popup = popup;
|
|
|
1010
1114
|
function prompt( text, title, callback, options = {} )
|
|
1011
1115
|
{
|
|
1012
1116
|
options.modal = true;
|
|
1117
|
+
options.className = "prompt";
|
|
1013
1118
|
|
|
1014
1119
|
let value = "";
|
|
1015
1120
|
|
|
@@ -1024,7 +1129,9 @@ function prompt( text, title, callback, options = {} )
|
|
|
1024
1129
|
|
|
1025
1130
|
p.sameLine( 2 );
|
|
1026
1131
|
|
|
1027
|
-
p.addButton(
|
|
1132
|
+
p.addButton(null, "Cancel", () => {if(options.on_cancel) options.on_cancel(); dialog.close();} );
|
|
1133
|
+
|
|
1134
|
+
p.addButton( null, options.accept || "Continue", () => {
|
|
1028
1135
|
if( options.required && value === '' )
|
|
1029
1136
|
{
|
|
1030
1137
|
text += text.includes("You must fill the input text.") ? "": "\nYou must fill the input text.";
|
|
@@ -1038,8 +1145,6 @@ function prompt( text, title, callback, options = {} )
|
|
|
1038
1145
|
}
|
|
1039
1146
|
}, { buttonClass: "primary" });
|
|
1040
1147
|
|
|
1041
|
-
p.addButton(null, "Cancel", () => {if(options.on_cancel) options.on_cancel(); dialog.close();} );
|
|
1042
|
-
|
|
1043
1148
|
}, options );
|
|
1044
1149
|
|
|
1045
1150
|
// Focus text prompt
|
|
@@ -1053,6 +1158,101 @@ function prompt( text, title, callback, options = {} )
|
|
|
1053
1158
|
|
|
1054
1159
|
LX.prompt = prompt;
|
|
1055
1160
|
|
|
1161
|
+
/**
|
|
1162
|
+
* @method toast
|
|
1163
|
+
* @param {String} title
|
|
1164
|
+
* @param {String} description (Optional)
|
|
1165
|
+
* @param {*} options
|
|
1166
|
+
* action: Data of the custom action { name, callback }
|
|
1167
|
+
* closable: Allow closing the toast
|
|
1168
|
+
* timeout: Time in which the toast closed automatically, in ms. -1 means persistent. [3000]
|
|
1169
|
+
*/
|
|
1170
|
+
|
|
1171
|
+
function toast( title, description, options = {} )
|
|
1172
|
+
{
|
|
1173
|
+
if( !title )
|
|
1174
|
+
{
|
|
1175
|
+
throw( "The toast needs at least a title!" );
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
console.assert( this.notifications );
|
|
1179
|
+
|
|
1180
|
+
const toast = document.createElement( "li" );
|
|
1181
|
+
toast.className = "lextoast";
|
|
1182
|
+
toast.style.translate = "0 calc(100% + 30px)";
|
|
1183
|
+
this.notifications.prepend( toast );
|
|
1184
|
+
|
|
1185
|
+
doAsync( () => {
|
|
1186
|
+
|
|
1187
|
+
if( this.notifications.offsetWidth > this.notifications.iWidth )
|
|
1188
|
+
{
|
|
1189
|
+
this.notifications.iWidth = Math.min( this.notifications.offsetWidth, 480 );
|
|
1190
|
+
this.notifications.style.width = this.notifications.iWidth + "px";
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
toast.dataset[ "open" ] = true;
|
|
1194
|
+
}, 10 );
|
|
1195
|
+
|
|
1196
|
+
const content = document.createElement( "div" );
|
|
1197
|
+
content.className = "lextoastcontent";
|
|
1198
|
+
toast.appendChild( content );
|
|
1199
|
+
|
|
1200
|
+
const titleContent = document.createElement( "div" );
|
|
1201
|
+
titleContent.className = "title";
|
|
1202
|
+
titleContent.innerHTML = title;
|
|
1203
|
+
content.appendChild( titleContent );
|
|
1204
|
+
|
|
1205
|
+
if( description )
|
|
1206
|
+
{
|
|
1207
|
+
const desc = document.createElement( "div" );
|
|
1208
|
+
desc.className = "desc";
|
|
1209
|
+
desc.innerHTML = description;
|
|
1210
|
+
content.appendChild( desc );
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
if( options.action )
|
|
1214
|
+
{
|
|
1215
|
+
const panel = new Panel();
|
|
1216
|
+
panel.addButton(null, options.action.name ?? "Accept", options.action.callback.bind( this, toast ), { width: "auto", maxWidth: "150px", className: "right", buttonClass: "outline" });
|
|
1217
|
+
toast.appendChild( panel.root.childNodes[ 0 ] );
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
const that = this;
|
|
1221
|
+
|
|
1222
|
+
toast.close = function() {
|
|
1223
|
+
this.dataset[ "closed" ] = true;
|
|
1224
|
+
doAsync( () => {
|
|
1225
|
+
this.remove();
|
|
1226
|
+
if( !that.notifications.childElementCount )
|
|
1227
|
+
{
|
|
1228
|
+
that.notifications.style.width = "unset";
|
|
1229
|
+
that.notifications.iWidth = 0;
|
|
1230
|
+
}
|
|
1231
|
+
}, 500 );
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1234
|
+
if( options.closable ?? true )
|
|
1235
|
+
{
|
|
1236
|
+
const closeButton = document.createElement( "a" );
|
|
1237
|
+
closeButton.className = "fa fa-xmark lexicon closer";
|
|
1238
|
+
closeButton.addEventListener( "click", () => {
|
|
1239
|
+
toast.close();
|
|
1240
|
+
} );
|
|
1241
|
+
toast.appendChild( closeButton );
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
const timeout = options.timeout ?? 3000;
|
|
1245
|
+
|
|
1246
|
+
if( timeout != -1 )
|
|
1247
|
+
{
|
|
1248
|
+
doAsync( () => {
|
|
1249
|
+
toast.close();
|
|
1250
|
+
}, timeout );
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
LX.toast = toast;
|
|
1255
|
+
|
|
1056
1256
|
/**
|
|
1057
1257
|
* @method badge
|
|
1058
1258
|
* @param {String} text
|
|
@@ -1354,7 +1554,8 @@ class Area {
|
|
|
1354
1554
|
|
|
1355
1555
|
function inner_mousemove( e )
|
|
1356
1556
|
{
|
|
1357
|
-
switch( that.type )
|
|
1557
|
+
switch( that.type )
|
|
1558
|
+
{
|
|
1358
1559
|
case "right":
|
|
1359
1560
|
var dt = ( lastMousePosition[ 0 ] - e.x );
|
|
1360
1561
|
var size = ( that.root.offsetWidth + dt );
|
|
@@ -1549,7 +1750,8 @@ class Area {
|
|
|
1549
1750
|
|
|
1550
1751
|
// Listen resize event on first area
|
|
1551
1752
|
const resizeObserver = new ResizeObserver( entries => {
|
|
1552
|
-
for (const entry of entries)
|
|
1753
|
+
for ( const entry of entries )
|
|
1754
|
+
{
|
|
1553
1755
|
const bb = entry.contentRect;
|
|
1554
1756
|
area2.root.style.height = "calc(100% - " + ( bb.height + 4) + "px )";
|
|
1555
1757
|
}
|
|
@@ -1690,9 +1892,15 @@ class Area {
|
|
|
1690
1892
|
this.root.style.height = height;
|
|
1691
1893
|
}
|
|
1692
1894
|
|
|
1693
|
-
|
|
1895
|
+
if( this.onresize )
|
|
1896
|
+
{
|
|
1897
|
+
this.onresize( this.root.getBoundingClientRect() );
|
|
1898
|
+
}
|
|
1694
1899
|
|
|
1695
|
-
|
|
1900
|
+
doAsync( () => {
|
|
1901
|
+
this.size = [ this.root.clientWidth, this.root.clientHeight ];
|
|
1902
|
+
this.propagateEvent( "onresize" );
|
|
1903
|
+
}, 150 );
|
|
1696
1904
|
}
|
|
1697
1905
|
|
|
1698
1906
|
/**
|
|
@@ -1709,7 +1917,7 @@ class Area {
|
|
|
1709
1917
|
let [area1, area2] = this.sections;
|
|
1710
1918
|
this.splitExtended = true;
|
|
1711
1919
|
|
|
1712
|
-
if(this.type == "vertical")
|
|
1920
|
+
if( this.type == "vertical")
|
|
1713
1921
|
{
|
|
1714
1922
|
this.offset = area2.root.offsetHeight;
|
|
1715
1923
|
area2.root.classList.add("fadeout-vertical");
|
|
@@ -1723,7 +1931,6 @@ class Area {
|
|
|
1723
1931
|
this._moveSplit(-Infinity, true, 8);
|
|
1724
1932
|
}
|
|
1725
1933
|
|
|
1726
|
-
// Async resize in some ms...
|
|
1727
1934
|
doAsync( () => this.propagateEvent('onresize'), 150 );
|
|
1728
1935
|
}
|
|
1729
1936
|
|
|
@@ -1739,7 +1946,7 @@ class Area {
|
|
|
1739
1946
|
this.splitExtended = false;
|
|
1740
1947
|
let [area1, area2] = this.sections;
|
|
1741
1948
|
|
|
1742
|
-
if(this.type == "vertical")
|
|
1949
|
+
if( this.type == "vertical")
|
|
1743
1950
|
{
|
|
1744
1951
|
area2.root.classList.add("fadein-vertical");
|
|
1745
1952
|
this._moveSplit(this.offset);
|
|
@@ -1750,7 +1957,6 @@ class Area {
|
|
|
1750
1957
|
this._moveSplit(this.offset);
|
|
1751
1958
|
}
|
|
1752
1959
|
|
|
1753
|
-
// Async resize in some ms...
|
|
1754
1960
|
doAsync( () => this.propagateEvent('onresize'), 150 );
|
|
1755
1961
|
}
|
|
1756
1962
|
|
|
@@ -1784,11 +1990,15 @@ class Area {
|
|
|
1784
1990
|
|
|
1785
1991
|
propagateEvent( eventName ) {
|
|
1786
1992
|
|
|
1787
|
-
for(var i = 0; i < this.sections.length; i++)
|
|
1993
|
+
for( var i = 0; i < this.sections.length; i++ )
|
|
1788
1994
|
{
|
|
1789
|
-
const area = this.sections[i];
|
|
1790
|
-
|
|
1995
|
+
const area = this.sections[ i ];
|
|
1996
|
+
|
|
1997
|
+
if( area[ eventName ] )
|
|
1998
|
+
{
|
|
1791
1999
|
area[ eventName ].call( this, area.root.getBoundingClientRect() );
|
|
2000
|
+
}
|
|
2001
|
+
|
|
1792
2002
|
area.propagateEvent( eventName );
|
|
1793
2003
|
}
|
|
1794
2004
|
}
|
|
@@ -1811,42 +2021,63 @@ class Area {
|
|
|
1811
2021
|
* @param {Function} callback Function to fill the menubar
|
|
1812
2022
|
* @param {*} options:
|
|
1813
2023
|
* float: Justify content (left, center, right) [left]
|
|
2024
|
+
* sticky: Fix menubar at the top [true]
|
|
1814
2025
|
*/
|
|
1815
2026
|
|
|
1816
2027
|
addMenubar( callback, options = {} ) {
|
|
1817
2028
|
|
|
1818
|
-
let menubar = new Menubar(options);
|
|
2029
|
+
let menubar = new Menubar( options );
|
|
1819
2030
|
|
|
1820
|
-
if(
|
|
2031
|
+
if( callback )
|
|
2032
|
+
{
|
|
2033
|
+
callback( menubar );
|
|
2034
|
+
}
|
|
1821
2035
|
|
|
1822
2036
|
LX.menubars.push( menubar );
|
|
1823
2037
|
|
|
1824
2038
|
const height = 48; // pixels
|
|
2039
|
+
const [ bar, content ] = this.split({ type: 'vertical', sizes: [height, null], resize: false, menubar: true });
|
|
2040
|
+
menubar.siblingArea = content;
|
|
1825
2041
|
|
|
1826
|
-
const [bar, content] = this.split({type: 'vertical', sizes: [height, null], resize: false, menubar: true});
|
|
1827
2042
|
bar.attach( menubar );
|
|
1828
|
-
bar.
|
|
2043
|
+
bar.isMenubar = true;
|
|
2044
|
+
|
|
2045
|
+
if( options.sticky ?? true )
|
|
2046
|
+
{
|
|
2047
|
+
bar.root.classList.add( "sticky" );
|
|
2048
|
+
}
|
|
2049
|
+
|
|
1829
2050
|
return menubar;
|
|
1830
2051
|
}
|
|
1831
2052
|
|
|
1832
2053
|
/**
|
|
1833
2054
|
* @method addSidebar
|
|
1834
2055
|
* @param {Function} callback Function to fill the sidebar
|
|
2056
|
+
* @param {Object} options: Sidebar options
|
|
2057
|
+
* width: Width of the sidebar [16rem]
|
|
1835
2058
|
*/
|
|
1836
2059
|
|
|
1837
2060
|
addSidebar( callback, options = {} ) {
|
|
1838
2061
|
|
|
1839
2062
|
let sidebar = new SideBar( options );
|
|
1840
2063
|
|
|
1841
|
-
if( callback )
|
|
2064
|
+
if( callback )
|
|
2065
|
+
{
|
|
2066
|
+
callback( sidebar );
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// Generate DOM elements after adding all entries
|
|
2070
|
+
sidebar._build();
|
|
1842
2071
|
|
|
1843
2072
|
LX.menubars.push( sidebar );
|
|
1844
2073
|
|
|
1845
|
-
const width =
|
|
2074
|
+
const width = options.width ?? "16rem";
|
|
2075
|
+
const [ bar, content ] = this.split( { type: 'horizontal', sizes: [ width, null ], resize: false, sidebar: true } );
|
|
2076
|
+
sidebar.siblingArea = content;
|
|
1846
2077
|
|
|
1847
|
-
const [bar, content] = this.split( { type: 'horizontal', sizes: [ width, null ], resize: false, sidebar: true } );
|
|
1848
2078
|
bar.attach( sidebar );
|
|
1849
|
-
bar.
|
|
2079
|
+
bar.isSidebar = true;
|
|
2080
|
+
|
|
1850
2081
|
return sidebar;
|
|
1851
2082
|
}
|
|
1852
2083
|
|
|
@@ -2102,7 +2333,8 @@ class Area {
|
|
|
2102
2333
|
|
|
2103
2334
|
this.size = [ rect.width, rect.height ];
|
|
2104
2335
|
|
|
2105
|
-
for(var i = 0; i < this.sections.length; i++)
|
|
2336
|
+
for( var i = 0; i < this.sections.length; i++ )
|
|
2337
|
+
{
|
|
2106
2338
|
this.sections[i]._update();
|
|
2107
2339
|
}
|
|
2108
2340
|
}
|
|
@@ -2126,7 +2358,7 @@ class Tabs {
|
|
|
2126
2358
|
static TAB_SIZE = 28;
|
|
2127
2359
|
static TAB_ID = 0;
|
|
2128
2360
|
|
|
2129
|
-
constructor( area, options = {} )
|
|
2361
|
+
constructor( area, options = {} ) {
|
|
2130
2362
|
|
|
2131
2363
|
this.onclose = options.onclose;
|
|
2132
2364
|
|
|
@@ -2208,24 +2440,28 @@ class Tabs {
|
|
|
2208
2440
|
}
|
|
2209
2441
|
|
|
2210
2442
|
// debug
|
|
2211
|
-
if(folding)
|
|
2443
|
+
if( folding )
|
|
2212
2444
|
{
|
|
2213
2445
|
this.folded = true;
|
|
2214
2446
|
this.folding = folding;
|
|
2215
2447
|
|
|
2216
|
-
if(folding == "up"
|
|
2448
|
+
if( folding == "up" )
|
|
2449
|
+
{
|
|
2450
|
+
area.root.insertChildAtIndex(area.sections[1].root, 0);
|
|
2451
|
+
}
|
|
2217
2452
|
|
|
2218
2453
|
// Listen resize event on parent area
|
|
2219
2454
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
2220
|
-
for (const entry of entries)
|
|
2455
|
+
for (const entry of entries)
|
|
2456
|
+
{
|
|
2221
2457
|
const bb = entry.contentRect;
|
|
2222
|
-
const sibling = area.parentArea.sections[0].root;
|
|
2223
|
-
const
|
|
2224
|
-
sibling.style.height = "calc(100% - " + ((
|
|
2458
|
+
const sibling = area.parentArea.sections[ 0 ].root;
|
|
2459
|
+
const addOffset = true; // hardcoded...
|
|
2460
|
+
sibling.style.height = "calc(100% - " + ((addOffset ? 42 : 0) + bb.height) + "px )";
|
|
2225
2461
|
}
|
|
2226
2462
|
});
|
|
2227
2463
|
|
|
2228
|
-
resizeObserver.observe(this.area.root);
|
|
2464
|
+
resizeObserver.observe( this.area.root );
|
|
2229
2465
|
this.area.root.classList.add('folded');
|
|
2230
2466
|
}
|
|
2231
2467
|
}
|
|
@@ -2362,7 +2598,8 @@ class Tabs {
|
|
|
2362
2598
|
|
|
2363
2599
|
setTimeout( () => {
|
|
2364
2600
|
|
|
2365
|
-
if( options.onCreate )
|
|
2601
|
+
if( options.onCreate )
|
|
2602
|
+
{
|
|
2366
2603
|
options.onCreate.call(this, this.area.root.getBoundingClientRect());
|
|
2367
2604
|
}
|
|
2368
2605
|
|
|
@@ -2424,34 +2661,41 @@ LX.Tabs = Tabs;
|
|
|
2424
2661
|
|
|
2425
2662
|
class Menubar {
|
|
2426
2663
|
|
|
2427
|
-
constructor( options = {} )
|
|
2664
|
+
constructor( options = {} ) {
|
|
2428
2665
|
|
|
2429
|
-
this.root = document.createElement(
|
|
2666
|
+
this.root = document.createElement( "div" );
|
|
2430
2667
|
this.root.className = "lexmenubar";
|
|
2431
|
-
|
|
2668
|
+
|
|
2669
|
+
if( options.float )
|
|
2670
|
+
{
|
|
2432
2671
|
this.root.style.justifyContent = options.float;
|
|
2433
|
-
|
|
2672
|
+
}
|
|
2434
2673
|
|
|
2435
|
-
this.
|
|
2436
|
-
this.
|
|
2437
|
-
this.
|
|
2674
|
+
this.items = [ ];
|
|
2675
|
+
this.buttons = [ ];
|
|
2676
|
+
this.icons = { };
|
|
2677
|
+
this.shorts = { };
|
|
2438
2678
|
}
|
|
2439
2679
|
|
|
2440
2680
|
/**
|
|
2441
2681
|
* @method add
|
|
2442
|
-
* @param {
|
|
2682
|
+
* @param {Object} options:
|
|
2443
2683
|
* callback: Function to call on each item
|
|
2684
|
+
* icon: Entry icon
|
|
2685
|
+
* short: Entry shortcut name
|
|
2444
2686
|
*/
|
|
2445
2687
|
|
|
2446
2688
|
add( path, options = {} ) {
|
|
2447
2689
|
|
|
2448
|
-
if(options.constructor == Function)
|
|
2690
|
+
if( options.constructor == Function )
|
|
2691
|
+
{
|
|
2449
2692
|
options = { callback: options };
|
|
2693
|
+
}
|
|
2450
2694
|
|
|
2451
|
-
//
|
|
2452
|
-
const tokens = path.split("/");
|
|
2695
|
+
// Process path
|
|
2696
|
+
const tokens = path.split( "/" );
|
|
2453
2697
|
|
|
2454
|
-
//
|
|
2698
|
+
// Assign icons and shortcuts to last token in path
|
|
2455
2699
|
const lastPath = tokens[tokens.length - 1];
|
|
2456
2700
|
this.icons[ lastPath ] = options.icon;
|
|
2457
2701
|
this.shorts[ lastPath ] = options.short;
|
|
@@ -2459,105 +2703,146 @@ class Menubar {
|
|
|
2459
2703
|
let idx = 0;
|
|
2460
2704
|
let that = this;
|
|
2461
2705
|
|
|
2462
|
-
const
|
|
2463
|
-
if(token == undefined)
|
|
2706
|
+
const _insertEntry = ( token, list ) => {
|
|
2707
|
+
if( token == undefined )
|
|
2708
|
+
{
|
|
2709
|
+
return;
|
|
2710
|
+
}
|
|
2464
2711
|
|
|
2465
2712
|
let found = null;
|
|
2466
2713
|
list.forEach( o => {
|
|
2467
|
-
const keys = Object.keys(o);
|
|
2714
|
+
const keys = Object.keys( o );
|
|
2468
2715
|
const key = keys.find( t => t == token );
|
|
2469
|
-
if(key) found = o[ key ];
|
|
2716
|
+
if( key ) found = o[ key ];
|
|
2470
2717
|
} );
|
|
2471
2718
|
|
|
2472
|
-
if(found)
|
|
2473
|
-
|
|
2719
|
+
if( found )
|
|
2720
|
+
{
|
|
2721
|
+
_insertEntry( tokens[ idx++ ], found );
|
|
2474
2722
|
}
|
|
2475
|
-
else
|
|
2723
|
+
else
|
|
2724
|
+
{
|
|
2476
2725
|
let item = {};
|
|
2477
2726
|
item[ token ] = [];
|
|
2478
|
-
const
|
|
2727
|
+
const nextToken = tokens[ idx++ ];
|
|
2479
2728
|
// Check if last token -> add callback
|
|
2480
|
-
if(!
|
|
2729
|
+
if( !nextToken )
|
|
2730
|
+
{
|
|
2481
2731
|
item[ 'callback' ] = options.callback;
|
|
2732
|
+
item[ 'disabled' ] = options.disabled;
|
|
2482
2733
|
item[ 'type' ] = options.type;
|
|
2483
2734
|
item[ 'checked' ] = options.checked;
|
|
2484
2735
|
}
|
|
2485
2736
|
list.push( item );
|
|
2486
|
-
|
|
2737
|
+
_insertEntry( nextToken, item[ token ] );
|
|
2487
2738
|
}
|
|
2488
2739
|
};
|
|
2489
2740
|
|
|
2490
|
-
|
|
2741
|
+
_insertEntry( tokens[idx++], this.items );
|
|
2491
2742
|
|
|
2492
2743
|
// Create elements
|
|
2493
2744
|
|
|
2494
2745
|
for( let item of this.items )
|
|
2495
2746
|
{
|
|
2496
|
-
let key = Object.keys(item)[0];
|
|
2497
|
-
let pKey = key.replace(/\s/g, '').replaceAll('.', '');
|
|
2747
|
+
let key = Object.keys( item )[ 0 ];
|
|
2748
|
+
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
2498
2749
|
|
|
2499
2750
|
// Item already created
|
|
2500
|
-
if( this.root.querySelector("#" + pKey) )
|
|
2751
|
+
if( this.root.querySelector( "#" + pKey ) )
|
|
2752
|
+
{
|
|
2501
2753
|
continue;
|
|
2754
|
+
}
|
|
2502
2755
|
|
|
2503
2756
|
let entry = document.createElement('div');
|
|
2504
2757
|
entry.className = "lexmenuentry";
|
|
2505
2758
|
entry.id = pKey;
|
|
2506
2759
|
entry.innerHTML = "<span>" + key + "</span>";
|
|
2507
|
-
|
|
2760
|
+
entry.tabIndex = "1";
|
|
2761
|
+
|
|
2762
|
+
if( options.position == "left" )
|
|
2763
|
+
{
|
|
2508
2764
|
this.root.prepend( entry );
|
|
2509
2765
|
}
|
|
2510
|
-
else
|
|
2511
|
-
|
|
2766
|
+
else
|
|
2767
|
+
{
|
|
2768
|
+
if( options.position == "right" )
|
|
2769
|
+
{
|
|
2512
2770
|
entry.right = true;
|
|
2513
|
-
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
2774
|
+
{
|
|
2514
2775
|
this.root.lastChild.before( entry );
|
|
2515
2776
|
}
|
|
2516
|
-
else
|
|
2777
|
+
else
|
|
2778
|
+
{
|
|
2517
2779
|
this.root.appendChild( entry );
|
|
2518
2780
|
}
|
|
2519
2781
|
}
|
|
2520
2782
|
|
|
2783
|
+
const _resetMenubar = function() {
|
|
2784
|
+
// Menu entries are in the menubar..
|
|
2785
|
+
that.root.querySelectorAll(".lexmenuentry").forEach( _entry => {
|
|
2786
|
+
_entry.classList.remove( 'selected' );
|
|
2787
|
+
_entry.built = false;
|
|
2788
|
+
} );
|
|
2789
|
+
// Menuboxes are in the root area!
|
|
2790
|
+
LX.root.querySelectorAll(".lexmenubox").forEach(e => e.remove());
|
|
2791
|
+
// Next time we need to click again
|
|
2792
|
+
that.focused = false;
|
|
2793
|
+
};
|
|
2794
|
+
|
|
2521
2795
|
const create_submenu = function( o, k, c, d ) {
|
|
2522
2796
|
|
|
2523
|
-
let
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2797
|
+
let menuElement = document.createElement('div');
|
|
2798
|
+
menuElement.className = "lexmenubox";
|
|
2799
|
+
menuElement.tabIndex = "0";
|
|
2800
|
+
c.currentMenu = menuElement;
|
|
2801
|
+
const isSubMenu = c.classList.contains( "lexmenuboxentry" );
|
|
2802
|
+
if( isSubMenu ) menuElement.dataset[ "submenu" ] = true;
|
|
2527
2803
|
var rect = c.getBoundingClientRect();
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
c.appendChild( contextmenu );
|
|
2804
|
+
menuElement.style.left = ( isSubMenu ? ( rect.x + rect.width ) : rect.left ) + "px";
|
|
2805
|
+
menuElement.style.top = ( isSubMenu ? rect.y : rect.bottom - 4 ) + "px";
|
|
2806
|
+
rect = menuElement.getBoundingClientRect();
|
|
2532
2807
|
|
|
2533
|
-
|
|
2808
|
+
doAsync( () => {
|
|
2809
|
+
menuElement.dataset[ "open" ] = true;
|
|
2810
|
+
}, 10 );
|
|
2534
2811
|
|
|
2535
|
-
|
|
2812
|
+
LX.root.appendChild( menuElement );
|
|
2536
2813
|
|
|
2537
|
-
for( var i = 0; i < o[k].length; ++i )
|
|
2814
|
+
for( var i = 0; i < o[ k ].length; ++i )
|
|
2538
2815
|
{
|
|
2539
|
-
const subitem = o[k][i];
|
|
2540
|
-
const subkey = Object.keys(subitem)[0];
|
|
2816
|
+
const subitem = o[ k ][ i ];
|
|
2817
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
2541
2818
|
const hasSubmenu = subitem[ subkey ].length;
|
|
2542
2819
|
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2543
2820
|
let subentry = document.createElement('div');
|
|
2544
|
-
subentry.className = "
|
|
2545
|
-
subentry.className += (i == o[k].length - 1 ? " last" : "");
|
|
2546
|
-
if(subkey == '')
|
|
2547
|
-
subentry.className = " lexseparator";
|
|
2548
|
-
else {
|
|
2821
|
+
subentry.className = "lexmenuboxentry";
|
|
2822
|
+
subentry.className += (i == o[k].length - 1 ? " last" : "") + ( subitem.disabled ? " disabled" : "" );
|
|
2549
2823
|
|
|
2824
|
+
if( subkey == '' )
|
|
2825
|
+
{
|
|
2826
|
+
subentry.className = " lexseparator";
|
|
2827
|
+
}
|
|
2828
|
+
else
|
|
2829
|
+
{
|
|
2550
2830
|
subentry.id = subkey;
|
|
2551
2831
|
let subentrycont = document.createElement('div');
|
|
2552
2832
|
subentrycont.innerHTML = "";
|
|
2553
|
-
subentrycont.classList = "
|
|
2833
|
+
subentrycont.classList = "lexmenuboxentrycontainer";
|
|
2554
2834
|
subentry.appendChild(subentrycont);
|
|
2555
2835
|
const icon = that.icons[ subkey ];
|
|
2556
|
-
if(isCheckbox)
|
|
2836
|
+
if( isCheckbox )
|
|
2837
|
+
{
|
|
2557
2838
|
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2558
|
-
}
|
|
2839
|
+
}
|
|
2840
|
+
else if( icon )
|
|
2841
|
+
{
|
|
2559
2842
|
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2560
|
-
}
|
|
2843
|
+
}
|
|
2844
|
+
else
|
|
2845
|
+
{
|
|
2561
2846
|
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2562
2847
|
subentrycont.classList.add( "noicon" );
|
|
2563
2848
|
|
|
@@ -2565,46 +2850,54 @@ class Menubar {
|
|
|
2565
2850
|
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2566
2851
|
}
|
|
2567
2852
|
|
|
2568
|
-
let
|
|
2569
|
-
if(
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2853
|
+
let checkboxInput = subentry.querySelector('input');
|
|
2854
|
+
if( checkboxInput )
|
|
2855
|
+
{
|
|
2856
|
+
checkboxInput.checked = subitem.checked ?? false;
|
|
2857
|
+
checkboxInput.addEventListener('change', e => {
|
|
2858
|
+
subitem.checked = checkboxInput.checked;
|
|
2573
2859
|
const f = subitem[ 'callback' ];
|
|
2574
|
-
if(f)
|
|
2860
|
+
if( f )
|
|
2861
|
+
{
|
|
2575
2862
|
f.call( this, subitem.checked, subkey, subentry );
|
|
2576
|
-
|
|
2863
|
+
_resetMenubar();
|
|
2577
2864
|
}
|
|
2578
2865
|
e.stopPropagation();
|
|
2579
2866
|
e.stopImmediatePropagation();
|
|
2580
2867
|
})
|
|
2581
2868
|
}
|
|
2582
2869
|
|
|
2583
|
-
|
|
2870
|
+
menuElement.appendChild( subentry );
|
|
2584
2871
|
|
|
2585
2872
|
// Nothing more for separators
|
|
2586
|
-
if(subkey == '')
|
|
2873
|
+
if( subkey == '' )
|
|
2874
|
+
{
|
|
2875
|
+
continue;
|
|
2876
|
+
}
|
|
2587
2877
|
|
|
2588
|
-
|
|
2878
|
+
menuElement.addEventListener('keydown', function(e) {
|
|
2589
2879
|
e.preventDefault();
|
|
2590
2880
|
let short = that.shorts[ subkey ];
|
|
2591
2881
|
if(!short) return;
|
|
2592
2882
|
// check if it's a letter or other key
|
|
2593
2883
|
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2594
|
-
if(short == e.key)
|
|
2884
|
+
if( short == e.key )
|
|
2885
|
+
{
|
|
2595
2886
|
subentry.click()
|
|
2596
2887
|
}
|
|
2597
2888
|
});
|
|
2598
2889
|
|
|
2599
2890
|
// Add callback
|
|
2600
2891
|
subentry.addEventListener("click", e => {
|
|
2601
|
-
if(
|
|
2892
|
+
if( checkboxInput )
|
|
2893
|
+
{
|
|
2602
2894
|
subitem.checked = !subitem.checked;
|
|
2603
2895
|
}
|
|
2604
2896
|
const f = subitem[ 'callback' ];
|
|
2605
|
-
if(f)
|
|
2606
|
-
|
|
2607
|
-
|
|
2897
|
+
if( f )
|
|
2898
|
+
{
|
|
2899
|
+
f.call( this, checkboxInput ? subitem.checked : subkey, checkboxInput ? subkey : subentry );
|
|
2900
|
+
_resetMenubar();
|
|
2608
2901
|
}
|
|
2609
2902
|
e.stopPropagation();
|
|
2610
2903
|
e.stopImmediatePropagation();
|
|
@@ -2613,7 +2906,8 @@ class Menubar {
|
|
|
2613
2906
|
// Add icon if has submenu, else check for shortcut
|
|
2614
2907
|
if( !hasSubmenu)
|
|
2615
2908
|
{
|
|
2616
|
-
if(that.shorts[ subkey ])
|
|
2909
|
+
if( that.shorts[ subkey ] )
|
|
2910
|
+
{
|
|
2617
2911
|
let shortEl = document.createElement('div');
|
|
2618
2912
|
shortEl.className = "lexentryshort";
|
|
2619
2913
|
shortEl.innerText = that.shorts[ subkey ];
|
|
@@ -2627,43 +2921,66 @@ class Menubar {
|
|
|
2627
2921
|
subentry.appendChild( submenuIcon );
|
|
2628
2922
|
|
|
2629
2923
|
subentry.addEventListener("mouseover", e => {
|
|
2630
|
-
if(subentry.built)
|
|
2631
|
-
|
|
2924
|
+
if( subentry.built )
|
|
2925
|
+
{
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2632
2928
|
subentry.built = true;
|
|
2633
2929
|
create_submenu( subitem, subkey, subentry, ++d );
|
|
2634
2930
|
e.stopPropagation();
|
|
2635
2931
|
});
|
|
2636
2932
|
|
|
2637
|
-
subentry.addEventListener("mouseleave", () => {
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2933
|
+
subentry.addEventListener("mouseleave", (e) => {
|
|
2934
|
+
if( subentry.currentMenu && ( subentry.currentMenu != e.toElement ) )
|
|
2935
|
+
{
|
|
2936
|
+
d = -1; // Reset depth
|
|
2937
|
+
delete subentry.built;
|
|
2938
|
+
subentry.currentMenu.remove();
|
|
2939
|
+
delete subentry.currentMenu;
|
|
2940
|
+
}
|
|
2641
2941
|
});
|
|
2642
2942
|
}
|
|
2643
2943
|
|
|
2644
2944
|
// Set final width
|
|
2645
|
-
|
|
2945
|
+
menuElement.style.width = menuElement.offsetWidth + "px";
|
|
2646
2946
|
};
|
|
2647
2947
|
|
|
2648
|
-
|
|
2948
|
+
const _showEntry = () => {
|
|
2949
|
+
_resetMenubar();
|
|
2950
|
+
entry.classList.add( "selected" );
|
|
2951
|
+
entry.built = true;
|
|
2952
|
+
create_submenu( item, key, entry, -1 );
|
|
2953
|
+
};
|
|
2649
2954
|
|
|
2955
|
+
entry.addEventListener("click", () => {
|
|
2650
2956
|
const f = item[ 'callback' ];
|
|
2651
|
-
if(f)
|
|
2957
|
+
if( f )
|
|
2958
|
+
{
|
|
2652
2959
|
f.call( this, key, entry );
|
|
2653
2960
|
return;
|
|
2654
2961
|
}
|
|
2655
2962
|
|
|
2656
|
-
|
|
2657
|
-
this.root.querySelectorAll(".lexmenuentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
2658
|
-
entry.classList.add( "selected" );
|
|
2963
|
+
_showEntry();
|
|
2659
2964
|
|
|
2660
|
-
this.
|
|
2661
|
-
|
|
2965
|
+
this.focused = true;
|
|
2966
|
+
});
|
|
2967
|
+
|
|
2968
|
+
entry.addEventListener( "mouseover", (e) => {
|
|
2969
|
+
|
|
2970
|
+
if( this.focused && !entry.built )
|
|
2971
|
+
{
|
|
2972
|
+
_showEntry();
|
|
2973
|
+
}
|
|
2662
2974
|
});
|
|
2663
2975
|
|
|
2664
|
-
entry.addEventListener("
|
|
2665
|
-
|
|
2666
|
-
|
|
2976
|
+
entry.addEventListener("blur", (e) => {
|
|
2977
|
+
|
|
2978
|
+
if( e.relatedTarget && e.relatedTarget.classList.contains( "lexmenubox" ) )
|
|
2979
|
+
{
|
|
2980
|
+
return;
|
|
2981
|
+
}
|
|
2982
|
+
|
|
2983
|
+
_resetMenubar();
|
|
2667
2984
|
});
|
|
2668
2985
|
}
|
|
2669
2986
|
}
|
|
@@ -2682,20 +2999,24 @@ class Menubar {
|
|
|
2682
2999
|
* @param {Object} item: parent item
|
|
2683
3000
|
* @param {Array} tokens: split path strings
|
|
2684
3001
|
*/
|
|
2685
|
-
getSubitem(item, tokens) {
|
|
3002
|
+
getSubitem( item, tokens ) {
|
|
2686
3003
|
|
|
2687
3004
|
let subitem = null;
|
|
2688
|
-
let path = tokens[0];
|
|
2689
|
-
for(let i = 0; i < item.length; i++) {
|
|
2690
|
-
if(item[i][path]) {
|
|
3005
|
+
let path = tokens[ 0 ];
|
|
2691
3006
|
|
|
2692
|
-
|
|
2693
|
-
|
|
3007
|
+
for( let i = 0; i < item.length; i++ )
|
|
3008
|
+
{
|
|
3009
|
+
if( item[ i ][ path ] )
|
|
3010
|
+
{
|
|
3011
|
+
if( tokens.length == 1 )
|
|
3012
|
+
{
|
|
3013
|
+
subitem = item[ i ];
|
|
2694
3014
|
return subitem;
|
|
2695
3015
|
}
|
|
2696
|
-
else
|
|
2697
|
-
|
|
2698
|
-
|
|
3016
|
+
else
|
|
3017
|
+
{
|
|
3018
|
+
tokens.splice( 0, 1 );
|
|
3019
|
+
return this.getSubitem( item[ i ][ path ], tokens );
|
|
2699
3020
|
}
|
|
2700
3021
|
|
|
2701
3022
|
}
|
|
@@ -2722,11 +3043,12 @@ class Menubar {
|
|
|
2722
3043
|
setButtonIcon( title, icon, callback, options = {} ) {
|
|
2723
3044
|
|
|
2724
3045
|
const button = this.buttons[ title ];
|
|
2725
|
-
if(button)
|
|
2726
|
-
|
|
3046
|
+
if( button )
|
|
3047
|
+
{
|
|
2727
3048
|
button.querySelector('a').className = "fa-solid" + " " + icon + " lexicon";
|
|
2728
3049
|
}
|
|
2729
|
-
else
|
|
3050
|
+
else
|
|
3051
|
+
{
|
|
2730
3052
|
let button = document.createElement('div');
|
|
2731
3053
|
const disabled = options.disabled ?? false;
|
|
2732
3054
|
button.className = "lexmenubutton" + (disabled ? " disabled" : "");
|
|
@@ -2736,15 +3058,21 @@ class Menubar {
|
|
|
2736
3058
|
button.style.maxHeight = "calc(100% - 10px)";
|
|
2737
3059
|
button.style.alignItems = "center";
|
|
2738
3060
|
|
|
2739
|
-
if(options.float == "right")
|
|
3061
|
+
if( options.float == "right" )
|
|
3062
|
+
{
|
|
2740
3063
|
button.right = true;
|
|
2741
|
-
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
3067
|
+
{
|
|
2742
3068
|
this.root.lastChild.before( button );
|
|
2743
3069
|
}
|
|
2744
|
-
else if(options.float == "left")
|
|
2745
|
-
|
|
3070
|
+
else if( options.float == "left" )
|
|
3071
|
+
{
|
|
3072
|
+
this.root.prepend( button );
|
|
2746
3073
|
}
|
|
2747
|
-
else
|
|
3074
|
+
else
|
|
3075
|
+
{
|
|
2748
3076
|
this.root.appendChild( button );
|
|
2749
3077
|
}
|
|
2750
3078
|
|
|
@@ -2764,11 +3092,12 @@ class Menubar {
|
|
|
2764
3092
|
|
|
2765
3093
|
setButtonImage( title, src, callback, options = {} ) {
|
|
2766
3094
|
const button = this.buttons[ title ];
|
|
2767
|
-
if(button)
|
|
2768
|
-
|
|
3095
|
+
if( button )
|
|
3096
|
+
{
|
|
2769
3097
|
button.querySelector('a').className = "fa-solid" + " " + icon + " lexicon";
|
|
2770
3098
|
}
|
|
2771
|
-
else
|
|
3099
|
+
else
|
|
3100
|
+
{
|
|
2772
3101
|
let button = document.createElement('div');
|
|
2773
3102
|
const disabled = options.disabled ?? false;
|
|
2774
3103
|
button.className = "lexmenubutton" + (disabled ? " disabled" : "");
|
|
@@ -2777,15 +3106,21 @@ class Menubar {
|
|
|
2777
3106
|
button.style.padding = "5px";
|
|
2778
3107
|
button.style.alignItems = "center";
|
|
2779
3108
|
|
|
2780
|
-
if(options.float == "right")
|
|
3109
|
+
if( options.float == "right" )
|
|
3110
|
+
{
|
|
2781
3111
|
button.right = true;
|
|
2782
|
-
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
3115
|
+
{
|
|
2783
3116
|
this.root.lastChild.before( button );
|
|
2784
3117
|
}
|
|
2785
|
-
else if(options.float == "left")
|
|
2786
|
-
|
|
3118
|
+
else if( options.float == "left" )
|
|
3119
|
+
{
|
|
3120
|
+
this.root.prepend( button );
|
|
2787
3121
|
}
|
|
2788
|
-
else
|
|
3122
|
+
else
|
|
3123
|
+
{
|
|
2789
3124
|
this.root.appendChild( button );
|
|
2790
3125
|
}
|
|
2791
3126
|
|
|
@@ -2898,90 +3233,306 @@ LX.Menubar = Menubar;
|
|
|
2898
3233
|
|
|
2899
3234
|
class SideBar {
|
|
2900
3235
|
|
|
2901
|
-
|
|
3236
|
+
/**
|
|
3237
|
+
* @param {Object} options
|
|
3238
|
+
* inset: TODO
|
|
3239
|
+
* filter: TODO
|
|
3240
|
+
* skipHeader: Do not use sidebar header [false]
|
|
3241
|
+
* headerImg: Image to be shown as avatar
|
|
3242
|
+
* headerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3243
|
+
* headerTitle
|
|
3244
|
+
* headerSubtitle
|
|
3245
|
+
* skipFooter: Do not use sidebar footer [false]
|
|
3246
|
+
* footerImg: Image to be shown as avatar
|
|
3247
|
+
* footerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3248
|
+
* footerTitle
|
|
3249
|
+
* footerSubtitle
|
|
3250
|
+
* collapsable: Sidebar can toggle between collapsed/expanded [true]
|
|
3251
|
+
* collapseToIcons: When Sidebar collapses, icons remains visible [true]
|
|
3252
|
+
* onHeaderPressed: Function to call when header is pressed
|
|
3253
|
+
* onFooterPressed: Function to call when footer is pressed
|
|
3254
|
+
*/
|
|
3255
|
+
|
|
3256
|
+
constructor( options = {} ) {
|
|
2902
3257
|
|
|
2903
3258
|
this.root = document.createElement( 'div' );
|
|
2904
3259
|
this.root.className = "lexsidebar";
|
|
2905
3260
|
|
|
2906
|
-
|
|
2907
|
-
this.footer.className = "lexsidebarfooter";
|
|
2908
|
-
this.root.appendChild( this.footer );
|
|
3261
|
+
window.sidebar = this;
|
|
2909
3262
|
|
|
2910
|
-
this.
|
|
2911
|
-
|
|
3263
|
+
this.collapsable = options.collapsable ?? true;
|
|
3264
|
+
this.collapseWidth = ( options.collapseToIcons ?? true ) ? "58px" : "0px";
|
|
3265
|
+
this.collapsed = false;
|
|
2912
3266
|
|
|
2913
|
-
|
|
2914
|
-
* @method add
|
|
2915
|
-
* @param {*} options:
|
|
2916
|
-
* callback: Function to call on each item
|
|
2917
|
-
* bottom: Bool to set item at the bottom as helper button (not selectable)
|
|
2918
|
-
* className: Add class to the entry DOM element
|
|
2919
|
-
*/
|
|
3267
|
+
doAsync( () => {
|
|
2920
3268
|
|
|
2921
|
-
|
|
3269
|
+
this.root.parentElement.ogWidth = this.root.parentElement.style.width;
|
|
3270
|
+
this.root.parentElement.style.transition = "width 0.25s ease-out";
|
|
2922
3271
|
|
|
2923
|
-
|
|
2924
|
-
|
|
3272
|
+
this.resizeObserver = new ResizeObserver( entries => {
|
|
3273
|
+
for ( const entry of entries )
|
|
3274
|
+
{
|
|
3275
|
+
this.siblingArea.setSize( [ "calc(100% - " + ( entry.contentRect.width ) + "px )", null ] );
|
|
3276
|
+
}
|
|
3277
|
+
});
|
|
3278
|
+
|
|
3279
|
+
}, 100 );
|
|
3280
|
+
|
|
3281
|
+
// This account for header, footer and all inner paddings
|
|
3282
|
+
let contentOffset = 32;
|
|
3283
|
+
|
|
3284
|
+
// Header
|
|
3285
|
+
if( !( options.skipHeader ?? false ) )
|
|
3286
|
+
{
|
|
3287
|
+
this.header = document.createElement( 'div' );
|
|
3288
|
+
this.header.className = "lexsidebarheader";
|
|
3289
|
+
this.root.appendChild( this.header );
|
|
3290
|
+
|
|
3291
|
+
this.header.addEventListener( "click", e => {
|
|
3292
|
+
if( this.collapsed )
|
|
3293
|
+
{
|
|
3294
|
+
e.preventDefault();
|
|
3295
|
+
e.stopPropagation();
|
|
3296
|
+
this.toggleCollapsed();
|
|
3297
|
+
}
|
|
3298
|
+
else if( options.onHeaderPressed )
|
|
3299
|
+
{
|
|
3300
|
+
options.onHeaderPressed( e );
|
|
3301
|
+
}
|
|
3302
|
+
} );
|
|
3303
|
+
|
|
3304
|
+
const avatar = document.createElement( 'span' );
|
|
3305
|
+
avatar.className = "lexavatar";
|
|
3306
|
+
this.header.appendChild( avatar );
|
|
3307
|
+
|
|
3308
|
+
if( options.headerImage )
|
|
3309
|
+
{
|
|
3310
|
+
const avatarImg = document.createElement( 'img' );
|
|
3311
|
+
avatarImg.src = options.headerImage;
|
|
3312
|
+
avatar.appendChild( avatarImg );
|
|
3313
|
+
}
|
|
3314
|
+
else if( options.headerIcon )
|
|
3315
|
+
{
|
|
3316
|
+
const avatarIcon = LX.makeIcon( options.headerIcon );
|
|
3317
|
+
avatar.appendChild( avatarIcon );
|
|
3318
|
+
}
|
|
3319
|
+
|
|
3320
|
+
// Info
|
|
3321
|
+
{
|
|
3322
|
+
const info = document.createElement( 'div' );
|
|
3323
|
+
this.header.appendChild( info );
|
|
3324
|
+
|
|
3325
|
+
const infoText = document.createElement( 'span' );
|
|
3326
|
+
infoText.innerHTML = options.headerTitle ?? "";
|
|
3327
|
+
info.appendChild( infoText );
|
|
3328
|
+
|
|
3329
|
+
const infoSubtext = document.createElement( 'span' );
|
|
3330
|
+
infoSubtext.innerHTML = options.headerSubtitle ?? "";
|
|
3331
|
+
info.appendChild( infoSubtext );
|
|
3332
|
+
}
|
|
3333
|
+
|
|
3334
|
+
if( this.collapsable )
|
|
3335
|
+
{
|
|
3336
|
+
const icon = LX.makeIcon( "Sidebar", "Toggle Sidebar" );
|
|
3337
|
+
this.header.appendChild( icon );
|
|
3338
|
+
|
|
3339
|
+
icon.addEventListener( "click", (e) => {
|
|
3340
|
+
e.preventDefault();
|
|
3341
|
+
e.stopPropagation();
|
|
3342
|
+
this.toggleCollapsed();
|
|
3343
|
+
} );
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
contentOffset += 52;
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
// Content
|
|
3350
|
+
{
|
|
3351
|
+
this.content = document.createElement( 'div' );
|
|
3352
|
+
this.content.className = "lexsidebarcontent";
|
|
3353
|
+
this.root.appendChild( this.content );
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3356
|
+
// Footer
|
|
3357
|
+
if( !( options.skipFooter ?? false ) )
|
|
3358
|
+
{
|
|
3359
|
+
this.footer = document.createElement( 'div' );
|
|
3360
|
+
this.footer.className = "lexsidebarfooter";
|
|
3361
|
+
this.root.appendChild( this.footer );
|
|
3362
|
+
|
|
3363
|
+
this.footer.addEventListener( "click", e => {
|
|
3364
|
+
if( options.onFooterPressed )
|
|
3365
|
+
{
|
|
3366
|
+
options.onFooterPressed( e );
|
|
3367
|
+
}
|
|
3368
|
+
} );
|
|
2925
3369
|
|
|
2926
|
-
|
|
3370
|
+
const avatar = document.createElement( 'span' );
|
|
3371
|
+
avatar.className = "lexavatar";
|
|
3372
|
+
this.footer.appendChild( avatar );
|
|
2927
3373
|
|
|
2928
|
-
|
|
3374
|
+
if( options.footerImage )
|
|
3375
|
+
{
|
|
3376
|
+
const avatarImg = document.createElement( 'img' );
|
|
3377
|
+
avatarImg.src = options.footerImage;
|
|
3378
|
+
avatar.appendChild( avatarImg );
|
|
3379
|
+
}
|
|
3380
|
+
else if( options.footerIcon )
|
|
3381
|
+
{
|
|
3382
|
+
const avatarIcon = LX.makeIcon( options.footerIcon );
|
|
3383
|
+
avatar.appendChild( avatarIcon );
|
|
3384
|
+
}
|
|
3385
|
+
|
|
3386
|
+
// Info
|
|
3387
|
+
{
|
|
3388
|
+
const info = document.createElement( 'div' );
|
|
3389
|
+
this.footer.appendChild( info );
|
|
3390
|
+
|
|
3391
|
+
const infoText = document.createElement( 'span' );
|
|
3392
|
+
infoText.innerHTML = options.footerTitle ?? "";
|
|
3393
|
+
info.appendChild( infoText );
|
|
3394
|
+
|
|
3395
|
+
const infoSubtext = document.createElement( 'span' );
|
|
3396
|
+
infoSubtext.innerHTML = options.footerSubtitle ?? "";
|
|
3397
|
+
info.appendChild( infoSubtext );
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
const icon = LX.makeIcon( "MenuArrows" );
|
|
3401
|
+
this.footer.appendChild( icon );
|
|
3402
|
+
|
|
3403
|
+
contentOffset += 52;
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3406
|
+
// Set width depending on header/footer
|
|
3407
|
+
this.content.style.height = `calc(100% - ${ contentOffset }px)`;
|
|
3408
|
+
|
|
3409
|
+
this.items = [ ];
|
|
3410
|
+
this.icons = { };
|
|
3411
|
+
this.groups = { };
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3414
|
+
/**
|
|
3415
|
+
* @method toggleCollapsed
|
|
3416
|
+
*/
|
|
3417
|
+
|
|
3418
|
+
toggleCollapsed() {
|
|
3419
|
+
|
|
3420
|
+
if( !this.collapsable )
|
|
2929
3421
|
{
|
|
2930
|
-
console.warn( `'${key}' already created in Sidebar` );
|
|
2931
3422
|
return;
|
|
2932
3423
|
}
|
|
2933
3424
|
|
|
2934
|
-
|
|
2935
|
-
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
2936
|
-
entry.id = pKey;
|
|
3425
|
+
this.collapsed = !this.collapsed;
|
|
2937
3426
|
|
|
2938
|
-
if(
|
|
3427
|
+
if( this.collapsed )
|
|
2939
3428
|
{
|
|
2940
|
-
this.
|
|
3429
|
+
this.root.classList.add( "collapsing" );
|
|
3430
|
+
this.root.parentElement.style.width = this.collapseWidth;
|
|
2941
3431
|
}
|
|
2942
3432
|
else
|
|
2943
3433
|
{
|
|
2944
|
-
this.root.
|
|
3434
|
+
this.root.classList.remove( "collapsing" );
|
|
3435
|
+
this.root.classList.remove( "collapsed" );
|
|
3436
|
+
this.root.parentElement.style.width = this.root.parentElement.ogWidth;
|
|
2945
3437
|
}
|
|
2946
3438
|
|
|
2947
|
-
|
|
2948
|
-
this.root.appendChild( this.footer );
|
|
3439
|
+
this.resizeObserver.observe( this.root.parentElement );
|
|
2949
3440
|
|
|
2950
|
-
|
|
2951
|
-
button.innerHTML = "<i class='"+ (options.icon ?? "") + "'></i>";
|
|
2952
|
-
entry.appendChild( button );
|
|
3441
|
+
doAsync( () => {
|
|
2953
3442
|
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
desc.innerHTML = key;
|
|
2957
|
-
entry.appendChild( desc );
|
|
3443
|
+
this.root.classList.toggle( "collapsed", this.collapsed );
|
|
3444
|
+
this.resizeObserver.unobserve( this.root.parentElement );
|
|
2958
3445
|
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
desc.style.display = "unset";
|
|
2962
|
-
}, 100 );
|
|
2963
|
-
});
|
|
3446
|
+
}, 250 );
|
|
3447
|
+
}
|
|
2964
3448
|
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
3449
|
+
/**
|
|
3450
|
+
* @method separator
|
|
3451
|
+
*/
|
|
3452
|
+
|
|
3453
|
+
separator() {
|
|
3454
|
+
|
|
3455
|
+
this.currentGroup = null;
|
|
3456
|
+
|
|
3457
|
+
this.add( "" );
|
|
3458
|
+
}
|
|
2970
3459
|
|
|
2971
|
-
|
|
3460
|
+
/**
|
|
3461
|
+
* @method group
|
|
3462
|
+
* @param {String} groupName
|
|
3463
|
+
* @param {Object} action: { icon, callback }
|
|
3464
|
+
*/
|
|
3465
|
+
|
|
3466
|
+
group( groupName, action ) {
|
|
2972
3467
|
|
|
2973
|
-
|
|
2974
|
-
|
|
3468
|
+
this.currentGroup = groupName;
|
|
3469
|
+
|
|
3470
|
+
this.groups[ groupName ] = action;
|
|
3471
|
+
}
|
|
2975
3472
|
|
|
2976
|
-
|
|
2977
|
-
|
|
3473
|
+
/**
|
|
3474
|
+
* @method add
|
|
3475
|
+
* @param {String} path
|
|
3476
|
+
* @param {Object} options:
|
|
3477
|
+
* callback: Function to call on each item
|
|
3478
|
+
* icon: Entry icon
|
|
3479
|
+
* collapsable: Add entry as a collapsable section
|
|
3480
|
+
* className: Add class to the entry DOM element
|
|
3481
|
+
*/
|
|
3482
|
+
|
|
3483
|
+
add( path, options = {} ) {
|
|
3484
|
+
|
|
3485
|
+
if( options.constructor == Function )
|
|
3486
|
+
{
|
|
3487
|
+
options = { callback: options };
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
// Process path
|
|
3491
|
+
const tokens = path.split( "/" );
|
|
3492
|
+
|
|
3493
|
+
// Assign icons and shortcuts to last token in path
|
|
3494
|
+
const lastPath = tokens[tokens.length - 1];
|
|
3495
|
+
this.icons[ lastPath ] = options.icon;
|
|
3496
|
+
|
|
3497
|
+
|
|
3498
|
+
let idx = 0;
|
|
3499
|
+
|
|
3500
|
+
const _insertEntry = ( token, list ) => {
|
|
3501
|
+
|
|
3502
|
+
if( token == undefined )
|
|
2978
3503
|
{
|
|
2979
|
-
|
|
2980
|
-
entry.classList.add( "selected" );
|
|
3504
|
+
return;
|
|
2981
3505
|
}
|
|
2982
|
-
});
|
|
2983
3506
|
|
|
2984
|
-
|
|
3507
|
+
let found = null;
|
|
3508
|
+
list.forEach( o => {
|
|
3509
|
+
const keys = Object.keys( o );
|
|
3510
|
+
const key = keys.find( t => t == token );
|
|
3511
|
+
if( key ) found = o[ key ];
|
|
3512
|
+
} );
|
|
3513
|
+
|
|
3514
|
+
if( found )
|
|
3515
|
+
{
|
|
3516
|
+
_insertEntry( tokens[ idx++ ], found );
|
|
3517
|
+
}
|
|
3518
|
+
else
|
|
3519
|
+
{
|
|
3520
|
+
let item = {};
|
|
3521
|
+
item[ token ] = [];
|
|
3522
|
+
const nextToken = tokens[ idx++ ];
|
|
3523
|
+
// Check if last token -> add callback
|
|
3524
|
+
if( !nextToken )
|
|
3525
|
+
{
|
|
3526
|
+
item[ 'callback' ] = options.callback;
|
|
3527
|
+
item[ 'group' ] = this.currentGroup;
|
|
3528
|
+
item[ 'options' ] = options;
|
|
3529
|
+
}
|
|
3530
|
+
list.push( item );
|
|
3531
|
+
_insertEntry( nextToken, item[ token ] );
|
|
3532
|
+
}
|
|
3533
|
+
};
|
|
3534
|
+
|
|
3535
|
+
_insertEntry( tokens[idx++], this.items );
|
|
2985
3536
|
}
|
|
2986
3537
|
|
|
2987
3538
|
/**
|
|
@@ -3000,6 +3551,246 @@ class SideBar {
|
|
|
3000
3551
|
|
|
3001
3552
|
entry.domEl.click();
|
|
3002
3553
|
}
|
|
3554
|
+
|
|
3555
|
+
_build() {
|
|
3556
|
+
|
|
3557
|
+
for( let item of this.items )
|
|
3558
|
+
{
|
|
3559
|
+
const options = item.options ?? { };
|
|
3560
|
+
|
|
3561
|
+
// Item already created
|
|
3562
|
+
if( item.dom )
|
|
3563
|
+
{
|
|
3564
|
+
continue;
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3567
|
+
let key = Object.keys( item )[ 0 ];
|
|
3568
|
+
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3569
|
+
let currentGroup = null;
|
|
3570
|
+
|
|
3571
|
+
let entry = document.createElement( 'div' );
|
|
3572
|
+
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
3573
|
+
entry.id = pKey;
|
|
3574
|
+
|
|
3575
|
+
if( item.group )
|
|
3576
|
+
{
|
|
3577
|
+
const pGroupKey = item.group.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3578
|
+
currentGroup = this.content.querySelector( "#" + pGroupKey );
|
|
3579
|
+
|
|
3580
|
+
if( !currentGroup )
|
|
3581
|
+
{
|
|
3582
|
+
currentGroup = document.createElement( 'div' );
|
|
3583
|
+
currentGroup.id = pGroupKey;
|
|
3584
|
+
currentGroup.className = "lexsidebargroup";
|
|
3585
|
+
this.content.appendChild( currentGroup );
|
|
3586
|
+
|
|
3587
|
+
let groupEntry = document.createElement( 'div' );
|
|
3588
|
+
groupEntry.className = "lexsidebargrouptitle";
|
|
3589
|
+
currentGroup.appendChild( groupEntry );
|
|
3590
|
+
|
|
3591
|
+
let groupLabel = document.createElement( 'div' );
|
|
3592
|
+
groupLabel.innerHTML = item.group;
|
|
3593
|
+
groupEntry.appendChild( groupLabel );
|
|
3594
|
+
|
|
3595
|
+
if( this.groups[ item.group ] != null )
|
|
3596
|
+
{
|
|
3597
|
+
let groupAction = document.createElement( 'a' );
|
|
3598
|
+
groupAction.className = ( this.groups[ item.group ].icon ?? "" ) + " lexicon";
|
|
3599
|
+
groupEntry.appendChild( groupAction );
|
|
3600
|
+
groupAction.addEventListener( "click", (e) => {
|
|
3601
|
+
if( this.groups[ item.group ].callback )
|
|
3602
|
+
{
|
|
3603
|
+
this.groups[ item.group ].callback( item.group, e );
|
|
3604
|
+
}
|
|
3605
|
+
} );
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
}
|
|
3609
|
+
else if( !currentGroup.classList.contains( "lexsidebargroup" ) )
|
|
3610
|
+
{
|
|
3611
|
+
throw( "Bad id: " + item.group );
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
if( pKey == "" )
|
|
3616
|
+
{
|
|
3617
|
+
let separatorDom = document.createElement( 'div' );
|
|
3618
|
+
separatorDom.className = "lexsidebarseparator";
|
|
3619
|
+
this.content.appendChild( separatorDom );
|
|
3620
|
+
continue;
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
if( this.collapseContainer )
|
|
3624
|
+
{
|
|
3625
|
+
this.collapseContainer.appendChild( entry );
|
|
3626
|
+
|
|
3627
|
+
this.collapseQueue--;
|
|
3628
|
+
if( !this.collapseQueue )
|
|
3629
|
+
{
|
|
3630
|
+
delete this.collapseContainer;
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3633
|
+
else if( currentGroup )
|
|
3634
|
+
{
|
|
3635
|
+
currentGroup.appendChild( entry );
|
|
3636
|
+
}
|
|
3637
|
+
else
|
|
3638
|
+
{
|
|
3639
|
+
this.content.appendChild( entry );
|
|
3640
|
+
}
|
|
3641
|
+
|
|
3642
|
+
let itemDom = document.createElement( 'div' );
|
|
3643
|
+
entry.appendChild( itemDom );
|
|
3644
|
+
item.dom = itemDom;
|
|
3645
|
+
|
|
3646
|
+
if( options.type == "checkbox" )
|
|
3647
|
+
{
|
|
3648
|
+
item.value = options.value ?? false;
|
|
3649
|
+
const panel = new Panel();
|
|
3650
|
+
item.checkbox = panel.addCheckbox(null, item.value, (value, event) => {
|
|
3651
|
+
event.preventDefault();
|
|
3652
|
+
event.stopPropagation();
|
|
3653
|
+
const f = options.callback;
|
|
3654
|
+
item.value = value;
|
|
3655
|
+
if( f ) f.call( this, key, value, event );
|
|
3656
|
+
}, { label: key, signal: ( "@checkbox_" + key ) });
|
|
3657
|
+
itemDom.appendChild( panel.root.childNodes[ 0 ] );
|
|
3658
|
+
}
|
|
3659
|
+
else
|
|
3660
|
+
{
|
|
3661
|
+
if( options.icon )
|
|
3662
|
+
{
|
|
3663
|
+
let itemIcon = document.createElement( 'i' );
|
|
3664
|
+
itemIcon.className = options.icon;
|
|
3665
|
+
itemDom.appendChild( itemIcon );
|
|
3666
|
+
}
|
|
3667
|
+
|
|
3668
|
+
let itemName = document.createElement( 'a' );
|
|
3669
|
+
itemName.innerHTML = key;
|
|
3670
|
+
itemDom.appendChild( itemName );
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3673
|
+
entry.addEventListener("click", ( e ) => {
|
|
3674
|
+
if( e.target && e.target.classList.contains( "lexcheckbox" ) )
|
|
3675
|
+
{
|
|
3676
|
+
return;
|
|
3677
|
+
}
|
|
3678
|
+
|
|
3679
|
+
if( options.collapsable )
|
|
3680
|
+
{
|
|
3681
|
+
itemDom.querySelector( ".collapser" ).click();
|
|
3682
|
+
}
|
|
3683
|
+
else
|
|
3684
|
+
{
|
|
3685
|
+
const f = options.callback;
|
|
3686
|
+
if( f ) f.call( this, key, item.value, e );
|
|
3687
|
+
|
|
3688
|
+
if( item.checkbox )
|
|
3689
|
+
{
|
|
3690
|
+
item.value = !item.value;
|
|
3691
|
+
item.checkbox.set( item.value, true );
|
|
3692
|
+
}
|
|
3693
|
+
}
|
|
3694
|
+
|
|
3695
|
+
// Manage selected
|
|
3696
|
+
this.root.querySelectorAll(".lexsidebarentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
3697
|
+
entry.classList.add( "selected" );
|
|
3698
|
+
});
|
|
3699
|
+
|
|
3700
|
+
if( options.action )
|
|
3701
|
+
{
|
|
3702
|
+
const actionIcon = LX.makeIcon( options.action.icon ?? "MoreHorizontal", options.action.name );
|
|
3703
|
+
itemDom.appendChild( actionIcon );
|
|
3704
|
+
|
|
3705
|
+
actionIcon.addEventListener( "click", (e) => {
|
|
3706
|
+
e.preventDefault();
|
|
3707
|
+
e.stopImmediatePropagation();
|
|
3708
|
+
const f = options.action.callback;
|
|
3709
|
+
if( f ) f.call( this, key, e );
|
|
3710
|
+
} );
|
|
3711
|
+
}
|
|
3712
|
+
else if( options.collapsable )
|
|
3713
|
+
{
|
|
3714
|
+
const collapsableContent = document.createElement( 'div' );
|
|
3715
|
+
Object.assign( collapsableContent.style, { width: "100%", display: "none" } );
|
|
3716
|
+
LX.makeCollapsible( itemDom, collapsableContent, currentGroup ?? this.content );
|
|
3717
|
+
this.collapseQueue = options.collapsable;
|
|
3718
|
+
this.collapseContainer = collapsableContent;
|
|
3719
|
+
}
|
|
3720
|
+
|
|
3721
|
+
let desc = document.createElement( 'span' );
|
|
3722
|
+
desc.className = 'lexsidebarentrydesc';
|
|
3723
|
+
desc.innerHTML = key;
|
|
3724
|
+
entry.appendChild( desc );
|
|
3725
|
+
|
|
3726
|
+
itemDom.addEventListener("mouseenter", () => {
|
|
3727
|
+
setTimeout( () => {
|
|
3728
|
+
desc.style.display = "unset";
|
|
3729
|
+
}, 150 );
|
|
3730
|
+
});
|
|
3731
|
+
|
|
3732
|
+
itemDom.addEventListener("mouseleave", () => {
|
|
3733
|
+
setTimeout( () => {
|
|
3734
|
+
desc.style.display = "none";
|
|
3735
|
+
}, 150 );
|
|
3736
|
+
});
|
|
3737
|
+
|
|
3738
|
+
// Subentries
|
|
3739
|
+
if( !item[ key ].length )
|
|
3740
|
+
{
|
|
3741
|
+
continue;
|
|
3742
|
+
}
|
|
3743
|
+
|
|
3744
|
+
let subentryContainer = document.createElement( 'div' );
|
|
3745
|
+
subentryContainer.className = "lexsidebarsubentrycontainer";
|
|
3746
|
+
|
|
3747
|
+
if( currentGroup )
|
|
3748
|
+
{
|
|
3749
|
+
currentGroup.appendChild( subentryContainer );
|
|
3750
|
+
}
|
|
3751
|
+
else
|
|
3752
|
+
{
|
|
3753
|
+
this.content.appendChild( subentryContainer );
|
|
3754
|
+
}
|
|
3755
|
+
|
|
3756
|
+
for( var i = 0; i < item[ key ].length; ++i )
|
|
3757
|
+
{
|
|
3758
|
+
const subitem = item[ key ][ i ];
|
|
3759
|
+
const suboptions = subitem.options ?? {};
|
|
3760
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
3761
|
+
|
|
3762
|
+
let subentry = document.createElement( 'div' );
|
|
3763
|
+
subentry.innerHTML = `<span>${ subkey }</span>`;
|
|
3764
|
+
|
|
3765
|
+
if( suboptions.action )
|
|
3766
|
+
{
|
|
3767
|
+
const actionIcon = LX.makeIcon( suboptions.action.icon ?? "MoreHorizontal", suboptions.action.name );
|
|
3768
|
+
subentry.appendChild( actionIcon );
|
|
3769
|
+
|
|
3770
|
+
actionIcon.addEventListener( "click", (e) => {
|
|
3771
|
+
e.preventDefault();
|
|
3772
|
+
e.stopImmediatePropagation();
|
|
3773
|
+
const f = suboptions.action.callback;
|
|
3774
|
+
if( f ) f.call( this, subkey, e );
|
|
3775
|
+
} );
|
|
3776
|
+
}
|
|
3777
|
+
|
|
3778
|
+
subentry.className = "lexsidebarentry";
|
|
3779
|
+
subentry.id = subkey;
|
|
3780
|
+
subentryContainer.appendChild( subentry );
|
|
3781
|
+
|
|
3782
|
+
subentry.addEventListener("click", (e) => {
|
|
3783
|
+
|
|
3784
|
+
const f = suboptions.callback;
|
|
3785
|
+
if( f ) f.call( this, subkey, subentry, e );
|
|
3786
|
+
|
|
3787
|
+
// Manage selected
|
|
3788
|
+
this.root.querySelectorAll(".lexsidebarentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
3789
|
+
entry.classList.add( "selected" );
|
|
3790
|
+
});
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3003
3794
|
};
|
|
3004
3795
|
|
|
3005
3796
|
LX.SideBar = SideBar;
|
|
@@ -3017,30 +3808,32 @@ class Widget {
|
|
|
3017
3808
|
static DROPDOWN = 4;
|
|
3018
3809
|
static CHECKBOX = 5;
|
|
3019
3810
|
static TOGGLE = 6;
|
|
3020
|
-
static
|
|
3021
|
-
static
|
|
3022
|
-
static
|
|
3023
|
-
static
|
|
3024
|
-
static
|
|
3025
|
-
static
|
|
3026
|
-
static
|
|
3027
|
-
static
|
|
3028
|
-
static
|
|
3029
|
-
static
|
|
3030
|
-
static
|
|
3031
|
-
static
|
|
3032
|
-
static
|
|
3033
|
-
static
|
|
3034
|
-
static
|
|
3035
|
-
static
|
|
3036
|
-
static
|
|
3037
|
-
static
|
|
3038
|
-
static
|
|
3039
|
-
static
|
|
3040
|
-
static
|
|
3041
|
-
static
|
|
3042
|
-
static
|
|
3043
|
-
static
|
|
3811
|
+
static RADIO = 7;
|
|
3812
|
+
static COLOR = 8;
|
|
3813
|
+
static RANGE = 9;
|
|
3814
|
+
static NUMBER = 10;
|
|
3815
|
+
static TITLE = 11;
|
|
3816
|
+
static VECTOR = 12;
|
|
3817
|
+
static TREE = 13;
|
|
3818
|
+
static PROGRESS = 14;
|
|
3819
|
+
static FILE = 15;
|
|
3820
|
+
static LAYERS = 16;
|
|
3821
|
+
static ARRAY = 17;
|
|
3822
|
+
static LIST = 18;
|
|
3823
|
+
static TAGS = 19;
|
|
3824
|
+
static CURVE = 20;
|
|
3825
|
+
static CARD = 21;
|
|
3826
|
+
static IMAGE = 22;
|
|
3827
|
+
static CONTENT = 23;
|
|
3828
|
+
static CUSTOM = 24;
|
|
3829
|
+
static SEPARATOR = 25;
|
|
3830
|
+
static KNOB = 26;
|
|
3831
|
+
static SIZE = 27;
|
|
3832
|
+
static PAD = 28;
|
|
3833
|
+
static FORM = 29;
|
|
3834
|
+
static DIAL = 30;
|
|
3835
|
+
static COUNTER = 31;
|
|
3836
|
+
static TABLE = 32;
|
|
3044
3837
|
|
|
3045
3838
|
static NO_CONTEXT_TYPES = [
|
|
3046
3839
|
Widget.BUTTON,
|
|
@@ -3068,7 +3861,9 @@ class Widget {
|
|
|
3068
3861
|
set( value, skipCallback = false, signalName = "" ) {
|
|
3069
3862
|
|
|
3070
3863
|
if( this.onSetValue )
|
|
3864
|
+
{
|
|
3071
3865
|
return this.onSetValue( value, skipCallback );
|
|
3866
|
+
}
|
|
3072
3867
|
|
|
3073
3868
|
console.warn("Can't set value of " + this.typeName());
|
|
3074
3869
|
}
|
|
@@ -3107,14 +3902,17 @@ class Widget {
|
|
|
3107
3902
|
|
|
3108
3903
|
typeName() {
|
|
3109
3904
|
|
|
3110
|
-
switch( this.type )
|
|
3905
|
+
switch( this.type )
|
|
3906
|
+
{
|
|
3111
3907
|
case Widget.TEXT: return "Text";
|
|
3112
3908
|
case Widget.TEXTAREA: return "TextArea";
|
|
3113
3909
|
case Widget.BUTTON: return "Button";
|
|
3114
3910
|
case Widget.DROPDOWN: return "Dropdown";
|
|
3115
3911
|
case Widget.CHECKBOX: return "Checkbox";
|
|
3116
3912
|
case Widget.TOGGLE: return "Toggle";
|
|
3913
|
+
case Widget.RADIO: return "Radio";
|
|
3117
3914
|
case Widget.COLOR: return "Color";
|
|
3915
|
+
case Widget.RANGE: return "Range";
|
|
3118
3916
|
case Widget.NUMBER: return "Number";
|
|
3119
3917
|
case Widget.VECTOR: return "Vector";
|
|
3120
3918
|
case Widget.TREE: return "Tree";
|
|
@@ -3192,11 +3990,12 @@ function ADD_CUSTOM_WIDGET( custom_widget_name, options = {} )
|
|
|
3192
3990
|
buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
|
|
3193
3991
|
|
|
3194
3992
|
let buttonEl = this.addButton(null, buttonName, (value, event) => {
|
|
3195
|
-
|
|
3196
|
-
|
|
3993
|
+
if( instance )
|
|
3994
|
+
{
|
|
3197
3995
|
element.querySelector(".lexcustomitems").toggleAttribute('hidden');
|
|
3198
3996
|
}
|
|
3199
|
-
else
|
|
3997
|
+
else
|
|
3998
|
+
{
|
|
3200
3999
|
addContextMenu(null, event, c => {
|
|
3201
4000
|
c.add("New " + custom_widget_name, () => {
|
|
3202
4001
|
instance = {};
|
|
@@ -3383,16 +4182,20 @@ class NodeTree {
|
|
|
3383
4182
|
|
|
3384
4183
|
// Add or remove
|
|
3385
4184
|
const idx = this.selected.indexOf( node );
|
|
3386
|
-
if( idx > -1 )
|
|
4185
|
+
if( idx > -1 )
|
|
4186
|
+
{
|
|
3387
4187
|
item.classList.remove( 'selected' );
|
|
3388
4188
|
this.selected.splice( idx, 1 );
|
|
3389
|
-
}
|
|
4189
|
+
}
|
|
4190
|
+
else
|
|
4191
|
+
{
|
|
3390
4192
|
item.classList.add( 'selected' );
|
|
3391
4193
|
this.selected.push( node );
|
|
3392
4194
|
}
|
|
3393
4195
|
|
|
3394
4196
|
// Only Show children...
|
|
3395
|
-
if( isParent && node.id.length > 1 /* Strange case... */)
|
|
4197
|
+
if( isParent && node.id.length > 1 /* Strange case... */)
|
|
4198
|
+
{
|
|
3396
4199
|
node.closed = false;
|
|
3397
4200
|
if( that.onevent )
|
|
3398
4201
|
{
|
|
@@ -3430,7 +4233,7 @@ class NodeTree {
|
|
|
3430
4233
|
|
|
3431
4234
|
e.preventDefault();
|
|
3432
4235
|
|
|
3433
|
-
if( that.onevent )
|
|
4236
|
+
if( !that.onevent )
|
|
3434
4237
|
{
|
|
3435
4238
|
return;
|
|
3436
4239
|
}
|
|
@@ -3486,7 +4289,8 @@ class NodeTree {
|
|
|
3486
4289
|
return;
|
|
3487
4290
|
}
|
|
3488
4291
|
|
|
3489
|
-
if( that.onevent )
|
|
4292
|
+
if( that.onevent )
|
|
4293
|
+
{
|
|
3490
4294
|
const event = new TreeEvent( TreeEvent.NODE_DELETED, node, e );
|
|
3491
4295
|
that.onevent( event );
|
|
3492
4296
|
}
|
|
@@ -3513,7 +4317,8 @@ class NodeTree {
|
|
|
3513
4317
|
if( e.key == "Delete" )
|
|
3514
4318
|
{
|
|
3515
4319
|
// Send event now so we have the info in selected array..
|
|
3516
|
-
if( that.onevent )
|
|
4320
|
+
if( that.onevent )
|
|
4321
|
+
{
|
|
3517
4322
|
const event = new TreeEvent( TreeEvent.NODE_DELETED, this.selected.length > 1 ? this.selected : node, e );
|
|
3518
4323
|
event.multiple = this.selected.length > 1;
|
|
3519
4324
|
that.onevent( event );
|
|
@@ -3544,22 +4349,24 @@ class NodeTree {
|
|
|
3544
4349
|
|
|
3545
4350
|
// Node rename
|
|
3546
4351
|
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
item.appendChild(
|
|
4352
|
+
const nameInput = document.createElement( "input" );
|
|
4353
|
+
nameInput.toggleAttribute( "hidden", !node.rename );
|
|
4354
|
+
nameInput.value = node.id;
|
|
4355
|
+
item.appendChild(nameInput);
|
|
3551
4356
|
|
|
3552
|
-
if(node.rename)
|
|
4357
|
+
if( node.rename )
|
|
4358
|
+
{
|
|
3553
4359
|
item.classList.add('selected');
|
|
3554
|
-
|
|
4360
|
+
nameInput.focus();
|
|
3555
4361
|
}
|
|
3556
4362
|
|
|
3557
|
-
|
|
3558
|
-
if(e.key ==
|
|
3559
|
-
|
|
4363
|
+
nameInput.addEventListener("keyup", function(e){
|
|
4364
|
+
if( e.key == "Enter" )
|
|
4365
|
+
{
|
|
3560
4366
|
this.value = this.value.replace(/\s/g, '_');
|
|
3561
4367
|
|
|
3562
|
-
if(that.onevent)
|
|
4368
|
+
if( that.onevent )
|
|
4369
|
+
{
|
|
3563
4370
|
const event = new TreeEvent(TreeEvent.NODE_RENAMED, node, this.value);
|
|
3564
4371
|
that.onevent( event );
|
|
3565
4372
|
}
|
|
@@ -3569,18 +4376,20 @@ class NodeTree {
|
|
|
3569
4376
|
that.frefresh( node.id );
|
|
3570
4377
|
list.querySelector("#" + node.id).classList.add('selected');
|
|
3571
4378
|
}
|
|
3572
|
-
if(e.key ==
|
|
4379
|
+
else if(e.key == "Escape")
|
|
4380
|
+
{
|
|
3573
4381
|
delete node.rename;
|
|
3574
4382
|
that.frefresh( node.id );
|
|
3575
4383
|
}
|
|
3576
4384
|
});
|
|
3577
4385
|
|
|
3578
|
-
|
|
4386
|
+
nameInput.addEventListener("blur", function(e){
|
|
3579
4387
|
delete node.rename;
|
|
3580
4388
|
that.refresh();
|
|
3581
4389
|
});
|
|
3582
4390
|
|
|
3583
|
-
if(this.options.draggable ?? true)
|
|
4391
|
+
if( this.options.draggable ?? true )
|
|
4392
|
+
{
|
|
3584
4393
|
// Drag nodes
|
|
3585
4394
|
if(parent) // Root doesn't move!
|
|
3586
4395
|
{
|
|
@@ -3606,29 +4415,32 @@ class NodeTree {
|
|
|
3606
4415
|
return;
|
|
3607
4416
|
let target = node;
|
|
3608
4417
|
// Can't drop to same node
|
|
3609
|
-
if(dragged.id == target.id)
|
|
4418
|
+
if( dragged.id == target.id )
|
|
4419
|
+
{
|
|
3610
4420
|
console.warn("Cannot parent node to itself!");
|
|
3611
4421
|
return;
|
|
3612
4422
|
}
|
|
3613
4423
|
|
|
3614
4424
|
// Can't drop to child node
|
|
3615
|
-
const isChild = function(
|
|
4425
|
+
const isChild = function( newParent, node ) {
|
|
3616
4426
|
var result = false;
|
|
3617
|
-
for( var c of node.children )
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
result |= isChild(
|
|
4427
|
+
for( var c of node.children )
|
|
4428
|
+
{
|
|
4429
|
+
if( c.id == newParent.id ) return true;
|
|
4430
|
+
result |= isChild( newParent, c );
|
|
3621
4431
|
}
|
|
3622
4432
|
return result;
|
|
3623
4433
|
};
|
|
3624
4434
|
|
|
3625
|
-
if(isChild(target, dragged))
|
|
4435
|
+
if( isChild( target, dragged ))
|
|
4436
|
+
{
|
|
3626
4437
|
console.warn("Cannot parent node to a current child!");
|
|
3627
4438
|
return;
|
|
3628
4439
|
}
|
|
3629
4440
|
|
|
3630
4441
|
// Trigger node dragger event
|
|
3631
|
-
if(that.onevent)
|
|
4442
|
+
if( that.onevent )
|
|
4443
|
+
{
|
|
3632
4444
|
const event = new TreeEvent(TreeEvent.NODE_DRAGGED, dragged, target);
|
|
3633
4445
|
that.onevent( event );
|
|
3634
4446
|
}
|
|
@@ -3644,7 +4456,8 @@ class NodeTree {
|
|
|
3644
4456
|
let handled = false;
|
|
3645
4457
|
|
|
3646
4458
|
// Show/hide children
|
|
3647
|
-
if(isParent)
|
|
4459
|
+
if( isParent )
|
|
4460
|
+
{
|
|
3648
4461
|
item.querySelector('a.hierarchy').addEventListener("click", function(e) {
|
|
3649
4462
|
|
|
3650
4463
|
handled = true;
|
|
@@ -3652,7 +4465,8 @@ class NodeTree {
|
|
|
3652
4465
|
e.stopPropagation();
|
|
3653
4466
|
|
|
3654
4467
|
node.closed = !node.closed;
|
|
3655
|
-
if(that.onevent)
|
|
4468
|
+
if( that.onevent )
|
|
4469
|
+
{
|
|
3656
4470
|
const event = new TreeEvent(TreeEvent.NODE_CARETCHANGED, node, node.closed);
|
|
3657
4471
|
that.onevent( event );
|
|
3658
4472
|
}
|
|
@@ -3672,7 +4486,8 @@ class NodeTree {
|
|
|
3672
4486
|
node.visible = node.visible === undefined ? false : !node.visible;
|
|
3673
4487
|
this.className = "itemicon fa-solid fa-eye" + (!node.visible ? "-slash" : "");
|
|
3674
4488
|
// Trigger visibility event
|
|
3675
|
-
if(that.onevent)
|
|
4489
|
+
if( that.onevent )
|
|
4490
|
+
{
|
|
3676
4491
|
const event = new TreeEvent(TreeEvent.NODE_VISIBILITY, node, node.visible);
|
|
3677
4492
|
that.onevent( event );
|
|
3678
4493
|
}
|
|
@@ -3681,9 +4496,10 @@ class NodeTree {
|
|
|
3681
4496
|
item.appendChild(visibility);
|
|
3682
4497
|
}
|
|
3683
4498
|
|
|
3684
|
-
if(node.actions)
|
|
4499
|
+
if( node.actions )
|
|
3685
4500
|
{
|
|
3686
|
-
for(var i = 0; i < node.actions.length; ++i)
|
|
4501
|
+
for( var i = 0; i < node.actions.length; ++i )
|
|
4502
|
+
{
|
|
3687
4503
|
let a = node.actions[i];
|
|
3688
4504
|
var actionEl = document.createElement('a');
|
|
3689
4505
|
actionEl.className = "itemicon " + a.icon;
|
|
@@ -3696,20 +4512,25 @@ class NodeTree {
|
|
|
3696
4512
|
}
|
|
3697
4513
|
}
|
|
3698
4514
|
|
|
3699
|
-
if(selectedId != undefined && node.id == selectedId)
|
|
3700
|
-
|
|
4515
|
+
if( selectedId != undefined && node.id == selectedId )
|
|
4516
|
+
{
|
|
4517
|
+
this.selected = [ node ];
|
|
3701
4518
|
item.click();
|
|
3702
4519
|
}
|
|
3703
4520
|
|
|
3704
|
-
if(node.closed )
|
|
4521
|
+
if( node.closed )
|
|
4522
|
+
{
|
|
3705
4523
|
return;
|
|
4524
|
+
}
|
|
3706
4525
|
|
|
3707
4526
|
for( var i = 0; i < node.children.length; ++i )
|
|
3708
4527
|
{
|
|
3709
|
-
let child = node.children[i];
|
|
4528
|
+
let child = node.children[ i ];
|
|
3710
4529
|
|
|
3711
|
-
if( this.options.onlyFolders && child.type != 'folder')
|
|
4530
|
+
if( this.options.onlyFolders && child.type != 'folder' )
|
|
4531
|
+
{
|
|
3712
4532
|
continue;
|
|
4533
|
+
}
|
|
3713
4534
|
|
|
3714
4535
|
this._create_item( node, child, level + 1 );
|
|
3715
4536
|
}
|
|
@@ -3748,12 +4569,12 @@ class Panel {
|
|
|
3748
4569
|
* style: CSS Style object to be applied to the panel
|
|
3749
4570
|
*/
|
|
3750
4571
|
|
|
3751
|
-
constructor( options = {} )
|
|
4572
|
+
constructor( options = {} ) {
|
|
3752
4573
|
var root = document.createElement('div');
|
|
3753
4574
|
root.className = "lexpanel";
|
|
3754
|
-
if(options.id)
|
|
4575
|
+
if( options.id )
|
|
3755
4576
|
root.id = options.id;
|
|
3756
|
-
if(options.className)
|
|
4577
|
+
if( options.className )
|
|
3757
4578
|
root.className += " " + options.className;
|
|
3758
4579
|
|
|
3759
4580
|
root.style.width = options.width || "calc( 100% - 6px )";
|
|
@@ -3830,23 +4651,31 @@ class Panel {
|
|
|
3830
4651
|
this.branches = [];
|
|
3831
4652
|
this.current_branch = null;
|
|
3832
4653
|
|
|
3833
|
-
for(let w in this.widgets)
|
|
3834
|
-
|
|
4654
|
+
for( let w in this.widgets )
|
|
4655
|
+
{
|
|
4656
|
+
if( this.widgets[w].options && this.widgets[w].options.signal )
|
|
4657
|
+
{
|
|
3835
4658
|
const signal = this.widgets[w].options.signal;
|
|
3836
|
-
for(let i = 0; i < LX.signals[signal].length; i++)
|
|
3837
|
-
|
|
4659
|
+
for( let i = 0; i < LX.signals[signal].length; i++ )
|
|
4660
|
+
{
|
|
4661
|
+
if( LX.signals[signal][i] == this.widgets[w] )
|
|
4662
|
+
{
|
|
3838
4663
|
LX.signals[signal] = [...LX.signals[signal].slice(0, i), ...LX.signals[signal].slice(i+1)];
|
|
3839
4664
|
}
|
|
3840
4665
|
}
|
|
3841
4666
|
}
|
|
3842
4667
|
}
|
|
3843
4668
|
|
|
3844
|
-
if(this.signals)
|
|
3845
|
-
|
|
4669
|
+
if( this.signals )
|
|
4670
|
+
{
|
|
4671
|
+
for( let w = 0; w < this.signals.length; w++ )
|
|
4672
|
+
{
|
|
3846
4673
|
let widget = Object.values(this.signals[w])[0];
|
|
3847
4674
|
let signal = widget.options.signal;
|
|
3848
|
-
for(let i = 0; i < LX.signals[signal].length; i++)
|
|
3849
|
-
|
|
4675
|
+
for( let i = 0; i < LX.signals[signal].length; i++ )
|
|
4676
|
+
{
|
|
4677
|
+
if( LX.signals[signal][i] == widget )
|
|
4678
|
+
{
|
|
3850
4679
|
LX.signals[signal] = [...LX.signals[signal].slice(0, i), ...LX.signals[signal].slice(i+1)];
|
|
3851
4680
|
}
|
|
3852
4681
|
}
|
|
@@ -3884,10 +4713,12 @@ class Panel {
|
|
|
3884
4713
|
|
|
3885
4714
|
this._inline_widgets_left = -1;
|
|
3886
4715
|
|
|
3887
|
-
if(!this._inlineContainer)
|
|
4716
|
+
if( !this._inlineContainer )
|
|
4717
|
+
{
|
|
3888
4718
|
this._inlineContainer = document.createElement('div');
|
|
3889
4719
|
this._inlineContainer.className = "lexinlinewidgets";
|
|
3890
|
-
|
|
4720
|
+
|
|
4721
|
+
if( justifyContent )
|
|
3891
4722
|
{
|
|
3892
4723
|
this._inlineContainer.style.justifyContent = justifyContent;
|
|
3893
4724
|
}
|
|
@@ -3901,7 +4732,7 @@ class Panel {
|
|
|
3901
4732
|
if(is_pair)
|
|
3902
4733
|
{
|
|
3903
4734
|
// eg. an array, inline items appended later to
|
|
3904
|
-
if(this._inline_queued_container)
|
|
4735
|
+
if( this._inline_queued_container)
|
|
3905
4736
|
this._inlineContainer.appendChild( item[0] );
|
|
3906
4737
|
// eg. a dropdown, item is appended to parent, not to inline cont.
|
|
3907
4738
|
else
|
|
@@ -3913,7 +4744,7 @@ class Panel {
|
|
|
3913
4744
|
|
|
3914
4745
|
if(!this._inline_queued_container)
|
|
3915
4746
|
{
|
|
3916
|
-
if(this.current_branch)
|
|
4747
|
+
if( this.current_branch)
|
|
3917
4748
|
this.current_branch.content.appendChild( this._inlineContainer );
|
|
3918
4749
|
else
|
|
3919
4750
|
this.root.appendChild( this._inlineContainer );
|
|
@@ -3952,7 +4783,7 @@ class Panel {
|
|
|
3952
4783
|
this.current_branch = branch;
|
|
3953
4784
|
|
|
3954
4785
|
// Append to panel
|
|
3955
|
-
if(this.branches.length == 0)
|
|
4786
|
+
if( this.branches.length == 0)
|
|
3956
4787
|
branch.root.classList.add('first');
|
|
3957
4788
|
|
|
3958
4789
|
// This is the last!
|
|
@@ -3963,7 +4794,8 @@ class Panel {
|
|
|
3963
4794
|
this.root.appendChild( branch.root );
|
|
3964
4795
|
|
|
3965
4796
|
// Add widget filter
|
|
3966
|
-
if(options.filter)
|
|
4797
|
+
if( options.filter )
|
|
4798
|
+
{
|
|
3967
4799
|
this._addFilter( options.filter, {callback: this._searchWidgets.bind(this, branch.name)} );
|
|
3968
4800
|
}
|
|
3969
4801
|
|
|
@@ -4080,14 +4912,18 @@ class Panel {
|
|
|
4080
4912
|
element.jsInstance = widget;
|
|
4081
4913
|
|
|
4082
4914
|
const insert_widget = el => {
|
|
4083
|
-
if(options.container)
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4915
|
+
if( options.container )
|
|
4916
|
+
{
|
|
4917
|
+
options.container.appendChild( el );
|
|
4918
|
+
}
|
|
4919
|
+
else if( !this.queuedContainer )
|
|
4920
|
+
{
|
|
4921
|
+
if( this.current_branch )
|
|
4088
4922
|
{
|
|
4089
|
-
if(!options.skipWidget)
|
|
4923
|
+
if( !options.skipWidget )
|
|
4924
|
+
{
|
|
4090
4925
|
this.current_branch.widgets.push( widget );
|
|
4926
|
+
}
|
|
4091
4927
|
this.current_branch.content.appendChild( el );
|
|
4092
4928
|
}
|
|
4093
4929
|
else
|
|
@@ -4097,40 +4933,47 @@ class Panel {
|
|
|
4097
4933
|
}
|
|
4098
4934
|
}
|
|
4099
4935
|
// Append content to queued tab container
|
|
4100
|
-
else
|
|
4936
|
+
else
|
|
4937
|
+
{
|
|
4101
4938
|
this.queuedContainer.appendChild( el );
|
|
4102
4939
|
}
|
|
4103
4940
|
};
|
|
4104
4941
|
|
|
4105
4942
|
const store_widget = el => {
|
|
4106
4943
|
|
|
4107
|
-
if(!this.queuedContainer)
|
|
4944
|
+
if( !this.queuedContainer )
|
|
4945
|
+
{
|
|
4108
4946
|
this._inlineWidgets.push( el );
|
|
4109
4947
|
}
|
|
4110
4948
|
// Append content to queued tab container
|
|
4111
|
-
else
|
|
4949
|
+
else
|
|
4950
|
+
{
|
|
4112
4951
|
this._inlineWidgets.push( [el, this.queuedContainer] );
|
|
4113
4952
|
}
|
|
4114
4953
|
};
|
|
4115
4954
|
|
|
4116
4955
|
// Process inline widgets
|
|
4117
|
-
if(this._inline_widgets_left > 0 && !options.skipInlineCount)
|
|
4956
|
+
if( this._inline_widgets_left > 0 && !options.skipInlineCount )
|
|
4118
4957
|
{
|
|
4119
|
-
if(!this._inlineWidgets)
|
|
4958
|
+
if( !this._inlineWidgets )
|
|
4959
|
+
{
|
|
4120
4960
|
this._inlineWidgets = [];
|
|
4121
4961
|
}
|
|
4122
4962
|
|
|
4123
4963
|
// Store widget and its container
|
|
4124
|
-
store_widget(element);
|
|
4964
|
+
store_widget( element );
|
|
4125
4965
|
|
|
4126
4966
|
this._inline_widgets_left--;
|
|
4127
4967
|
|
|
4128
4968
|
// Last widget
|
|
4129
|
-
if(!this._inline_widgets_left)
|
|
4969
|
+
if( !this._inline_widgets_left )
|
|
4970
|
+
{
|
|
4130
4971
|
this.endLine();
|
|
4131
4972
|
}
|
|
4132
|
-
}
|
|
4133
|
-
|
|
4973
|
+
}
|
|
4974
|
+
else
|
|
4975
|
+
{
|
|
4976
|
+
insert_widget( element );
|
|
4134
4977
|
}
|
|
4135
4978
|
|
|
4136
4979
|
return widget;
|
|
@@ -4167,15 +5010,20 @@ class Panel {
|
|
|
4167
5010
|
|
|
4168
5011
|
_searchWidgets(branchName, value) {
|
|
4169
5012
|
|
|
4170
|
-
for( let b of this.branches )
|
|
4171
|
-
|
|
4172
|
-
if(b.name !== branchName)
|
|
5013
|
+
for( let b of this.branches )
|
|
5014
|
+
{
|
|
5015
|
+
if( b.name !== branchName )
|
|
5016
|
+
{
|
|
4173
5017
|
continue;
|
|
5018
|
+
}
|
|
4174
5019
|
|
|
4175
5020
|
// remove all widgets
|
|
4176
|
-
for( let w of b.widgets )
|
|
4177
|
-
|
|
5021
|
+
for( let w of b.widgets )
|
|
5022
|
+
{
|
|
5023
|
+
if( w.domEl.classList.contains('lexfilter') )
|
|
5024
|
+
{
|
|
4178
5025
|
continue;
|
|
5026
|
+
}
|
|
4179
5027
|
w.domEl.remove();
|
|
4180
5028
|
}
|
|
4181
5029
|
|
|
@@ -4185,9 +5033,9 @@ class Panel {
|
|
|
4185
5033
|
const emptyFilter = !value.length;
|
|
4186
5034
|
|
|
4187
5035
|
// add widgets
|
|
4188
|
-
for( let w of b.widgets )
|
|
4189
|
-
|
|
4190
|
-
if(!emptyFilter)
|
|
5036
|
+
for( let w of b.widgets )
|
|
5037
|
+
{
|
|
5038
|
+
if( !emptyFilter )
|
|
4191
5039
|
{
|
|
4192
5040
|
if(!w.name) continue;
|
|
4193
5041
|
const filterWord = value.toLowerCase();
|
|
@@ -4281,7 +5129,7 @@ class Panel {
|
|
|
4281
5129
|
|
|
4282
5130
|
clearQueue() {
|
|
4283
5131
|
|
|
4284
|
-
if(this._queue && this._queue.length)
|
|
5132
|
+
if( this._queue && this._queue.length)
|
|
4285
5133
|
{
|
|
4286
5134
|
this.queuedContainer = this._queue.pop();
|
|
4287
5135
|
return;
|
|
@@ -4507,7 +5355,8 @@ class Panel {
|
|
|
4507
5355
|
element.appendChild( container );
|
|
4508
5356
|
|
|
4509
5357
|
// Remove branch padding and margins
|
|
4510
|
-
if( !widget.name )
|
|
5358
|
+
if( !widget.name )
|
|
5359
|
+
{
|
|
4511
5360
|
element.className += " noname";
|
|
4512
5361
|
container.style.width = "100%";
|
|
4513
5362
|
}
|
|
@@ -4607,7 +5456,8 @@ class Panel {
|
|
|
4607
5456
|
element.appendChild(container);
|
|
4608
5457
|
|
|
4609
5458
|
// Remove branch padding and margins
|
|
4610
|
-
if(!widget.name)
|
|
5459
|
+
if( !widget.name )
|
|
5460
|
+
{
|
|
4611
5461
|
element.className += " noname";
|
|
4612
5462
|
container.style.width = "100%";
|
|
4613
5463
|
}
|
|
@@ -4712,11 +5562,12 @@ class Panel {
|
|
|
4712
5562
|
/**
|
|
4713
5563
|
* @method addComboButtons
|
|
4714
5564
|
* @param {String} name Widget name
|
|
4715
|
-
* @param {Array} values Each of the {value, callback} items
|
|
5565
|
+
* @param {Array} values Each of the {value, callback, selected, disabled} items
|
|
4716
5566
|
* @param {*} options:
|
|
4717
5567
|
* float: Justify content (left, center, right) [center]
|
|
4718
|
-
* selected: Selected item by default by value
|
|
5568
|
+
* @legacy selected: Selected item by default by value
|
|
4719
5569
|
* noSelection: Buttons can be clicked, but they are not selectable
|
|
5570
|
+
* toggle: Buttons can be toggled insted of selecting only one
|
|
4720
5571
|
*/
|
|
4721
5572
|
|
|
4722
5573
|
addComboButtons( name, values, options = {} ) {
|
|
@@ -4738,7 +5589,8 @@ class Panel {
|
|
|
4738
5589
|
let buttonsBox = document.createElement('div');
|
|
4739
5590
|
buttonsBox.className = "lexcombobuttonsbox ";
|
|
4740
5591
|
|
|
4741
|
-
|
|
5592
|
+
const shouldSelect = !( options.noSelection ?? false );
|
|
5593
|
+
const shouldToggle = shouldSelect && ( options.toggle ?? false );
|
|
4742
5594
|
|
|
4743
5595
|
for( let b of values )
|
|
4744
5596
|
{
|
|
@@ -4757,14 +5609,14 @@ class Panel {
|
|
|
4757
5609
|
buttonEl.classList.add( options.buttonClass );
|
|
4758
5610
|
}
|
|
4759
5611
|
|
|
4760
|
-
if( shouldSelect && options.selected == b.value )
|
|
5612
|
+
if( shouldSelect && ( b.selected || options.selected == b.value ) )
|
|
4761
5613
|
{
|
|
4762
5614
|
buttonEl.classList.add("selected");
|
|
4763
5615
|
}
|
|
4764
5616
|
|
|
4765
5617
|
buttonEl.innerHTML = ( b.icon ? "<a class='" + b.icon +"'></a>" : "" ) + "<span>" + ( b.icon ? "" : b.value ) + "</span>";
|
|
4766
5618
|
|
|
4767
|
-
if(
|
|
5619
|
+
if( b.disabled )
|
|
4768
5620
|
{
|
|
4769
5621
|
buttonEl.setAttribute( "disabled", true );
|
|
4770
5622
|
}
|
|
@@ -4772,8 +5624,15 @@ class Panel {
|
|
|
4772
5624
|
buttonEl.addEventListener("click", function( e ) {
|
|
4773
5625
|
if( shouldSelect )
|
|
4774
5626
|
{
|
|
4775
|
-
|
|
4776
|
-
|
|
5627
|
+
if( shouldToggle )
|
|
5628
|
+
{
|
|
5629
|
+
this.classList.toggle('selected');
|
|
5630
|
+
}
|
|
5631
|
+
else
|
|
5632
|
+
{
|
|
5633
|
+
container.querySelectorAll('button').forEach( s => s.classList.remove('selected'));
|
|
5634
|
+
this.classList.add('selected');
|
|
5635
|
+
}
|
|
4777
5636
|
}
|
|
4778
5637
|
|
|
4779
5638
|
that._trigger( new IEvent( name, b.value, e ), b.callback );
|
|
@@ -4783,7 +5642,7 @@ class Panel {
|
|
|
4783
5642
|
}
|
|
4784
5643
|
|
|
4785
5644
|
// Remove branch padding and margins
|
|
4786
|
-
if( !widget.name)
|
|
5645
|
+
if( !widget.name )
|
|
4787
5646
|
{
|
|
4788
5647
|
element.className += " noname";
|
|
4789
5648
|
container.style.width = "100%";
|
|
@@ -4957,7 +5816,8 @@ class Panel {
|
|
|
4957
5816
|
|
|
4958
5817
|
element.appendChild( container );
|
|
4959
5818
|
|
|
4960
|
-
if( !widget.name || options.hideName )
|
|
5819
|
+
if( !widget.name || options.hideName )
|
|
5820
|
+
{
|
|
4961
5821
|
element.className += " noname";
|
|
4962
5822
|
container.style.width = "100%";
|
|
4963
5823
|
}
|
|
@@ -5093,8 +5953,6 @@ class Panel {
|
|
|
5093
5953
|
|
|
5094
5954
|
const _placeOptions = ( parent ) => {
|
|
5095
5955
|
|
|
5096
|
-
console.log("Replacing container");
|
|
5097
|
-
|
|
5098
5956
|
const overflowContainer = parent.getParentArea();
|
|
5099
5957
|
const rect = selectedOption.getBoundingClientRect();
|
|
5100
5958
|
const nestedDialog = parent.parentElement.closest( "dialog" );
|
|
@@ -5378,15 +6236,16 @@ class Panel {
|
|
|
5378
6236
|
|
|
5379
6237
|
addCurve( name, values, callback, options = {} ) {
|
|
5380
6238
|
|
|
5381
|
-
if(!name)
|
|
5382
|
-
|
|
6239
|
+
if( !name )
|
|
6240
|
+
{
|
|
6241
|
+
throw( "Set Widget Name!" );
|
|
5383
6242
|
}
|
|
5384
6243
|
|
|
5385
6244
|
let that = this;
|
|
5386
|
-
let widget = this.create_widget(name, Widget.CURVE, options);
|
|
6245
|
+
let widget = this.create_widget( name, Widget.CURVE, options );
|
|
5387
6246
|
|
|
5388
6247
|
widget.onGetValue = () => {
|
|
5389
|
-
return JSON.parse(JSON.stringify(curveInstance.element.value));
|
|
6248
|
+
return JSON.parse(JSON.stringify( curveInstance.element.value ));
|
|
5390
6249
|
};
|
|
5391
6250
|
|
|
5392
6251
|
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
@@ -5531,7 +6390,8 @@ class Panel {
|
|
|
5531
6390
|
|
|
5532
6391
|
addLayers( name, value, callback, options = {} ) {
|
|
5533
6392
|
|
|
5534
|
-
if(!name)
|
|
6393
|
+
if( !name )
|
|
6394
|
+
{
|
|
5535
6395
|
throw("Set Widget Name!");
|
|
5536
6396
|
}
|
|
5537
6397
|
|
|
@@ -5573,7 +6433,8 @@ class Panel {
|
|
|
5573
6433
|
let binary = value.toString( 2 );
|
|
5574
6434
|
let nbits = binary.length;
|
|
5575
6435
|
// fill zeros
|
|
5576
|
-
for(var i = 0; i < (16 - nbits); ++i)
|
|
6436
|
+
for( var i = 0; i < (16 - nbits); ++i )
|
|
6437
|
+
{
|
|
5577
6438
|
binary = '0' + binary;
|
|
5578
6439
|
}
|
|
5579
6440
|
|
|
@@ -5626,8 +6487,9 @@ class Panel {
|
|
|
5626
6487
|
|
|
5627
6488
|
addArray( name, values = [], callback, options = {} ) {
|
|
5628
6489
|
|
|
5629
|
-
if(!name)
|
|
5630
|
-
|
|
6490
|
+
if( !name )
|
|
6491
|
+
{
|
|
6492
|
+
throw( "Set Widget Name!" );
|
|
5631
6493
|
}
|
|
5632
6494
|
|
|
5633
6495
|
let widget = this.create_widget(name, Widget.ARRAY, options);
|
|
@@ -5808,7 +6670,8 @@ class Panel {
|
|
|
5808
6670
|
widget.updateValues( values );
|
|
5809
6671
|
|
|
5810
6672
|
// Remove branch padding and margins
|
|
5811
|
-
if( !widget.name )
|
|
6673
|
+
if( !widget.name )
|
|
6674
|
+
{
|
|
5812
6675
|
element.className += " noname";
|
|
5813
6676
|
listContainer.style.width = "100%";
|
|
5814
6677
|
}
|
|
@@ -5895,7 +6758,7 @@ class Panel {
|
|
|
5895
6758
|
tagsContainer.appendChild( tagInput );
|
|
5896
6759
|
|
|
5897
6760
|
tagInput.onkeydown = function( e ) {
|
|
5898
|
-
const val = this.value.replace(/\s/g, '');
|
|
6761
|
+
const val = this.value.replace( /\s/g, '' );
|
|
5899
6762
|
if( e.key == ' ' || e.key == 'Enter' )
|
|
5900
6763
|
{
|
|
5901
6764
|
e.preventDefault();
|
|
@@ -5933,15 +6796,16 @@ class Panel {
|
|
|
5933
6796
|
* @param {Function} callback Callback function on change
|
|
5934
6797
|
* @param {*} options:
|
|
5935
6798
|
* disabled: Make the widget disabled [false]
|
|
6799
|
+
* label: Checkbox label
|
|
5936
6800
|
* suboptions: Callback to add widgets in case of TRUE value
|
|
5937
|
-
* className:
|
|
6801
|
+
* className: Extra classes to customize style
|
|
5938
6802
|
*/
|
|
5939
6803
|
|
|
5940
6804
|
addCheckbox( name, value, callback, options = {} ) {
|
|
5941
6805
|
|
|
5942
|
-
if( !name )
|
|
6806
|
+
if( !name && !options.label )
|
|
5943
6807
|
{
|
|
5944
|
-
throw( "Set Widget Name!" );
|
|
6808
|
+
throw( "Set Widget Name or at least a label!" );
|
|
5945
6809
|
}
|
|
5946
6810
|
|
|
5947
6811
|
let widget = this.create_widget( name, Widget.CHECKBOX, options );
|
|
@@ -5961,10 +6825,13 @@ class Panel {
|
|
|
5961
6825
|
let element = widget.domEl;
|
|
5962
6826
|
|
|
5963
6827
|
// Add reset functionality
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
Panel.
|
|
5967
|
-
|
|
6828
|
+
if( name )
|
|
6829
|
+
{
|
|
6830
|
+
Panel._add_reset_property( element.domName, function() {
|
|
6831
|
+
checkbox.checked = !checkbox.checked;
|
|
6832
|
+
Panel._dispatch_event( checkbox, "change" );
|
|
6833
|
+
});
|
|
6834
|
+
}
|
|
5968
6835
|
|
|
5969
6836
|
// Add widget value
|
|
5970
6837
|
|
|
@@ -5980,7 +6847,7 @@ class Panel {
|
|
|
5980
6847
|
|
|
5981
6848
|
let valueName = document.createElement( 'span' );
|
|
5982
6849
|
valueName.className = "checkboxtext";
|
|
5983
|
-
valueName.innerHTML = "On";
|
|
6850
|
+
valueName.innerHTML = options.label ?? "On";
|
|
5984
6851
|
|
|
5985
6852
|
container.appendChild( checkbox );
|
|
5986
6853
|
container.appendChild( valueName );
|
|
@@ -6118,6 +6985,96 @@ class Panel {
|
|
|
6118
6985
|
return widget;
|
|
6119
6986
|
}
|
|
6120
6987
|
|
|
6988
|
+
/**
|
|
6989
|
+
* @method addRadioGroup
|
|
6990
|
+
* @param {String} label Radio label
|
|
6991
|
+
* @param {Array} values Radio options
|
|
6992
|
+
* @param {Function} callback Callback function on change
|
|
6993
|
+
* @param {*} options:
|
|
6994
|
+
* disabled: Make the widget disabled [false]
|
|
6995
|
+
* className: Customize colors
|
|
6996
|
+
*/
|
|
6997
|
+
|
|
6998
|
+
addRadioGroup( label, values, callback, options = {} ) {
|
|
6999
|
+
|
|
7000
|
+
let widget = this.create_widget( null, Widget.RADIO, options );
|
|
7001
|
+
|
|
7002
|
+
widget.onGetValue = () => {
|
|
7003
|
+
const items = container.querySelectorAll( 'button' );
|
|
7004
|
+
for( let i = 0; i < items.length; ++i )
|
|
7005
|
+
{
|
|
7006
|
+
const optionItem = items[ i ];
|
|
7007
|
+
if( optionItem.checked )
|
|
7008
|
+
{
|
|
7009
|
+
return [ i, values[ i ] ];
|
|
7010
|
+
}
|
|
7011
|
+
}
|
|
7012
|
+
};
|
|
7013
|
+
|
|
7014
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
7015
|
+
const items = container.querySelectorAll( 'button' );
|
|
7016
|
+
for( let i = 0; i < items.length; ++i )
|
|
7017
|
+
{
|
|
7018
|
+
const optionItem = items[ i ];
|
|
7019
|
+
if( newValue == i )
|
|
7020
|
+
{
|
|
7021
|
+
Panel._dispatch_event( optionItem, "click", skipCallback );
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
};
|
|
7025
|
+
|
|
7026
|
+
let element = widget.domEl;
|
|
7027
|
+
|
|
7028
|
+
// Add widget value
|
|
7029
|
+
var container = document.createElement( 'div' );
|
|
7030
|
+
container.className = "lexradiogroup " + ( options.className ?? "" );
|
|
7031
|
+
|
|
7032
|
+
let labelSpan = document.createElement( 'span' );
|
|
7033
|
+
labelSpan.innerHTML = label;
|
|
7034
|
+
container.appendChild( labelSpan );
|
|
7035
|
+
|
|
7036
|
+
const that = this;
|
|
7037
|
+
|
|
7038
|
+
for( let i = 0; i < values.length; ++i )
|
|
7039
|
+
{
|
|
7040
|
+
const optionItem = document.createElement( 'div' );
|
|
7041
|
+
optionItem.className = "lexradiogroupitem";
|
|
7042
|
+
container.appendChild( optionItem );
|
|
7043
|
+
|
|
7044
|
+
const optionButton = document.createElement( 'button' );
|
|
7045
|
+
optionButton.className = "lexbutton";
|
|
7046
|
+
optionButton.disabled = options.disabled ?? false;
|
|
7047
|
+
optionItem.appendChild( optionButton );
|
|
7048
|
+
|
|
7049
|
+
optionButton.addEventListener( "click", function( e ) {
|
|
7050
|
+
const skipCallback = ( e.detail?.constructor == Number ? null : e.detail );
|
|
7051
|
+
container.querySelectorAll( 'button' ).forEach( e => { e.checked = false; e.classList.remove( "checked" ) } );
|
|
7052
|
+
this.checked = !this.checked;
|
|
7053
|
+
this.classList.toggle( "checked" );
|
|
7054
|
+
if( !skipCallback ) that._trigger( new IEvent( null, [ i, values[ i ] ], e ), callback );
|
|
7055
|
+
} );
|
|
7056
|
+
|
|
7057
|
+
{
|
|
7058
|
+
const checkedSpan = document.createElement( 'span' );
|
|
7059
|
+
optionButton.appendChild( checkedSpan );
|
|
7060
|
+
}
|
|
7061
|
+
|
|
7062
|
+
const optionLabel = document.createElement( 'span' );
|
|
7063
|
+
optionLabel.innerHTML = values[ i ];
|
|
7064
|
+
optionItem.appendChild( optionLabel );
|
|
7065
|
+
}
|
|
7066
|
+
|
|
7067
|
+
if( options.selected )
|
|
7068
|
+
{
|
|
7069
|
+
console.assert( options.selected.constructor == Number );
|
|
7070
|
+
widget.set( options.selected, true );
|
|
7071
|
+
}
|
|
7072
|
+
|
|
7073
|
+
element.appendChild( container );
|
|
7074
|
+
|
|
7075
|
+
return widget;
|
|
7076
|
+
}
|
|
7077
|
+
|
|
6121
7078
|
/**
|
|
6122
7079
|
* @method addColor
|
|
6123
7080
|
* @param {String} name Widget name
|
|
@@ -6130,7 +7087,8 @@ class Panel {
|
|
|
6130
7087
|
|
|
6131
7088
|
addColor( name, value, callback, options = {} ) {
|
|
6132
7089
|
|
|
6133
|
-
if( !name )
|
|
7090
|
+
if( !name )
|
|
7091
|
+
{
|
|
6134
7092
|
throw( "Set Widget Name!" );
|
|
6135
7093
|
}
|
|
6136
7094
|
|
|
@@ -6168,7 +7126,8 @@ class Panel {
|
|
|
6168
7126
|
color.useRGB = options.useRGB ?? false;
|
|
6169
7127
|
color.value = color.iValue = value.constructor === Array ? rgbToHex( value ) : value;
|
|
6170
7128
|
|
|
6171
|
-
if( options.disabled )
|
|
7129
|
+
if( options.disabled )
|
|
7130
|
+
{
|
|
6172
7131
|
color.disabled = true;
|
|
6173
7132
|
}
|
|
6174
7133
|
|
|
@@ -6213,6 +7172,137 @@ class Panel {
|
|
|
6213
7172
|
return widget;
|
|
6214
7173
|
}
|
|
6215
7174
|
|
|
7175
|
+
/**
|
|
7176
|
+
* @method addRange
|
|
7177
|
+
* @param {String} name Widget name
|
|
7178
|
+
* @param {Number} value Default number value
|
|
7179
|
+
* @param {Function} callback Callback function on change
|
|
7180
|
+
* @param {*} options:
|
|
7181
|
+
* className: Extra classes to customize style
|
|
7182
|
+
* disabled: Make the widget disabled [false]
|
|
7183
|
+
* left: The slider goes to the left instead of the right
|
|
7184
|
+
* fill: Fill slider progress [true]
|
|
7185
|
+
* step: Step of the input
|
|
7186
|
+
* min, max: Min and Max values for the input
|
|
7187
|
+
*/
|
|
7188
|
+
|
|
7189
|
+
addRange( name, value, callback, options = {} ) {
|
|
7190
|
+
|
|
7191
|
+
let widget = this.create_widget( name, Widget.RANGE, options );
|
|
7192
|
+
|
|
7193
|
+
widget.onGetValue = () => {
|
|
7194
|
+
return +slider.value;
|
|
7195
|
+
};
|
|
7196
|
+
|
|
7197
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
7198
|
+
slider.value = newValue;
|
|
7199
|
+
Panel._dispatch_event( slider, "input", skipCallback );
|
|
7200
|
+
};
|
|
7201
|
+
|
|
7202
|
+
let element = widget.domEl;
|
|
7203
|
+
|
|
7204
|
+
// add reset functionality
|
|
7205
|
+
if( widget.name )
|
|
7206
|
+
{
|
|
7207
|
+
Panel._add_reset_property( element.domName, function() {
|
|
7208
|
+
this.style.display = "none";
|
|
7209
|
+
slider.value = slider.iValue;
|
|
7210
|
+
Panel._dispatch_event( slider, "input" );
|
|
7211
|
+
});
|
|
7212
|
+
}
|
|
7213
|
+
|
|
7214
|
+
// add widget value
|
|
7215
|
+
|
|
7216
|
+
var container = document.createElement( 'div' );
|
|
7217
|
+
container.className = "lexrange";
|
|
7218
|
+
container.style.width = options.inputWidth || "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
7219
|
+
|
|
7220
|
+
let slider = document.createElement( 'input' );
|
|
7221
|
+
slider.className = "lexrangeslider " + ( options.className ?? "" );
|
|
7222
|
+
slider.value = slider.iValue = value;
|
|
7223
|
+
slider.min = options.min;
|
|
7224
|
+
slider.max = options.max;
|
|
7225
|
+
slider.step = options.step ?? 1;
|
|
7226
|
+
slider.type = "range";
|
|
7227
|
+
slider.disabled = options.disabled ?? false;
|
|
7228
|
+
|
|
7229
|
+
if( options.left ?? false )
|
|
7230
|
+
{
|
|
7231
|
+
slider.classList.add( "left" );
|
|
7232
|
+
}
|
|
7233
|
+
|
|
7234
|
+
if( !( options.fill ?? true ) )
|
|
7235
|
+
{
|
|
7236
|
+
slider.classList.add( "no-fill" );
|
|
7237
|
+
}
|
|
7238
|
+
|
|
7239
|
+
slider.addEventListener( "input", e => {
|
|
7240
|
+
|
|
7241
|
+
if( isNaN( e.target.valueAsNumber ) )
|
|
7242
|
+
{
|
|
7243
|
+
return;
|
|
7244
|
+
}
|
|
7245
|
+
|
|
7246
|
+
const skipCallback = e.detail;
|
|
7247
|
+
|
|
7248
|
+
let val = e.target.value = clamp( +e.target.valueAsNumber, +slider.min, +slider.max );
|
|
7249
|
+
slider.value = val;
|
|
7250
|
+
|
|
7251
|
+
// Reset button (default value)
|
|
7252
|
+
if( !skipCallback )
|
|
7253
|
+
{
|
|
7254
|
+
let btn = element.querySelector( ".lexwidgetname .lexicon" );
|
|
7255
|
+
if( btn ) btn.style.display = val != slider.iValue ? "block": "none";
|
|
7256
|
+
}
|
|
7257
|
+
|
|
7258
|
+
if( options.left )
|
|
7259
|
+
{
|
|
7260
|
+
val = ( +slider.max ) - val + ( +slider.min );
|
|
7261
|
+
}
|
|
7262
|
+
|
|
7263
|
+
if( !skipCallback ) this._trigger( new IEvent( name, val, e ), callback );
|
|
7264
|
+
}, { passive: false });
|
|
7265
|
+
|
|
7266
|
+
slider.addEventListener( "mousedown", function( e ) {
|
|
7267
|
+
if( options.onPress )
|
|
7268
|
+
{
|
|
7269
|
+
options.onPress.bind( slider )( e, slider );
|
|
7270
|
+
}
|
|
7271
|
+
}, false );
|
|
7272
|
+
|
|
7273
|
+
slider.addEventListener( "mouseup", function( e ) {
|
|
7274
|
+
if( options.onRelease )
|
|
7275
|
+
{
|
|
7276
|
+
options.onRelease.bind( slider )( e, slider );
|
|
7277
|
+
}
|
|
7278
|
+
}, false );
|
|
7279
|
+
|
|
7280
|
+
// Method to change min, max, step parameters
|
|
7281
|
+
widget.setLimits = ( newMin, newMax, newStep ) => {
|
|
7282
|
+
slider.min = newMin ?? slider.min;
|
|
7283
|
+
slider.max = newMax ?? slider.max;
|
|
7284
|
+
slider.step = newStep ?? slider.step;
|
|
7285
|
+
Panel._dispatch_event( slider, "input", true );
|
|
7286
|
+
};
|
|
7287
|
+
|
|
7288
|
+
if( value.constructor == Number )
|
|
7289
|
+
{
|
|
7290
|
+
value = clamp( value, +slider.min, +slider.max );
|
|
7291
|
+
}
|
|
7292
|
+
|
|
7293
|
+
container.appendChild( slider );
|
|
7294
|
+
element.appendChild( container );
|
|
7295
|
+
|
|
7296
|
+
// Remove branch padding and margins
|
|
7297
|
+
if( !widget.name )
|
|
7298
|
+
{
|
|
7299
|
+
element.className += " noname";
|
|
7300
|
+
container.style.width = "100%";
|
|
7301
|
+
}
|
|
7302
|
+
|
|
7303
|
+
return widget;
|
|
7304
|
+
}
|
|
7305
|
+
|
|
6216
7306
|
/**
|
|
6217
7307
|
* @method addNumber
|
|
6218
7308
|
* @param {String} name Widget name
|
|
@@ -6245,7 +7335,8 @@ class Panel {
|
|
|
6245
7335
|
let element = widget.domEl;
|
|
6246
7336
|
|
|
6247
7337
|
// add reset functionality
|
|
6248
|
-
if( widget.name )
|
|
7338
|
+
if( widget.name )
|
|
7339
|
+
{
|
|
6249
7340
|
Panel._add_reset_property( element.domName, function() {
|
|
6250
7341
|
this.style.display = "none";
|
|
6251
7342
|
vecinput.value = vecinput.iValue;
|
|
@@ -6513,7 +7604,8 @@ class Panel {
|
|
|
6513
7604
|
return;
|
|
6514
7605
|
}
|
|
6515
7606
|
|
|
6516
|
-
for( let i = 0; i < inputs.length; ++i )
|
|
7607
|
+
for( let i = 0; i < inputs.length; ++i )
|
|
7608
|
+
{
|
|
6517
7609
|
let value = newValue[ i ];
|
|
6518
7610
|
inputs[ i ].value = round( value, options.precision ) ?? 0;
|
|
6519
7611
|
Panel._dispatch_event( inputs[ i ], "change", skipCallback );
|
|
@@ -6525,7 +7617,8 @@ class Panel {
|
|
|
6525
7617
|
// Add reset functionality
|
|
6526
7618
|
Panel._add_reset_property( element.domName, function() {
|
|
6527
7619
|
this.style.display = "none";
|
|
6528
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7620
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7621
|
+
{
|
|
6529
7622
|
v.value = v.iValue;
|
|
6530
7623
|
Panel._dispatch_event( v, "change" );
|
|
6531
7624
|
}
|
|
@@ -6537,8 +7630,8 @@ class Panel {
|
|
|
6537
7630
|
container.className = "lexvector";
|
|
6538
7631
|
container.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
6539
7632
|
|
|
6540
|
-
for( let i = 0; i < num_components; ++i )
|
|
6541
|
-
|
|
7633
|
+
for( let i = 0; i < num_components; ++i )
|
|
7634
|
+
{
|
|
6542
7635
|
let box = document.createElement( 'div' );
|
|
6543
7636
|
box.className = "vecbox";
|
|
6544
7637
|
box.innerHTML = "<span class='" + Panel.VECTOR_COMPONENTS[ i ] + "'></span>";
|
|
@@ -6614,7 +7707,8 @@ class Panel {
|
|
|
6614
7707
|
|
|
6615
7708
|
if( locker.locked )
|
|
6616
7709
|
{
|
|
6617
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7710
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7711
|
+
{
|
|
6618
7712
|
v.value = val;
|
|
6619
7713
|
value[ v.idx ] = val;
|
|
6620
7714
|
}
|
|
@@ -6672,7 +7766,8 @@ class Panel {
|
|
|
6672
7766
|
|
|
6673
7767
|
if( locker.locked )
|
|
6674
7768
|
{
|
|
6675
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7769
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7770
|
+
{
|
|
6676
7771
|
v.value = round( +v.valueAsNumber + mult * dt, options.precision );
|
|
6677
7772
|
Panel._dispatch_event( v, "change" );
|
|
6678
7773
|
}
|
|
@@ -6798,7 +7893,7 @@ class Panel {
|
|
|
6798
7893
|
const value = [];
|
|
6799
7894
|
for( let i = 0; i < element.dimensions.length; ++i )
|
|
6800
7895
|
{
|
|
6801
|
-
value.push( element.dimensions[ i ].
|
|
7896
|
+
value.push( element.dimensions[ i ].value() );
|
|
6802
7897
|
}
|
|
6803
7898
|
return value;
|
|
6804
7899
|
};
|
|
@@ -6806,7 +7901,7 @@ class Panel {
|
|
|
6806
7901
|
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
6807
7902
|
for( let i = 0; i < element.dimensions.length; ++i )
|
|
6808
7903
|
{
|
|
6809
|
-
element.dimensions[ i ].
|
|
7904
|
+
element.dimensions[ i ].set( newValue[ i ], skipCallback );
|
|
6810
7905
|
}
|
|
6811
7906
|
};
|
|
6812
7907
|
|
|
@@ -6821,14 +7916,14 @@ class Panel {
|
|
|
6821
7916
|
{
|
|
6822
7917
|
element.dimensions[ i ] = this.addNumber( null, value[ i ], ( v ) => {
|
|
6823
7918
|
|
|
6824
|
-
const value = widget.
|
|
7919
|
+
const value = widget.value();
|
|
6825
7920
|
|
|
6826
7921
|
if( element.locked )
|
|
6827
7922
|
{
|
|
6828
7923
|
const ar = ( i == 0 ? 1.0 / element.aspectRatio : element.aspectRatio );
|
|
6829
7924
|
const index = ( 1 + i ) % 2;
|
|
6830
7925
|
value[ index ] = v * ar;
|
|
6831
|
-
element.dimensions[ index ].
|
|
7926
|
+
element.dimensions[ index ].set( value[ index ], true );
|
|
6832
7927
|
}
|
|
6833
7928
|
|
|
6834
7929
|
if( callback )
|
|
@@ -6871,7 +7966,7 @@ class Panel {
|
|
|
6871
7966
|
this.classList.remove( "fa-lock-open" );
|
|
6872
7967
|
|
|
6873
7968
|
// Recompute ratio
|
|
6874
|
-
const value = widget.
|
|
7969
|
+
const value = widget.value();
|
|
6875
7970
|
element.aspectRatio = value[ 0 ] / value[ 1 ];
|
|
6876
7971
|
}
|
|
6877
7972
|
else
|
|
@@ -7268,7 +8363,8 @@ class Panel {
|
|
|
7268
8363
|
let container = document.createElement('div');
|
|
7269
8364
|
container.className = "lextree";
|
|
7270
8365
|
|
|
7271
|
-
if(name)
|
|
8366
|
+
if( name )
|
|
8367
|
+
{
|
|
7272
8368
|
let title = document.createElement('span');
|
|
7273
8369
|
title.innerHTML = name;
|
|
7274
8370
|
container.appendChild(title);
|
|
@@ -7280,8 +8376,8 @@ class Panel {
|
|
|
7280
8376
|
toolsDiv.className += " notitle";
|
|
7281
8377
|
|
|
7282
8378
|
// Tree icons
|
|
7283
|
-
if(options.icons)
|
|
7284
|
-
|
|
8379
|
+
if( options.icons )
|
|
8380
|
+
{
|
|
7285
8381
|
for( let data of options.icons )
|
|
7286
8382
|
{
|
|
7287
8383
|
let iconEl = document.createElement('a');
|
|
@@ -7341,11 +8437,15 @@ class Panel {
|
|
|
7341
8437
|
let widget = new Widget( null, Widget.SEPARATOR );
|
|
7342
8438
|
widget.domEl = element;
|
|
7343
8439
|
|
|
7344
|
-
if(this.current_branch)
|
|
8440
|
+
if( this.current_branch )
|
|
8441
|
+
{
|
|
7345
8442
|
this.current_branch.content.appendChild( element );
|
|
7346
8443
|
this.current_branch.widgets.push( widget );
|
|
7347
|
-
}
|
|
7348
|
-
|
|
8444
|
+
}
|
|
8445
|
+
else
|
|
8446
|
+
{
|
|
8447
|
+
this.root.appendChild( element );
|
|
8448
|
+
}
|
|
7349
8449
|
}
|
|
7350
8450
|
|
|
7351
8451
|
/**
|
|
@@ -7670,6 +8770,12 @@ class Panel {
|
|
|
7670
8770
|
|
|
7671
8771
|
input.addEventListener( 'change', function() {
|
|
7672
8772
|
data.checkMap[ rowId ] = this.checked;
|
|
8773
|
+
|
|
8774
|
+
if( !this.checked )
|
|
8775
|
+
{
|
|
8776
|
+
const input = table.querySelector( "thead input[type='checkbox']" );
|
|
8777
|
+
input.checked = data.checkMap[ ":root" ] = false;
|
|
8778
|
+
}
|
|
7673
8779
|
});
|
|
7674
8780
|
|
|
7675
8781
|
row.appendChild( td );
|
|
@@ -7795,7 +8901,7 @@ class Branch {
|
|
|
7795
8901
|
root.appendChild( title );
|
|
7796
8902
|
|
|
7797
8903
|
var branchContent = document.createElement( 'div' );
|
|
7798
|
-
branchContent.id = name.replace(/\s/g, '');
|
|
8904
|
+
branchContent.id = name.replace( /\s/g, '' );
|
|
7799
8905
|
branchContent.className = "lexbranchcontent";
|
|
7800
8906
|
root.appendChild(branchContent);
|
|
7801
8907
|
this.content = branchContent;
|
|
@@ -7851,7 +8957,8 @@ class Branch {
|
|
|
7851
8957
|
|
|
7852
8958
|
const dialog = new Dialog(this.name, p => {
|
|
7853
8959
|
// add widgets
|
|
7854
|
-
for( let w of this.widgets )
|
|
8960
|
+
for( let w of this.widgets )
|
|
8961
|
+
{
|
|
7855
8962
|
p.root.appendChild( w.domEl );
|
|
7856
8963
|
}
|
|
7857
8964
|
});
|
|
@@ -7944,8 +9051,8 @@ class Branch {
|
|
|
7944
9051
|
var size = this.grabber.style.marginLeft;
|
|
7945
9052
|
|
|
7946
9053
|
// Update sizes of widgets inside
|
|
7947
|
-
for(var i = 0; i < this.widgets.length; i++)
|
|
7948
|
-
|
|
9054
|
+
for( var i = 0; i < this.widgets.length; i++ )
|
|
9055
|
+
{
|
|
7949
9056
|
let widget = this.widgets[ i ];
|
|
7950
9057
|
let element = widget.domEl;
|
|
7951
9058
|
|
|
@@ -7964,9 +9071,6 @@ class Branch {
|
|
|
7964
9071
|
case Widget.FILE:
|
|
7965
9072
|
padding = "10%";
|
|
7966
9073
|
break;
|
|
7967
|
-
case Widget.TEXT:
|
|
7968
|
-
padding = "8px";
|
|
7969
|
-
break;
|
|
7970
9074
|
};
|
|
7971
9075
|
|
|
7972
9076
|
value.style.width = "-moz-calc( 100% - " + size + " - " + padding + " )";
|
|
@@ -8105,7 +9209,7 @@ class Dialog {
|
|
|
8105
9209
|
modal = options.modal ?? false;
|
|
8106
9210
|
|
|
8107
9211
|
var root = document.createElement('dialog');
|
|
8108
|
-
root.className = "lexdialog " + (options.
|
|
9212
|
+
root.className = "lexdialog " + (options.className ?? "");
|
|
8109
9213
|
root.id = options.id ?? "dialog" + Dialog._last_id++;
|
|
8110
9214
|
LX.root.appendChild( root );
|
|
8111
9215
|
|
|
@@ -8263,15 +9367,15 @@ class Dialog {
|
|
|
8263
9367
|
|
|
8264
9368
|
root.style.width = size[ 0 ] ? (size[ 0 ]) : "25%";
|
|
8265
9369
|
root.style.height = size[ 1 ] ? (size[ 1 ]) : "auto";
|
|
9370
|
+
root.style.translate = options.position ? "unset" : "-50% -50%";
|
|
8266
9371
|
|
|
8267
9372
|
if( options.size )
|
|
8268
9373
|
{
|
|
8269
9374
|
this.size = size;
|
|
8270
9375
|
}
|
|
8271
9376
|
|
|
8272
|
-
|
|
8273
|
-
root.style.
|
|
8274
|
-
root.style.top = position[ 1 ] ? (position[ 1 ]) : "calc( 50% - " + ( rect.height * 0.5 ) + "px )";
|
|
9377
|
+
root.style.left = position[ 0 ] ?? "50%";
|
|
9378
|
+
root.style.top = position[ 1 ] ?? "50%";
|
|
8275
9379
|
|
|
8276
9380
|
panel.root.style.width = "calc( 100% - 30px )";
|
|
8277
9381
|
panel.root.style.height = title ? "calc( 100% - " + ( titleDiv.offsetHeight + 30 ) + "px )" : "calc( 100% - 51px )";
|
|
@@ -8288,7 +9392,7 @@ class Dialog {
|
|
|
8288
9392
|
this._oncreate.call(this, this.panel);
|
|
8289
9393
|
}
|
|
8290
9394
|
|
|
8291
|
-
setPosition(x, y) {
|
|
9395
|
+
setPosition( x, y ) {
|
|
8292
9396
|
|
|
8293
9397
|
this.root.style.left = x + "px";
|
|
8294
9398
|
this.root.style.top = y + "px";
|
|
@@ -8334,6 +9438,9 @@ class PocketDialog extends Dialog {
|
|
|
8334
9438
|
|
|
8335
9439
|
// Custom
|
|
8336
9440
|
this.root.classList.add( "pocket" );
|
|
9441
|
+
|
|
9442
|
+
this.root.style.translate = "none";
|
|
9443
|
+
this.root.style.top = "0";
|
|
8337
9444
|
this.root.style.left = "unset";
|
|
8338
9445
|
|
|
8339
9446
|
if( !options.position )
|
|
@@ -8349,6 +9456,11 @@ class PocketDialog extends Dialog {
|
|
|
8349
9456
|
this.minimized = false;
|
|
8350
9457
|
this.title.tabIndex = -1;
|
|
8351
9458
|
this.title.addEventListener("click", e => {
|
|
9459
|
+
if( this.title._eventCatched )
|
|
9460
|
+
{
|
|
9461
|
+
this.title._eventCatched = false;
|
|
9462
|
+
return;
|
|
9463
|
+
}
|
|
8352
9464
|
|
|
8353
9465
|
// Sized dialogs have to keep their size
|
|
8354
9466
|
if( this.size )
|
|
@@ -8431,12 +9543,12 @@ class ContextMenu {
|
|
|
8431
9543
|
constructor( event, title, options = {} ) {
|
|
8432
9544
|
|
|
8433
9545
|
// remove all context menus
|
|
8434
|
-
document.body.querySelectorAll(".
|
|
9546
|
+
document.body.querySelectorAll( ".lexcontextmenu" ).forEach( e => e.remove() );
|
|
8435
9547
|
|
|
8436
|
-
this.root = document.createElement(
|
|
8437
|
-
this.root.className = "
|
|
8438
|
-
this.root.style.left = (event.x - 48 + document.scrollingElement.scrollLeft) + "px";
|
|
8439
|
-
this.root.style.top = (event.y - 8 + document.scrollingElement.scrollTop) + "px";
|
|
9548
|
+
this.root = document.createElement( "div" );
|
|
9549
|
+
this.root.className = "lexcontextmenu";
|
|
9550
|
+
this.root.style.left = ( event.x - 48 + document.scrollingElement.scrollLeft ) + "px";
|
|
9551
|
+
this.root.style.top = ( event.y - 8 + document.scrollingElement.scrollTop ) + "px";
|
|
8440
9552
|
|
|
8441
9553
|
this.root.addEventListener("mouseleave", function() {
|
|
8442
9554
|
this.remove();
|
|
@@ -8449,8 +9561,8 @@ class ContextMenu {
|
|
|
8449
9561
|
{
|
|
8450
9562
|
const item = {};
|
|
8451
9563
|
item[ title ] = [];
|
|
8452
|
-
item[
|
|
8453
|
-
item[
|
|
9564
|
+
item[ "className" ] = "cmtitle";
|
|
9565
|
+
item[ "icon" ] = options.icon;
|
|
8454
9566
|
this.items.push( item );
|
|
8455
9567
|
}
|
|
8456
9568
|
}
|
|
@@ -8498,16 +9610,16 @@ class ContextMenu {
|
|
|
8498
9610
|
|
|
8499
9611
|
_create_submenu( o, k, c, d ) {
|
|
8500
9612
|
|
|
8501
|
-
this.root.querySelectorAll(".
|
|
9613
|
+
this.root.querySelectorAll( ".lexcontextmenu" ).forEach( cm => cm.remove() );
|
|
8502
9614
|
|
|
8503
9615
|
let contextmenu = document.createElement('div');
|
|
8504
|
-
contextmenu.className = "
|
|
9616
|
+
contextmenu.className = "lexcontextmenu";
|
|
8505
9617
|
c.appendChild( contextmenu );
|
|
8506
9618
|
|
|
8507
9619
|
for( var i = 0; i < o[k].length; ++i )
|
|
8508
9620
|
{
|
|
8509
|
-
const subitem = o[k][i];
|
|
8510
|
-
const subkey = Object.keys(subitem)[0];
|
|
9621
|
+
const subitem = o[ k ][ i ];
|
|
9622
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
8511
9623
|
this._create_entry(subitem, subkey, contextmenu, d);
|
|
8512
9624
|
}
|
|
8513
9625
|
|
|
@@ -8523,22 +9635,25 @@ class ContextMenu {
|
|
|
8523
9635
|
|
|
8524
9636
|
const hasSubmenu = o[ k ].length;
|
|
8525
9637
|
let entry = document.createElement('div');
|
|
8526
|
-
entry.className = "
|
|
9638
|
+
entry.className = "lexmenuboxentry" + (o[ 'className' ] ? " " + o[ 'className' ] : "" );
|
|
8527
9639
|
entry.id = o.id ?? ("eId" + getSupportedDOMName( k ));
|
|
8528
9640
|
entry.innerHTML = "";
|
|
8529
9641
|
const icon = o[ 'icon' ];
|
|
8530
|
-
if(icon)
|
|
9642
|
+
if( icon )
|
|
9643
|
+
{
|
|
8531
9644
|
entry.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
8532
9645
|
}
|
|
8533
9646
|
const disabled = o['disabled'];
|
|
8534
9647
|
entry.innerHTML += "<div class='lexentryname" + (disabled ? " disabled" : "") + "'>" + k + "</div>";
|
|
8535
9648
|
c.appendChild( entry );
|
|
8536
9649
|
|
|
8537
|
-
if( this.colors[ k ] )
|
|
9650
|
+
if( this.colors[ k ] )
|
|
9651
|
+
{
|
|
8538
9652
|
entry.style.borderColor = this.colors[ k ];
|
|
8539
9653
|
}
|
|
8540
9654
|
|
|
8541
|
-
if( k == "" )
|
|
9655
|
+
if( k == "" )
|
|
9656
|
+
{
|
|
8542
9657
|
entry.className += " cmseparator";
|
|
8543
9658
|
return;
|
|
8544
9659
|
}
|
|
@@ -8551,7 +9666,8 @@ class ContextMenu {
|
|
|
8551
9666
|
if(disabled) return;
|
|
8552
9667
|
|
|
8553
9668
|
const f = o[ 'callback' ];
|
|
8554
|
-
if(f)
|
|
9669
|
+
if( f )
|
|
9670
|
+
{
|
|
8555
9671
|
f.call( this, k, entry );
|
|
8556
9672
|
this.root.remove();
|
|
8557
9673
|
}
|
|
@@ -8583,8 +9699,7 @@ class ContextMenu {
|
|
|
8583
9699
|
|
|
8584
9700
|
entry.addEventListener("mouseleave", () => {
|
|
8585
9701
|
d = -1; // Reset depth
|
|
8586
|
-
|
|
8587
|
-
c.querySelectorAll(".lexcontextmenubox").forEach(e => e.remove());
|
|
9702
|
+
c.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
8588
9703
|
});
|
|
8589
9704
|
}
|
|
8590
9705
|
|
|
@@ -8617,22 +9732,25 @@ class ContextMenu {
|
|
|
8617
9732
|
if(key) found = o[ key ];
|
|
8618
9733
|
} );
|
|
8619
9734
|
|
|
8620
|
-
if(found)
|
|
9735
|
+
if( found )
|
|
9736
|
+
{
|
|
8621
9737
|
insert( tokens[idx++], found );
|
|
8622
9738
|
}
|
|
8623
|
-
else
|
|
9739
|
+
else
|
|
9740
|
+
{
|
|
8624
9741
|
let item = {};
|
|
8625
9742
|
item[ token ] = [];
|
|
8626
|
-
const
|
|
9743
|
+
const nextToken = tokens[idx++];
|
|
8627
9744
|
// Check if last token -> add callback
|
|
8628
|
-
if(!
|
|
9745
|
+
if( !nextToken )
|
|
9746
|
+
{
|
|
8629
9747
|
item[ 'id' ] = options.id;
|
|
8630
9748
|
item[ 'callback' ] = options.callback;
|
|
8631
9749
|
item[ 'disabled' ] = options.disabled ?? false;
|
|
8632
9750
|
}
|
|
8633
9751
|
|
|
8634
9752
|
list.push( item );
|
|
8635
|
-
insert(
|
|
9753
|
+
insert( nextToken, item[ token ] );
|
|
8636
9754
|
}
|
|
8637
9755
|
};
|
|
8638
9756
|
|
|
@@ -8656,7 +9774,8 @@ class ContextMenu {
|
|
|
8656
9774
|
_item[ key ].unshift( parent );
|
|
8657
9775
|
}
|
|
8658
9776
|
|
|
8659
|
-
for( var child of _item[ key ] )
|
|
9777
|
+
for( var child of _item[ key ] )
|
|
9778
|
+
{
|
|
8660
9779
|
let k = Object.keys(child)[0];
|
|
8661
9780
|
for( var i = 0; i < child[k].length; ++i )
|
|
8662
9781
|
setParent(child);
|
|
@@ -8670,7 +9789,7 @@ class ContextMenu {
|
|
|
8670
9789
|
|
|
8671
9790
|
for( let item of this.items )
|
|
8672
9791
|
{
|
|
8673
|
-
let key = Object.keys(item)[0];
|
|
9792
|
+
let key = Object.keys( item )[ 0 ];
|
|
8674
9793
|
let pKey = "eId" + getSupportedDOMName( key );
|
|
8675
9794
|
|
|
8676
9795
|
// Item already created
|
|
@@ -8787,7 +9906,7 @@ class Curve {
|
|
|
8787
9906
|
|
|
8788
9907
|
var r = [];
|
|
8789
9908
|
var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
|
|
8790
|
-
for(var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
9909
|
+
for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx )
|
|
8791
9910
|
{
|
|
8792
9911
|
r.push( element.getValueAt(i) );
|
|
8793
9912
|
}
|
|
@@ -8796,7 +9915,8 @@ class Curve {
|
|
|
8796
9915
|
|
|
8797
9916
|
element.addValue = function(v) {
|
|
8798
9917
|
|
|
8799
|
-
for(var i = 0; i < element.value; i++)
|
|
9918
|
+
for( var i = 0; i < element.value; i++ )
|
|
9919
|
+
{
|
|
8800
9920
|
var value = element.value[i];
|
|
8801
9921
|
if(value[0] < v[0]) continue;
|
|
8802
9922
|
element.value.splice(i,0,v);
|
|
@@ -8822,7 +9942,7 @@ class Curve {
|
|
|
8822
9942
|
|
|
8823
9943
|
var selected = -1;
|
|
8824
9944
|
|
|
8825
|
-
element.redraw = function( o = {} )
|
|
9945
|
+
element.redraw = function( o = {} ) {
|
|
8826
9946
|
|
|
8827
9947
|
if( o.value ) element.value = o.value;
|
|
8828
9948
|
if( o.xrange ) element.xrange = o.xrange;
|
|
@@ -8851,13 +9971,16 @@ class Curve {
|
|
|
8851
9971
|
ctx.moveTo( pos[ 0 ], pos[ 1 ] );
|
|
8852
9972
|
let values = [pos[ 0 ], pos[ 1 ]];
|
|
8853
9973
|
|
|
8854
|
-
for(var i in element.value)
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
values.push(pos[
|
|
8859
|
-
|
|
9974
|
+
for( var i in element.value )
|
|
9975
|
+
{
|
|
9976
|
+
var value = element.value[ i ];
|
|
9977
|
+
pos = convert( value );
|
|
9978
|
+
values.push( pos[ 0 ] );
|
|
9979
|
+
values.push( pos[ 1 ] );
|
|
9980
|
+
if( !element.smooth )
|
|
9981
|
+
{
|
|
8860
9982
|
ctx.lineTo( pos[ 0 ], pos[ 1 ] );
|
|
9983
|
+
}
|
|
8861
9984
|
}
|
|
8862
9985
|
|
|
8863
9986
|
pos = convert([ element.xrange[ 1 ], element.defaulty ]);
|
|
@@ -8874,7 +9997,8 @@ class Curve {
|
|
|
8874
9997
|
}
|
|
8875
9998
|
|
|
8876
9999
|
// Draw points
|
|
8877
|
-
for( var i = 0; i < element.value.length; i += 1 )
|
|
10000
|
+
for( var i = 0; i < element.value.length; i += 1 )
|
|
10001
|
+
{
|
|
8878
10002
|
var value = element.value[ i ];
|
|
8879
10003
|
pos = convert( value );
|
|
8880
10004
|
if( selected == i )
|
|
@@ -8886,10 +10010,11 @@ class Curve {
|
|
|
8886
10010
|
ctx.fill();
|
|
8887
10011
|
}
|
|
8888
10012
|
|
|
8889
|
-
if(element.show_samples)
|
|
10013
|
+
if( element.show_samples )
|
|
10014
|
+
{
|
|
8890
10015
|
var samples = element.resample(element.show_samples);
|
|
8891
10016
|
ctx.fillStyle = "#888";
|
|
8892
|
-
for(var i = 0; i < samples.length; i += 1)
|
|
10017
|
+
for( var i = 0; i < samples.length; i += 1)
|
|
8893
10018
|
{
|
|
8894
10019
|
var value = [ i * ((element.xrange[ 1 ] - element.xrange[ 0 ]) / element.show_samples) + element.xrange[ 0 ], samples[ i ] ];
|
|
8895
10020
|
pos = convert(value);
|
|
@@ -8912,7 +10037,8 @@ class Curve {
|
|
|
8912
10037
|
|
|
8913
10038
|
selected = computeSelected( mousex, canvas.height - mousey );
|
|
8914
10039
|
|
|
8915
|
-
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10040
|
+
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10041
|
+
{
|
|
8916
10042
|
var v = unconvert([ mousex, canvas.height - mousey ]);
|
|
8917
10043
|
element.value.push( v );
|
|
8918
10044
|
sortValues();
|
|
@@ -8960,7 +10086,8 @@ class Curve {
|
|
|
8960
10086
|
var dy = element.draggable_y ? last_mouse[ 1 ] - mousey : 0;
|
|
8961
10087
|
var delta = unconvert([ -dx, dy ]);
|
|
8962
10088
|
|
|
8963
|
-
if( selected != -1 )
|
|
10089
|
+
if( selected != -1 )
|
|
10090
|
+
{
|
|
8964
10091
|
var minx = element.xrange[ 0 ];
|
|
8965
10092
|
var maxx = element.xrange[ 1 ];
|
|
8966
10093
|
|
|
@@ -9117,7 +10244,7 @@ class Dial {
|
|
|
9117
10244
|
|
|
9118
10245
|
var r = [];
|
|
9119
10246
|
var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
|
|
9120
|
-
for(var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
10247
|
+
for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
9121
10248
|
{
|
|
9122
10249
|
r.push( element.getValueAt(i) );
|
|
9123
10250
|
}
|
|
@@ -9126,15 +10253,16 @@ class Dial {
|
|
|
9126
10253
|
|
|
9127
10254
|
element.addValue = function(v) {
|
|
9128
10255
|
|
|
9129
|
-
for(var i = 0; i < element.value; i++)
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
10256
|
+
for( var i = 0; i < element.value; i++ )
|
|
10257
|
+
{
|
|
10258
|
+
var value = element.value[ i ];
|
|
10259
|
+
if(value[ 0 ] < v[ 0 ]) continue;
|
|
10260
|
+
element.value.splice( i, 0, v );
|
|
9133
10261
|
redraw();
|
|
9134
10262
|
return;
|
|
9135
10263
|
}
|
|
9136
10264
|
|
|
9137
|
-
element.value.push(v);
|
|
10265
|
+
element.value.push( v );
|
|
9138
10266
|
redraw();
|
|
9139
10267
|
}
|
|
9140
10268
|
|
|
@@ -9154,7 +10282,7 @@ class Dial {
|
|
|
9154
10282
|
|
|
9155
10283
|
var selected = -1;
|
|
9156
10284
|
|
|
9157
|
-
element.redraw = function( o = {} )
|
|
10285
|
+
element.redraw = function( o = {} ) {
|
|
9158
10286
|
|
|
9159
10287
|
if( o.value ) element.value = o.value;
|
|
9160
10288
|
if( o.xrange ) element.xrange = o.xrange;
|
|
@@ -9183,17 +10311,17 @@ class Dial {
|
|
|
9183
10311
|
ctx.moveTo( pos[ 0 ], pos[ 1 ] );
|
|
9184
10312
|
let values = [pos[ 0 ], pos[ 1 ]];
|
|
9185
10313
|
|
|
9186
|
-
for(var i in element.value)
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
values.push(pos[
|
|
9191
|
-
|
|
10314
|
+
for( var i in element.value)
|
|
10315
|
+
{
|
|
10316
|
+
var value = element.value[ i ];
|
|
10317
|
+
pos = convert( value );
|
|
10318
|
+
values.push( pos[ 0 ] );
|
|
10319
|
+
values.push( pos[ 1 ] );
|
|
9192
10320
|
}
|
|
9193
10321
|
|
|
9194
10322
|
pos = convert([ element.xrange[ 1 ], element.defaulty ]);
|
|
9195
|
-
values.push(pos[ 0 ]);
|
|
9196
|
-
values.push(pos[ 1 ]);
|
|
10323
|
+
values.push( pos[ 0 ] );
|
|
10324
|
+
values.push( pos[ 1 ] );
|
|
9197
10325
|
|
|
9198
10326
|
// Draw points
|
|
9199
10327
|
const center = [0,0];
|
|
@@ -9203,7 +10331,8 @@ class Dial {
|
|
|
9203
10331
|
ctx.arc( pos[ 0 ], pos[ 1 ], 3, 0, Math.PI * 2);
|
|
9204
10332
|
ctx.fill();
|
|
9205
10333
|
|
|
9206
|
-
for( var i = 0; i < element.value.length; i += 1 )
|
|
10334
|
+
for( var i = 0; i < element.value.length; i += 1 )
|
|
10335
|
+
{
|
|
9207
10336
|
var value = element.value[ i ];
|
|
9208
10337
|
pos = convert( value );
|
|
9209
10338
|
if( selected == i )
|
|
@@ -9215,10 +10344,11 @@ class Dial {
|
|
|
9215
10344
|
ctx.fill();
|
|
9216
10345
|
}
|
|
9217
10346
|
|
|
9218
|
-
if(element.show_samples)
|
|
10347
|
+
if( element.show_samples )
|
|
10348
|
+
{
|
|
9219
10349
|
var samples = element.resample(element.show_samples);
|
|
9220
10350
|
ctx.fillStyle = "#888";
|
|
9221
|
-
for(var i = 0; i < samples.length; i += 1)
|
|
10351
|
+
for( var i = 0; i < samples.length; i += 1)
|
|
9222
10352
|
{
|
|
9223
10353
|
var value = [ i * ((element.xrange[ 1 ] - element.xrange[ 0 ]) / element.show_samples) + element.xrange[ 0 ], samples[ i ] ];
|
|
9224
10354
|
pos = convert(value);
|
|
@@ -9241,7 +10371,8 @@ class Dial {
|
|
|
9241
10371
|
|
|
9242
10372
|
selected = computeSelected( mousex, canvas.height - mousey );
|
|
9243
10373
|
|
|
9244
|
-
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10374
|
+
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10375
|
+
{
|
|
9245
10376
|
var v = unconvert([ mousex, canvas.height - mousey ]);
|
|
9246
10377
|
element.value.push( v );
|
|
9247
10378
|
sortValues();
|
|
@@ -9289,7 +10420,8 @@ class Dial {
|
|
|
9289
10420
|
var dy = element.draggable_y ? last_mouse[ 1 ] - mousey : 0;
|
|
9290
10421
|
var delta = unconvert([ -dx, dy ]);
|
|
9291
10422
|
|
|
9292
|
-
if( selected != -1 )
|
|
10423
|
+
if( selected != -1 )
|
|
10424
|
+
{
|
|
9293
10425
|
var minx = element.xrange[ 0 ];
|
|
9294
10426
|
var maxx = element.xrange[ 1 ];
|
|
9295
10427
|
|
|
@@ -9397,7 +10529,8 @@ class AssetViewEvent {
|
|
|
9397
10529
|
}
|
|
9398
10530
|
|
|
9399
10531
|
string() {
|
|
9400
|
-
switch(this.type)
|
|
10532
|
+
switch(this.type)
|
|
10533
|
+
{
|
|
9401
10534
|
case AssetViewEvent.NONE: return "assetview_event_none";
|
|
9402
10535
|
case AssetViewEvent.ASSET_SELECTED: return "assetview_event_selected";
|
|
9403
10536
|
case AssetViewEvent.ASSET_DELETED: return "assetview_event_deleted";
|
|
@@ -9751,8 +10884,8 @@ class AssetView {
|
|
|
9751
10884
|
icon: "fa-solid fa-arrows-rotate",
|
|
9752
10885
|
callback: domEl => { this._refreshContent(); }
|
|
9753
10886
|
}
|
|
9754
|
-
], { width: "
|
|
9755
|
-
this.rightPanel.addText(null, this.path.join('/'), null, { disabled: true, signal: "@on_folder_change", style: { fontWeight: "bolder", fontSize: "16px", color: "#aaa" } });
|
|
10887
|
+
], { width: "20%", minWidth: "164px", noSelection: true } );
|
|
10888
|
+
this.rightPanel.addText(null, this.path.join('/'), null, { width: "70%", maxWidth: "calc(70% - 64px)", minWidth: "164px", disabled: true, signal: "@on_folder_change", style: { fontWeight: "bolder", fontSize: "16px", color: "#aaa" } });
|
|
9756
10889
|
this.rightPanel.addText(null, "Page " + this.contentPage + " / " + ((((this.currentData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1), null, {disabled: true, signal: "@on_page_change", width: "fit-content"})
|
|
9757
10890
|
this.rightPanel.endLine();
|
|
9758
10891
|
}
|
|
@@ -9878,8 +11011,8 @@ class AssetView {
|
|
|
9878
11011
|
title.innerText = item.id;
|
|
9879
11012
|
itemEl.appendChild( title );
|
|
9880
11013
|
|
|
9881
|
-
if( !that.skipPreview )
|
|
9882
|
-
|
|
11014
|
+
if( !that.skipPreview )
|
|
11015
|
+
{
|
|
9883
11016
|
let preview = null;
|
|
9884
11017
|
const hasImage = item.src && (['png', 'jpg'].indexOf( getExtension( item.src ) ) > -1 || item.src.includes("data:image/") ); // Support b64 image as src
|
|
9885
11018
|
|
|
@@ -9906,7 +11039,8 @@ class AssetView {
|
|
|
9906
11039
|
var newEmSize = charsPerLine / newLength;
|
|
9907
11040
|
var textBaseSize = 64;
|
|
9908
11041
|
|
|
9909
|
-
if(newEmSize < 1)
|
|
11042
|
+
if( newEmSize < 1 )
|
|
11043
|
+
{
|
|
9910
11044
|
var newFontSize = newEmSize * textBaseSize;
|
|
9911
11045
|
textEl.style.fontSize = newFontSize + "px";
|
|
9912
11046
|
preview.style.paddingTop = "calc(50% - " + (textEl.offsetHeight * 0.5 + 10) + "px)"
|
|
@@ -10135,7 +11269,8 @@ class AssetView {
|
|
|
10135
11269
|
|
|
10136
11270
|
this.currentData.push( item );
|
|
10137
11271
|
|
|
10138
|
-
if(i == (num_files - 1))
|
|
11272
|
+
if( i == (num_files - 1) )
|
|
11273
|
+
{
|
|
10139
11274
|
this._refreshContent();
|
|
10140
11275
|
if( !this.skipBrowser )
|
|
10141
11276
|
this.tree.refresh();
|
|
@@ -10187,7 +11322,7 @@ class AssetView {
|
|
|
10187
11322
|
this.currentData.splice( idx, 1 );
|
|
10188
11323
|
this._refreshContent( this.searchValue, this.filter );
|
|
10189
11324
|
|
|
10190
|
-
if(this.onevent)
|
|
11325
|
+
if( this.onevent)
|
|
10191
11326
|
{
|
|
10192
11327
|
const event = new AssetViewEvent( AssetViewEvent.ASSET_DELETED, item );
|
|
10193
11328
|
this.onevent( event );
|
|
@@ -10263,7 +11398,7 @@ Object.assign(LX, {
|
|
|
10263
11398
|
xhr.onload = function(load)
|
|
10264
11399
|
{
|
|
10265
11400
|
var response = this.response;
|
|
10266
|
-
if(this.status != 200)
|
|
11401
|
+
if( this.status != 200)
|
|
10267
11402
|
{
|
|
10268
11403
|
var err = "Error " + this.status;
|
|
10269
11404
|
if(request.error)
|
|
@@ -10311,7 +11446,7 @@ Object.assign(LX, {
|
|
|
10311
11446
|
var data = new FormData();
|
|
10312
11447
|
if( request.data )
|
|
10313
11448
|
{
|
|
10314
|
-
for(var i in request.data)
|
|
11449
|
+
for( var i in request.data)
|
|
10315
11450
|
data.append(i,request.data[i]);
|
|
10316
11451
|
}
|
|
10317
11452
|
|
|
@@ -10372,7 +11507,7 @@ Object.assign(LX, {
|
|
|
10372
11507
|
var size = total;
|
|
10373
11508
|
var loaded_scripts = [];
|
|
10374
11509
|
|
|
10375
|
-
for(var i in url)
|
|
11510
|
+
for( var i in url)
|
|
10376
11511
|
{
|
|
10377
11512
|
var script = document.createElement('script');
|
|
10378
11513
|
script.num = i;
|
|
@@ -10497,6 +11632,18 @@ Element.prototype.getParentArea = function() {
|
|
|
10497
11632
|
}
|
|
10498
11633
|
}
|
|
10499
11634
|
|
|
11635
|
+
LX.ICONS = {
|
|
11636
|
+
"Sidebar": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_iconCarrier"> <g id="Complete"> <g id="sidebar-left"> <g> <rect id="Square-2" data-name="Square" x="3" y="3" width="18" height="18" rx="2" ry="2" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></rect> <line x1="9" y1="21" x2="9" y2="3" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></line> </g> </g> </g> </g></svg>`,
|
|
11637
|
+
"More": `<svg fill="#000000" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_iconCarrier"> <g id="Complete"> <g id="F-More"> <path id="Vertical" d="M12,16a2,2,0,1,1-2,2A2,2,0,0,1,12,16ZM10,6a2,2,0,1,0,2-2A2,2,0,0,0,10,6Zm0,6a2,2,0,1,0,2-2A2,2,0,0,0,10,12Z"></path> </g> </g> </g></svg>`,
|
|
11638
|
+
"MoreHorizontal": `<svg fill="#000000" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_iconCarrier"> <g id="Complete"> <g id="F-More"> <path id="Horizontal" d="M8,12a2,2,0,1,1-2-2A2,2,0,0,1,8,12Zm10-2a2,2,0,1,0,2,2A2,2,0,0,0,18,10Zm-6,0a2,2,0,1,0,2,2A2,2,0,0,0,12,10Z"></path> </g> </g> </g></svg>`,
|
|
11639
|
+
"MenuArrows": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#000000" transform="rotate(90)"><g id="SVGRepo_iconCarrier"> <g id="Complete"> <g id="Code"> <g> <polyline id="Right-2" data-name="Right" points="15.5 7 20.5 12 15.5 17" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline> <polyline id="Left-2" data-name="Left" points="8.5 7 3.5 12 8.5 17" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline> </g> </g> </g> </g></svg>`,
|
|
11640
|
+
"Plus": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#000000"<g id="SVGRepo_iconCarrier"> <g id="Complete"> <g id="add-2" data-name="add"> <g> <line x1="12" y1="19" x2="12" y2="5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line> <line x1="5" y1="12" x2="19" y2="12" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></line> </g> </g> </g> </g></svg>`,
|
|
11641
|
+
"Down": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#000000"><g id="SVGRepo_iconCarrier"> <title>i</title> <g id="Complete"> <g id="F-Chevron"> <polyline id="Down" points="5 8.5 12 15.5 19 8.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline> </g> </g> </g></svg>`,
|
|
11642
|
+
"Up": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#000000"><g id="SVGRepo_iconCarrier"> <title>i</title> <g id="Complete"> <g id="F-Chevron"> <polyline id="Up" points="5 15.5 12 8.5 19 15.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline> </g> </g> </g></svg>`,
|
|
11643
|
+
"Right": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#000000"><g id="SVGRepo_iconCarrier"> <title>i</title> <g id="Complete"> <g id="F-Chevron"> <polyline id="Right" points="8.5 5 15.5 12 8.5 19" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline> </g> </g> </g></svg>`,
|
|
11644
|
+
"Left": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#000000"><g id="SVGRepo_iconCarrier"> <title>i</title> <g id="Complete"> <g id="F-Chevron"> <polyline id="Left" points="15.5 5 8.5 12 15.5 19" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></polyline> </g> </g> </g></svg>`,
|
|
11645
|
+
}
|
|
11646
|
+
|
|
10500
11647
|
LX.UTILS = {
|
|
10501
11648
|
getTime() { return new Date().getTime() },
|
|
10502
11649
|
compareThreshold( v, p, n, t ) { return Math.abs(v - p) >= t || Math.abs(v - n) >= t },
|
|
@@ -10536,17 +11683,19 @@ LX.UTILS = {
|
|
|
10536
11683
|
drawSpline( ctx, pts, t ) {
|
|
10537
11684
|
|
|
10538
11685
|
ctx.save();
|
|
10539
|
-
var cp=[]; // array of control points, as x0,y0,x1,y1,...
|
|
10540
|
-
var n=pts.length;
|
|
11686
|
+
var cp = []; // array of control points, as x0,y0,x1,y1,...
|
|
11687
|
+
var n = pts.length;
|
|
10541
11688
|
|
|
10542
11689
|
// Draw an open curve, not connected at the ends
|
|
10543
|
-
for(var i=0;i<n-4;i+=2)
|
|
10544
|
-
|
|
11690
|
+
for( var i = 0; i < (n - 4); i += 2 )
|
|
11691
|
+
{
|
|
11692
|
+
cp = cp.concat(LX.UTILS.getControlPoints(pts[i],pts[i+1],pts[i+2],pts[i+3],pts[i+4],pts[i+5],t));
|
|
10545
11693
|
}
|
|
10546
11694
|
|
|
10547
|
-
for(var i=2;i<pts.length-5;i+=2)
|
|
11695
|
+
for( var i = 2; i < ( pts.length - 5 ); i += 2 )
|
|
11696
|
+
{
|
|
10548
11697
|
ctx.beginPath();
|
|
10549
|
-
ctx.moveTo(pts[i],pts[i+1]);
|
|
11698
|
+
ctx.moveTo(pts[i], pts[i+1]);
|
|
10550
11699
|
ctx.bezierCurveTo(cp[2*i-2],cp[2*i-1],cp[2*i],cp[2*i+1],pts[i+2],pts[i+3]);
|
|
10551
11700
|
ctx.stroke();
|
|
10552
11701
|
ctx.closePath();
|
|
@@ -10554,14 +11703,14 @@ LX.UTILS = {
|
|
|
10554
11703
|
|
|
10555
11704
|
// For open curves the first and last arcs are simple quadratics.
|
|
10556
11705
|
ctx.beginPath();
|
|
10557
|
-
ctx.moveTo(pts[0],pts[1]);
|
|
10558
|
-
ctx.quadraticCurveTo(cp[0],cp[1],pts[2],pts[3]);
|
|
11706
|
+
ctx.moveTo( pts[ 0 ], pts[ 1 ] );
|
|
11707
|
+
ctx.quadraticCurveTo( cp[ 0 ], cp[ 1 ], pts[ 2 ], pts[ 3 ]);
|
|
10559
11708
|
ctx.stroke();
|
|
10560
11709
|
ctx.closePath();
|
|
10561
11710
|
|
|
10562
11711
|
ctx.beginPath();
|
|
10563
|
-
ctx.moveTo(pts[n-2],pts[n-1]);
|
|
10564
|
-
ctx.quadraticCurveTo(cp[2*n-10],cp[2*n-9],pts[n-4],pts[n-3]);
|
|
11712
|
+
ctx.moveTo( pts[ n-2 ], pts[ n-1 ] );
|
|
11713
|
+
ctx.quadraticCurveTo( cp[ 2*n-10 ], cp[ 2*n-9 ], pts[ n-4 ], pts[ n-3 ]);
|
|
10565
11714
|
ctx.stroke();
|
|
10566
11715
|
ctx.closePath();
|
|
10567
11716
|
|