lexgui 0.2.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/build/components/nodegraph.js +84 -78
- package/build/components/timeline.js +47 -25
- package/build/lexgui.css +960 -324
- package/build/lexgui.js +1794 -562
- package/build/lexgui.min.css +1 -1
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +1794 -562
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +48 -2
- package/demo.js +6 -6
- 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.module.js
CHANGED
|
@@ -8,23 +8,26 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
var LX = {
|
|
11
|
-
version: "0.
|
|
11
|
+
version: "0.4.1",
|
|
12
12
|
ready: false,
|
|
13
|
-
components: [], //
|
|
14
|
-
signals: {}, //
|
|
15
|
-
extraCommandbarEntries: [] //
|
|
13
|
+
components: [], // Specific pre-build components
|
|
14
|
+
signals: {}, // Events and triggers
|
|
15
|
+
extraCommandbarEntries: [], // User specific entries for command bar
|
|
16
|
+
activeDraggable: null // Watch for the current active draggable
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
LX.MOUSE_LEFT_CLICK = 0;
|
|
19
20
|
LX.MOUSE_MIDDLE_CLICK = 1;
|
|
20
21
|
LX.MOUSE_RIGHT_CLICK = 2;
|
|
21
22
|
|
|
22
|
-
LX.MOUSE_DOUBLE_CLICK
|
|
23
|
-
LX.MOUSE_TRIPLE_CLICK
|
|
23
|
+
LX.MOUSE_DOUBLE_CLICK = 2;
|
|
24
|
+
LX.MOUSE_TRIPLE_CLICK = 3;
|
|
24
25
|
|
|
25
|
-
LX.CURVE_MOVEOUT_CLAMP
|
|
26
|
+
LX.CURVE_MOVEOUT_CLAMP = 0;
|
|
26
27
|
LX.CURVE_MOVEOUT_DELETE = 1;
|
|
27
28
|
|
|
29
|
+
LX.DRAGGABLE_Z_INDEX = 101;
|
|
30
|
+
|
|
28
31
|
function clamp( num, min, max ) { return Math.min( Math.max( num, min ), max ); }
|
|
29
32
|
function round( number, precision ) { return precision == 0 ? Math.floor( number ) : +(( number ).toFixed( precision ?? 2 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' )); }
|
|
30
33
|
function remapRange( oldValue, oldMin, oldMax, newMin, newMax ) { return ((( oldValue - oldMin ) * ( newMax - newMin )) / ( oldMax - oldMin )) + newMin; }
|
|
@@ -84,7 +87,7 @@ LX.doAsync = doAsync;
|
|
|
84
87
|
*/
|
|
85
88
|
function getSupportedDOMName( text )
|
|
86
89
|
{
|
|
87
|
-
return text.replace(/\s/g, '').replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll('.', '');
|
|
90
|
+
return text.replace( /\s/g, '' ).replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll( '.', '' );
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
LX.getSupportedDOMName = getSupportedDOMName;
|
|
@@ -223,7 +226,8 @@ LX.hexToRgb = hexToRgb;
|
|
|
223
226
|
function rgbToHex( rgb )
|
|
224
227
|
{
|
|
225
228
|
let hex = "#";
|
|
226
|
-
for( let c of rgb )
|
|
229
|
+
for( let c of rgb )
|
|
230
|
+
{
|
|
227
231
|
c = Math.floor( c * 255 );
|
|
228
232
|
hex += c.toString( 16 );
|
|
229
233
|
}
|
|
@@ -298,7 +302,7 @@ LX.buildTextPattern = buildTextPattern;
|
|
|
298
302
|
|
|
299
303
|
/**
|
|
300
304
|
* @method makeDraggable
|
|
301
|
-
* @description
|
|
305
|
+
* @description Allows an element to be dragged
|
|
302
306
|
* @param {Element} domEl
|
|
303
307
|
* @param {Object} options
|
|
304
308
|
* autoAdjust (Bool): Sets in a correct position at the beggining
|
|
@@ -323,6 +327,7 @@ function makeDraggable( domEl, options = { } )
|
|
|
323
327
|
top = top ?? e.clientY - offsetY - parentRect.y;
|
|
324
328
|
domEl.style.left = clamp( left, dragMargin + fixedOffset.x, fixedOffset.x + parentRect.width - domEl.offsetWidth - dragMargin ) + 'px';
|
|
325
329
|
domEl.style.top = clamp( top, dragMargin + fixedOffset.y, fixedOffset.y + parentRect.height - domEl.offsetHeight - dragMargin ) + 'px';
|
|
330
|
+
domEl.style.translate = "none"; // Force remove translation
|
|
326
331
|
};
|
|
327
332
|
|
|
328
333
|
// Initial adjustment
|
|
@@ -367,26 +372,45 @@ function makeDraggable( domEl, options = { } )
|
|
|
367
372
|
e.preventDefault();
|
|
368
373
|
e.stopPropagation();
|
|
369
374
|
e.stopImmediatePropagation();
|
|
370
|
-
|
|
375
|
+
|
|
376
|
+
if( !currentTarget )
|
|
377
|
+
{
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
371
381
|
// Remove image when dragging
|
|
372
382
|
var img = new Image();
|
|
373
383
|
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=';
|
|
374
384
|
e.dataTransfer.setDragImage( img, 0, 0 );
|
|
375
385
|
e.dataTransfer.effectAllowed = "move";
|
|
386
|
+
|
|
376
387
|
const rect = e.target.getBoundingClientRect();
|
|
377
388
|
const parentRect = currentTarget.parentElement.getBoundingClientRect();
|
|
378
389
|
const isFixed = ( currentTarget.style.position == "fixed" );
|
|
379
390
|
const fixedOffset = isFixed ? new LX.vec2( parentRect.x, parentRect.y ) : new LX.vec2();
|
|
380
391
|
offsetX = e.clientX - rect.x - fixedOffset.x;
|
|
381
392
|
offsetY = e.clientY - rect.y - fixedOffset.y;
|
|
393
|
+
|
|
382
394
|
document.addEventListener( "mousemove", onMove );
|
|
395
|
+
|
|
396
|
+
currentTarget._eventCatched = true;
|
|
397
|
+
|
|
398
|
+
// Force active dialog to show on top
|
|
399
|
+
if( LX.activeDraggable )
|
|
400
|
+
{
|
|
401
|
+
LX.activeDraggable.style.zIndex = LX.DRAGGABLE_Z_INDEX;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
LX.activeDraggable = domEl;
|
|
405
|
+
LX.activeDraggable.style.zIndex = LX.DRAGGABLE_Z_INDEX + 1;
|
|
406
|
+
|
|
383
407
|
if( onDragStart )
|
|
384
408
|
{
|
|
385
409
|
onDragStart( currentTarget, e );
|
|
386
410
|
}
|
|
387
411
|
}, false );
|
|
388
412
|
|
|
389
|
-
document.addEventListener( 'mouseup', () => {
|
|
413
|
+
document.addEventListener( 'mouseup', (e) => {
|
|
390
414
|
if( currentTarget )
|
|
391
415
|
{
|
|
392
416
|
currentTarget = null;
|
|
@@ -397,6 +421,48 @@ function makeDraggable( domEl, options = { } )
|
|
|
397
421
|
|
|
398
422
|
LX.makeDraggable = makeDraggable;
|
|
399
423
|
|
|
424
|
+
/**
|
|
425
|
+
* @method makeCollapsible
|
|
426
|
+
* @description Allows an element to be collapsed/expanded
|
|
427
|
+
* @param {Element} domEl: Element to be treated as collapsible
|
|
428
|
+
* @param {Element} content: Content to display/hide on collapse/extend
|
|
429
|
+
* @param {Element} parent: Element where the content will be appended (default is domEl.parent)
|
|
430
|
+
* @param {Object} options
|
|
431
|
+
*/
|
|
432
|
+
function makeCollapsible( domEl, content, parent, options = { } )
|
|
433
|
+
{
|
|
434
|
+
domEl.classList.add( "collapsible" );
|
|
435
|
+
|
|
436
|
+
const collapsed = ( options.collapsed ?? true );
|
|
437
|
+
const actionIcon = LX.makeIcon( "Right" );
|
|
438
|
+
actionIcon.classList.add( "collapser" );
|
|
439
|
+
actionIcon.dataset[ "collapsed" ] = collapsed;
|
|
440
|
+
actionIcon.style.marginLeft = "auto";
|
|
441
|
+
|
|
442
|
+
actionIcon.addEventListener( "click", function(e) {
|
|
443
|
+
e.preventDefault();
|
|
444
|
+
e.stopPropagation();
|
|
445
|
+
if( this.dataset[ "collapsed" ] )
|
|
446
|
+
{
|
|
447
|
+
delete this.dataset[ "collapsed" ];
|
|
448
|
+
content.style.display = "block";
|
|
449
|
+
}
|
|
450
|
+
else
|
|
451
|
+
{
|
|
452
|
+
this.dataset[ "collapsed" ] = true;
|
|
453
|
+
content.style.display = "none";
|
|
454
|
+
}
|
|
455
|
+
} );
|
|
456
|
+
|
|
457
|
+
domEl.appendChild( actionIcon );
|
|
458
|
+
|
|
459
|
+
parent = parent ?? domEl.parentElement;
|
|
460
|
+
|
|
461
|
+
parent.appendChild( content );
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
LX.makeCollapsible = makeCollapsible;
|
|
465
|
+
|
|
400
466
|
/**
|
|
401
467
|
* @method makeCodeSnippet
|
|
402
468
|
* @description Create a code snippet in a specific language
|
|
@@ -499,6 +565,23 @@ function makeCodeSnippet( code, size, options = { } )
|
|
|
499
565
|
|
|
500
566
|
LX.makeCodeSnippet = makeCodeSnippet;
|
|
501
567
|
|
|
568
|
+
/**
|
|
569
|
+
* @method makeIcon
|
|
570
|
+
* @description Gets an SVG element using one of LX.ICONS
|
|
571
|
+
* @param {String} iconName
|
|
572
|
+
* @param {String} iconTitle
|
|
573
|
+
*/
|
|
574
|
+
function makeIcon( iconName, iconTitle )
|
|
575
|
+
{
|
|
576
|
+
const icon = document.createElement( "a" );
|
|
577
|
+
icon.title = iconTitle ?? "";
|
|
578
|
+
icon.className = "lexicon";
|
|
579
|
+
icon.innerHTML = LX.ICONS[ iconName ] ?? "";
|
|
580
|
+
return icon;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
LX.makeIcon = makeIcon;
|
|
584
|
+
|
|
502
585
|
/**
|
|
503
586
|
* @method registerCommandbarEntry
|
|
504
587
|
* @description Adds an extra command bar entry
|
|
@@ -768,12 +851,12 @@ function _createCommandbar( root )
|
|
|
768
851
|
if( LX.has('CodeEditor') )
|
|
769
852
|
{
|
|
770
853
|
const instances = LX.CodeEditor.getInstances();
|
|
771
|
-
if(!instances.length) return;
|
|
854
|
+
if( !instances.length ) return;
|
|
772
855
|
|
|
773
856
|
const languages = instances[ 0 ].languages;
|
|
774
857
|
|
|
775
|
-
for( let l of Object.keys( languages ) )
|
|
776
|
-
|
|
858
|
+
for( let l of Object.keys( languages ) )
|
|
859
|
+
{
|
|
777
860
|
const key = "Language: " + l;
|
|
778
861
|
const icon = instances[ 0 ]._getFileIcon( null, languages[ l ].ext );
|
|
779
862
|
|
|
@@ -781,9 +864,11 @@ function _createCommandbar( root )
|
|
|
781
864
|
"<img src='" + ( "https://raw.githubusercontent.com/jxarco/lexgui.js/master/" + icon ) + "'>";
|
|
782
865
|
|
|
783
866
|
value += key + " <span class='lang-ext'>(" + languages[ l ].ext + ")</span>";
|
|
784
|
-
if( key.toLowerCase().includes( filter ) )
|
|
867
|
+
if( key.toLowerCase().includes( filter ) )
|
|
868
|
+
{
|
|
785
869
|
_addElement( value, () => {
|
|
786
|
-
for( let i of instances )
|
|
870
|
+
for( let i of instances )
|
|
871
|
+
{
|
|
787
872
|
i._changeLanguage( l );
|
|
788
873
|
}
|
|
789
874
|
}, "", {} );
|
|
@@ -841,7 +926,19 @@ function init( options = { } )
|
|
|
841
926
|
this.container = document.getElementById( options.container );
|
|
842
927
|
}
|
|
843
928
|
|
|
844
|
-
|
|
929
|
+
this.usingStrictViewport = options.strictViewport ?? true;
|
|
930
|
+
document.documentElement.setAttribute( "data-strictVP", ( this.usingStrictViewport ) ? "true" : "false" );
|
|
931
|
+
|
|
932
|
+
if( !this.usingStrictViewport )
|
|
933
|
+
{
|
|
934
|
+
document.addEventListener( "scroll", e => {
|
|
935
|
+
// Get all active menuboxes
|
|
936
|
+
const mbs = document.body.querySelectorAll( ".lexmenubox" );
|
|
937
|
+
mbs.forEach( ( mb ) => {
|
|
938
|
+
mb._updatePosition();
|
|
939
|
+
} );
|
|
940
|
+
} );
|
|
941
|
+
}
|
|
845
942
|
|
|
846
943
|
this.commandbar = _createCommandbar( this.container );
|
|
847
944
|
|
|
@@ -856,6 +953,25 @@ function init( options = { } )
|
|
|
856
953
|
this.root = document.body;
|
|
857
954
|
}
|
|
858
955
|
|
|
956
|
+
// Notifications
|
|
957
|
+
{
|
|
958
|
+
const notifSection = document.createElement( "section" );
|
|
959
|
+
notifSection.className = "notifications";
|
|
960
|
+
this.notifications = document.createElement( "ol" );
|
|
961
|
+
this.notifications.className = "";
|
|
962
|
+
this.notifications.iWidth = 0;
|
|
963
|
+
notifSection.appendChild( this.notifications );
|
|
964
|
+
this.container.appendChild( notifSection );
|
|
965
|
+
|
|
966
|
+
this.notifications.addEventListener( "mouseenter", () => {
|
|
967
|
+
this.notifications.classList.add( "list" );
|
|
968
|
+
} );
|
|
969
|
+
|
|
970
|
+
this.notifications.addEventListener( "mouseleave", () => {
|
|
971
|
+
this.notifications.classList.remove( "list" );
|
|
972
|
+
} );
|
|
973
|
+
}
|
|
974
|
+
|
|
859
975
|
// Disable drag icon
|
|
860
976
|
root.addEventListener( 'dragover', function( e ) {
|
|
861
977
|
e.preventDefault();
|
|
@@ -1006,6 +1122,7 @@ LX.popup = popup;
|
|
|
1006
1122
|
function prompt( text, title, callback, options = {} )
|
|
1007
1123
|
{
|
|
1008
1124
|
options.modal = true;
|
|
1125
|
+
options.className = "prompt";
|
|
1009
1126
|
|
|
1010
1127
|
let value = "";
|
|
1011
1128
|
|
|
@@ -1020,7 +1137,9 @@ function prompt( text, title, callback, options = {} )
|
|
|
1020
1137
|
|
|
1021
1138
|
p.sameLine( 2 );
|
|
1022
1139
|
|
|
1023
|
-
p.addButton(
|
|
1140
|
+
p.addButton(null, "Cancel", () => {if(options.on_cancel) options.on_cancel(); dialog.close();} );
|
|
1141
|
+
|
|
1142
|
+
p.addButton( null, options.accept || "Continue", () => {
|
|
1024
1143
|
if( options.required && value === '' )
|
|
1025
1144
|
{
|
|
1026
1145
|
text += text.includes("You must fill the input text.") ? "": "\nYou must fill the input text.";
|
|
@@ -1034,8 +1153,6 @@ function prompt( text, title, callback, options = {} )
|
|
|
1034
1153
|
}
|
|
1035
1154
|
}, { buttonClass: "primary" });
|
|
1036
1155
|
|
|
1037
|
-
p.addButton(null, "Cancel", () => {if(options.on_cancel) options.on_cancel(); dialog.close();} );
|
|
1038
|
-
|
|
1039
1156
|
}, options );
|
|
1040
1157
|
|
|
1041
1158
|
// Focus text prompt
|
|
@@ -1049,6 +1166,101 @@ function prompt( text, title, callback, options = {} )
|
|
|
1049
1166
|
|
|
1050
1167
|
LX.prompt = prompt;
|
|
1051
1168
|
|
|
1169
|
+
/**
|
|
1170
|
+
* @method toast
|
|
1171
|
+
* @param {String} title
|
|
1172
|
+
* @param {String} description (Optional)
|
|
1173
|
+
* @param {*} options
|
|
1174
|
+
* action: Data of the custom action { name, callback }
|
|
1175
|
+
* closable: Allow closing the toast
|
|
1176
|
+
* timeout: Time in which the toast closed automatically, in ms. -1 means persistent. [3000]
|
|
1177
|
+
*/
|
|
1178
|
+
|
|
1179
|
+
function toast( title, description, options = {} )
|
|
1180
|
+
{
|
|
1181
|
+
if( !title )
|
|
1182
|
+
{
|
|
1183
|
+
throw( "The toast needs at least a title!" );
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
console.assert( this.notifications );
|
|
1187
|
+
|
|
1188
|
+
const toast = document.createElement( "li" );
|
|
1189
|
+
toast.className = "lextoast";
|
|
1190
|
+
toast.style.translate = "0 calc(100% + 30px)";
|
|
1191
|
+
this.notifications.prepend( toast );
|
|
1192
|
+
|
|
1193
|
+
doAsync( () => {
|
|
1194
|
+
|
|
1195
|
+
if( this.notifications.offsetWidth > this.notifications.iWidth )
|
|
1196
|
+
{
|
|
1197
|
+
this.notifications.iWidth = Math.min( this.notifications.offsetWidth, 480 );
|
|
1198
|
+
this.notifications.style.width = this.notifications.iWidth + "px";
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
toast.dataset[ "open" ] = true;
|
|
1202
|
+
}, 10 );
|
|
1203
|
+
|
|
1204
|
+
const content = document.createElement( "div" );
|
|
1205
|
+
content.className = "lextoastcontent";
|
|
1206
|
+
toast.appendChild( content );
|
|
1207
|
+
|
|
1208
|
+
const titleContent = document.createElement( "div" );
|
|
1209
|
+
titleContent.className = "title";
|
|
1210
|
+
titleContent.innerHTML = title;
|
|
1211
|
+
content.appendChild( titleContent );
|
|
1212
|
+
|
|
1213
|
+
if( description )
|
|
1214
|
+
{
|
|
1215
|
+
const desc = document.createElement( "div" );
|
|
1216
|
+
desc.className = "desc";
|
|
1217
|
+
desc.innerHTML = description;
|
|
1218
|
+
content.appendChild( desc );
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
if( options.action )
|
|
1222
|
+
{
|
|
1223
|
+
const panel = new Panel();
|
|
1224
|
+
panel.addButton(null, options.action.name ?? "Accept", options.action.callback.bind( this, toast ), { width: "auto", maxWidth: "150px", className: "right", buttonClass: "outline" });
|
|
1225
|
+
toast.appendChild( panel.root.childNodes[ 0 ] );
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
const that = this;
|
|
1229
|
+
|
|
1230
|
+
toast.close = function() {
|
|
1231
|
+
this.dataset[ "closed" ] = true;
|
|
1232
|
+
doAsync( () => {
|
|
1233
|
+
this.remove();
|
|
1234
|
+
if( !that.notifications.childElementCount )
|
|
1235
|
+
{
|
|
1236
|
+
that.notifications.style.width = "unset";
|
|
1237
|
+
that.notifications.iWidth = 0;
|
|
1238
|
+
}
|
|
1239
|
+
}, 500 );
|
|
1240
|
+
};
|
|
1241
|
+
|
|
1242
|
+
if( options.closable ?? true )
|
|
1243
|
+
{
|
|
1244
|
+
const closeButton = document.createElement( "a" );
|
|
1245
|
+
closeButton.className = "fa fa-xmark lexicon closer";
|
|
1246
|
+
closeButton.addEventListener( "click", () => {
|
|
1247
|
+
toast.close();
|
|
1248
|
+
} );
|
|
1249
|
+
toast.appendChild( closeButton );
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
const timeout = options.timeout ?? 3000;
|
|
1253
|
+
|
|
1254
|
+
if( timeout != -1 )
|
|
1255
|
+
{
|
|
1256
|
+
doAsync( () => {
|
|
1257
|
+
toast.close();
|
|
1258
|
+
}, timeout );
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
LX.toast = toast;
|
|
1263
|
+
|
|
1052
1264
|
/**
|
|
1053
1265
|
* @method badge
|
|
1054
1266
|
* @param {String} text
|
|
@@ -1350,7 +1562,8 @@ class Area {
|
|
|
1350
1562
|
|
|
1351
1563
|
function inner_mousemove( e )
|
|
1352
1564
|
{
|
|
1353
|
-
switch( that.type )
|
|
1565
|
+
switch( that.type )
|
|
1566
|
+
{
|
|
1354
1567
|
case "right":
|
|
1355
1568
|
var dt = ( lastMousePosition[ 0 ] - e.x );
|
|
1356
1569
|
var size = ( that.root.offsetWidth + dt );
|
|
@@ -1545,7 +1758,8 @@ class Area {
|
|
|
1545
1758
|
|
|
1546
1759
|
// Listen resize event on first area
|
|
1547
1760
|
const resizeObserver = new ResizeObserver( entries => {
|
|
1548
|
-
for (const entry of entries)
|
|
1761
|
+
for ( const entry of entries )
|
|
1762
|
+
{
|
|
1549
1763
|
const bb = entry.contentRect;
|
|
1550
1764
|
area2.root.style.height = "calc(100% - " + ( bb.height + 4) + "px )";
|
|
1551
1765
|
}
|
|
@@ -1686,9 +1900,15 @@ class Area {
|
|
|
1686
1900
|
this.root.style.height = height;
|
|
1687
1901
|
}
|
|
1688
1902
|
|
|
1689
|
-
|
|
1903
|
+
if( this.onresize )
|
|
1904
|
+
{
|
|
1905
|
+
this.onresize( this.root.getBoundingClientRect() );
|
|
1906
|
+
}
|
|
1690
1907
|
|
|
1691
|
-
|
|
1908
|
+
doAsync( () => {
|
|
1909
|
+
this.size = [ this.root.clientWidth, this.root.clientHeight ];
|
|
1910
|
+
this.propagateEvent( "onresize" );
|
|
1911
|
+
}, 150 );
|
|
1692
1912
|
}
|
|
1693
1913
|
|
|
1694
1914
|
/**
|
|
@@ -1705,7 +1925,7 @@ class Area {
|
|
|
1705
1925
|
let [area1, area2] = this.sections;
|
|
1706
1926
|
this.splitExtended = true;
|
|
1707
1927
|
|
|
1708
|
-
if(this.type == "vertical")
|
|
1928
|
+
if( this.type == "vertical")
|
|
1709
1929
|
{
|
|
1710
1930
|
this.offset = area2.root.offsetHeight;
|
|
1711
1931
|
area2.root.classList.add("fadeout-vertical");
|
|
@@ -1719,7 +1939,6 @@ class Area {
|
|
|
1719
1939
|
this._moveSplit(-Infinity, true, 8);
|
|
1720
1940
|
}
|
|
1721
1941
|
|
|
1722
|
-
// Async resize in some ms...
|
|
1723
1942
|
doAsync( () => this.propagateEvent('onresize'), 150 );
|
|
1724
1943
|
}
|
|
1725
1944
|
|
|
@@ -1735,7 +1954,7 @@ class Area {
|
|
|
1735
1954
|
this.splitExtended = false;
|
|
1736
1955
|
let [area1, area2] = this.sections;
|
|
1737
1956
|
|
|
1738
|
-
if(this.type == "vertical")
|
|
1957
|
+
if( this.type == "vertical")
|
|
1739
1958
|
{
|
|
1740
1959
|
area2.root.classList.add("fadein-vertical");
|
|
1741
1960
|
this._moveSplit(this.offset);
|
|
@@ -1746,7 +1965,6 @@ class Area {
|
|
|
1746
1965
|
this._moveSplit(this.offset);
|
|
1747
1966
|
}
|
|
1748
1967
|
|
|
1749
|
-
// Async resize in some ms...
|
|
1750
1968
|
doAsync( () => this.propagateEvent('onresize'), 150 );
|
|
1751
1969
|
}
|
|
1752
1970
|
|
|
@@ -1780,11 +1998,15 @@ class Area {
|
|
|
1780
1998
|
|
|
1781
1999
|
propagateEvent( eventName ) {
|
|
1782
2000
|
|
|
1783
|
-
for(var i = 0; i < this.sections.length; i++)
|
|
2001
|
+
for( var i = 0; i < this.sections.length; i++ )
|
|
1784
2002
|
{
|
|
1785
|
-
const area = this.sections[i];
|
|
1786
|
-
|
|
2003
|
+
const area = this.sections[ i ];
|
|
2004
|
+
|
|
2005
|
+
if( area[ eventName ] )
|
|
2006
|
+
{
|
|
1787
2007
|
area[ eventName ].call( this, area.root.getBoundingClientRect() );
|
|
2008
|
+
}
|
|
2009
|
+
|
|
1788
2010
|
area.propagateEvent( eventName );
|
|
1789
2011
|
}
|
|
1790
2012
|
}
|
|
@@ -1807,42 +2029,63 @@ class Area {
|
|
|
1807
2029
|
* @param {Function} callback Function to fill the menubar
|
|
1808
2030
|
* @param {*} options:
|
|
1809
2031
|
* float: Justify content (left, center, right) [left]
|
|
2032
|
+
* sticky: Fix menubar at the top [true]
|
|
1810
2033
|
*/
|
|
1811
2034
|
|
|
1812
2035
|
addMenubar( callback, options = {} ) {
|
|
1813
2036
|
|
|
1814
|
-
let menubar = new Menubar(options);
|
|
2037
|
+
let menubar = new Menubar( options );
|
|
1815
2038
|
|
|
1816
|
-
if(
|
|
2039
|
+
if( callback )
|
|
2040
|
+
{
|
|
2041
|
+
callback( menubar );
|
|
2042
|
+
}
|
|
1817
2043
|
|
|
1818
2044
|
LX.menubars.push( menubar );
|
|
1819
2045
|
|
|
1820
2046
|
const height = 48; // pixels
|
|
2047
|
+
const [ bar, content ] = this.split({ type: 'vertical', sizes: [height, null], resize: false, menubar: true });
|
|
2048
|
+
menubar.siblingArea = content;
|
|
1821
2049
|
|
|
1822
|
-
const [bar, content] = this.split({type: 'vertical', sizes: [height, null], resize: false, menubar: true});
|
|
1823
2050
|
bar.attach( menubar );
|
|
1824
|
-
bar.
|
|
2051
|
+
bar.isMenubar = true;
|
|
2052
|
+
|
|
2053
|
+
if( options.sticky ?? true )
|
|
2054
|
+
{
|
|
2055
|
+
bar.root.classList.add( "sticky" );
|
|
2056
|
+
}
|
|
2057
|
+
|
|
1825
2058
|
return menubar;
|
|
1826
2059
|
}
|
|
1827
2060
|
|
|
1828
2061
|
/**
|
|
1829
2062
|
* @method addSidebar
|
|
1830
2063
|
* @param {Function} callback Function to fill the sidebar
|
|
2064
|
+
* @param {Object} options: Sidebar options
|
|
2065
|
+
* width: Width of the sidebar [16rem]
|
|
1831
2066
|
*/
|
|
1832
2067
|
|
|
1833
2068
|
addSidebar( callback, options = {} ) {
|
|
1834
2069
|
|
|
1835
2070
|
let sidebar = new SideBar( options );
|
|
1836
2071
|
|
|
1837
|
-
if( callback )
|
|
2072
|
+
if( callback )
|
|
2073
|
+
{
|
|
2074
|
+
callback( sidebar );
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
// Generate DOM elements after adding all entries
|
|
2078
|
+
sidebar.update();
|
|
1838
2079
|
|
|
1839
2080
|
LX.menubars.push( sidebar );
|
|
1840
2081
|
|
|
1841
|
-
const width =
|
|
2082
|
+
const width = options.width ?? "16rem";
|
|
2083
|
+
const [ bar, content ] = this.split( { type: 'horizontal', sizes: [ width, null ], resize: false, sidebar: true } );
|
|
2084
|
+
sidebar.siblingArea = content;
|
|
1842
2085
|
|
|
1843
|
-
const [bar, content] = this.split( { type: 'horizontal', sizes: [ width, null ], resize: false, sidebar: true } );
|
|
1844
2086
|
bar.attach( sidebar );
|
|
1845
|
-
bar.
|
|
2087
|
+
bar.isSidebar = true;
|
|
2088
|
+
|
|
1846
2089
|
return sidebar;
|
|
1847
2090
|
}
|
|
1848
2091
|
|
|
@@ -2098,7 +2341,8 @@ class Area {
|
|
|
2098
2341
|
|
|
2099
2342
|
this.size = [ rect.width, rect.height ];
|
|
2100
2343
|
|
|
2101
|
-
for(var i = 0; i < this.sections.length; i++)
|
|
2344
|
+
for( var i = 0; i < this.sections.length; i++ )
|
|
2345
|
+
{
|
|
2102
2346
|
this.sections[i]._update();
|
|
2103
2347
|
}
|
|
2104
2348
|
}
|
|
@@ -2122,7 +2366,7 @@ class Tabs {
|
|
|
2122
2366
|
static TAB_SIZE = 28;
|
|
2123
2367
|
static TAB_ID = 0;
|
|
2124
2368
|
|
|
2125
|
-
constructor( area, options = {} )
|
|
2369
|
+
constructor( area, options = {} ) {
|
|
2126
2370
|
|
|
2127
2371
|
this.onclose = options.onclose;
|
|
2128
2372
|
|
|
@@ -2204,24 +2448,28 @@ class Tabs {
|
|
|
2204
2448
|
}
|
|
2205
2449
|
|
|
2206
2450
|
// debug
|
|
2207
|
-
if(folding)
|
|
2451
|
+
if( folding )
|
|
2208
2452
|
{
|
|
2209
2453
|
this.folded = true;
|
|
2210
2454
|
this.folding = folding;
|
|
2211
2455
|
|
|
2212
|
-
if(folding == "up"
|
|
2456
|
+
if( folding == "up" )
|
|
2457
|
+
{
|
|
2458
|
+
area.root.insertChildAtIndex(area.sections[1].root, 0);
|
|
2459
|
+
}
|
|
2213
2460
|
|
|
2214
2461
|
// Listen resize event on parent area
|
|
2215
2462
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
2216
|
-
for (const entry of entries)
|
|
2463
|
+
for (const entry of entries)
|
|
2464
|
+
{
|
|
2217
2465
|
const bb = entry.contentRect;
|
|
2218
|
-
const sibling = area.parentArea.sections[0].root;
|
|
2219
|
-
const
|
|
2220
|
-
sibling.style.height = "calc(100% - " + ((
|
|
2466
|
+
const sibling = area.parentArea.sections[ 0 ].root;
|
|
2467
|
+
const addOffset = true; // hardcoded...
|
|
2468
|
+
sibling.style.height = "calc(100% - " + ((addOffset ? 42 : 0) + bb.height) + "px )";
|
|
2221
2469
|
}
|
|
2222
2470
|
});
|
|
2223
2471
|
|
|
2224
|
-
resizeObserver.observe(this.area.root);
|
|
2472
|
+
resizeObserver.observe( this.area.root );
|
|
2225
2473
|
this.area.root.classList.add('folded');
|
|
2226
2474
|
}
|
|
2227
2475
|
}
|
|
@@ -2358,7 +2606,8 @@ class Tabs {
|
|
|
2358
2606
|
|
|
2359
2607
|
setTimeout( () => {
|
|
2360
2608
|
|
|
2361
|
-
if( options.onCreate )
|
|
2609
|
+
if( options.onCreate )
|
|
2610
|
+
{
|
|
2362
2611
|
options.onCreate.call(this, this.area.root.getBoundingClientRect());
|
|
2363
2612
|
}
|
|
2364
2613
|
|
|
@@ -2420,34 +2669,230 @@ LX.Tabs = Tabs;
|
|
|
2420
2669
|
|
|
2421
2670
|
class Menubar {
|
|
2422
2671
|
|
|
2423
|
-
constructor( options = {} )
|
|
2672
|
+
constructor( options = {} ) {
|
|
2424
2673
|
|
|
2425
|
-
this.root = document.createElement(
|
|
2674
|
+
this.root = document.createElement( "div" );
|
|
2426
2675
|
this.root.className = "lexmenubar";
|
|
2427
|
-
|
|
2676
|
+
|
|
2677
|
+
if( options.float )
|
|
2678
|
+
{
|
|
2428
2679
|
this.root.style.justifyContent = options.float;
|
|
2429
|
-
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
this.items = [ ];
|
|
2683
|
+
this.buttons = [ ];
|
|
2684
|
+
this.icons = { };
|
|
2685
|
+
this.shorts = { };
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
_resetMenubar() {
|
|
2689
|
+
|
|
2690
|
+
// Menu entries are in the menubar..
|
|
2691
|
+
this.root.querySelectorAll(".lexmenuentry").forEach( _entry => {
|
|
2692
|
+
_entry.classList.remove( 'selected' );
|
|
2693
|
+
_entry.built = false;
|
|
2694
|
+
} );
|
|
2695
|
+
|
|
2696
|
+
// Menuboxes are in the root area!
|
|
2697
|
+
LX.root.querySelectorAll(".lexmenubox").forEach(e => e.remove());
|
|
2698
|
+
|
|
2699
|
+
// Next time we need to click again
|
|
2700
|
+
this.focused = false;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
_createSubmenu( o, k, c, d ) {
|
|
2704
|
+
|
|
2705
|
+
let menuElement = document.createElement('div');
|
|
2706
|
+
menuElement.className = "lexmenubox";
|
|
2707
|
+
menuElement.tabIndex = "0";
|
|
2708
|
+
c.currentMenu = menuElement;
|
|
2709
|
+
menuElement.parentEntry = c;
|
|
2710
|
+
|
|
2711
|
+
const isSubMenu = c.classList.contains( "lexmenuboxentry" );
|
|
2712
|
+
if( isSubMenu )
|
|
2713
|
+
{
|
|
2714
|
+
menuElement.dataset[ "submenu" ] = true;
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
menuElement._updatePosition = () => {
|
|
2718
|
+
|
|
2719
|
+
// Remove transitions for this change..
|
|
2720
|
+
const transition = menuElement.style.transition;
|
|
2721
|
+
menuElement.style.transition = "none";
|
|
2722
|
+
flushCss( menuElement );
|
|
2723
|
+
|
|
2724
|
+
doAsync( () => {
|
|
2725
|
+
let rect = c.getBoundingClientRect();
|
|
2726
|
+
rect.x += document.scrollingElement.scrollLeft;
|
|
2727
|
+
rect.y += document.scrollingElement.scrollTop;
|
|
2728
|
+
menuElement.style.left = ( isSubMenu ? ( rect.x + rect.width ) : rect.x ) + "px";
|
|
2729
|
+
menuElement.style.top = ( isSubMenu ? rect.y : ( ( rect.y + rect.height ) ) - 4 ) + "px";
|
|
2730
|
+
|
|
2731
|
+
menuElement.style.transition = transition;
|
|
2732
|
+
} );
|
|
2733
|
+
};
|
|
2734
|
+
|
|
2735
|
+
menuElement._updatePosition();
|
|
2736
|
+
|
|
2737
|
+
doAsync( () => {
|
|
2738
|
+
menuElement.dataset[ "open" ] = true;
|
|
2739
|
+
}, 10 );
|
|
2740
|
+
|
|
2741
|
+
LX.root.appendChild( menuElement );
|
|
2742
|
+
|
|
2743
|
+
for( var i = 0; i < o[ k ].length; ++i )
|
|
2744
|
+
{
|
|
2745
|
+
const subitem = o[ k ][ i ];
|
|
2746
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
2747
|
+
const hasSubmenu = subitem[ subkey ].length;
|
|
2748
|
+
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2749
|
+
let subentry = document.createElement('div');
|
|
2750
|
+
subentry.className = "lexmenuboxentry";
|
|
2751
|
+
subentry.className += (i == o[k].length - 1 ? " last" : "") + ( subitem.disabled ? " disabled" : "" );
|
|
2752
|
+
|
|
2753
|
+
if( subkey == '' )
|
|
2754
|
+
{
|
|
2755
|
+
subentry.className = " lexseparator";
|
|
2756
|
+
}
|
|
2757
|
+
else
|
|
2758
|
+
{
|
|
2759
|
+
subentry.id = subkey;
|
|
2760
|
+
let subentrycont = document.createElement('div');
|
|
2761
|
+
subentrycont.innerHTML = "";
|
|
2762
|
+
subentrycont.classList = "lexmenuboxentrycontainer";
|
|
2763
|
+
subentry.appendChild(subentrycont);
|
|
2764
|
+
const icon = this.icons[ subkey ];
|
|
2765
|
+
if( isCheckbox )
|
|
2766
|
+
{
|
|
2767
|
+
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2768
|
+
}
|
|
2769
|
+
else if( icon )
|
|
2770
|
+
{
|
|
2771
|
+
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2772
|
+
}
|
|
2773
|
+
else
|
|
2774
|
+
{
|
|
2775
|
+
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2776
|
+
subentrycont.classList.add( "noicon" );
|
|
2777
|
+
|
|
2778
|
+
}
|
|
2779
|
+
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
let checkboxInput = subentry.querySelector('input');
|
|
2783
|
+
if( checkboxInput )
|
|
2784
|
+
{
|
|
2785
|
+
checkboxInput.checked = subitem.checked ?? false;
|
|
2786
|
+
checkboxInput.addEventListener('change', e => {
|
|
2787
|
+
subitem.checked = checkboxInput.checked;
|
|
2788
|
+
const f = subitem[ 'callback' ];
|
|
2789
|
+
if( f )
|
|
2790
|
+
{
|
|
2791
|
+
f.call( this, subitem.checked, subkey, subentry );
|
|
2792
|
+
this._resetMenubar();
|
|
2793
|
+
}
|
|
2794
|
+
e.stopPropagation();
|
|
2795
|
+
e.stopImmediatePropagation();
|
|
2796
|
+
})
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
menuElement.appendChild( subentry );
|
|
2800
|
+
|
|
2801
|
+
// Nothing more for separators
|
|
2802
|
+
if( subkey == '' )
|
|
2803
|
+
{
|
|
2804
|
+
continue;
|
|
2805
|
+
}
|
|
2430
2806
|
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2807
|
+
menuElement.addEventListener('keydown', e => {
|
|
2808
|
+
e.preventDefault();
|
|
2809
|
+
let short = this.shorts[ subkey ];
|
|
2810
|
+
if(!short) return;
|
|
2811
|
+
// check if it's a letter or other key
|
|
2812
|
+
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2813
|
+
if( short == e.key )
|
|
2814
|
+
{
|
|
2815
|
+
subentry.click()
|
|
2816
|
+
}
|
|
2817
|
+
});
|
|
2818
|
+
|
|
2819
|
+
// Add callback
|
|
2820
|
+
subentry.addEventListener("click", e => {
|
|
2821
|
+
if( checkboxInput )
|
|
2822
|
+
{
|
|
2823
|
+
subitem.checked = !subitem.checked;
|
|
2824
|
+
}
|
|
2825
|
+
const f = subitem[ 'callback' ];
|
|
2826
|
+
if( f )
|
|
2827
|
+
{
|
|
2828
|
+
f.call( this, checkboxInput ? subitem.checked : subkey, checkboxInput ? subkey : subentry );
|
|
2829
|
+
this._resetMenubar();
|
|
2830
|
+
}
|
|
2831
|
+
e.stopPropagation();
|
|
2832
|
+
e.stopImmediatePropagation();
|
|
2833
|
+
});
|
|
2834
|
+
|
|
2835
|
+
// Add icon if has submenu, else check for shortcut
|
|
2836
|
+
if( !hasSubmenu)
|
|
2837
|
+
{
|
|
2838
|
+
if( this.shorts[ subkey ] )
|
|
2839
|
+
{
|
|
2840
|
+
let shortEl = document.createElement('div');
|
|
2841
|
+
shortEl.className = "lexentryshort";
|
|
2842
|
+
shortEl.innerText = this.shorts[ subkey ];
|
|
2843
|
+
subentry.appendChild( shortEl );
|
|
2844
|
+
}
|
|
2845
|
+
continue;
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
let submenuIcon = document.createElement('a');
|
|
2849
|
+
submenuIcon.className = "fa-solid fa-angle-right fa-xs";
|
|
2850
|
+
subentry.appendChild( submenuIcon );
|
|
2851
|
+
|
|
2852
|
+
subentry.addEventListener("mouseover", e => {
|
|
2853
|
+
if( subentry.built )
|
|
2854
|
+
{
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2857
|
+
subentry.built = true;
|
|
2858
|
+
this._createSubmenu( subitem, subkey, subentry, ++d );
|
|
2859
|
+
e.stopPropagation();
|
|
2860
|
+
});
|
|
2861
|
+
|
|
2862
|
+
subentry.addEventListener("mouseleave", e => {
|
|
2863
|
+
if( subentry.currentMenu && ( subentry.currentMenu != e.toElement ) )
|
|
2864
|
+
{
|
|
2865
|
+
d = -1; // Reset depth
|
|
2866
|
+
delete subentry.built;
|
|
2867
|
+
subentry.currentMenu.remove();
|
|
2868
|
+
delete subentry.currentMenu;
|
|
2869
|
+
}
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
// Set final width
|
|
2874
|
+
menuElement.style.width = menuElement.offsetWidth + "px";
|
|
2434
2875
|
}
|
|
2435
2876
|
|
|
2436
2877
|
/**
|
|
2437
2878
|
* @method add
|
|
2438
|
-
* @param {
|
|
2879
|
+
* @param {Object} options:
|
|
2439
2880
|
* callback: Function to call on each item
|
|
2881
|
+
* icon: Entry icon
|
|
2882
|
+
* short: Entry shortcut name
|
|
2440
2883
|
*/
|
|
2441
2884
|
|
|
2442
2885
|
add( path, options = {} ) {
|
|
2443
2886
|
|
|
2444
|
-
if(options.constructor == Function)
|
|
2887
|
+
if( options.constructor == Function )
|
|
2888
|
+
{
|
|
2445
2889
|
options = { callback: options };
|
|
2890
|
+
}
|
|
2446
2891
|
|
|
2447
|
-
//
|
|
2448
|
-
const tokens = path.split("/");
|
|
2892
|
+
// Process path
|
|
2893
|
+
const tokens = path.split( "/" );
|
|
2449
2894
|
|
|
2450
|
-
//
|
|
2895
|
+
// Assign icons and shortcuts to last token in path
|
|
2451
2896
|
const lastPath = tokens[tokens.length - 1];
|
|
2452
2897
|
this.icons[ lastPath ] = options.icon;
|
|
2453
2898
|
this.shorts[ lastPath ] = options.short;
|
|
@@ -2455,211 +2900,119 @@ class Menubar {
|
|
|
2455
2900
|
let idx = 0;
|
|
2456
2901
|
let that = this;
|
|
2457
2902
|
|
|
2458
|
-
const
|
|
2459
|
-
if(token == undefined)
|
|
2903
|
+
const _insertEntry = ( token, list ) => {
|
|
2904
|
+
if( token == undefined )
|
|
2905
|
+
{
|
|
2906
|
+
return;
|
|
2907
|
+
}
|
|
2460
2908
|
|
|
2461
2909
|
let found = null;
|
|
2462
2910
|
list.forEach( o => {
|
|
2463
|
-
const keys = Object.keys(o);
|
|
2911
|
+
const keys = Object.keys( o );
|
|
2464
2912
|
const key = keys.find( t => t == token );
|
|
2465
|
-
if(key) found = o[ key ];
|
|
2913
|
+
if( key ) found = o[ key ];
|
|
2466
2914
|
} );
|
|
2467
2915
|
|
|
2468
|
-
if(found)
|
|
2469
|
-
|
|
2916
|
+
if( found )
|
|
2917
|
+
{
|
|
2918
|
+
_insertEntry( tokens[ idx++ ], found );
|
|
2470
2919
|
}
|
|
2471
|
-
else
|
|
2920
|
+
else
|
|
2921
|
+
{
|
|
2472
2922
|
let item = {};
|
|
2473
2923
|
item[ token ] = [];
|
|
2474
|
-
const
|
|
2924
|
+
const nextToken = tokens[ idx++ ];
|
|
2475
2925
|
// Check if last token -> add callback
|
|
2476
|
-
if(!
|
|
2926
|
+
if( !nextToken )
|
|
2927
|
+
{
|
|
2477
2928
|
item[ 'callback' ] = options.callback;
|
|
2929
|
+
item[ 'disabled' ] = options.disabled;
|
|
2478
2930
|
item[ 'type' ] = options.type;
|
|
2479
2931
|
item[ 'checked' ] = options.checked;
|
|
2480
2932
|
}
|
|
2481
2933
|
list.push( item );
|
|
2482
|
-
|
|
2934
|
+
_insertEntry( nextToken, item[ token ] );
|
|
2483
2935
|
}
|
|
2484
2936
|
};
|
|
2485
2937
|
|
|
2486
|
-
|
|
2938
|
+
_insertEntry( tokens[idx++], this.items );
|
|
2487
2939
|
|
|
2488
2940
|
// Create elements
|
|
2489
2941
|
|
|
2490
2942
|
for( let item of this.items )
|
|
2491
2943
|
{
|
|
2492
|
-
let key = Object.keys(item)[0];
|
|
2493
|
-
let pKey = key.replace(/\s/g, '').replaceAll('.', '');
|
|
2944
|
+
let key = Object.keys( item )[ 0 ];
|
|
2945
|
+
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
2494
2946
|
|
|
2495
2947
|
// Item already created
|
|
2496
|
-
if( this.root.querySelector("#" + pKey) )
|
|
2948
|
+
if( this.root.querySelector( "#" + pKey ) )
|
|
2949
|
+
{
|
|
2497
2950
|
continue;
|
|
2951
|
+
}
|
|
2498
2952
|
|
|
2499
2953
|
let entry = document.createElement('div');
|
|
2500
2954
|
entry.className = "lexmenuentry";
|
|
2501
2955
|
entry.id = pKey;
|
|
2502
2956
|
entry.innerHTML = "<span>" + key + "</span>";
|
|
2503
|
-
|
|
2957
|
+
entry.tabIndex = "1";
|
|
2958
|
+
|
|
2959
|
+
if( options.position == "left" )
|
|
2960
|
+
{
|
|
2504
2961
|
this.root.prepend( entry );
|
|
2505
2962
|
}
|
|
2506
|
-
else
|
|
2507
|
-
|
|
2963
|
+
else
|
|
2964
|
+
{
|
|
2965
|
+
if( options.position == "right" )
|
|
2966
|
+
{
|
|
2508
2967
|
entry.right = true;
|
|
2509
|
-
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
2971
|
+
{
|
|
2510
2972
|
this.root.lastChild.before( entry );
|
|
2511
2973
|
}
|
|
2512
|
-
else
|
|
2974
|
+
else
|
|
2975
|
+
{
|
|
2513
2976
|
this.root.appendChild( entry );
|
|
2514
2977
|
}
|
|
2515
2978
|
}
|
|
2516
2979
|
|
|
2517
|
-
const
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
const isSubMenu = c.classList.contains('lexcontextmenuentry');
|
|
2523
|
-
var rect = c.getBoundingClientRect();
|
|
2524
|
-
contextmenu.style.left = (isSubMenu ? rect.width : rect.left) + "px";
|
|
2525
|
-
// Entries use css to set top relative to parent
|
|
2526
|
-
contextmenu.style.top = (isSubMenu ? 0 : rect.bottom - 4) + "px";
|
|
2527
|
-
c.appendChild( contextmenu );
|
|
2528
|
-
|
|
2529
|
-
contextmenu.focus();
|
|
2530
|
-
|
|
2531
|
-
rect = contextmenu.getBoundingClientRect();
|
|
2532
|
-
|
|
2533
|
-
for( var i = 0; i < o[k].length; ++i )
|
|
2534
|
-
{
|
|
2535
|
-
const subitem = o[k][i];
|
|
2536
|
-
const subkey = Object.keys(subitem)[0];
|
|
2537
|
-
const hasSubmenu = subitem[ subkey ].length;
|
|
2538
|
-
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2539
|
-
let subentry = document.createElement('div');
|
|
2540
|
-
subentry.className = "lexcontextmenuentry";
|
|
2541
|
-
subentry.className += (i == o[k].length - 1 ? " last" : "");
|
|
2542
|
-
if(subkey == '')
|
|
2543
|
-
subentry.className = " lexseparator";
|
|
2544
|
-
else {
|
|
2545
|
-
|
|
2546
|
-
subentry.id = subkey;
|
|
2547
|
-
let subentrycont = document.createElement('div');
|
|
2548
|
-
subentrycont.innerHTML = "";
|
|
2549
|
-
subentrycont.classList = "lexcontextmenuentrycontainer";
|
|
2550
|
-
subentry.appendChild(subentrycont);
|
|
2551
|
-
const icon = that.icons[ subkey ];
|
|
2552
|
-
if(isCheckbox){
|
|
2553
|
-
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2554
|
-
}else if(icon) {
|
|
2555
|
-
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2556
|
-
}else {
|
|
2557
|
-
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2558
|
-
subentrycont.classList.add( "noicon" );
|
|
2559
|
-
|
|
2560
|
-
}
|
|
2561
|
-
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2562
|
-
}
|
|
2563
|
-
|
|
2564
|
-
let checkbox_input = subentry.querySelector('input');
|
|
2565
|
-
if(checkbox_input) {
|
|
2566
|
-
checkbox_input.checked = subitem.checked ?? false;
|
|
2567
|
-
checkbox_input.addEventListener('change', (e) => {
|
|
2568
|
-
subitem.checked = checkbox_input.checked;
|
|
2569
|
-
const f = subitem[ 'callback' ];
|
|
2570
|
-
if(f) {
|
|
2571
|
-
f.call( this, subitem.checked, subkey, subentry );
|
|
2572
|
-
that.root.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
2573
|
-
}
|
|
2574
|
-
e.stopPropagation();
|
|
2575
|
-
e.stopImmediatePropagation();
|
|
2576
|
-
})
|
|
2577
|
-
}
|
|
2578
|
-
|
|
2579
|
-
contextmenu.appendChild( subentry );
|
|
2580
|
-
|
|
2581
|
-
// Nothing more for separators
|
|
2582
|
-
if(subkey == '') continue;
|
|
2583
|
-
|
|
2584
|
-
contextmenu.addEventListener('keydown', function(e) {
|
|
2585
|
-
e.preventDefault();
|
|
2586
|
-
let short = that.shorts[ subkey ];
|
|
2587
|
-
if(!short) return;
|
|
2588
|
-
// check if it's a letter or other key
|
|
2589
|
-
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2590
|
-
if(short == e.key) {
|
|
2591
|
-
subentry.click()
|
|
2592
|
-
}
|
|
2593
|
-
});
|
|
2594
|
-
|
|
2595
|
-
// Add callback
|
|
2596
|
-
subentry.addEventListener("click", e => {
|
|
2597
|
-
if(checkbox_input) {
|
|
2598
|
-
subitem.checked = !subitem.checked;
|
|
2599
|
-
}
|
|
2600
|
-
const f = subitem[ 'callback' ];
|
|
2601
|
-
if(f) {
|
|
2602
|
-
f.call( this, checkbox_input ? subitem.checked : subkey, checkbox_input ? subkey : subentry );
|
|
2603
|
-
that.root.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
2604
|
-
}
|
|
2605
|
-
e.stopPropagation();
|
|
2606
|
-
e.stopImmediatePropagation();
|
|
2607
|
-
});
|
|
2608
|
-
|
|
2609
|
-
// Add icon if has submenu, else check for shortcut
|
|
2610
|
-
if( !hasSubmenu)
|
|
2611
|
-
{
|
|
2612
|
-
if(that.shorts[ subkey ]) {
|
|
2613
|
-
let shortEl = document.createElement('div');
|
|
2614
|
-
shortEl.className = "lexentryshort";
|
|
2615
|
-
shortEl.innerText = that.shorts[ subkey ];
|
|
2616
|
-
subentry.appendChild( shortEl );
|
|
2617
|
-
}
|
|
2618
|
-
continue;
|
|
2619
|
-
}
|
|
2620
|
-
|
|
2621
|
-
let submenuIcon = document.createElement('a');
|
|
2622
|
-
submenuIcon.className = "fa-solid fa-angle-right fa-xs";
|
|
2623
|
-
subentry.appendChild( submenuIcon );
|
|
2624
|
-
|
|
2625
|
-
subentry.addEventListener("mouseover", e => {
|
|
2626
|
-
if(subentry.built)
|
|
2627
|
-
return;
|
|
2628
|
-
subentry.built = true;
|
|
2629
|
-
create_submenu( subitem, subkey, subentry, ++d );
|
|
2630
|
-
e.stopPropagation();
|
|
2631
|
-
});
|
|
2632
|
-
|
|
2633
|
-
subentry.addEventListener("mouseleave", () => {
|
|
2634
|
-
d = -1; // Reset depth
|
|
2635
|
-
delete subentry.built;
|
|
2636
|
-
contextmenu.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
2637
|
-
});
|
|
2638
|
-
}
|
|
2639
|
-
|
|
2640
|
-
// Set final width
|
|
2641
|
-
contextmenu.style.width = contextmenu.offsetWidth + "px";
|
|
2980
|
+
const _showEntry = () => {
|
|
2981
|
+
this._resetMenubar();
|
|
2982
|
+
entry.classList.add( "selected" );
|
|
2983
|
+
entry.built = true;
|
|
2984
|
+
this._createSubmenu( item, key, entry, -1 );
|
|
2642
2985
|
};
|
|
2643
2986
|
|
|
2644
2987
|
entry.addEventListener("click", () => {
|
|
2645
|
-
|
|
2646
2988
|
const f = item[ 'callback' ];
|
|
2647
|
-
if(f)
|
|
2989
|
+
if( f )
|
|
2990
|
+
{
|
|
2648
2991
|
f.call( this, key, entry );
|
|
2649
2992
|
return;
|
|
2650
2993
|
}
|
|
2651
2994
|
|
|
2652
|
-
|
|
2653
|
-
this.root.querySelectorAll(".lexmenuentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
2654
|
-
entry.classList.add( "selected" );
|
|
2995
|
+
_showEntry();
|
|
2655
2996
|
|
|
2656
|
-
this.
|
|
2657
|
-
create_submenu( item, key, entry, -1 );
|
|
2997
|
+
this.focused = true;
|
|
2658
2998
|
});
|
|
2659
2999
|
|
|
2660
|
-
entry.addEventListener("
|
|
2661
|
-
|
|
2662
|
-
this.
|
|
3000
|
+
entry.addEventListener( "mouseover", (e) => {
|
|
3001
|
+
|
|
3002
|
+
if( this.focused && !entry.built )
|
|
3003
|
+
{
|
|
3004
|
+
_showEntry();
|
|
3005
|
+
}
|
|
3006
|
+
});
|
|
3007
|
+
|
|
3008
|
+
entry.addEventListener("blur", (e) => {
|
|
3009
|
+
|
|
3010
|
+
if( e.relatedTarget && e.relatedTarget.classList.contains( "lexmenubox" ) )
|
|
3011
|
+
{
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
3014
|
+
|
|
3015
|
+
this._resetMenubar();
|
|
2663
3016
|
});
|
|
2664
3017
|
}
|
|
2665
3018
|
}
|
|
@@ -2678,20 +3031,24 @@ class Menubar {
|
|
|
2678
3031
|
* @param {Object} item: parent item
|
|
2679
3032
|
* @param {Array} tokens: split path strings
|
|
2680
3033
|
*/
|
|
2681
|
-
getSubitem(item, tokens) {
|
|
3034
|
+
getSubitem( item, tokens ) {
|
|
2682
3035
|
|
|
2683
3036
|
let subitem = null;
|
|
2684
|
-
let path = tokens[0];
|
|
2685
|
-
for(let i = 0; i < item.length; i++) {
|
|
2686
|
-
if(item[i][path]) {
|
|
3037
|
+
let path = tokens[ 0 ];
|
|
2687
3038
|
|
|
2688
|
-
|
|
2689
|
-
|
|
3039
|
+
for( let i = 0; i < item.length; i++ )
|
|
3040
|
+
{
|
|
3041
|
+
if( item[ i ][ path ] )
|
|
3042
|
+
{
|
|
3043
|
+
if( tokens.length == 1 )
|
|
3044
|
+
{
|
|
3045
|
+
subitem = item[ i ];
|
|
2690
3046
|
return subitem;
|
|
2691
3047
|
}
|
|
2692
|
-
else
|
|
2693
|
-
|
|
2694
|
-
|
|
3048
|
+
else
|
|
3049
|
+
{
|
|
3050
|
+
tokens.splice( 0, 1 );
|
|
3051
|
+
return this.getSubitem( item[ i ][ path ], tokens );
|
|
2695
3052
|
}
|
|
2696
3053
|
|
|
2697
3054
|
}
|
|
@@ -2718,11 +3075,12 @@ class Menubar {
|
|
|
2718
3075
|
setButtonIcon( title, icon, callback, options = {} ) {
|
|
2719
3076
|
|
|
2720
3077
|
const button = this.buttons[ title ];
|
|
2721
|
-
if(button)
|
|
2722
|
-
|
|
3078
|
+
if( button )
|
|
3079
|
+
{
|
|
2723
3080
|
button.querySelector('a').className = "fa-solid" + " " + icon + " lexicon";
|
|
2724
3081
|
}
|
|
2725
|
-
else
|
|
3082
|
+
else
|
|
3083
|
+
{
|
|
2726
3084
|
let button = document.createElement('div');
|
|
2727
3085
|
const disabled = options.disabled ?? false;
|
|
2728
3086
|
button.className = "lexmenubutton" + (disabled ? " disabled" : "");
|
|
@@ -2732,15 +3090,21 @@ class Menubar {
|
|
|
2732
3090
|
button.style.maxHeight = "calc(100% - 10px)";
|
|
2733
3091
|
button.style.alignItems = "center";
|
|
2734
3092
|
|
|
2735
|
-
if(options.float == "right")
|
|
3093
|
+
if( options.float == "right" )
|
|
3094
|
+
{
|
|
2736
3095
|
button.right = true;
|
|
2737
|
-
|
|
3096
|
+
}
|
|
3097
|
+
|
|
3098
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
3099
|
+
{
|
|
2738
3100
|
this.root.lastChild.before( button );
|
|
2739
3101
|
}
|
|
2740
|
-
else if(options.float == "left")
|
|
2741
|
-
|
|
3102
|
+
else if( options.float == "left" )
|
|
3103
|
+
{
|
|
3104
|
+
this.root.prepend( button );
|
|
2742
3105
|
}
|
|
2743
|
-
else
|
|
3106
|
+
else
|
|
3107
|
+
{
|
|
2744
3108
|
this.root.appendChild( button );
|
|
2745
3109
|
}
|
|
2746
3110
|
|
|
@@ -2760,11 +3124,12 @@ class Menubar {
|
|
|
2760
3124
|
|
|
2761
3125
|
setButtonImage( title, src, callback, options = {} ) {
|
|
2762
3126
|
const button = this.buttons[ title ];
|
|
2763
|
-
if(button)
|
|
2764
|
-
|
|
3127
|
+
if( button )
|
|
3128
|
+
{
|
|
2765
3129
|
button.querySelector('a').className = "fa-solid" + " " + icon + " lexicon";
|
|
2766
3130
|
}
|
|
2767
|
-
else
|
|
3131
|
+
else
|
|
3132
|
+
{
|
|
2768
3133
|
let button = document.createElement('div');
|
|
2769
3134
|
const disabled = options.disabled ?? false;
|
|
2770
3135
|
button.className = "lexmenubutton" + (disabled ? " disabled" : "");
|
|
@@ -2773,15 +3138,21 @@ class Menubar {
|
|
|
2773
3138
|
button.style.padding = "5px";
|
|
2774
3139
|
button.style.alignItems = "center";
|
|
2775
3140
|
|
|
2776
|
-
if(options.float == "right")
|
|
3141
|
+
if( options.float == "right" )
|
|
3142
|
+
{
|
|
2777
3143
|
button.right = true;
|
|
2778
|
-
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
3147
|
+
{
|
|
2779
3148
|
this.root.lastChild.before( button );
|
|
2780
3149
|
}
|
|
2781
|
-
else if(options.float == "left")
|
|
2782
|
-
|
|
3150
|
+
else if( options.float == "left" )
|
|
3151
|
+
{
|
|
3152
|
+
this.root.prepend( button );
|
|
2783
3153
|
}
|
|
2784
|
-
else
|
|
3154
|
+
else
|
|
3155
|
+
{
|
|
2785
3156
|
this.root.appendChild( button );
|
|
2786
3157
|
}
|
|
2787
3158
|
|
|
@@ -2894,90 +3265,323 @@ LX.Menubar = Menubar;
|
|
|
2894
3265
|
|
|
2895
3266
|
class SideBar {
|
|
2896
3267
|
|
|
2897
|
-
|
|
3268
|
+
/**
|
|
3269
|
+
* @param {Object} options
|
|
3270
|
+
* filter: Add search bar to filter entries [false]
|
|
3271
|
+
* skipHeader: Do not use sidebar header [false]
|
|
3272
|
+
* headerImg: Image to be shown as avatar
|
|
3273
|
+
* headerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3274
|
+
* headerTitle: Header title
|
|
3275
|
+
* headerSubtitle: Header subtitle
|
|
3276
|
+
* skipFooter: Do not use sidebar footer [false]
|
|
3277
|
+
* footerImg: Image to be shown as avatar
|
|
3278
|
+
* footerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3279
|
+
* footerTitle: Footer title
|
|
3280
|
+
* footerSubtitle: Footer subtitle
|
|
3281
|
+
* collapsable: Sidebar can toggle between collapsed/expanded [true]
|
|
3282
|
+
* collapseToIcons: When Sidebar collapses, icons remains visible [true]
|
|
3283
|
+
* onHeaderPressed: Function to call when header is pressed
|
|
3284
|
+
* onFooterPressed: Function to call when footer is pressed
|
|
3285
|
+
*/
|
|
3286
|
+
|
|
3287
|
+
constructor( options = {} ) {
|
|
2898
3288
|
|
|
2899
3289
|
this.root = document.createElement( 'div' );
|
|
2900
3290
|
this.root.className = "lexsidebar";
|
|
2901
3291
|
|
|
2902
|
-
this.
|
|
2903
|
-
this.
|
|
2904
|
-
this.
|
|
3292
|
+
this.collapsable = options.collapsable ?? true;
|
|
3293
|
+
this._collapseWidth = ( options.collapseToIcons ?? true ) ? "58px" : "0px";
|
|
3294
|
+
this.collapsed = false;
|
|
3295
|
+
|
|
3296
|
+
this.filterString = "";
|
|
3297
|
+
|
|
3298
|
+
doAsync( () => {
|
|
3299
|
+
|
|
3300
|
+
this.root.parentElement.ogWidth = this.root.parentElement.style.width;
|
|
3301
|
+
this.root.parentElement.style.transition = "width 0.25s ease-out";
|
|
3302
|
+
|
|
3303
|
+
this.resizeObserver = new ResizeObserver( entries => {
|
|
3304
|
+
for ( const entry of entries )
|
|
3305
|
+
{
|
|
3306
|
+
this.siblingArea.setSize( [ "calc(100% - " + ( entry.contentRect.width ) + "px )", null ] );
|
|
3307
|
+
}
|
|
3308
|
+
});
|
|
3309
|
+
|
|
3310
|
+
}, 10 );
|
|
3311
|
+
|
|
3312
|
+
// This account for header, footer and all inner paddings
|
|
3313
|
+
let contentOffset = 32;
|
|
3314
|
+
|
|
3315
|
+
// Header
|
|
3316
|
+
if( !( options.skipHeader ?? false ) )
|
|
3317
|
+
{
|
|
3318
|
+
this.header = document.createElement( 'div' );
|
|
3319
|
+
this.header.className = "lexsidebarheader";
|
|
3320
|
+
this.root.appendChild( this.header );
|
|
3321
|
+
|
|
3322
|
+
this.header.addEventListener( "click", e => {
|
|
3323
|
+
if( this.collapsed )
|
|
3324
|
+
{
|
|
3325
|
+
e.preventDefault();
|
|
3326
|
+
e.stopPropagation();
|
|
3327
|
+
this.toggleCollapsed();
|
|
3328
|
+
}
|
|
3329
|
+
else if( options.onHeaderPressed )
|
|
3330
|
+
{
|
|
3331
|
+
options.onHeaderPressed( e );
|
|
3332
|
+
}
|
|
3333
|
+
} );
|
|
3334
|
+
|
|
3335
|
+
const avatar = document.createElement( 'span' );
|
|
3336
|
+
avatar.className = "lexavatar";
|
|
3337
|
+
this.header.appendChild( avatar );
|
|
3338
|
+
|
|
3339
|
+
if( options.headerImage )
|
|
3340
|
+
{
|
|
3341
|
+
const avatarImg = document.createElement( 'img' );
|
|
3342
|
+
avatarImg.src = options.headerImage;
|
|
3343
|
+
avatar.appendChild( avatarImg );
|
|
3344
|
+
}
|
|
3345
|
+
else if( options.headerIcon )
|
|
3346
|
+
{
|
|
3347
|
+
const avatarIcon = LX.makeIcon( options.headerIcon );
|
|
3348
|
+
avatar.appendChild( avatarIcon );
|
|
3349
|
+
}
|
|
3350
|
+
|
|
3351
|
+
// Info
|
|
3352
|
+
{
|
|
3353
|
+
const info = document.createElement( 'div' );
|
|
3354
|
+
this.header.appendChild( info );
|
|
3355
|
+
|
|
3356
|
+
const infoText = document.createElement( 'span' );
|
|
3357
|
+
infoText.innerHTML = options.headerTitle ?? "";
|
|
3358
|
+
info.appendChild( infoText );
|
|
3359
|
+
|
|
3360
|
+
const infoSubtext = document.createElement( 'span' );
|
|
3361
|
+
infoSubtext.innerHTML = options.headerSubtitle ?? "";
|
|
3362
|
+
info.appendChild( infoSubtext );
|
|
3363
|
+
}
|
|
3364
|
+
|
|
3365
|
+
if( this.collapsable )
|
|
3366
|
+
{
|
|
3367
|
+
const icon = LX.makeIcon( "Sidebar", "Toggle Sidebar" );
|
|
3368
|
+
this.header.appendChild( icon );
|
|
3369
|
+
|
|
3370
|
+
icon.addEventListener( "click", (e) => {
|
|
3371
|
+
e.preventDefault();
|
|
3372
|
+
e.stopPropagation();
|
|
3373
|
+
this.toggleCollapsed();
|
|
3374
|
+
} );
|
|
3375
|
+
}
|
|
3376
|
+
|
|
3377
|
+
contentOffset += 52;
|
|
3378
|
+
}
|
|
3379
|
+
|
|
3380
|
+
// Entry filter
|
|
3381
|
+
if( !( options.filter ?? false ) )
|
|
3382
|
+
{
|
|
3383
|
+
const panel = new Panel();
|
|
3384
|
+
panel.addText(null, "", (value, event) => {
|
|
3385
|
+
this.filterString = value;
|
|
3386
|
+
this.update();
|
|
3387
|
+
}, { placeholder: "Search...", icon: "fa-solid fa-magnifying-glass" });
|
|
3388
|
+
this.filter = panel.root.childNodes[ 0 ];
|
|
3389
|
+
this.root.appendChild( this.filter );
|
|
3390
|
+
contentOffset += 31;
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3393
|
+
// Content
|
|
3394
|
+
{
|
|
3395
|
+
this.content = document.createElement( 'div' );
|
|
3396
|
+
this.content.className = "lexsidebarcontent";
|
|
3397
|
+
this.root.appendChild( this.content );
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
// Footer
|
|
3401
|
+
if( !( options.skipFooter ?? false ) )
|
|
3402
|
+
{
|
|
3403
|
+
this.footer = document.createElement( 'div' );
|
|
3404
|
+
this.footer.className = "lexsidebarfooter";
|
|
3405
|
+
this.root.appendChild( this.footer );
|
|
3406
|
+
|
|
3407
|
+
this.footer.addEventListener( "click", e => {
|
|
3408
|
+
if( options.onFooterPressed )
|
|
3409
|
+
{
|
|
3410
|
+
options.onFooterPressed( e );
|
|
3411
|
+
}
|
|
3412
|
+
} );
|
|
3413
|
+
|
|
3414
|
+
const avatar = document.createElement( 'span' );
|
|
3415
|
+
avatar.className = "lexavatar";
|
|
3416
|
+
this.footer.appendChild( avatar );
|
|
3417
|
+
|
|
3418
|
+
if( options.footerImage )
|
|
3419
|
+
{
|
|
3420
|
+
const avatarImg = document.createElement( 'img' );
|
|
3421
|
+
avatarImg.src = options.footerImage;
|
|
3422
|
+
avatar.appendChild( avatarImg );
|
|
3423
|
+
}
|
|
3424
|
+
else if( options.footerIcon )
|
|
3425
|
+
{
|
|
3426
|
+
const avatarIcon = LX.makeIcon( options.footerIcon );
|
|
3427
|
+
avatar.appendChild( avatarIcon );
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
// Info
|
|
3431
|
+
{
|
|
3432
|
+
const info = document.createElement( 'div' );
|
|
3433
|
+
this.footer.appendChild( info );
|
|
3434
|
+
|
|
3435
|
+
const infoText = document.createElement( 'span' );
|
|
3436
|
+
infoText.innerHTML = options.footerTitle ?? "";
|
|
3437
|
+
info.appendChild( infoText );
|
|
3438
|
+
|
|
3439
|
+
const infoSubtext = document.createElement( 'span' );
|
|
3440
|
+
infoSubtext.innerHTML = options.footerSubtitle ?? "";
|
|
3441
|
+
info.appendChild( infoSubtext );
|
|
3442
|
+
}
|
|
3443
|
+
|
|
3444
|
+
const icon = LX.makeIcon( "MenuArrows" );
|
|
3445
|
+
this.footer.appendChild( icon );
|
|
3446
|
+
|
|
3447
|
+
contentOffset += 52;
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3450
|
+
// Set width depending on header/footer
|
|
3451
|
+
this.content.style.height = `calc(100% - ${ contentOffset }px)`;
|
|
2905
3452
|
|
|
2906
3453
|
this.items = [ ];
|
|
3454
|
+
this.icons = { };
|
|
3455
|
+
this.groups = { };
|
|
2907
3456
|
}
|
|
2908
3457
|
|
|
2909
3458
|
/**
|
|
2910
|
-
* @method
|
|
2911
|
-
* @param {
|
|
2912
|
-
* callback: Function to call on each item
|
|
2913
|
-
* bottom: Bool to set item at the bottom as helper button (not selectable)
|
|
2914
|
-
* className: Add class to the entry DOM element
|
|
3459
|
+
* @method toggleCollapsed
|
|
3460
|
+
* @param {Boolean} force: Force collapsed state
|
|
2915
3461
|
*/
|
|
2916
3462
|
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
if( options.constructor == Function )
|
|
2920
|
-
options = { callback: options };
|
|
3463
|
+
toggleCollapsed( force ) {
|
|
2921
3464
|
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
if( this.items.findIndex( (v, i) => v.key == pKey ) > -1 )
|
|
3465
|
+
if( !this.collapsable )
|
|
2925
3466
|
{
|
|
2926
|
-
console.warn( `'${key}' already created in Sidebar` );
|
|
2927
3467
|
return;
|
|
2928
3468
|
}
|
|
2929
3469
|
|
|
2930
|
-
|
|
2931
|
-
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
2932
|
-
entry.id = pKey;
|
|
3470
|
+
this.collapsed = force ?? !this.collapsed;
|
|
2933
3471
|
|
|
2934
|
-
if(
|
|
3472
|
+
if( this.collapsed )
|
|
2935
3473
|
{
|
|
2936
|
-
this.
|
|
3474
|
+
this.root.classList.add( "collapsing" );
|
|
3475
|
+
this.root.parentElement.style.width = this._collapseWidth;
|
|
2937
3476
|
}
|
|
2938
3477
|
else
|
|
2939
3478
|
{
|
|
2940
|
-
this.root.
|
|
3479
|
+
this.root.classList.remove( "collapsing" );
|
|
3480
|
+
this.root.classList.remove( "collapsed" );
|
|
3481
|
+
this.root.parentElement.style.width = this.root.parentElement.ogWidth;
|
|
2941
3482
|
}
|
|
2942
3483
|
|
|
2943
|
-
|
|
2944
|
-
|
|
3484
|
+
if( !this.resizeObserver )
|
|
3485
|
+
{
|
|
3486
|
+
throw( "Wait until ResizeObserver has been created!" );
|
|
3487
|
+
}
|
|
2945
3488
|
|
|
2946
|
-
|
|
2947
|
-
button.innerHTML = "<i class='"+ (options.icon ?? "") + "'></i>";
|
|
2948
|
-
entry.appendChild( button );
|
|
3489
|
+
this.resizeObserver.observe( this.root.parentElement );
|
|
2949
3490
|
|
|
2950
|
-
|
|
2951
|
-
desc.className = 'lexsidebarentrydesc';
|
|
2952
|
-
desc.innerHTML = key;
|
|
2953
|
-
entry.appendChild( desc );
|
|
3491
|
+
doAsync( () => {
|
|
2954
3492
|
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
desc.style.display = "unset";
|
|
2958
|
-
}, 100 );
|
|
2959
|
-
});
|
|
3493
|
+
this.root.classList.toggle( "collapsed", this.collapsed );
|
|
3494
|
+
this.resizeObserver.unobserve( this.root.parentElement );
|
|
2960
3495
|
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
desc.style.display = "none";
|
|
2964
|
-
}, 100 );
|
|
2965
|
-
});
|
|
3496
|
+
}, 250 );
|
|
3497
|
+
}
|
|
2966
3498
|
|
|
2967
|
-
|
|
3499
|
+
/**
|
|
3500
|
+
* @method separator
|
|
3501
|
+
*/
|
|
3502
|
+
|
|
3503
|
+
separator() {
|
|
2968
3504
|
|
|
2969
|
-
|
|
2970
|
-
if( f ) f.call( this, key, entry );
|
|
3505
|
+
this.currentGroup = null;
|
|
2971
3506
|
|
|
2972
|
-
|
|
2973
|
-
|
|
3507
|
+
this.add( "" );
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
/**
|
|
3511
|
+
* @method group
|
|
3512
|
+
* @param {String} groupName
|
|
3513
|
+
* @param {Object} action: { icon, callback }
|
|
3514
|
+
*/
|
|
3515
|
+
|
|
3516
|
+
group( groupName, action ) {
|
|
3517
|
+
|
|
3518
|
+
this.currentGroup = groupName;
|
|
3519
|
+
|
|
3520
|
+
this.groups[ groupName ] = action;
|
|
3521
|
+
}
|
|
3522
|
+
|
|
3523
|
+
/**
|
|
3524
|
+
* @method add
|
|
3525
|
+
* @param {String} path
|
|
3526
|
+
* @param {Object} options:
|
|
3527
|
+
* callback: Function to call on each item
|
|
3528
|
+
* icon: Entry icon
|
|
3529
|
+
* collapsable: Add entry as a collapsable section
|
|
3530
|
+
* className: Add class to the entry DOM element
|
|
3531
|
+
*/
|
|
3532
|
+
|
|
3533
|
+
add( path, options = {} ) {
|
|
3534
|
+
|
|
3535
|
+
if( options.constructor == Function )
|
|
3536
|
+
{
|
|
3537
|
+
options = { callback: options };
|
|
3538
|
+
}
|
|
3539
|
+
|
|
3540
|
+
// Process path
|
|
3541
|
+
const tokens = path.split( "/" );
|
|
3542
|
+
|
|
3543
|
+
// Assign icons and shortcuts to last token in path
|
|
3544
|
+
const lastPath = tokens[tokens.length - 1];
|
|
3545
|
+
this.icons[ lastPath ] = options.icon;
|
|
3546
|
+
|
|
3547
|
+
let idx = 0;
|
|
3548
|
+
|
|
3549
|
+
const _insertEntry = ( token, list ) => {
|
|
3550
|
+
|
|
3551
|
+
if( token == undefined )
|
|
2974
3552
|
{
|
|
2975
|
-
|
|
2976
|
-
entry.classList.add( "selected" );
|
|
3553
|
+
return;
|
|
2977
3554
|
}
|
|
2978
|
-
});
|
|
2979
3555
|
|
|
2980
|
-
|
|
3556
|
+
let found = null;
|
|
3557
|
+
list.forEach( o => {
|
|
3558
|
+
const keys = Object.keys( o );
|
|
3559
|
+
const key = keys.find( t => t == token );
|
|
3560
|
+
if( key ) found = o[ key ];
|
|
3561
|
+
} );
|
|
3562
|
+
|
|
3563
|
+
if( found )
|
|
3564
|
+
{
|
|
3565
|
+
_insertEntry( tokens[ idx++ ], found );
|
|
3566
|
+
}
|
|
3567
|
+
else
|
|
3568
|
+
{
|
|
3569
|
+
let item = {};
|
|
3570
|
+
item[ token ] = [];
|
|
3571
|
+
const nextToken = tokens[ idx++ ];
|
|
3572
|
+
// Check if last token -> add callback
|
|
3573
|
+
if( !nextToken )
|
|
3574
|
+
{
|
|
3575
|
+
item[ 'callback' ] = options.callback;
|
|
3576
|
+
item[ 'group' ] = this.currentGroup;
|
|
3577
|
+
item[ 'options' ] = options;
|
|
3578
|
+
}
|
|
3579
|
+
list.push( item );
|
|
3580
|
+
_insertEntry( nextToken, item[ token ] );
|
|
3581
|
+
}
|
|
3582
|
+
};
|
|
3583
|
+
|
|
3584
|
+
_insertEntry( tokens[idx++], this.items );
|
|
2981
3585
|
}
|
|
2982
3586
|
|
|
2983
3587
|
/**
|
|
@@ -2994,7 +3598,267 @@ class SideBar {
|
|
|
2994
3598
|
if( !entry )
|
|
2995
3599
|
return;
|
|
2996
3600
|
|
|
2997
|
-
entry.
|
|
3601
|
+
entry.dom.click();
|
|
3602
|
+
}
|
|
3603
|
+
|
|
3604
|
+
update() {
|
|
3605
|
+
|
|
3606
|
+
// Reset first
|
|
3607
|
+
|
|
3608
|
+
this.content.innerHTML = "";
|
|
3609
|
+
|
|
3610
|
+
for( let item of this.items )
|
|
3611
|
+
{
|
|
3612
|
+
delete item.dom;
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
for( let item of this.items )
|
|
3616
|
+
{
|
|
3617
|
+
const options = item.options ?? { };
|
|
3618
|
+
|
|
3619
|
+
// Item already created
|
|
3620
|
+
if( item.dom )
|
|
3621
|
+
{
|
|
3622
|
+
continue;
|
|
3623
|
+
}
|
|
3624
|
+
|
|
3625
|
+
let key = Object.keys( item )[ 0 ];
|
|
3626
|
+
|
|
3627
|
+
if( this.filterString.length && !key.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3628
|
+
{
|
|
3629
|
+
continue;
|
|
3630
|
+
}
|
|
3631
|
+
|
|
3632
|
+
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3633
|
+
let currentGroup = null;
|
|
3634
|
+
|
|
3635
|
+
let entry = document.createElement( 'div' );
|
|
3636
|
+
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
3637
|
+
entry.id = item.name = pKey;
|
|
3638
|
+
|
|
3639
|
+
if( item.group )
|
|
3640
|
+
{
|
|
3641
|
+
const pGroupKey = item.group.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3642
|
+
currentGroup = this.content.querySelector( "#" + pGroupKey );
|
|
3643
|
+
|
|
3644
|
+
if( !currentGroup )
|
|
3645
|
+
{
|
|
3646
|
+
currentGroup = document.createElement( 'div' );
|
|
3647
|
+
currentGroup.id = pGroupKey;
|
|
3648
|
+
currentGroup.className = "lexsidebargroup";
|
|
3649
|
+
this.content.appendChild( currentGroup );
|
|
3650
|
+
|
|
3651
|
+
let groupEntry = document.createElement( 'div' );
|
|
3652
|
+
groupEntry.className = "lexsidebargrouptitle";
|
|
3653
|
+
currentGroup.appendChild( groupEntry );
|
|
3654
|
+
|
|
3655
|
+
let groupLabel = document.createElement( 'div' );
|
|
3656
|
+
groupLabel.innerHTML = item.group;
|
|
3657
|
+
groupEntry.appendChild( groupLabel );
|
|
3658
|
+
|
|
3659
|
+
if( this.groups[ item.group ] != null )
|
|
3660
|
+
{
|
|
3661
|
+
let groupAction = document.createElement( 'a' );
|
|
3662
|
+
groupAction.className = ( this.groups[ item.group ].icon ?? "" ) + " lexicon";
|
|
3663
|
+
groupEntry.appendChild( groupAction );
|
|
3664
|
+
groupAction.addEventListener( "click", (e) => {
|
|
3665
|
+
if( this.groups[ item.group ].callback )
|
|
3666
|
+
{
|
|
3667
|
+
this.groups[ item.group ].callback( item.group, e );
|
|
3668
|
+
}
|
|
3669
|
+
} );
|
|
3670
|
+
}
|
|
3671
|
+
|
|
3672
|
+
}
|
|
3673
|
+
else if( !currentGroup.classList.contains( "lexsidebargroup" ) )
|
|
3674
|
+
{
|
|
3675
|
+
throw( "Bad id: " + item.group );
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
|
|
3679
|
+
if( pKey == "" )
|
|
3680
|
+
{
|
|
3681
|
+
let separatorDom = document.createElement( 'div' );
|
|
3682
|
+
separatorDom.className = "lexsidebarseparator";
|
|
3683
|
+
this.content.appendChild( separatorDom );
|
|
3684
|
+
continue;
|
|
3685
|
+
}
|
|
3686
|
+
|
|
3687
|
+
if( this.collapseContainer )
|
|
3688
|
+
{
|
|
3689
|
+
this.collapseContainer.appendChild( entry );
|
|
3690
|
+
|
|
3691
|
+
this.collapseQueue--;
|
|
3692
|
+
if( !this.collapseQueue )
|
|
3693
|
+
{
|
|
3694
|
+
delete this.collapseContainer;
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
else if( currentGroup )
|
|
3698
|
+
{
|
|
3699
|
+
currentGroup.appendChild( entry );
|
|
3700
|
+
}
|
|
3701
|
+
else
|
|
3702
|
+
{
|
|
3703
|
+
this.content.appendChild( entry );
|
|
3704
|
+
}
|
|
3705
|
+
|
|
3706
|
+
let itemDom = document.createElement( 'div' );
|
|
3707
|
+
entry.appendChild( itemDom );
|
|
3708
|
+
item.dom = entry;
|
|
3709
|
+
|
|
3710
|
+
if( options.type == "checkbox" )
|
|
3711
|
+
{
|
|
3712
|
+
item.value = options.value ?? false;
|
|
3713
|
+
const panel = new Panel();
|
|
3714
|
+
item.checkbox = panel.addCheckbox(null, item.value, (value, event) => {
|
|
3715
|
+
event.preventDefault();
|
|
3716
|
+
event.stopPropagation();
|
|
3717
|
+
const f = options.callback;
|
|
3718
|
+
item.value = value;
|
|
3719
|
+
if( f ) f.call( this, key, value, event );
|
|
3720
|
+
}, { label: key, signal: ( "@checkbox_" + key ) });
|
|
3721
|
+
itemDom.appendChild( panel.root.childNodes[ 0 ] );
|
|
3722
|
+
}
|
|
3723
|
+
else
|
|
3724
|
+
{
|
|
3725
|
+
if( options.icon )
|
|
3726
|
+
{
|
|
3727
|
+
let itemIcon = document.createElement( 'i' );
|
|
3728
|
+
itemIcon.className = options.icon;
|
|
3729
|
+
itemDom.appendChild( itemIcon );
|
|
3730
|
+
}
|
|
3731
|
+
|
|
3732
|
+
let itemName = document.createElement( 'a' );
|
|
3733
|
+
itemName.innerHTML = key;
|
|
3734
|
+
itemDom.appendChild( itemName );
|
|
3735
|
+
}
|
|
3736
|
+
|
|
3737
|
+
entry.addEventListener("click", ( e ) => {
|
|
3738
|
+
if( e.target && e.target.classList.contains( "lexcheckbox" ) )
|
|
3739
|
+
{
|
|
3740
|
+
return;
|
|
3741
|
+
}
|
|
3742
|
+
|
|
3743
|
+
if( options.collapsable )
|
|
3744
|
+
{
|
|
3745
|
+
itemDom.querySelector( ".collapser" ).click();
|
|
3746
|
+
}
|
|
3747
|
+
else
|
|
3748
|
+
{
|
|
3749
|
+
const f = options.callback;
|
|
3750
|
+
if( f ) f.call( this, key, item.value, e );
|
|
3751
|
+
|
|
3752
|
+
if( item.checkbox )
|
|
3753
|
+
{
|
|
3754
|
+
item.value = !item.value;
|
|
3755
|
+
item.checkbox.set( item.value, true );
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
// Manage selected
|
|
3760
|
+
this.root.querySelectorAll(".lexsidebarentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
3761
|
+
entry.classList.add( "selected" );
|
|
3762
|
+
});
|
|
3763
|
+
|
|
3764
|
+
if( options.action )
|
|
3765
|
+
{
|
|
3766
|
+
const actionIcon = LX.makeIcon( options.action.icon ?? "MoreHorizontal", options.action.name );
|
|
3767
|
+
itemDom.appendChild( actionIcon );
|
|
3768
|
+
|
|
3769
|
+
actionIcon.addEventListener( "click", (e) => {
|
|
3770
|
+
e.preventDefault();
|
|
3771
|
+
e.stopImmediatePropagation();
|
|
3772
|
+
const f = options.action.callback;
|
|
3773
|
+
if( f ) f.call( this, key, e );
|
|
3774
|
+
} );
|
|
3775
|
+
}
|
|
3776
|
+
else if( options.collapsable )
|
|
3777
|
+
{
|
|
3778
|
+
const collapsableContent = document.createElement( 'div' );
|
|
3779
|
+
Object.assign( collapsableContent.style, { width: "100%", display: "none" } );
|
|
3780
|
+
LX.makeCollapsible( itemDom, collapsableContent, currentGroup ?? this.content );
|
|
3781
|
+
this.collapseQueue = options.collapsable;
|
|
3782
|
+
this.collapseContainer = collapsableContent;
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
let desc = document.createElement( 'span' );
|
|
3786
|
+
desc.className = 'lexsidebarentrydesc';
|
|
3787
|
+
desc.innerHTML = key;
|
|
3788
|
+
entry.appendChild( desc );
|
|
3789
|
+
|
|
3790
|
+
itemDom.addEventListener("mouseenter", () => {
|
|
3791
|
+
setTimeout( () => {
|
|
3792
|
+
desc.style.display = "unset";
|
|
3793
|
+
}, 150 );
|
|
3794
|
+
});
|
|
3795
|
+
|
|
3796
|
+
itemDom.addEventListener("mouseleave", () => {
|
|
3797
|
+
setTimeout( () => {
|
|
3798
|
+
desc.style.display = "none";
|
|
3799
|
+
}, 150 );
|
|
3800
|
+
});
|
|
3801
|
+
|
|
3802
|
+
// Subentries
|
|
3803
|
+
if( !item[ key ].length )
|
|
3804
|
+
{
|
|
3805
|
+
continue;
|
|
3806
|
+
}
|
|
3807
|
+
|
|
3808
|
+
let subentryContainer = document.createElement( 'div' );
|
|
3809
|
+
subentryContainer.className = "lexsidebarsubentrycontainer";
|
|
3810
|
+
|
|
3811
|
+
if( currentGroup )
|
|
3812
|
+
{
|
|
3813
|
+
currentGroup.appendChild( subentryContainer );
|
|
3814
|
+
}
|
|
3815
|
+
else
|
|
3816
|
+
{
|
|
3817
|
+
this.content.appendChild( subentryContainer );
|
|
3818
|
+
}
|
|
3819
|
+
|
|
3820
|
+
for( let i = 0; i < item[ key ].length; ++i )
|
|
3821
|
+
{
|
|
3822
|
+
const subitem = item[ key ][ i ];
|
|
3823
|
+
const suboptions = subitem.options ?? {};
|
|
3824
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
3825
|
+
|
|
3826
|
+
if( this.filterString.length && !subkey.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3827
|
+
{
|
|
3828
|
+
continue;
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3831
|
+
let subentry = document.createElement( 'div' );
|
|
3832
|
+
subentry.innerHTML = `<span>${ subkey }</span>`;
|
|
3833
|
+
|
|
3834
|
+
if( suboptions.action )
|
|
3835
|
+
{
|
|
3836
|
+
const actionIcon = LX.makeIcon( suboptions.action.icon ?? "MoreHorizontal", suboptions.action.name );
|
|
3837
|
+
subentry.appendChild( actionIcon );
|
|
3838
|
+
|
|
3839
|
+
actionIcon.addEventListener( "click", (e) => {
|
|
3840
|
+
e.preventDefault();
|
|
3841
|
+
e.stopImmediatePropagation();
|
|
3842
|
+
const f = suboptions.action.callback;
|
|
3843
|
+
if( f ) f.call( this, subkey, e );
|
|
3844
|
+
} );
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
subentry.className = "lexsidebarentry";
|
|
3848
|
+
subentry.id = subkey;
|
|
3849
|
+
subentryContainer.appendChild( subentry );
|
|
3850
|
+
|
|
3851
|
+
subentry.addEventListener("click", (e) => {
|
|
3852
|
+
|
|
3853
|
+
const f = suboptions.callback;
|
|
3854
|
+
if( f ) f.call( this, subkey, subentry, e );
|
|
3855
|
+
|
|
3856
|
+
// Manage selected
|
|
3857
|
+
this.root.querySelectorAll(".lexsidebarentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
3858
|
+
entry.classList.add( "selected" );
|
|
3859
|
+
});
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
2998
3862
|
}
|
|
2999
3863
|
};
|
|
3000
3864
|
|
|
@@ -3013,30 +3877,32 @@ class Widget {
|
|
|
3013
3877
|
static DROPDOWN = 4;
|
|
3014
3878
|
static CHECKBOX = 5;
|
|
3015
3879
|
static TOGGLE = 6;
|
|
3016
|
-
static
|
|
3017
|
-
static
|
|
3018
|
-
static
|
|
3019
|
-
static
|
|
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
|
|
3880
|
+
static RADIO = 7;
|
|
3881
|
+
static COLOR = 8;
|
|
3882
|
+
static RANGE = 9;
|
|
3883
|
+
static NUMBER = 10;
|
|
3884
|
+
static TITLE = 11;
|
|
3885
|
+
static VECTOR = 12;
|
|
3886
|
+
static TREE = 13;
|
|
3887
|
+
static PROGRESS = 14;
|
|
3888
|
+
static FILE = 15;
|
|
3889
|
+
static LAYERS = 16;
|
|
3890
|
+
static ARRAY = 17;
|
|
3891
|
+
static LIST = 18;
|
|
3892
|
+
static TAGS = 19;
|
|
3893
|
+
static CURVE = 20;
|
|
3894
|
+
static CARD = 21;
|
|
3895
|
+
static IMAGE = 22;
|
|
3896
|
+
static CONTENT = 23;
|
|
3897
|
+
static CUSTOM = 24;
|
|
3898
|
+
static SEPARATOR = 25;
|
|
3899
|
+
static KNOB = 26;
|
|
3900
|
+
static SIZE = 27;
|
|
3901
|
+
static PAD = 28;
|
|
3902
|
+
static FORM = 29;
|
|
3903
|
+
static DIAL = 30;
|
|
3904
|
+
static COUNTER = 31;
|
|
3905
|
+
static TABLE = 32;
|
|
3040
3906
|
|
|
3041
3907
|
static NO_CONTEXT_TYPES = [
|
|
3042
3908
|
Widget.BUTTON,
|
|
@@ -3064,7 +3930,9 @@ class Widget {
|
|
|
3064
3930
|
set( value, skipCallback = false, signalName = "" ) {
|
|
3065
3931
|
|
|
3066
3932
|
if( this.onSetValue )
|
|
3933
|
+
{
|
|
3067
3934
|
return this.onSetValue( value, skipCallback );
|
|
3935
|
+
}
|
|
3068
3936
|
|
|
3069
3937
|
console.warn("Can't set value of " + this.typeName());
|
|
3070
3938
|
}
|
|
@@ -3103,14 +3971,17 @@ class Widget {
|
|
|
3103
3971
|
|
|
3104
3972
|
typeName() {
|
|
3105
3973
|
|
|
3106
|
-
switch( this.type )
|
|
3974
|
+
switch( this.type )
|
|
3975
|
+
{
|
|
3107
3976
|
case Widget.TEXT: return "Text";
|
|
3108
3977
|
case Widget.TEXTAREA: return "TextArea";
|
|
3109
3978
|
case Widget.BUTTON: return "Button";
|
|
3110
3979
|
case Widget.DROPDOWN: return "Dropdown";
|
|
3111
3980
|
case Widget.CHECKBOX: return "Checkbox";
|
|
3112
3981
|
case Widget.TOGGLE: return "Toggle";
|
|
3982
|
+
case Widget.RADIO: return "Radio";
|
|
3113
3983
|
case Widget.COLOR: return "Color";
|
|
3984
|
+
case Widget.RANGE: return "Range";
|
|
3114
3985
|
case Widget.NUMBER: return "Number";
|
|
3115
3986
|
case Widget.VECTOR: return "Vector";
|
|
3116
3987
|
case Widget.TREE: return "Tree";
|
|
@@ -3188,11 +4059,12 @@ function ADD_CUSTOM_WIDGET( custom_widget_name, options = {} )
|
|
|
3188
4059
|
buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
|
|
3189
4060
|
|
|
3190
4061
|
let buttonEl = this.addButton(null, buttonName, (value, event) => {
|
|
3191
|
-
|
|
3192
|
-
|
|
4062
|
+
if( instance )
|
|
4063
|
+
{
|
|
3193
4064
|
element.querySelector(".lexcustomitems").toggleAttribute('hidden');
|
|
3194
4065
|
}
|
|
3195
|
-
else
|
|
4066
|
+
else
|
|
4067
|
+
{
|
|
3196
4068
|
addContextMenu(null, event, c => {
|
|
3197
4069
|
c.add("New " + custom_widget_name, () => {
|
|
3198
4070
|
instance = {};
|
|
@@ -3379,16 +4251,20 @@ class NodeTree {
|
|
|
3379
4251
|
|
|
3380
4252
|
// Add or remove
|
|
3381
4253
|
const idx = this.selected.indexOf( node );
|
|
3382
|
-
if( idx > -1 )
|
|
4254
|
+
if( idx > -1 )
|
|
4255
|
+
{
|
|
3383
4256
|
item.classList.remove( 'selected' );
|
|
3384
4257
|
this.selected.splice( idx, 1 );
|
|
3385
|
-
}
|
|
4258
|
+
}
|
|
4259
|
+
else
|
|
4260
|
+
{
|
|
3386
4261
|
item.classList.add( 'selected' );
|
|
3387
4262
|
this.selected.push( node );
|
|
3388
4263
|
}
|
|
3389
4264
|
|
|
3390
4265
|
// Only Show children...
|
|
3391
|
-
if( isParent && node.id.length > 1 /* Strange case... */)
|
|
4266
|
+
if( isParent && node.id.length > 1 /* Strange case... */)
|
|
4267
|
+
{
|
|
3392
4268
|
node.closed = false;
|
|
3393
4269
|
if( that.onevent )
|
|
3394
4270
|
{
|
|
@@ -3426,7 +4302,7 @@ class NodeTree {
|
|
|
3426
4302
|
|
|
3427
4303
|
e.preventDefault();
|
|
3428
4304
|
|
|
3429
|
-
if( that.onevent )
|
|
4305
|
+
if( !that.onevent )
|
|
3430
4306
|
{
|
|
3431
4307
|
return;
|
|
3432
4308
|
}
|
|
@@ -3482,7 +4358,8 @@ class NodeTree {
|
|
|
3482
4358
|
return;
|
|
3483
4359
|
}
|
|
3484
4360
|
|
|
3485
|
-
if( that.onevent )
|
|
4361
|
+
if( that.onevent )
|
|
4362
|
+
{
|
|
3486
4363
|
const event = new TreeEvent( TreeEvent.NODE_DELETED, node, e );
|
|
3487
4364
|
that.onevent( event );
|
|
3488
4365
|
}
|
|
@@ -3509,7 +4386,8 @@ class NodeTree {
|
|
|
3509
4386
|
if( e.key == "Delete" )
|
|
3510
4387
|
{
|
|
3511
4388
|
// Send event now so we have the info in selected array..
|
|
3512
|
-
if( that.onevent )
|
|
4389
|
+
if( that.onevent )
|
|
4390
|
+
{
|
|
3513
4391
|
const event = new TreeEvent( TreeEvent.NODE_DELETED, this.selected.length > 1 ? this.selected : node, e );
|
|
3514
4392
|
event.multiple = this.selected.length > 1;
|
|
3515
4393
|
that.onevent( event );
|
|
@@ -3540,22 +4418,24 @@ class NodeTree {
|
|
|
3540
4418
|
|
|
3541
4419
|
// Node rename
|
|
3542
4420
|
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
item.appendChild(
|
|
4421
|
+
const nameInput = document.createElement( "input" );
|
|
4422
|
+
nameInput.toggleAttribute( "hidden", !node.rename );
|
|
4423
|
+
nameInput.value = node.id;
|
|
4424
|
+
item.appendChild(nameInput);
|
|
3547
4425
|
|
|
3548
|
-
if(node.rename)
|
|
4426
|
+
if( node.rename )
|
|
4427
|
+
{
|
|
3549
4428
|
item.classList.add('selected');
|
|
3550
|
-
|
|
4429
|
+
nameInput.focus();
|
|
3551
4430
|
}
|
|
3552
4431
|
|
|
3553
|
-
|
|
3554
|
-
if(e.key ==
|
|
3555
|
-
|
|
4432
|
+
nameInput.addEventListener("keyup", function(e){
|
|
4433
|
+
if( e.key == "Enter" )
|
|
4434
|
+
{
|
|
3556
4435
|
this.value = this.value.replace(/\s/g, '_');
|
|
3557
4436
|
|
|
3558
|
-
if(that.onevent)
|
|
4437
|
+
if( that.onevent )
|
|
4438
|
+
{
|
|
3559
4439
|
const event = new TreeEvent(TreeEvent.NODE_RENAMED, node, this.value);
|
|
3560
4440
|
that.onevent( event );
|
|
3561
4441
|
}
|
|
@@ -3565,18 +4445,20 @@ class NodeTree {
|
|
|
3565
4445
|
that.frefresh( node.id );
|
|
3566
4446
|
list.querySelector("#" + node.id).classList.add('selected');
|
|
3567
4447
|
}
|
|
3568
|
-
if(e.key ==
|
|
4448
|
+
else if(e.key == "Escape")
|
|
4449
|
+
{
|
|
3569
4450
|
delete node.rename;
|
|
3570
4451
|
that.frefresh( node.id );
|
|
3571
4452
|
}
|
|
3572
4453
|
});
|
|
3573
4454
|
|
|
3574
|
-
|
|
4455
|
+
nameInput.addEventListener("blur", function(e){
|
|
3575
4456
|
delete node.rename;
|
|
3576
4457
|
that.refresh();
|
|
3577
4458
|
});
|
|
3578
4459
|
|
|
3579
|
-
if(this.options.draggable ?? true)
|
|
4460
|
+
if( this.options.draggable ?? true )
|
|
4461
|
+
{
|
|
3580
4462
|
// Drag nodes
|
|
3581
4463
|
if(parent) // Root doesn't move!
|
|
3582
4464
|
{
|
|
@@ -3602,29 +4484,32 @@ class NodeTree {
|
|
|
3602
4484
|
return;
|
|
3603
4485
|
let target = node;
|
|
3604
4486
|
// Can't drop to same node
|
|
3605
|
-
if(dragged.id == target.id)
|
|
4487
|
+
if( dragged.id == target.id )
|
|
4488
|
+
{
|
|
3606
4489
|
console.warn("Cannot parent node to itself!");
|
|
3607
4490
|
return;
|
|
3608
4491
|
}
|
|
3609
4492
|
|
|
3610
4493
|
// Can't drop to child node
|
|
3611
|
-
const isChild = function(
|
|
4494
|
+
const isChild = function( newParent, node ) {
|
|
3612
4495
|
var result = false;
|
|
3613
|
-
for( var c of node.children )
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
result |= isChild(
|
|
4496
|
+
for( var c of node.children )
|
|
4497
|
+
{
|
|
4498
|
+
if( c.id == newParent.id ) return true;
|
|
4499
|
+
result |= isChild( newParent, c );
|
|
3617
4500
|
}
|
|
3618
4501
|
return result;
|
|
3619
4502
|
};
|
|
3620
4503
|
|
|
3621
|
-
if(isChild(target, dragged))
|
|
4504
|
+
if( isChild( target, dragged ))
|
|
4505
|
+
{
|
|
3622
4506
|
console.warn("Cannot parent node to a current child!");
|
|
3623
4507
|
return;
|
|
3624
4508
|
}
|
|
3625
4509
|
|
|
3626
4510
|
// Trigger node dragger event
|
|
3627
|
-
if(that.onevent)
|
|
4511
|
+
if( that.onevent )
|
|
4512
|
+
{
|
|
3628
4513
|
const event = new TreeEvent(TreeEvent.NODE_DRAGGED, dragged, target);
|
|
3629
4514
|
that.onevent( event );
|
|
3630
4515
|
}
|
|
@@ -3640,7 +4525,8 @@ class NodeTree {
|
|
|
3640
4525
|
let handled = false;
|
|
3641
4526
|
|
|
3642
4527
|
// Show/hide children
|
|
3643
|
-
if(isParent)
|
|
4528
|
+
if( isParent )
|
|
4529
|
+
{
|
|
3644
4530
|
item.querySelector('a.hierarchy').addEventListener("click", function(e) {
|
|
3645
4531
|
|
|
3646
4532
|
handled = true;
|
|
@@ -3648,7 +4534,8 @@ class NodeTree {
|
|
|
3648
4534
|
e.stopPropagation();
|
|
3649
4535
|
|
|
3650
4536
|
node.closed = !node.closed;
|
|
3651
|
-
if(that.onevent)
|
|
4537
|
+
if( that.onevent )
|
|
4538
|
+
{
|
|
3652
4539
|
const event = new TreeEvent(TreeEvent.NODE_CARETCHANGED, node, node.closed);
|
|
3653
4540
|
that.onevent( event );
|
|
3654
4541
|
}
|
|
@@ -3668,7 +4555,8 @@ class NodeTree {
|
|
|
3668
4555
|
node.visible = node.visible === undefined ? false : !node.visible;
|
|
3669
4556
|
this.className = "itemicon fa-solid fa-eye" + (!node.visible ? "-slash" : "");
|
|
3670
4557
|
// Trigger visibility event
|
|
3671
|
-
if(that.onevent)
|
|
4558
|
+
if( that.onevent )
|
|
4559
|
+
{
|
|
3672
4560
|
const event = new TreeEvent(TreeEvent.NODE_VISIBILITY, node, node.visible);
|
|
3673
4561
|
that.onevent( event );
|
|
3674
4562
|
}
|
|
@@ -3677,9 +4565,10 @@ class NodeTree {
|
|
|
3677
4565
|
item.appendChild(visibility);
|
|
3678
4566
|
}
|
|
3679
4567
|
|
|
3680
|
-
if(node.actions)
|
|
4568
|
+
if( node.actions )
|
|
3681
4569
|
{
|
|
3682
|
-
for(var i = 0; i < node.actions.length; ++i)
|
|
4570
|
+
for( var i = 0; i < node.actions.length; ++i )
|
|
4571
|
+
{
|
|
3683
4572
|
let a = node.actions[i];
|
|
3684
4573
|
var actionEl = document.createElement('a');
|
|
3685
4574
|
actionEl.className = "itemicon " + a.icon;
|
|
@@ -3692,20 +4581,25 @@ class NodeTree {
|
|
|
3692
4581
|
}
|
|
3693
4582
|
}
|
|
3694
4583
|
|
|
3695
|
-
if(selectedId != undefined && node.id == selectedId)
|
|
3696
|
-
|
|
4584
|
+
if( selectedId != undefined && node.id == selectedId )
|
|
4585
|
+
{
|
|
4586
|
+
this.selected = [ node ];
|
|
3697
4587
|
item.click();
|
|
3698
4588
|
}
|
|
3699
4589
|
|
|
3700
|
-
if(node.closed )
|
|
4590
|
+
if( node.closed )
|
|
4591
|
+
{
|
|
3701
4592
|
return;
|
|
4593
|
+
}
|
|
3702
4594
|
|
|
3703
4595
|
for( var i = 0; i < node.children.length; ++i )
|
|
3704
4596
|
{
|
|
3705
|
-
let child = node.children[i];
|
|
4597
|
+
let child = node.children[ i ];
|
|
3706
4598
|
|
|
3707
|
-
if( this.options.onlyFolders && child.type != 'folder')
|
|
4599
|
+
if( this.options.onlyFolders && child.type != 'folder' )
|
|
4600
|
+
{
|
|
3708
4601
|
continue;
|
|
4602
|
+
}
|
|
3709
4603
|
|
|
3710
4604
|
this._create_item( node, child, level + 1 );
|
|
3711
4605
|
}
|
|
@@ -3744,12 +4638,12 @@ class Panel {
|
|
|
3744
4638
|
* style: CSS Style object to be applied to the panel
|
|
3745
4639
|
*/
|
|
3746
4640
|
|
|
3747
|
-
constructor( options = {} )
|
|
4641
|
+
constructor( options = {} ) {
|
|
3748
4642
|
var root = document.createElement('div');
|
|
3749
4643
|
root.className = "lexpanel";
|
|
3750
|
-
if(options.id)
|
|
4644
|
+
if( options.id )
|
|
3751
4645
|
root.id = options.id;
|
|
3752
|
-
if(options.className)
|
|
4646
|
+
if( options.className )
|
|
3753
4647
|
root.className += " " + options.className;
|
|
3754
4648
|
|
|
3755
4649
|
root.style.width = options.width || "calc( 100% - 6px )";
|
|
@@ -3826,23 +4720,31 @@ class Panel {
|
|
|
3826
4720
|
this.branches = [];
|
|
3827
4721
|
this.current_branch = null;
|
|
3828
4722
|
|
|
3829
|
-
for(let w in this.widgets)
|
|
3830
|
-
|
|
4723
|
+
for( let w in this.widgets )
|
|
4724
|
+
{
|
|
4725
|
+
if( this.widgets[w].options && this.widgets[w].options.signal )
|
|
4726
|
+
{
|
|
3831
4727
|
const signal = this.widgets[w].options.signal;
|
|
3832
|
-
for(let i = 0; i < LX.signals[signal].length; i++)
|
|
3833
|
-
|
|
4728
|
+
for( let i = 0; i < LX.signals[signal].length; i++ )
|
|
4729
|
+
{
|
|
4730
|
+
if( LX.signals[signal][i] == this.widgets[w] )
|
|
4731
|
+
{
|
|
3834
4732
|
LX.signals[signal] = [...LX.signals[signal].slice(0, i), ...LX.signals[signal].slice(i+1)];
|
|
3835
4733
|
}
|
|
3836
4734
|
}
|
|
3837
4735
|
}
|
|
3838
4736
|
}
|
|
3839
4737
|
|
|
3840
|
-
if(this.signals)
|
|
3841
|
-
|
|
4738
|
+
if( this.signals )
|
|
4739
|
+
{
|
|
4740
|
+
for( let w = 0; w < this.signals.length; w++ )
|
|
4741
|
+
{
|
|
3842
4742
|
let widget = Object.values(this.signals[w])[0];
|
|
3843
4743
|
let signal = widget.options.signal;
|
|
3844
|
-
for(let i = 0; i < LX.signals[signal].length; i++)
|
|
3845
|
-
|
|
4744
|
+
for( let i = 0; i < LX.signals[signal].length; i++ )
|
|
4745
|
+
{
|
|
4746
|
+
if( LX.signals[signal][i] == widget )
|
|
4747
|
+
{
|
|
3846
4748
|
LX.signals[signal] = [...LX.signals[signal].slice(0, i), ...LX.signals[signal].slice(i+1)];
|
|
3847
4749
|
}
|
|
3848
4750
|
}
|
|
@@ -3880,10 +4782,12 @@ class Panel {
|
|
|
3880
4782
|
|
|
3881
4783
|
this._inline_widgets_left = -1;
|
|
3882
4784
|
|
|
3883
|
-
if(!this._inlineContainer)
|
|
4785
|
+
if( !this._inlineContainer )
|
|
4786
|
+
{
|
|
3884
4787
|
this._inlineContainer = document.createElement('div');
|
|
3885
4788
|
this._inlineContainer.className = "lexinlinewidgets";
|
|
3886
|
-
|
|
4789
|
+
|
|
4790
|
+
if( justifyContent )
|
|
3887
4791
|
{
|
|
3888
4792
|
this._inlineContainer.style.justifyContent = justifyContent;
|
|
3889
4793
|
}
|
|
@@ -3897,7 +4801,7 @@ class Panel {
|
|
|
3897
4801
|
if(is_pair)
|
|
3898
4802
|
{
|
|
3899
4803
|
// eg. an array, inline items appended later to
|
|
3900
|
-
if(this._inline_queued_container)
|
|
4804
|
+
if( this._inline_queued_container)
|
|
3901
4805
|
this._inlineContainer.appendChild( item[0] );
|
|
3902
4806
|
// eg. a dropdown, item is appended to parent, not to inline cont.
|
|
3903
4807
|
else
|
|
@@ -3909,7 +4813,7 @@ class Panel {
|
|
|
3909
4813
|
|
|
3910
4814
|
if(!this._inline_queued_container)
|
|
3911
4815
|
{
|
|
3912
|
-
if(this.current_branch)
|
|
4816
|
+
if( this.current_branch)
|
|
3913
4817
|
this.current_branch.content.appendChild( this._inlineContainer );
|
|
3914
4818
|
else
|
|
3915
4819
|
this.root.appendChild( this._inlineContainer );
|
|
@@ -3948,7 +4852,7 @@ class Panel {
|
|
|
3948
4852
|
this.current_branch = branch;
|
|
3949
4853
|
|
|
3950
4854
|
// Append to panel
|
|
3951
|
-
if(this.branches.length == 0)
|
|
4855
|
+
if( this.branches.length == 0)
|
|
3952
4856
|
branch.root.classList.add('first');
|
|
3953
4857
|
|
|
3954
4858
|
// This is the last!
|
|
@@ -3959,7 +4863,8 @@ class Panel {
|
|
|
3959
4863
|
this.root.appendChild( branch.root );
|
|
3960
4864
|
|
|
3961
4865
|
// Add widget filter
|
|
3962
|
-
if(options.filter)
|
|
4866
|
+
if( options.filter )
|
|
4867
|
+
{
|
|
3963
4868
|
this._addFilter( options.filter, {callback: this._searchWidgets.bind(this, branch.name)} );
|
|
3964
4869
|
}
|
|
3965
4870
|
|
|
@@ -4076,14 +4981,18 @@ class Panel {
|
|
|
4076
4981
|
element.jsInstance = widget;
|
|
4077
4982
|
|
|
4078
4983
|
const insert_widget = el => {
|
|
4079
|
-
if(options.container)
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4984
|
+
if( options.container )
|
|
4985
|
+
{
|
|
4986
|
+
options.container.appendChild( el );
|
|
4987
|
+
}
|
|
4988
|
+
else if( !this.queuedContainer )
|
|
4989
|
+
{
|
|
4990
|
+
if( this.current_branch )
|
|
4084
4991
|
{
|
|
4085
|
-
if(!options.skipWidget)
|
|
4992
|
+
if( !options.skipWidget )
|
|
4993
|
+
{
|
|
4086
4994
|
this.current_branch.widgets.push( widget );
|
|
4995
|
+
}
|
|
4087
4996
|
this.current_branch.content.appendChild( el );
|
|
4088
4997
|
}
|
|
4089
4998
|
else
|
|
@@ -4093,40 +5002,47 @@ class Panel {
|
|
|
4093
5002
|
}
|
|
4094
5003
|
}
|
|
4095
5004
|
// Append content to queued tab container
|
|
4096
|
-
else
|
|
5005
|
+
else
|
|
5006
|
+
{
|
|
4097
5007
|
this.queuedContainer.appendChild( el );
|
|
4098
5008
|
}
|
|
4099
5009
|
};
|
|
4100
5010
|
|
|
4101
5011
|
const store_widget = el => {
|
|
4102
5012
|
|
|
4103
|
-
if(!this.queuedContainer)
|
|
5013
|
+
if( !this.queuedContainer )
|
|
5014
|
+
{
|
|
4104
5015
|
this._inlineWidgets.push( el );
|
|
4105
5016
|
}
|
|
4106
5017
|
// Append content to queued tab container
|
|
4107
|
-
else
|
|
5018
|
+
else
|
|
5019
|
+
{
|
|
4108
5020
|
this._inlineWidgets.push( [el, this.queuedContainer] );
|
|
4109
5021
|
}
|
|
4110
5022
|
};
|
|
4111
5023
|
|
|
4112
5024
|
// Process inline widgets
|
|
4113
|
-
if(this._inline_widgets_left > 0 && !options.skipInlineCount)
|
|
5025
|
+
if( this._inline_widgets_left > 0 && !options.skipInlineCount )
|
|
4114
5026
|
{
|
|
4115
|
-
if(!this._inlineWidgets)
|
|
5027
|
+
if( !this._inlineWidgets )
|
|
5028
|
+
{
|
|
4116
5029
|
this._inlineWidgets = [];
|
|
4117
5030
|
}
|
|
4118
5031
|
|
|
4119
5032
|
// Store widget and its container
|
|
4120
|
-
store_widget(element);
|
|
5033
|
+
store_widget( element );
|
|
4121
5034
|
|
|
4122
5035
|
this._inline_widgets_left--;
|
|
4123
5036
|
|
|
4124
5037
|
// Last widget
|
|
4125
|
-
if(!this._inline_widgets_left)
|
|
5038
|
+
if( !this._inline_widgets_left )
|
|
5039
|
+
{
|
|
4126
5040
|
this.endLine();
|
|
4127
5041
|
}
|
|
4128
|
-
}
|
|
4129
|
-
|
|
5042
|
+
}
|
|
5043
|
+
else
|
|
5044
|
+
{
|
|
5045
|
+
insert_widget( element );
|
|
4130
5046
|
}
|
|
4131
5047
|
|
|
4132
5048
|
return widget;
|
|
@@ -4163,15 +5079,20 @@ class Panel {
|
|
|
4163
5079
|
|
|
4164
5080
|
_searchWidgets(branchName, value) {
|
|
4165
5081
|
|
|
4166
|
-
for( let b of this.branches )
|
|
4167
|
-
|
|
4168
|
-
if(b.name !== branchName)
|
|
5082
|
+
for( let b of this.branches )
|
|
5083
|
+
{
|
|
5084
|
+
if( b.name !== branchName )
|
|
5085
|
+
{
|
|
4169
5086
|
continue;
|
|
5087
|
+
}
|
|
4170
5088
|
|
|
4171
5089
|
// remove all widgets
|
|
4172
|
-
for( let w of b.widgets )
|
|
4173
|
-
|
|
5090
|
+
for( let w of b.widgets )
|
|
5091
|
+
{
|
|
5092
|
+
if( w.domEl.classList.contains('lexfilter') )
|
|
5093
|
+
{
|
|
4174
5094
|
continue;
|
|
5095
|
+
}
|
|
4175
5096
|
w.domEl.remove();
|
|
4176
5097
|
}
|
|
4177
5098
|
|
|
@@ -4181,9 +5102,9 @@ class Panel {
|
|
|
4181
5102
|
const emptyFilter = !value.length;
|
|
4182
5103
|
|
|
4183
5104
|
// add widgets
|
|
4184
|
-
for( let w of b.widgets )
|
|
4185
|
-
|
|
4186
|
-
if(!emptyFilter)
|
|
5105
|
+
for( let w of b.widgets )
|
|
5106
|
+
{
|
|
5107
|
+
if( !emptyFilter )
|
|
4187
5108
|
{
|
|
4188
5109
|
if(!w.name) continue;
|
|
4189
5110
|
const filterWord = value.toLowerCase();
|
|
@@ -4277,7 +5198,7 @@ class Panel {
|
|
|
4277
5198
|
|
|
4278
5199
|
clearQueue() {
|
|
4279
5200
|
|
|
4280
|
-
if(this._queue && this._queue.length)
|
|
5201
|
+
if( this._queue && this._queue.length)
|
|
4281
5202
|
{
|
|
4282
5203
|
this.queuedContainer = this._queue.pop();
|
|
4283
5204
|
return;
|
|
@@ -4437,7 +5358,7 @@ class Panel {
|
|
|
4437
5358
|
|
|
4438
5359
|
var resolve = ( function( val, event ) {
|
|
4439
5360
|
|
|
4440
|
-
if( !widget.valid() )
|
|
5361
|
+
if( !widget.valid() || ( this._lastValueTriggered == val ) )
|
|
4441
5362
|
{
|
|
4442
5363
|
return;
|
|
4443
5364
|
}
|
|
@@ -4450,6 +5371,8 @@ class Panel {
|
|
|
4450
5371
|
this._trigger( new IEvent( name, val, event ), callback );
|
|
4451
5372
|
}
|
|
4452
5373
|
|
|
5374
|
+
this._lastValueTriggered = val;
|
|
5375
|
+
|
|
4453
5376
|
}).bind( this );
|
|
4454
5377
|
|
|
4455
5378
|
const trigger = options.trigger ?? 'default';
|
|
@@ -4503,7 +5426,8 @@ class Panel {
|
|
|
4503
5426
|
element.appendChild( container );
|
|
4504
5427
|
|
|
4505
5428
|
// Remove branch padding and margins
|
|
4506
|
-
if( !widget.name )
|
|
5429
|
+
if( !widget.name )
|
|
5430
|
+
{
|
|
4507
5431
|
element.className += " noname";
|
|
4508
5432
|
container.style.width = "100%";
|
|
4509
5433
|
}
|
|
@@ -4603,7 +5527,8 @@ class Panel {
|
|
|
4603
5527
|
element.appendChild(container);
|
|
4604
5528
|
|
|
4605
5529
|
// Remove branch padding and margins
|
|
4606
|
-
if(!widget.name)
|
|
5530
|
+
if( !widget.name )
|
|
5531
|
+
{
|
|
4607
5532
|
element.className += " noname";
|
|
4608
5533
|
container.style.width = "100%";
|
|
4609
5534
|
}
|
|
@@ -4708,11 +5633,12 @@ class Panel {
|
|
|
4708
5633
|
/**
|
|
4709
5634
|
* @method addComboButtons
|
|
4710
5635
|
* @param {String} name Widget name
|
|
4711
|
-
* @param {Array} values Each of the {value, callback} items
|
|
5636
|
+
* @param {Array} values Each of the {value, callback, selected, disabled} items
|
|
4712
5637
|
* @param {*} options:
|
|
4713
5638
|
* float: Justify content (left, center, right) [center]
|
|
4714
|
-
* selected: Selected item by default by value
|
|
5639
|
+
* @legacy selected: Selected item by default by value
|
|
4715
5640
|
* noSelection: Buttons can be clicked, but they are not selectable
|
|
5641
|
+
* toggle: Buttons can be toggled insted of selecting only one
|
|
4716
5642
|
*/
|
|
4717
5643
|
|
|
4718
5644
|
addComboButtons( name, values, options = {} ) {
|
|
@@ -4734,7 +5660,8 @@ class Panel {
|
|
|
4734
5660
|
let buttonsBox = document.createElement('div');
|
|
4735
5661
|
buttonsBox.className = "lexcombobuttonsbox ";
|
|
4736
5662
|
|
|
4737
|
-
|
|
5663
|
+
const shouldSelect = !( options.noSelection ?? false );
|
|
5664
|
+
const shouldToggle = shouldSelect && ( options.toggle ?? false );
|
|
4738
5665
|
|
|
4739
5666
|
for( let b of values )
|
|
4740
5667
|
{
|
|
@@ -4753,14 +5680,14 @@ class Panel {
|
|
|
4753
5680
|
buttonEl.classList.add( options.buttonClass );
|
|
4754
5681
|
}
|
|
4755
5682
|
|
|
4756
|
-
if( shouldSelect && options.selected == b.value )
|
|
5683
|
+
if( shouldSelect && ( b.selected || options.selected == b.value ) )
|
|
4757
5684
|
{
|
|
4758
5685
|
buttonEl.classList.add("selected");
|
|
4759
5686
|
}
|
|
4760
5687
|
|
|
4761
5688
|
buttonEl.innerHTML = ( b.icon ? "<a class='" + b.icon +"'></a>" : "" ) + "<span>" + ( b.icon ? "" : b.value ) + "</span>";
|
|
4762
5689
|
|
|
4763
|
-
if(
|
|
5690
|
+
if( b.disabled )
|
|
4764
5691
|
{
|
|
4765
5692
|
buttonEl.setAttribute( "disabled", true );
|
|
4766
5693
|
}
|
|
@@ -4768,8 +5695,15 @@ class Panel {
|
|
|
4768
5695
|
buttonEl.addEventListener("click", function( e ) {
|
|
4769
5696
|
if( shouldSelect )
|
|
4770
5697
|
{
|
|
4771
|
-
|
|
4772
|
-
|
|
5698
|
+
if( shouldToggle )
|
|
5699
|
+
{
|
|
5700
|
+
this.classList.toggle('selected');
|
|
5701
|
+
}
|
|
5702
|
+
else
|
|
5703
|
+
{
|
|
5704
|
+
container.querySelectorAll('button').forEach( s => s.classList.remove('selected'));
|
|
5705
|
+
this.classList.add('selected');
|
|
5706
|
+
}
|
|
4773
5707
|
}
|
|
4774
5708
|
|
|
4775
5709
|
that._trigger( new IEvent( name, b.value, e ), b.callback );
|
|
@@ -4779,7 +5713,7 @@ class Panel {
|
|
|
4779
5713
|
}
|
|
4780
5714
|
|
|
4781
5715
|
// Remove branch padding and margins
|
|
4782
|
-
if( !widget.name)
|
|
5716
|
+
if( !widget.name )
|
|
4783
5717
|
{
|
|
4784
5718
|
element.className += " noname";
|
|
4785
5719
|
container.style.width = "100%";
|
|
@@ -4953,7 +5887,8 @@ class Panel {
|
|
|
4953
5887
|
|
|
4954
5888
|
element.appendChild( container );
|
|
4955
5889
|
|
|
4956
|
-
if( !widget.name || options.hideName )
|
|
5890
|
+
if( !widget.name || options.hideName )
|
|
5891
|
+
{
|
|
4957
5892
|
element.className += " noname";
|
|
4958
5893
|
container.style.width = "100%";
|
|
4959
5894
|
}
|
|
@@ -5089,8 +6024,6 @@ class Panel {
|
|
|
5089
6024
|
|
|
5090
6025
|
const _placeOptions = ( parent ) => {
|
|
5091
6026
|
|
|
5092
|
-
console.log("Replacing container");
|
|
5093
|
-
|
|
5094
6027
|
const overflowContainer = parent.getParentArea();
|
|
5095
6028
|
const rect = selectedOption.getBoundingClientRect();
|
|
5096
6029
|
const nestedDialog = parent.parentElement.closest( "dialog" );
|
|
@@ -5374,15 +6307,16 @@ class Panel {
|
|
|
5374
6307
|
|
|
5375
6308
|
addCurve( name, values, callback, options = {} ) {
|
|
5376
6309
|
|
|
5377
|
-
if(!name)
|
|
5378
|
-
|
|
6310
|
+
if( !name )
|
|
6311
|
+
{
|
|
6312
|
+
throw( "Set Widget Name!" );
|
|
5379
6313
|
}
|
|
5380
6314
|
|
|
5381
6315
|
let that = this;
|
|
5382
|
-
let widget = this.create_widget(name, Widget.CURVE, options);
|
|
6316
|
+
let widget = this.create_widget( name, Widget.CURVE, options );
|
|
5383
6317
|
|
|
5384
6318
|
widget.onGetValue = () => {
|
|
5385
|
-
return JSON.parse(JSON.stringify(curveInstance.element.value));
|
|
6319
|
+
return JSON.parse(JSON.stringify( curveInstance.element.value ));
|
|
5386
6320
|
};
|
|
5387
6321
|
|
|
5388
6322
|
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
@@ -5527,7 +6461,8 @@ class Panel {
|
|
|
5527
6461
|
|
|
5528
6462
|
addLayers( name, value, callback, options = {} ) {
|
|
5529
6463
|
|
|
5530
|
-
if(!name)
|
|
6464
|
+
if( !name )
|
|
6465
|
+
{
|
|
5531
6466
|
throw("Set Widget Name!");
|
|
5532
6467
|
}
|
|
5533
6468
|
|
|
@@ -5569,7 +6504,8 @@ class Panel {
|
|
|
5569
6504
|
let binary = value.toString( 2 );
|
|
5570
6505
|
let nbits = binary.length;
|
|
5571
6506
|
// fill zeros
|
|
5572
|
-
for(var i = 0; i < (16 - nbits); ++i)
|
|
6507
|
+
for( var i = 0; i < (16 - nbits); ++i )
|
|
6508
|
+
{
|
|
5573
6509
|
binary = '0' + binary;
|
|
5574
6510
|
}
|
|
5575
6511
|
|
|
@@ -5622,8 +6558,9 @@ class Panel {
|
|
|
5622
6558
|
|
|
5623
6559
|
addArray( name, values = [], callback, options = {} ) {
|
|
5624
6560
|
|
|
5625
|
-
if(!name)
|
|
5626
|
-
|
|
6561
|
+
if( !name )
|
|
6562
|
+
{
|
|
6563
|
+
throw( "Set Widget Name!" );
|
|
5627
6564
|
}
|
|
5628
6565
|
|
|
5629
6566
|
let widget = this.create_widget(name, Widget.ARRAY, options);
|
|
@@ -5804,7 +6741,8 @@ class Panel {
|
|
|
5804
6741
|
widget.updateValues( values );
|
|
5805
6742
|
|
|
5806
6743
|
// Remove branch padding and margins
|
|
5807
|
-
if( !widget.name )
|
|
6744
|
+
if( !widget.name )
|
|
6745
|
+
{
|
|
5808
6746
|
element.className += " noname";
|
|
5809
6747
|
listContainer.style.width = "100%";
|
|
5810
6748
|
}
|
|
@@ -5891,7 +6829,7 @@ class Panel {
|
|
|
5891
6829
|
tagsContainer.appendChild( tagInput );
|
|
5892
6830
|
|
|
5893
6831
|
tagInput.onkeydown = function( e ) {
|
|
5894
|
-
const val = this.value.replace(/\s/g, '');
|
|
6832
|
+
const val = this.value.replace( /\s/g, '' );
|
|
5895
6833
|
if( e.key == ' ' || e.key == 'Enter' )
|
|
5896
6834
|
{
|
|
5897
6835
|
e.preventDefault();
|
|
@@ -5929,15 +6867,16 @@ class Panel {
|
|
|
5929
6867
|
* @param {Function} callback Callback function on change
|
|
5930
6868
|
* @param {*} options:
|
|
5931
6869
|
* disabled: Make the widget disabled [false]
|
|
6870
|
+
* label: Checkbox label
|
|
5932
6871
|
* suboptions: Callback to add widgets in case of TRUE value
|
|
5933
|
-
* className:
|
|
6872
|
+
* className: Extra classes to customize style
|
|
5934
6873
|
*/
|
|
5935
6874
|
|
|
5936
6875
|
addCheckbox( name, value, callback, options = {} ) {
|
|
5937
6876
|
|
|
5938
|
-
if( !name )
|
|
6877
|
+
if( !name && !options.label )
|
|
5939
6878
|
{
|
|
5940
|
-
throw( "Set Widget Name!" );
|
|
6879
|
+
throw( "Set Widget Name or at least a label!" );
|
|
5941
6880
|
}
|
|
5942
6881
|
|
|
5943
6882
|
let widget = this.create_widget( name, Widget.CHECKBOX, options );
|
|
@@ -5957,10 +6896,13 @@ class Panel {
|
|
|
5957
6896
|
let element = widget.domEl;
|
|
5958
6897
|
|
|
5959
6898
|
// Add reset functionality
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
Panel.
|
|
5963
|
-
|
|
6899
|
+
if( name )
|
|
6900
|
+
{
|
|
6901
|
+
Panel._add_reset_property( element.domName, function() {
|
|
6902
|
+
checkbox.checked = !checkbox.checked;
|
|
6903
|
+
Panel._dispatch_event( checkbox, "change" );
|
|
6904
|
+
});
|
|
6905
|
+
}
|
|
5964
6906
|
|
|
5965
6907
|
// Add widget value
|
|
5966
6908
|
|
|
@@ -5976,7 +6918,7 @@ class Panel {
|
|
|
5976
6918
|
|
|
5977
6919
|
let valueName = document.createElement( 'span' );
|
|
5978
6920
|
valueName.className = "checkboxtext";
|
|
5979
|
-
valueName.innerHTML = "On";
|
|
6921
|
+
valueName.innerHTML = options.label ?? "On";
|
|
5980
6922
|
|
|
5981
6923
|
container.appendChild( checkbox );
|
|
5982
6924
|
container.appendChild( valueName );
|
|
@@ -6114,6 +7056,96 @@ class Panel {
|
|
|
6114
7056
|
return widget;
|
|
6115
7057
|
}
|
|
6116
7058
|
|
|
7059
|
+
/**
|
|
7060
|
+
* @method addRadioGroup
|
|
7061
|
+
* @param {String} label Radio label
|
|
7062
|
+
* @param {Array} values Radio options
|
|
7063
|
+
* @param {Function} callback Callback function on change
|
|
7064
|
+
* @param {*} options:
|
|
7065
|
+
* disabled: Make the widget disabled [false]
|
|
7066
|
+
* className: Customize colors
|
|
7067
|
+
*/
|
|
7068
|
+
|
|
7069
|
+
addRadioGroup( label, values, callback, options = {} ) {
|
|
7070
|
+
|
|
7071
|
+
let widget = this.create_widget( null, Widget.RADIO, options );
|
|
7072
|
+
|
|
7073
|
+
widget.onGetValue = () => {
|
|
7074
|
+
const items = container.querySelectorAll( 'button' );
|
|
7075
|
+
for( let i = 0; i < items.length; ++i )
|
|
7076
|
+
{
|
|
7077
|
+
const optionItem = items[ i ];
|
|
7078
|
+
if( optionItem.checked )
|
|
7079
|
+
{
|
|
7080
|
+
return [ i, values[ i ] ];
|
|
7081
|
+
}
|
|
7082
|
+
}
|
|
7083
|
+
};
|
|
7084
|
+
|
|
7085
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
7086
|
+
const items = container.querySelectorAll( 'button' );
|
|
7087
|
+
for( let i = 0; i < items.length; ++i )
|
|
7088
|
+
{
|
|
7089
|
+
const optionItem = items[ i ];
|
|
7090
|
+
if( newValue == i )
|
|
7091
|
+
{
|
|
7092
|
+
Panel._dispatch_event( optionItem, "click", skipCallback );
|
|
7093
|
+
}
|
|
7094
|
+
}
|
|
7095
|
+
};
|
|
7096
|
+
|
|
7097
|
+
let element = widget.domEl;
|
|
7098
|
+
|
|
7099
|
+
// Add widget value
|
|
7100
|
+
var container = document.createElement( 'div' );
|
|
7101
|
+
container.className = "lexradiogroup " + ( options.className ?? "" );
|
|
7102
|
+
|
|
7103
|
+
let labelSpan = document.createElement( 'span' );
|
|
7104
|
+
labelSpan.innerHTML = label;
|
|
7105
|
+
container.appendChild( labelSpan );
|
|
7106
|
+
|
|
7107
|
+
const that = this;
|
|
7108
|
+
|
|
7109
|
+
for( let i = 0; i < values.length; ++i )
|
|
7110
|
+
{
|
|
7111
|
+
const optionItem = document.createElement( 'div' );
|
|
7112
|
+
optionItem.className = "lexradiogroupitem";
|
|
7113
|
+
container.appendChild( optionItem );
|
|
7114
|
+
|
|
7115
|
+
const optionButton = document.createElement( 'button' );
|
|
7116
|
+
optionButton.className = "lexbutton";
|
|
7117
|
+
optionButton.disabled = options.disabled ?? false;
|
|
7118
|
+
optionItem.appendChild( optionButton );
|
|
7119
|
+
|
|
7120
|
+
optionButton.addEventListener( "click", function( e ) {
|
|
7121
|
+
const skipCallback = ( e.detail?.constructor == Number ? null : e.detail );
|
|
7122
|
+
container.querySelectorAll( 'button' ).forEach( e => { e.checked = false; e.classList.remove( "checked" ) } );
|
|
7123
|
+
this.checked = !this.checked;
|
|
7124
|
+
this.classList.toggle( "checked" );
|
|
7125
|
+
if( !skipCallback ) that._trigger( new IEvent( null, [ i, values[ i ] ], e ), callback );
|
|
7126
|
+
} );
|
|
7127
|
+
|
|
7128
|
+
{
|
|
7129
|
+
const checkedSpan = document.createElement( 'span' );
|
|
7130
|
+
optionButton.appendChild( checkedSpan );
|
|
7131
|
+
}
|
|
7132
|
+
|
|
7133
|
+
const optionLabel = document.createElement( 'span' );
|
|
7134
|
+
optionLabel.innerHTML = values[ i ];
|
|
7135
|
+
optionItem.appendChild( optionLabel );
|
|
7136
|
+
}
|
|
7137
|
+
|
|
7138
|
+
if( options.selected )
|
|
7139
|
+
{
|
|
7140
|
+
console.assert( options.selected.constructor == Number );
|
|
7141
|
+
widget.set( options.selected, true );
|
|
7142
|
+
}
|
|
7143
|
+
|
|
7144
|
+
element.appendChild( container );
|
|
7145
|
+
|
|
7146
|
+
return widget;
|
|
7147
|
+
}
|
|
7148
|
+
|
|
6117
7149
|
/**
|
|
6118
7150
|
* @method addColor
|
|
6119
7151
|
* @param {String} name Widget name
|
|
@@ -6126,7 +7158,8 @@ class Panel {
|
|
|
6126
7158
|
|
|
6127
7159
|
addColor( name, value, callback, options = {} ) {
|
|
6128
7160
|
|
|
6129
|
-
if( !name )
|
|
7161
|
+
if( !name )
|
|
7162
|
+
{
|
|
6130
7163
|
throw( "Set Widget Name!" );
|
|
6131
7164
|
}
|
|
6132
7165
|
|
|
@@ -6164,7 +7197,8 @@ class Panel {
|
|
|
6164
7197
|
color.useRGB = options.useRGB ?? false;
|
|
6165
7198
|
color.value = color.iValue = value.constructor === Array ? rgbToHex( value ) : value;
|
|
6166
7199
|
|
|
6167
|
-
if( options.disabled )
|
|
7200
|
+
if( options.disabled )
|
|
7201
|
+
{
|
|
6168
7202
|
color.disabled = true;
|
|
6169
7203
|
}
|
|
6170
7204
|
|
|
@@ -6209,6 +7243,137 @@ class Panel {
|
|
|
6209
7243
|
return widget;
|
|
6210
7244
|
}
|
|
6211
7245
|
|
|
7246
|
+
/**
|
|
7247
|
+
* @method addRange
|
|
7248
|
+
* @param {String} name Widget name
|
|
7249
|
+
* @param {Number} value Default number value
|
|
7250
|
+
* @param {Function} callback Callback function on change
|
|
7251
|
+
* @param {*} options:
|
|
7252
|
+
* className: Extra classes to customize style
|
|
7253
|
+
* disabled: Make the widget disabled [false]
|
|
7254
|
+
* left: The slider goes to the left instead of the right
|
|
7255
|
+
* fill: Fill slider progress [true]
|
|
7256
|
+
* step: Step of the input
|
|
7257
|
+
* min, max: Min and Max values for the input
|
|
7258
|
+
*/
|
|
7259
|
+
|
|
7260
|
+
addRange( name, value, callback, options = {} ) {
|
|
7261
|
+
|
|
7262
|
+
let widget = this.create_widget( name, Widget.RANGE, options );
|
|
7263
|
+
|
|
7264
|
+
widget.onGetValue = () => {
|
|
7265
|
+
return +slider.value;
|
|
7266
|
+
};
|
|
7267
|
+
|
|
7268
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
7269
|
+
slider.value = newValue;
|
|
7270
|
+
Panel._dispatch_event( slider, "input", skipCallback );
|
|
7271
|
+
};
|
|
7272
|
+
|
|
7273
|
+
let element = widget.domEl;
|
|
7274
|
+
|
|
7275
|
+
// add reset functionality
|
|
7276
|
+
if( widget.name )
|
|
7277
|
+
{
|
|
7278
|
+
Panel._add_reset_property( element.domName, function() {
|
|
7279
|
+
this.style.display = "none";
|
|
7280
|
+
slider.value = slider.iValue;
|
|
7281
|
+
Panel._dispatch_event( slider, "input" );
|
|
7282
|
+
});
|
|
7283
|
+
}
|
|
7284
|
+
|
|
7285
|
+
// add widget value
|
|
7286
|
+
|
|
7287
|
+
var container = document.createElement( 'div' );
|
|
7288
|
+
container.className = "lexrange";
|
|
7289
|
+
container.style.width = options.inputWidth || "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
7290
|
+
|
|
7291
|
+
let slider = document.createElement( 'input' );
|
|
7292
|
+
slider.className = "lexrangeslider " + ( options.className ?? "" );
|
|
7293
|
+
slider.value = slider.iValue = value;
|
|
7294
|
+
slider.min = options.min;
|
|
7295
|
+
slider.max = options.max;
|
|
7296
|
+
slider.step = options.step ?? 1;
|
|
7297
|
+
slider.type = "range";
|
|
7298
|
+
slider.disabled = options.disabled ?? false;
|
|
7299
|
+
|
|
7300
|
+
if( options.left ?? false )
|
|
7301
|
+
{
|
|
7302
|
+
slider.classList.add( "left" );
|
|
7303
|
+
}
|
|
7304
|
+
|
|
7305
|
+
if( !( options.fill ?? true ) )
|
|
7306
|
+
{
|
|
7307
|
+
slider.classList.add( "no-fill" );
|
|
7308
|
+
}
|
|
7309
|
+
|
|
7310
|
+
slider.addEventListener( "input", e => {
|
|
7311
|
+
|
|
7312
|
+
if( isNaN( e.target.valueAsNumber ) )
|
|
7313
|
+
{
|
|
7314
|
+
return;
|
|
7315
|
+
}
|
|
7316
|
+
|
|
7317
|
+
const skipCallback = e.detail;
|
|
7318
|
+
|
|
7319
|
+
let val = e.target.value = clamp( +e.target.valueAsNumber, +slider.min, +slider.max );
|
|
7320
|
+
slider.value = val;
|
|
7321
|
+
|
|
7322
|
+
// Reset button (default value)
|
|
7323
|
+
if( !skipCallback )
|
|
7324
|
+
{
|
|
7325
|
+
let btn = element.querySelector( ".lexwidgetname .lexicon" );
|
|
7326
|
+
if( btn ) btn.style.display = val != slider.iValue ? "block": "none";
|
|
7327
|
+
}
|
|
7328
|
+
|
|
7329
|
+
if( options.left )
|
|
7330
|
+
{
|
|
7331
|
+
val = ( +slider.max ) - val + ( +slider.min );
|
|
7332
|
+
}
|
|
7333
|
+
|
|
7334
|
+
if( !skipCallback ) this._trigger( new IEvent( name, val, e ), callback );
|
|
7335
|
+
}, { passive: false });
|
|
7336
|
+
|
|
7337
|
+
slider.addEventListener( "mousedown", function( e ) {
|
|
7338
|
+
if( options.onPress )
|
|
7339
|
+
{
|
|
7340
|
+
options.onPress.bind( slider )( e, slider );
|
|
7341
|
+
}
|
|
7342
|
+
}, false );
|
|
7343
|
+
|
|
7344
|
+
slider.addEventListener( "mouseup", function( e ) {
|
|
7345
|
+
if( options.onRelease )
|
|
7346
|
+
{
|
|
7347
|
+
options.onRelease.bind( slider )( e, slider );
|
|
7348
|
+
}
|
|
7349
|
+
}, false );
|
|
7350
|
+
|
|
7351
|
+
// Method to change min, max, step parameters
|
|
7352
|
+
widget.setLimits = ( newMin, newMax, newStep ) => {
|
|
7353
|
+
slider.min = newMin ?? slider.min;
|
|
7354
|
+
slider.max = newMax ?? slider.max;
|
|
7355
|
+
slider.step = newStep ?? slider.step;
|
|
7356
|
+
Panel._dispatch_event( slider, "input", true );
|
|
7357
|
+
};
|
|
7358
|
+
|
|
7359
|
+
if( value.constructor == Number )
|
|
7360
|
+
{
|
|
7361
|
+
value = clamp( value, +slider.min, +slider.max );
|
|
7362
|
+
}
|
|
7363
|
+
|
|
7364
|
+
container.appendChild( slider );
|
|
7365
|
+
element.appendChild( container );
|
|
7366
|
+
|
|
7367
|
+
// Remove branch padding and margins
|
|
7368
|
+
if( !widget.name )
|
|
7369
|
+
{
|
|
7370
|
+
element.className += " noname";
|
|
7371
|
+
container.style.width = "100%";
|
|
7372
|
+
}
|
|
7373
|
+
|
|
7374
|
+
return widget;
|
|
7375
|
+
}
|
|
7376
|
+
|
|
6212
7377
|
/**
|
|
6213
7378
|
* @method addNumber
|
|
6214
7379
|
* @param {String} name Widget name
|
|
@@ -6241,7 +7406,8 @@ class Panel {
|
|
|
6241
7406
|
let element = widget.domEl;
|
|
6242
7407
|
|
|
6243
7408
|
// add reset functionality
|
|
6244
|
-
if( widget.name )
|
|
7409
|
+
if( widget.name )
|
|
7410
|
+
{
|
|
6245
7411
|
Panel._add_reset_property( element.domName, function() {
|
|
6246
7412
|
this.style.display = "none";
|
|
6247
7413
|
vecinput.value = vecinput.iValue;
|
|
@@ -6509,7 +7675,8 @@ class Panel {
|
|
|
6509
7675
|
return;
|
|
6510
7676
|
}
|
|
6511
7677
|
|
|
6512
|
-
for( let i = 0; i < inputs.length; ++i )
|
|
7678
|
+
for( let i = 0; i < inputs.length; ++i )
|
|
7679
|
+
{
|
|
6513
7680
|
let value = newValue[ i ];
|
|
6514
7681
|
inputs[ i ].value = round( value, options.precision ) ?? 0;
|
|
6515
7682
|
Panel._dispatch_event( inputs[ i ], "change", skipCallback );
|
|
@@ -6521,7 +7688,8 @@ class Panel {
|
|
|
6521
7688
|
// Add reset functionality
|
|
6522
7689
|
Panel._add_reset_property( element.domName, function() {
|
|
6523
7690
|
this.style.display = "none";
|
|
6524
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7691
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7692
|
+
{
|
|
6525
7693
|
v.value = v.iValue;
|
|
6526
7694
|
Panel._dispatch_event( v, "change" );
|
|
6527
7695
|
}
|
|
@@ -6533,8 +7701,8 @@ class Panel {
|
|
|
6533
7701
|
container.className = "lexvector";
|
|
6534
7702
|
container.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
6535
7703
|
|
|
6536
|
-
for( let i = 0; i < num_components; ++i )
|
|
6537
|
-
|
|
7704
|
+
for( let i = 0; i < num_components; ++i )
|
|
7705
|
+
{
|
|
6538
7706
|
let box = document.createElement( 'div' );
|
|
6539
7707
|
box.className = "vecbox";
|
|
6540
7708
|
box.innerHTML = "<span class='" + Panel.VECTOR_COMPONENTS[ i ] + "'></span>";
|
|
@@ -6610,7 +7778,8 @@ class Panel {
|
|
|
6610
7778
|
|
|
6611
7779
|
if( locker.locked )
|
|
6612
7780
|
{
|
|
6613
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7781
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7782
|
+
{
|
|
6614
7783
|
v.value = val;
|
|
6615
7784
|
value[ v.idx ] = val;
|
|
6616
7785
|
}
|
|
@@ -6668,7 +7837,8 @@ class Panel {
|
|
|
6668
7837
|
|
|
6669
7838
|
if( locker.locked )
|
|
6670
7839
|
{
|
|
6671
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7840
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7841
|
+
{
|
|
6672
7842
|
v.value = round( +v.valueAsNumber + mult * dt, options.precision );
|
|
6673
7843
|
Panel._dispatch_event( v, "change" );
|
|
6674
7844
|
}
|
|
@@ -6794,7 +7964,7 @@ class Panel {
|
|
|
6794
7964
|
const value = [];
|
|
6795
7965
|
for( let i = 0; i < element.dimensions.length; ++i )
|
|
6796
7966
|
{
|
|
6797
|
-
value.push( element.dimensions[ i ].
|
|
7967
|
+
value.push( element.dimensions[ i ].value() );
|
|
6798
7968
|
}
|
|
6799
7969
|
return value;
|
|
6800
7970
|
};
|
|
@@ -6802,7 +7972,7 @@ class Panel {
|
|
|
6802
7972
|
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
6803
7973
|
for( let i = 0; i < element.dimensions.length; ++i )
|
|
6804
7974
|
{
|
|
6805
|
-
element.dimensions[ i ].
|
|
7975
|
+
element.dimensions[ i ].set( newValue[ i ], skipCallback );
|
|
6806
7976
|
}
|
|
6807
7977
|
};
|
|
6808
7978
|
|
|
@@ -6817,14 +7987,14 @@ class Panel {
|
|
|
6817
7987
|
{
|
|
6818
7988
|
element.dimensions[ i ] = this.addNumber( null, value[ i ], ( v ) => {
|
|
6819
7989
|
|
|
6820
|
-
const value = widget.
|
|
7990
|
+
const value = widget.value();
|
|
6821
7991
|
|
|
6822
7992
|
if( element.locked )
|
|
6823
7993
|
{
|
|
6824
7994
|
const ar = ( i == 0 ? 1.0 / element.aspectRatio : element.aspectRatio );
|
|
6825
7995
|
const index = ( 1 + i ) % 2;
|
|
6826
7996
|
value[ index ] = v * ar;
|
|
6827
|
-
element.dimensions[ index ].
|
|
7997
|
+
element.dimensions[ index ].set( value[ index ], true );
|
|
6828
7998
|
}
|
|
6829
7999
|
|
|
6830
8000
|
if( callback )
|
|
@@ -6867,7 +8037,7 @@ class Panel {
|
|
|
6867
8037
|
this.classList.remove( "fa-lock-open" );
|
|
6868
8038
|
|
|
6869
8039
|
// Recompute ratio
|
|
6870
|
-
const value = widget.
|
|
8040
|
+
const value = widget.value();
|
|
6871
8041
|
element.aspectRatio = value[ 0 ] / value[ 1 ];
|
|
6872
8042
|
}
|
|
6873
8043
|
else
|
|
@@ -7264,7 +8434,8 @@ class Panel {
|
|
|
7264
8434
|
let container = document.createElement('div');
|
|
7265
8435
|
container.className = "lextree";
|
|
7266
8436
|
|
|
7267
|
-
if(name)
|
|
8437
|
+
if( name )
|
|
8438
|
+
{
|
|
7268
8439
|
let title = document.createElement('span');
|
|
7269
8440
|
title.innerHTML = name;
|
|
7270
8441
|
container.appendChild(title);
|
|
@@ -7276,8 +8447,8 @@ class Panel {
|
|
|
7276
8447
|
toolsDiv.className += " notitle";
|
|
7277
8448
|
|
|
7278
8449
|
// Tree icons
|
|
7279
|
-
if(options.icons)
|
|
7280
|
-
|
|
8450
|
+
if( options.icons )
|
|
8451
|
+
{
|
|
7281
8452
|
for( let data of options.icons )
|
|
7282
8453
|
{
|
|
7283
8454
|
let iconEl = document.createElement('a');
|
|
@@ -7337,11 +8508,15 @@ class Panel {
|
|
|
7337
8508
|
let widget = new Widget( null, Widget.SEPARATOR );
|
|
7338
8509
|
widget.domEl = element;
|
|
7339
8510
|
|
|
7340
|
-
if(this.current_branch)
|
|
8511
|
+
if( this.current_branch )
|
|
8512
|
+
{
|
|
7341
8513
|
this.current_branch.content.appendChild( element );
|
|
7342
8514
|
this.current_branch.widgets.push( widget );
|
|
7343
|
-
}
|
|
7344
|
-
|
|
8515
|
+
}
|
|
8516
|
+
else
|
|
8517
|
+
{
|
|
8518
|
+
this.root.appendChild( element );
|
|
8519
|
+
}
|
|
7345
8520
|
}
|
|
7346
8521
|
|
|
7347
8522
|
/**
|
|
@@ -7666,6 +8841,12 @@ class Panel {
|
|
|
7666
8841
|
|
|
7667
8842
|
input.addEventListener( 'change', function() {
|
|
7668
8843
|
data.checkMap[ rowId ] = this.checked;
|
|
8844
|
+
|
|
8845
|
+
if( !this.checked )
|
|
8846
|
+
{
|
|
8847
|
+
const input = table.querySelector( "thead input[type='checkbox']" );
|
|
8848
|
+
input.checked = data.checkMap[ ":root" ] = false;
|
|
8849
|
+
}
|
|
7669
8850
|
});
|
|
7670
8851
|
|
|
7671
8852
|
row.appendChild( td );
|
|
@@ -7791,7 +8972,7 @@ class Branch {
|
|
|
7791
8972
|
root.appendChild( title );
|
|
7792
8973
|
|
|
7793
8974
|
var branchContent = document.createElement( 'div' );
|
|
7794
|
-
branchContent.id = name.replace(/\s/g, '');
|
|
8975
|
+
branchContent.id = name.replace( /\s/g, '' );
|
|
7795
8976
|
branchContent.className = "lexbranchcontent";
|
|
7796
8977
|
root.appendChild(branchContent);
|
|
7797
8978
|
this.content = branchContent;
|
|
@@ -7847,7 +9028,8 @@ class Branch {
|
|
|
7847
9028
|
|
|
7848
9029
|
const dialog = new Dialog(this.name, p => {
|
|
7849
9030
|
// add widgets
|
|
7850
|
-
for( let w of this.widgets )
|
|
9031
|
+
for( let w of this.widgets )
|
|
9032
|
+
{
|
|
7851
9033
|
p.root.appendChild( w.domEl );
|
|
7852
9034
|
}
|
|
7853
9035
|
});
|
|
@@ -7940,8 +9122,8 @@ class Branch {
|
|
|
7940
9122
|
var size = this.grabber.style.marginLeft;
|
|
7941
9123
|
|
|
7942
9124
|
// Update sizes of widgets inside
|
|
7943
|
-
for(var i = 0; i < this.widgets.length; i++)
|
|
7944
|
-
|
|
9125
|
+
for( var i = 0; i < this.widgets.length; i++ )
|
|
9126
|
+
{
|
|
7945
9127
|
let widget = this.widgets[ i ];
|
|
7946
9128
|
let element = widget.domEl;
|
|
7947
9129
|
|
|
@@ -7960,9 +9142,6 @@ class Branch {
|
|
|
7960
9142
|
case Widget.FILE:
|
|
7961
9143
|
padding = "10%";
|
|
7962
9144
|
break;
|
|
7963
|
-
case Widget.TEXT:
|
|
7964
|
-
padding = "8px";
|
|
7965
|
-
break;
|
|
7966
9145
|
};
|
|
7967
9146
|
|
|
7968
9147
|
value.style.width = "-moz-calc( 100% - " + size + " - " + padding + " )";
|
|
@@ -8101,7 +9280,7 @@ class Dialog {
|
|
|
8101
9280
|
modal = options.modal ?? false;
|
|
8102
9281
|
|
|
8103
9282
|
var root = document.createElement('dialog');
|
|
8104
|
-
root.className = "lexdialog " + (options.
|
|
9283
|
+
root.className = "lexdialog " + (options.className ?? "");
|
|
8105
9284
|
root.id = options.id ?? "dialog" + Dialog._last_id++;
|
|
8106
9285
|
LX.root.appendChild( root );
|
|
8107
9286
|
|
|
@@ -8259,15 +9438,15 @@ class Dialog {
|
|
|
8259
9438
|
|
|
8260
9439
|
root.style.width = size[ 0 ] ? (size[ 0 ]) : "25%";
|
|
8261
9440
|
root.style.height = size[ 1 ] ? (size[ 1 ]) : "auto";
|
|
9441
|
+
root.style.translate = options.position ? "unset" : "-50% -50%";
|
|
8262
9442
|
|
|
8263
9443
|
if( options.size )
|
|
8264
9444
|
{
|
|
8265
9445
|
this.size = size;
|
|
8266
9446
|
}
|
|
8267
9447
|
|
|
8268
|
-
|
|
8269
|
-
root.style.
|
|
8270
|
-
root.style.top = position[ 1 ] ? (position[ 1 ]) : "calc( 50% - " + ( rect.height * 0.5 ) + "px )";
|
|
9448
|
+
root.style.left = position[ 0 ] ?? "50%";
|
|
9449
|
+
root.style.top = position[ 1 ] ?? "50%";
|
|
8271
9450
|
|
|
8272
9451
|
panel.root.style.width = "calc( 100% - 30px )";
|
|
8273
9452
|
panel.root.style.height = title ? "calc( 100% - " + ( titleDiv.offsetHeight + 30 ) + "px )" : "calc( 100% - 51px )";
|
|
@@ -8284,7 +9463,7 @@ class Dialog {
|
|
|
8284
9463
|
this._oncreate.call(this, this.panel);
|
|
8285
9464
|
}
|
|
8286
9465
|
|
|
8287
|
-
setPosition(x, y) {
|
|
9466
|
+
setPosition( x, y ) {
|
|
8288
9467
|
|
|
8289
9468
|
this.root.style.left = x + "px";
|
|
8290
9469
|
this.root.style.top = y + "px";
|
|
@@ -8330,6 +9509,9 @@ class PocketDialog extends Dialog {
|
|
|
8330
9509
|
|
|
8331
9510
|
// Custom
|
|
8332
9511
|
this.root.classList.add( "pocket" );
|
|
9512
|
+
|
|
9513
|
+
this.root.style.translate = "none";
|
|
9514
|
+
this.root.style.top = "0";
|
|
8333
9515
|
this.root.style.left = "unset";
|
|
8334
9516
|
|
|
8335
9517
|
if( !options.position )
|
|
@@ -8345,6 +9527,11 @@ class PocketDialog extends Dialog {
|
|
|
8345
9527
|
this.minimized = false;
|
|
8346
9528
|
this.title.tabIndex = -1;
|
|
8347
9529
|
this.title.addEventListener("click", e => {
|
|
9530
|
+
if( this.title._eventCatched )
|
|
9531
|
+
{
|
|
9532
|
+
this.title._eventCatched = false;
|
|
9533
|
+
return;
|
|
9534
|
+
}
|
|
8348
9535
|
|
|
8349
9536
|
// Sized dialogs have to keep their size
|
|
8350
9537
|
if( this.size )
|
|
@@ -8427,12 +9614,12 @@ class ContextMenu {
|
|
|
8427
9614
|
constructor( event, title, options = {} ) {
|
|
8428
9615
|
|
|
8429
9616
|
// remove all context menus
|
|
8430
|
-
document.body.querySelectorAll(".
|
|
9617
|
+
document.body.querySelectorAll( ".lexcontextmenu" ).forEach( e => e.remove() );
|
|
8431
9618
|
|
|
8432
|
-
this.root = document.createElement(
|
|
8433
|
-
this.root.className = "
|
|
8434
|
-
this.root.style.left = (event.x - 48 + document.scrollingElement.scrollLeft) + "px";
|
|
8435
|
-
this.root.style.top = (event.y - 8 + document.scrollingElement.scrollTop) + "px";
|
|
9619
|
+
this.root = document.createElement( "div" );
|
|
9620
|
+
this.root.className = "lexcontextmenu";
|
|
9621
|
+
this.root.style.left = ( event.x - 48 + document.scrollingElement.scrollLeft ) + "px";
|
|
9622
|
+
this.root.style.top = ( event.y - 8 + document.scrollingElement.scrollTop ) + "px";
|
|
8436
9623
|
|
|
8437
9624
|
this.root.addEventListener("mouseleave", function() {
|
|
8438
9625
|
this.remove();
|
|
@@ -8445,13 +9632,13 @@ class ContextMenu {
|
|
|
8445
9632
|
{
|
|
8446
9633
|
const item = {};
|
|
8447
9634
|
item[ title ] = [];
|
|
8448
|
-
item[
|
|
8449
|
-
item[
|
|
9635
|
+
item[ "className" ] = "cmtitle";
|
|
9636
|
+
item[ "icon" ] = options.icon;
|
|
8450
9637
|
this.items.push( item );
|
|
8451
9638
|
}
|
|
8452
9639
|
}
|
|
8453
9640
|
|
|
8454
|
-
|
|
9641
|
+
_adjustPosition( div, margin, useAbsolute = false ) {
|
|
8455
9642
|
|
|
8456
9643
|
let rect = div.getBoundingClientRect();
|
|
8457
9644
|
|
|
@@ -8492,19 +9679,19 @@ class ContextMenu {
|
|
|
8492
9679
|
}
|
|
8493
9680
|
}
|
|
8494
9681
|
|
|
8495
|
-
|
|
9682
|
+
_createSubmenu( o, k, c, d ) {
|
|
8496
9683
|
|
|
8497
|
-
this.root.querySelectorAll(".
|
|
9684
|
+
this.root.querySelectorAll( ".lexcontextmenu" ).forEach( cm => cm.remove() );
|
|
8498
9685
|
|
|
8499
9686
|
let contextmenu = document.createElement('div');
|
|
8500
|
-
contextmenu.className = "
|
|
9687
|
+
contextmenu.className = "lexcontextmenu";
|
|
8501
9688
|
c.appendChild( contextmenu );
|
|
8502
9689
|
|
|
8503
9690
|
for( var i = 0; i < o[k].length; ++i )
|
|
8504
9691
|
{
|
|
8505
|
-
const subitem = o[k][i];
|
|
8506
|
-
const subkey = Object.keys(subitem)[0];
|
|
8507
|
-
this.
|
|
9692
|
+
const subitem = o[ k ][ i ];
|
|
9693
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
9694
|
+
this._createEntry(subitem, subkey, contextmenu, d);
|
|
8508
9695
|
}
|
|
8509
9696
|
|
|
8510
9697
|
var rect = c.getBoundingClientRect();
|
|
@@ -8512,29 +9699,32 @@ class ContextMenu {
|
|
|
8512
9699
|
contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
|
|
8513
9700
|
|
|
8514
9701
|
// Set final width
|
|
8515
|
-
this.
|
|
9702
|
+
this._adjustPosition( contextmenu, 6, true );
|
|
8516
9703
|
}
|
|
8517
9704
|
|
|
8518
|
-
|
|
9705
|
+
_createEntry( o, k, c, d ) {
|
|
8519
9706
|
|
|
8520
9707
|
const hasSubmenu = o[ k ].length;
|
|
8521
9708
|
let entry = document.createElement('div');
|
|
8522
|
-
entry.className = "
|
|
9709
|
+
entry.className = "lexmenuboxentry" + (o[ 'className' ] ? " " + o[ 'className' ] : "" );
|
|
8523
9710
|
entry.id = o.id ?? ("eId" + getSupportedDOMName( k ));
|
|
8524
9711
|
entry.innerHTML = "";
|
|
8525
9712
|
const icon = o[ 'icon' ];
|
|
8526
|
-
if(icon)
|
|
9713
|
+
if( icon )
|
|
9714
|
+
{
|
|
8527
9715
|
entry.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
8528
9716
|
}
|
|
8529
9717
|
const disabled = o['disabled'];
|
|
8530
9718
|
entry.innerHTML += "<div class='lexentryname" + (disabled ? " disabled" : "") + "'>" + k + "</div>";
|
|
8531
9719
|
c.appendChild( entry );
|
|
8532
9720
|
|
|
8533
|
-
if( this.colors[ k ] )
|
|
9721
|
+
if( this.colors[ k ] )
|
|
9722
|
+
{
|
|
8534
9723
|
entry.style.borderColor = this.colors[ k ];
|
|
8535
9724
|
}
|
|
8536
9725
|
|
|
8537
|
-
if( k == "" )
|
|
9726
|
+
if( k == "" )
|
|
9727
|
+
{
|
|
8538
9728
|
entry.className += " cmseparator";
|
|
8539
9729
|
return;
|
|
8540
9730
|
}
|
|
@@ -8547,7 +9737,8 @@ class ContextMenu {
|
|
|
8547
9737
|
if(disabled) return;
|
|
8548
9738
|
|
|
8549
9739
|
const f = o[ 'callback' ];
|
|
8550
|
-
if(f)
|
|
9740
|
+
if( f )
|
|
9741
|
+
{
|
|
8551
9742
|
f.call( this, k, entry );
|
|
8552
9743
|
this.root.remove();
|
|
8553
9744
|
}
|
|
@@ -8556,7 +9747,7 @@ class ContextMenu {
|
|
|
8556
9747
|
return;
|
|
8557
9748
|
|
|
8558
9749
|
if( LX.OPEN_CONTEXTMENU_ENTRY == 'click' )
|
|
8559
|
-
this.
|
|
9750
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
8560
9751
|
});
|
|
8561
9752
|
|
|
8562
9753
|
if( !hasSubmenu )
|
|
@@ -8572,20 +9763,19 @@ class ContextMenu {
|
|
|
8572
9763
|
if(entry.built)
|
|
8573
9764
|
return;
|
|
8574
9765
|
entry.built = true;
|
|
8575
|
-
this.
|
|
9766
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
8576
9767
|
e.stopPropagation();
|
|
8577
9768
|
});
|
|
8578
9769
|
}
|
|
8579
9770
|
|
|
8580
9771
|
entry.addEventListener("mouseleave", () => {
|
|
8581
9772
|
d = -1; // Reset depth
|
|
8582
|
-
|
|
8583
|
-
c.querySelectorAll(".lexcontextmenubox").forEach(e => e.remove());
|
|
9773
|
+
c.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
8584
9774
|
});
|
|
8585
9775
|
}
|
|
8586
9776
|
|
|
8587
9777
|
onCreate() {
|
|
8588
|
-
doAsync( () => this.
|
|
9778
|
+
doAsync( () => this._adjustPosition( this.root, 6 ) );
|
|
8589
9779
|
}
|
|
8590
9780
|
|
|
8591
9781
|
add( path, options = {} ) {
|
|
@@ -8613,22 +9803,25 @@ class ContextMenu {
|
|
|
8613
9803
|
if(key) found = o[ key ];
|
|
8614
9804
|
} );
|
|
8615
9805
|
|
|
8616
|
-
if(found)
|
|
8617
|
-
|
|
9806
|
+
if( found )
|
|
9807
|
+
{
|
|
9808
|
+
insert( tokens[ idx++ ], found );
|
|
8618
9809
|
}
|
|
8619
|
-
else
|
|
9810
|
+
else
|
|
9811
|
+
{
|
|
8620
9812
|
let item = {};
|
|
8621
9813
|
item[ token ] = [];
|
|
8622
|
-
const
|
|
9814
|
+
const nextToken = tokens[ idx++ ];
|
|
8623
9815
|
// Check if last token -> add callback
|
|
8624
|
-
if(!
|
|
9816
|
+
if( !nextToken )
|
|
9817
|
+
{
|
|
8625
9818
|
item[ 'id' ] = options.id;
|
|
8626
9819
|
item[ 'callback' ] = options.callback;
|
|
8627
9820
|
item[ 'disabled' ] = options.disabled ?? false;
|
|
8628
9821
|
}
|
|
8629
9822
|
|
|
8630
9823
|
list.push( item );
|
|
8631
|
-
insert(
|
|
9824
|
+
insert( nextToken, item[ token ] );
|
|
8632
9825
|
}
|
|
8633
9826
|
};
|
|
8634
9827
|
|
|
@@ -8638,13 +9831,15 @@ class ContextMenu {
|
|
|
8638
9831
|
|
|
8639
9832
|
const setParent = _item => {
|
|
8640
9833
|
|
|
8641
|
-
let key = Object.keys(_item)[0];
|
|
9834
|
+
let key = Object.keys( _item )[ 0 ];
|
|
8642
9835
|
let children = _item[ key ];
|
|
8643
9836
|
|
|
8644
|
-
if(!children.length)
|
|
9837
|
+
if( !children.length )
|
|
9838
|
+
{
|
|
8645
9839
|
return;
|
|
9840
|
+
}
|
|
8646
9841
|
|
|
8647
|
-
if(children.find( c => Object.keys(c)[0] == key ) == null)
|
|
9842
|
+
if( children.find( c => Object.keys(c)[0] == key ) == null )
|
|
8648
9843
|
{
|
|
8649
9844
|
const parent = {};
|
|
8650
9845
|
parent[ key ] = [];
|
|
@@ -8652,27 +9847,34 @@ class ContextMenu {
|
|
|
8652
9847
|
_item[ key ].unshift( parent );
|
|
8653
9848
|
}
|
|
8654
9849
|
|
|
8655
|
-
for( var child of _item[ key ] )
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
9850
|
+
for( var child of _item[ key ] )
|
|
9851
|
+
{
|
|
9852
|
+
let k = Object.keys( child )[ 0 ];
|
|
9853
|
+
for( var i = 0; i < child[ k ].length; ++i )
|
|
9854
|
+
{
|
|
9855
|
+
setParent( child );
|
|
9856
|
+
}
|
|
8659
9857
|
}
|
|
8660
9858
|
};
|
|
8661
9859
|
|
|
8662
9860
|
for( let item of this.items )
|
|
8663
|
-
|
|
9861
|
+
{
|
|
9862
|
+
setParent( item );
|
|
9863
|
+
}
|
|
8664
9864
|
|
|
8665
9865
|
// Create elements
|
|
8666
9866
|
|
|
8667
9867
|
for( let item of this.items )
|
|
8668
9868
|
{
|
|
8669
|
-
let key = Object.keys(item)[0];
|
|
9869
|
+
let key = Object.keys( item )[ 0 ];
|
|
8670
9870
|
let pKey = "eId" + getSupportedDOMName( key );
|
|
8671
9871
|
|
|
8672
9872
|
// Item already created
|
|
8673
|
-
const id = "#" + (item.id ?? pKey);
|
|
8674
|
-
if( !this.root.querySelector(id) )
|
|
8675
|
-
|
|
9873
|
+
const id = "#" + ( item.id ?? pKey );
|
|
9874
|
+
if( !this.root.querySelector( id ) )
|
|
9875
|
+
{
|
|
9876
|
+
this._createEntry( item, key, this.root, -1 );
|
|
9877
|
+
}
|
|
8676
9878
|
}
|
|
8677
9879
|
}
|
|
8678
9880
|
|
|
@@ -8783,7 +9985,7 @@ class Curve {
|
|
|
8783
9985
|
|
|
8784
9986
|
var r = [];
|
|
8785
9987
|
var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
|
|
8786
|
-
for(var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
9988
|
+
for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx )
|
|
8787
9989
|
{
|
|
8788
9990
|
r.push( element.getValueAt(i) );
|
|
8789
9991
|
}
|
|
@@ -8792,7 +9994,8 @@ class Curve {
|
|
|
8792
9994
|
|
|
8793
9995
|
element.addValue = function(v) {
|
|
8794
9996
|
|
|
8795
|
-
for(var i = 0; i < element.value; i++)
|
|
9997
|
+
for( var i = 0; i < element.value; i++ )
|
|
9998
|
+
{
|
|
8796
9999
|
var value = element.value[i];
|
|
8797
10000
|
if(value[0] < v[0]) continue;
|
|
8798
10001
|
element.value.splice(i,0,v);
|
|
@@ -8818,7 +10021,7 @@ class Curve {
|
|
|
8818
10021
|
|
|
8819
10022
|
var selected = -1;
|
|
8820
10023
|
|
|
8821
|
-
element.redraw = function( o = {} )
|
|
10024
|
+
element.redraw = function( o = {} ) {
|
|
8822
10025
|
|
|
8823
10026
|
if( o.value ) element.value = o.value;
|
|
8824
10027
|
if( o.xrange ) element.xrange = o.xrange;
|
|
@@ -8847,13 +10050,16 @@ class Curve {
|
|
|
8847
10050
|
ctx.moveTo( pos[ 0 ], pos[ 1 ] );
|
|
8848
10051
|
let values = [pos[ 0 ], pos[ 1 ]];
|
|
8849
10052
|
|
|
8850
|
-
for(var i in element.value)
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
values.push(pos[
|
|
8855
|
-
|
|
10053
|
+
for( var i in element.value )
|
|
10054
|
+
{
|
|
10055
|
+
var value = element.value[ i ];
|
|
10056
|
+
pos = convert( value );
|
|
10057
|
+
values.push( pos[ 0 ] );
|
|
10058
|
+
values.push( pos[ 1 ] );
|
|
10059
|
+
if( !element.smooth )
|
|
10060
|
+
{
|
|
8856
10061
|
ctx.lineTo( pos[ 0 ], pos[ 1 ] );
|
|
10062
|
+
}
|
|
8857
10063
|
}
|
|
8858
10064
|
|
|
8859
10065
|
pos = convert([ element.xrange[ 1 ], element.defaulty ]);
|
|
@@ -8870,7 +10076,8 @@ class Curve {
|
|
|
8870
10076
|
}
|
|
8871
10077
|
|
|
8872
10078
|
// Draw points
|
|
8873
|
-
for( var i = 0; i < element.value.length; i += 1 )
|
|
10079
|
+
for( var i = 0; i < element.value.length; i += 1 )
|
|
10080
|
+
{
|
|
8874
10081
|
var value = element.value[ i ];
|
|
8875
10082
|
pos = convert( value );
|
|
8876
10083
|
if( selected == i )
|
|
@@ -8882,10 +10089,11 @@ class Curve {
|
|
|
8882
10089
|
ctx.fill();
|
|
8883
10090
|
}
|
|
8884
10091
|
|
|
8885
|
-
if(element.show_samples)
|
|
10092
|
+
if( element.show_samples )
|
|
10093
|
+
{
|
|
8886
10094
|
var samples = element.resample(element.show_samples);
|
|
8887
10095
|
ctx.fillStyle = "#888";
|
|
8888
|
-
for(var i = 0; i < samples.length; i += 1)
|
|
10096
|
+
for( var i = 0; i < samples.length; i += 1)
|
|
8889
10097
|
{
|
|
8890
10098
|
var value = [ i * ((element.xrange[ 1 ] - element.xrange[ 0 ]) / element.show_samples) + element.xrange[ 0 ], samples[ i ] ];
|
|
8891
10099
|
pos = convert(value);
|
|
@@ -8908,7 +10116,8 @@ class Curve {
|
|
|
8908
10116
|
|
|
8909
10117
|
selected = computeSelected( mousex, canvas.height - mousey );
|
|
8910
10118
|
|
|
8911
|
-
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10119
|
+
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10120
|
+
{
|
|
8912
10121
|
var v = unconvert([ mousex, canvas.height - mousey ]);
|
|
8913
10122
|
element.value.push( v );
|
|
8914
10123
|
sortValues();
|
|
@@ -8956,7 +10165,8 @@ class Curve {
|
|
|
8956
10165
|
var dy = element.draggable_y ? last_mouse[ 1 ] - mousey : 0;
|
|
8957
10166
|
var delta = unconvert([ -dx, dy ]);
|
|
8958
10167
|
|
|
8959
|
-
if( selected != -1 )
|
|
10168
|
+
if( selected != -1 )
|
|
10169
|
+
{
|
|
8960
10170
|
var minx = element.xrange[ 0 ];
|
|
8961
10171
|
var maxx = element.xrange[ 1 ];
|
|
8962
10172
|
|
|
@@ -9113,7 +10323,7 @@ class Dial {
|
|
|
9113
10323
|
|
|
9114
10324
|
var r = [];
|
|
9115
10325
|
var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
|
|
9116
|
-
for(var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
10326
|
+
for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
9117
10327
|
{
|
|
9118
10328
|
r.push( element.getValueAt(i) );
|
|
9119
10329
|
}
|
|
@@ -9122,15 +10332,16 @@ class Dial {
|
|
|
9122
10332
|
|
|
9123
10333
|
element.addValue = function(v) {
|
|
9124
10334
|
|
|
9125
|
-
for(var i = 0; i < element.value; i++)
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
10335
|
+
for( var i = 0; i < element.value; i++ )
|
|
10336
|
+
{
|
|
10337
|
+
var value = element.value[ i ];
|
|
10338
|
+
if(value[ 0 ] < v[ 0 ]) continue;
|
|
10339
|
+
element.value.splice( i, 0, v );
|
|
9129
10340
|
redraw();
|
|
9130
10341
|
return;
|
|
9131
10342
|
}
|
|
9132
10343
|
|
|
9133
|
-
element.value.push(v);
|
|
10344
|
+
element.value.push( v );
|
|
9134
10345
|
redraw();
|
|
9135
10346
|
}
|
|
9136
10347
|
|
|
@@ -9150,7 +10361,7 @@ class Dial {
|
|
|
9150
10361
|
|
|
9151
10362
|
var selected = -1;
|
|
9152
10363
|
|
|
9153
|
-
element.redraw = function( o = {} )
|
|
10364
|
+
element.redraw = function( o = {} ) {
|
|
9154
10365
|
|
|
9155
10366
|
if( o.value ) element.value = o.value;
|
|
9156
10367
|
if( o.xrange ) element.xrange = o.xrange;
|
|
@@ -9179,17 +10390,17 @@ class Dial {
|
|
|
9179
10390
|
ctx.moveTo( pos[ 0 ], pos[ 1 ] );
|
|
9180
10391
|
let values = [pos[ 0 ], pos[ 1 ]];
|
|
9181
10392
|
|
|
9182
|
-
for(var i in element.value)
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
values.push(pos[
|
|
9187
|
-
|
|
10393
|
+
for( var i in element.value)
|
|
10394
|
+
{
|
|
10395
|
+
var value = element.value[ i ];
|
|
10396
|
+
pos = convert( value );
|
|
10397
|
+
values.push( pos[ 0 ] );
|
|
10398
|
+
values.push( pos[ 1 ] );
|
|
9188
10399
|
}
|
|
9189
10400
|
|
|
9190
10401
|
pos = convert([ element.xrange[ 1 ], element.defaulty ]);
|
|
9191
|
-
values.push(pos[ 0 ]);
|
|
9192
|
-
values.push(pos[ 1 ]);
|
|
10402
|
+
values.push( pos[ 0 ] );
|
|
10403
|
+
values.push( pos[ 1 ] );
|
|
9193
10404
|
|
|
9194
10405
|
// Draw points
|
|
9195
10406
|
const center = [0,0];
|
|
@@ -9199,7 +10410,8 @@ class Dial {
|
|
|
9199
10410
|
ctx.arc( pos[ 0 ], pos[ 1 ], 3, 0, Math.PI * 2);
|
|
9200
10411
|
ctx.fill();
|
|
9201
10412
|
|
|
9202
|
-
for( var i = 0; i < element.value.length; i += 1 )
|
|
10413
|
+
for( var i = 0; i < element.value.length; i += 1 )
|
|
10414
|
+
{
|
|
9203
10415
|
var value = element.value[ i ];
|
|
9204
10416
|
pos = convert( value );
|
|
9205
10417
|
if( selected == i )
|
|
@@ -9211,10 +10423,11 @@ class Dial {
|
|
|
9211
10423
|
ctx.fill();
|
|
9212
10424
|
}
|
|
9213
10425
|
|
|
9214
|
-
if(element.show_samples)
|
|
10426
|
+
if( element.show_samples )
|
|
10427
|
+
{
|
|
9215
10428
|
var samples = element.resample(element.show_samples);
|
|
9216
10429
|
ctx.fillStyle = "#888";
|
|
9217
|
-
for(var i = 0; i < samples.length; i += 1)
|
|
10430
|
+
for( var i = 0; i < samples.length; i += 1)
|
|
9218
10431
|
{
|
|
9219
10432
|
var value = [ i * ((element.xrange[ 1 ] - element.xrange[ 0 ]) / element.show_samples) + element.xrange[ 0 ], samples[ i ] ];
|
|
9220
10433
|
pos = convert(value);
|
|
@@ -9237,7 +10450,8 @@ class Dial {
|
|
|
9237
10450
|
|
|
9238
10451
|
selected = computeSelected( mousex, canvas.height - mousey );
|
|
9239
10452
|
|
|
9240
|
-
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10453
|
+
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10454
|
+
{
|
|
9241
10455
|
var v = unconvert([ mousex, canvas.height - mousey ]);
|
|
9242
10456
|
element.value.push( v );
|
|
9243
10457
|
sortValues();
|
|
@@ -9285,7 +10499,8 @@ class Dial {
|
|
|
9285
10499
|
var dy = element.draggable_y ? last_mouse[ 1 ] - mousey : 0;
|
|
9286
10500
|
var delta = unconvert([ -dx, dy ]);
|
|
9287
10501
|
|
|
9288
|
-
if( selected != -1 )
|
|
10502
|
+
if( selected != -1 )
|
|
10503
|
+
{
|
|
9289
10504
|
var minx = element.xrange[ 0 ];
|
|
9290
10505
|
var maxx = element.xrange[ 1 ];
|
|
9291
10506
|
|
|
@@ -9393,7 +10608,8 @@ class AssetViewEvent {
|
|
|
9393
10608
|
}
|
|
9394
10609
|
|
|
9395
10610
|
string() {
|
|
9396
|
-
switch(this.type)
|
|
10611
|
+
switch(this.type)
|
|
10612
|
+
{
|
|
9397
10613
|
case AssetViewEvent.NONE: return "assetview_event_none";
|
|
9398
10614
|
case AssetViewEvent.ASSET_SELECTED: return "assetview_event_selected";
|
|
9399
10615
|
case AssetViewEvent.ASSET_DELETED: return "assetview_event_deleted";
|
|
@@ -9747,8 +10963,8 @@ class AssetView {
|
|
|
9747
10963
|
icon: "fa-solid fa-arrows-rotate",
|
|
9748
10964
|
callback: domEl => { this._refreshContent(); }
|
|
9749
10965
|
}
|
|
9750
|
-
], { width: "
|
|
9751
|
-
this.rightPanel.addText(null, this.path.join('/'), null, { disabled: true, signal: "@on_folder_change", style: { fontWeight: "bolder", fontSize: "16px", color: "#aaa" } });
|
|
10966
|
+
], { width: "20%", minWidth: "164px", noSelection: true } );
|
|
10967
|
+
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" } });
|
|
9752
10968
|
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"})
|
|
9753
10969
|
this.rightPanel.endLine();
|
|
9754
10970
|
}
|
|
@@ -9874,8 +11090,8 @@ class AssetView {
|
|
|
9874
11090
|
title.innerText = item.id;
|
|
9875
11091
|
itemEl.appendChild( title );
|
|
9876
11092
|
|
|
9877
|
-
if( !that.skipPreview )
|
|
9878
|
-
|
|
11093
|
+
if( !that.skipPreview )
|
|
11094
|
+
{
|
|
9879
11095
|
let preview = null;
|
|
9880
11096
|
const hasImage = item.src && (['png', 'jpg'].indexOf( getExtension( item.src ) ) > -1 || item.src.includes("data:image/") ); // Support b64 image as src
|
|
9881
11097
|
|
|
@@ -9902,7 +11118,8 @@ class AssetView {
|
|
|
9902
11118
|
var newEmSize = charsPerLine / newLength;
|
|
9903
11119
|
var textBaseSize = 64;
|
|
9904
11120
|
|
|
9905
|
-
if(newEmSize < 1)
|
|
11121
|
+
if( newEmSize < 1 )
|
|
11122
|
+
{
|
|
9906
11123
|
var newFontSize = newEmSize * textBaseSize;
|
|
9907
11124
|
textEl.style.fontSize = newFontSize + "px";
|
|
9908
11125
|
preview.style.paddingTop = "calc(50% - " + (textEl.offsetHeight * 0.5 + 10) + "px)"
|
|
@@ -10131,7 +11348,8 @@ class AssetView {
|
|
|
10131
11348
|
|
|
10132
11349
|
this.currentData.push( item );
|
|
10133
11350
|
|
|
10134
|
-
if(i == (num_files - 1))
|
|
11351
|
+
if( i == (num_files - 1) )
|
|
11352
|
+
{
|
|
10135
11353
|
this._refreshContent();
|
|
10136
11354
|
if( !this.skipBrowser )
|
|
10137
11355
|
this.tree.refresh();
|
|
@@ -10183,7 +11401,7 @@ class AssetView {
|
|
|
10183
11401
|
this.currentData.splice( idx, 1 );
|
|
10184
11402
|
this._refreshContent( this.searchValue, this.filter );
|
|
10185
11403
|
|
|
10186
|
-
if(this.onevent)
|
|
11404
|
+
if( this.onevent)
|
|
10187
11405
|
{
|
|
10188
11406
|
const event = new AssetViewEvent( AssetViewEvent.ASSET_DELETED, item );
|
|
10189
11407
|
this.onevent( event );
|
|
@@ -10259,7 +11477,7 @@ Object.assign(LX, {
|
|
|
10259
11477
|
xhr.onload = function(load)
|
|
10260
11478
|
{
|
|
10261
11479
|
var response = this.response;
|
|
10262
|
-
if(this.status != 200)
|
|
11480
|
+
if( this.status != 200)
|
|
10263
11481
|
{
|
|
10264
11482
|
var err = "Error " + this.status;
|
|
10265
11483
|
if(request.error)
|
|
@@ -10307,7 +11525,7 @@ Object.assign(LX, {
|
|
|
10307
11525
|
var data = new FormData();
|
|
10308
11526
|
if( request.data )
|
|
10309
11527
|
{
|
|
10310
|
-
for(var i in request.data)
|
|
11528
|
+
for( var i in request.data)
|
|
10311
11529
|
data.append(i,request.data[i]);
|
|
10312
11530
|
}
|
|
10313
11531
|
|
|
@@ -10368,7 +11586,7 @@ Object.assign(LX, {
|
|
|
10368
11586
|
var size = total;
|
|
10369
11587
|
var loaded_scripts = [];
|
|
10370
11588
|
|
|
10371
|
-
for(var i in url)
|
|
11589
|
+
for( var i in url)
|
|
10372
11590
|
{
|
|
10373
11591
|
var script = document.createElement('script');
|
|
10374
11592
|
script.num = i;
|
|
@@ -10493,6 +11711,18 @@ Element.prototype.getParentArea = function() {
|
|
|
10493
11711
|
}
|
|
10494
11712
|
}
|
|
10495
11713
|
|
|
11714
|
+
LX.ICONS = {
|
|
11715
|
+
"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>`,
|
|
11716
|
+
"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>`,
|
|
11717
|
+
"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>`,
|
|
11718
|
+
"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>`,
|
|
11719
|
+
"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>`,
|
|
11720
|
+
"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>`,
|
|
11721
|
+
"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>`,
|
|
11722
|
+
"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>`,
|
|
11723
|
+
"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>`,
|
|
11724
|
+
}
|
|
11725
|
+
|
|
10496
11726
|
LX.UTILS = {
|
|
10497
11727
|
getTime() { return new Date().getTime() },
|
|
10498
11728
|
compareThreshold( v, p, n, t ) { return Math.abs(v - p) >= t || Math.abs(v - n) >= t },
|
|
@@ -10532,17 +11762,19 @@ LX.UTILS = {
|
|
|
10532
11762
|
drawSpline( ctx, pts, t ) {
|
|
10533
11763
|
|
|
10534
11764
|
ctx.save();
|
|
10535
|
-
var cp=[]; // array of control points, as x0,y0,x1,y1,...
|
|
10536
|
-
var n=pts.length;
|
|
11765
|
+
var cp = []; // array of control points, as x0,y0,x1,y1,...
|
|
11766
|
+
var n = pts.length;
|
|
10537
11767
|
|
|
10538
11768
|
// Draw an open curve, not connected at the ends
|
|
10539
|
-
for(var i=0;i<n-4;i+=2)
|
|
10540
|
-
|
|
11769
|
+
for( var i = 0; i < (n - 4); i += 2 )
|
|
11770
|
+
{
|
|
11771
|
+
cp = cp.concat(LX.UTILS.getControlPoints(pts[i],pts[i+1],pts[i+2],pts[i+3],pts[i+4],pts[i+5],t));
|
|
10541
11772
|
}
|
|
10542
11773
|
|
|
10543
|
-
for(var i=2;i<pts.length-5;i+=2)
|
|
11774
|
+
for( var i = 2; i < ( pts.length - 5 ); i += 2 )
|
|
11775
|
+
{
|
|
10544
11776
|
ctx.beginPath();
|
|
10545
|
-
ctx.moveTo(pts[i],pts[i+1]);
|
|
11777
|
+
ctx.moveTo(pts[i], pts[i+1]);
|
|
10546
11778
|
ctx.bezierCurveTo(cp[2*i-2],cp[2*i-1],cp[2*i],cp[2*i+1],pts[i+2],pts[i+3]);
|
|
10547
11779
|
ctx.stroke();
|
|
10548
11780
|
ctx.closePath();
|
|
@@ -10550,14 +11782,14 @@ LX.UTILS = {
|
|
|
10550
11782
|
|
|
10551
11783
|
// For open curves the first and last arcs are simple quadratics.
|
|
10552
11784
|
ctx.beginPath();
|
|
10553
|
-
ctx.moveTo(pts[0],pts[1]);
|
|
10554
|
-
ctx.quadraticCurveTo(cp[0],cp[1],pts[2],pts[3]);
|
|
11785
|
+
ctx.moveTo( pts[ 0 ], pts[ 1 ] );
|
|
11786
|
+
ctx.quadraticCurveTo( cp[ 0 ], cp[ 1 ], pts[ 2 ], pts[ 3 ]);
|
|
10555
11787
|
ctx.stroke();
|
|
10556
11788
|
ctx.closePath();
|
|
10557
11789
|
|
|
10558
11790
|
ctx.beginPath();
|
|
10559
|
-
ctx.moveTo(pts[n-2],pts[n-1]);
|
|
10560
|
-
ctx.quadraticCurveTo(cp[2*n-10],cp[2*n-9],pts[n-4],pts[n-3]);
|
|
11791
|
+
ctx.moveTo( pts[ n-2 ], pts[ n-1 ] );
|
|
11792
|
+
ctx.quadraticCurveTo( cp[ 2*n-10 ], cp[ 2*n-9 ], pts[ n-4 ], pts[ n-3 ]);
|
|
10561
11793
|
ctx.stroke();
|
|
10562
11794
|
ctx.closePath();
|
|
10563
11795
|
|