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.js
CHANGED
|
@@ -12,23 +12,26 @@ console.warn( 'Script _build/lexgui.js_ is depracated and will be removed soon.
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
var LX = {
|
|
15
|
-
version: "0.
|
|
15
|
+
version: "0.4.1",
|
|
16
16
|
ready: false,
|
|
17
|
-
components: [], //
|
|
18
|
-
signals: {}, //
|
|
19
|
-
extraCommandbarEntries: [] //
|
|
17
|
+
components: [], // Specific pre-build components
|
|
18
|
+
signals: {}, // Events and triggers
|
|
19
|
+
extraCommandbarEntries: [], // User specific entries for command bar
|
|
20
|
+
activeDraggable: null // Watch for the current active draggable
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
LX.MOUSE_LEFT_CLICK = 0;
|
|
23
24
|
LX.MOUSE_MIDDLE_CLICK = 1;
|
|
24
25
|
LX.MOUSE_RIGHT_CLICK = 2;
|
|
25
26
|
|
|
26
|
-
LX.MOUSE_DOUBLE_CLICK
|
|
27
|
-
LX.MOUSE_TRIPLE_CLICK
|
|
27
|
+
LX.MOUSE_DOUBLE_CLICK = 2;
|
|
28
|
+
LX.MOUSE_TRIPLE_CLICK = 3;
|
|
28
29
|
|
|
29
|
-
LX.CURVE_MOVEOUT_CLAMP
|
|
30
|
+
LX.CURVE_MOVEOUT_CLAMP = 0;
|
|
30
31
|
LX.CURVE_MOVEOUT_DELETE = 1;
|
|
31
32
|
|
|
33
|
+
LX.DRAGGABLE_Z_INDEX = 101;
|
|
34
|
+
|
|
32
35
|
function clamp( num, min, max ) { return Math.min( Math.max( num, min ), max ); }
|
|
33
36
|
function round( number, precision ) { return precision == 0 ? Math.floor( number ) : +(( number ).toFixed( precision ?? 2 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' )); }
|
|
34
37
|
function remapRange( oldValue, oldMin, oldMax, newMin, newMax ) { return ((( oldValue - oldMin ) * ( newMax - newMin )) / ( oldMax - oldMin )) + newMin; }
|
|
@@ -88,7 +91,7 @@ LX.doAsync = doAsync;
|
|
|
88
91
|
*/
|
|
89
92
|
function getSupportedDOMName( text )
|
|
90
93
|
{
|
|
91
|
-
return text.replace(/\s/g, '').replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll('.', '');
|
|
94
|
+
return text.replace( /\s/g, '' ).replaceAll('@', '_').replaceAll('+', '_plus_').replaceAll( '.', '' );
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
LX.getSupportedDOMName = getSupportedDOMName;
|
|
@@ -227,7 +230,8 @@ LX.hexToRgb = hexToRgb;
|
|
|
227
230
|
function rgbToHex( rgb )
|
|
228
231
|
{
|
|
229
232
|
let hex = "#";
|
|
230
|
-
for( let c of rgb )
|
|
233
|
+
for( let c of rgb )
|
|
234
|
+
{
|
|
231
235
|
c = Math.floor( c * 255 );
|
|
232
236
|
hex += c.toString( 16 );
|
|
233
237
|
}
|
|
@@ -302,7 +306,7 @@ LX.buildTextPattern = buildTextPattern;
|
|
|
302
306
|
|
|
303
307
|
/**
|
|
304
308
|
* @method makeDraggable
|
|
305
|
-
* @description
|
|
309
|
+
* @description Allows an element to be dragged
|
|
306
310
|
* @param {Element} domEl
|
|
307
311
|
* @param {Object} options
|
|
308
312
|
* autoAdjust (Bool): Sets in a correct position at the beggining
|
|
@@ -327,6 +331,7 @@ function makeDraggable( domEl, options = { } )
|
|
|
327
331
|
top = top ?? e.clientY - offsetY - parentRect.y;
|
|
328
332
|
domEl.style.left = clamp( left, dragMargin + fixedOffset.x, fixedOffset.x + parentRect.width - domEl.offsetWidth - dragMargin ) + 'px';
|
|
329
333
|
domEl.style.top = clamp( top, dragMargin + fixedOffset.y, fixedOffset.y + parentRect.height - domEl.offsetHeight - dragMargin ) + 'px';
|
|
334
|
+
domEl.style.translate = "none"; // Force remove translation
|
|
330
335
|
};
|
|
331
336
|
|
|
332
337
|
// Initial adjustment
|
|
@@ -371,26 +376,45 @@ function makeDraggable( domEl, options = { } )
|
|
|
371
376
|
e.preventDefault();
|
|
372
377
|
e.stopPropagation();
|
|
373
378
|
e.stopImmediatePropagation();
|
|
374
|
-
|
|
379
|
+
|
|
380
|
+
if( !currentTarget )
|
|
381
|
+
{
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
375
385
|
// Remove image when dragging
|
|
376
386
|
var img = new Image();
|
|
377
387
|
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=';
|
|
378
388
|
e.dataTransfer.setDragImage( img, 0, 0 );
|
|
379
389
|
e.dataTransfer.effectAllowed = "move";
|
|
390
|
+
|
|
380
391
|
const rect = e.target.getBoundingClientRect();
|
|
381
392
|
const parentRect = currentTarget.parentElement.getBoundingClientRect();
|
|
382
393
|
const isFixed = ( currentTarget.style.position == "fixed" );
|
|
383
394
|
const fixedOffset = isFixed ? new LX.vec2( parentRect.x, parentRect.y ) : new LX.vec2();
|
|
384
395
|
offsetX = e.clientX - rect.x - fixedOffset.x;
|
|
385
396
|
offsetY = e.clientY - rect.y - fixedOffset.y;
|
|
397
|
+
|
|
386
398
|
document.addEventListener( "mousemove", onMove );
|
|
399
|
+
|
|
400
|
+
currentTarget._eventCatched = true;
|
|
401
|
+
|
|
402
|
+
// Force active dialog to show on top
|
|
403
|
+
if( LX.activeDraggable )
|
|
404
|
+
{
|
|
405
|
+
LX.activeDraggable.style.zIndex = LX.DRAGGABLE_Z_INDEX;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
LX.activeDraggable = domEl;
|
|
409
|
+
LX.activeDraggable.style.zIndex = LX.DRAGGABLE_Z_INDEX + 1;
|
|
410
|
+
|
|
387
411
|
if( onDragStart )
|
|
388
412
|
{
|
|
389
413
|
onDragStart( currentTarget, e );
|
|
390
414
|
}
|
|
391
415
|
}, false );
|
|
392
416
|
|
|
393
|
-
document.addEventListener( 'mouseup', () => {
|
|
417
|
+
document.addEventListener( 'mouseup', (e) => {
|
|
394
418
|
if( currentTarget )
|
|
395
419
|
{
|
|
396
420
|
currentTarget = null;
|
|
@@ -401,6 +425,48 @@ function makeDraggable( domEl, options = { } )
|
|
|
401
425
|
|
|
402
426
|
LX.makeDraggable = makeDraggable;
|
|
403
427
|
|
|
428
|
+
/**
|
|
429
|
+
* @method makeCollapsible
|
|
430
|
+
* @description Allows an element to be collapsed/expanded
|
|
431
|
+
* @param {Element} domEl: Element to be treated as collapsible
|
|
432
|
+
* @param {Element} content: Content to display/hide on collapse/extend
|
|
433
|
+
* @param {Element} parent: Element where the content will be appended (default is domEl.parent)
|
|
434
|
+
* @param {Object} options
|
|
435
|
+
*/
|
|
436
|
+
function makeCollapsible( domEl, content, parent, options = { } )
|
|
437
|
+
{
|
|
438
|
+
domEl.classList.add( "collapsible" );
|
|
439
|
+
|
|
440
|
+
const collapsed = ( options.collapsed ?? true );
|
|
441
|
+
const actionIcon = LX.makeIcon( "Right" );
|
|
442
|
+
actionIcon.classList.add( "collapser" );
|
|
443
|
+
actionIcon.dataset[ "collapsed" ] = collapsed;
|
|
444
|
+
actionIcon.style.marginLeft = "auto";
|
|
445
|
+
|
|
446
|
+
actionIcon.addEventListener( "click", function(e) {
|
|
447
|
+
e.preventDefault();
|
|
448
|
+
e.stopPropagation();
|
|
449
|
+
if( this.dataset[ "collapsed" ] )
|
|
450
|
+
{
|
|
451
|
+
delete this.dataset[ "collapsed" ];
|
|
452
|
+
content.style.display = "block";
|
|
453
|
+
}
|
|
454
|
+
else
|
|
455
|
+
{
|
|
456
|
+
this.dataset[ "collapsed" ] = true;
|
|
457
|
+
content.style.display = "none";
|
|
458
|
+
}
|
|
459
|
+
} );
|
|
460
|
+
|
|
461
|
+
domEl.appendChild( actionIcon );
|
|
462
|
+
|
|
463
|
+
parent = parent ?? domEl.parentElement;
|
|
464
|
+
|
|
465
|
+
parent.appendChild( content );
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
LX.makeCollapsible = makeCollapsible;
|
|
469
|
+
|
|
404
470
|
/**
|
|
405
471
|
* @method makeCodeSnippet
|
|
406
472
|
* @description Create a code snippet in a specific language
|
|
@@ -503,6 +569,23 @@ function makeCodeSnippet( code, size, options = { } )
|
|
|
503
569
|
|
|
504
570
|
LX.makeCodeSnippet = makeCodeSnippet;
|
|
505
571
|
|
|
572
|
+
/**
|
|
573
|
+
* @method makeIcon
|
|
574
|
+
* @description Gets an SVG element using one of LX.ICONS
|
|
575
|
+
* @param {String} iconName
|
|
576
|
+
* @param {String} iconTitle
|
|
577
|
+
*/
|
|
578
|
+
function makeIcon( iconName, iconTitle )
|
|
579
|
+
{
|
|
580
|
+
const icon = document.createElement( "a" );
|
|
581
|
+
icon.title = iconTitle ?? "";
|
|
582
|
+
icon.className = "lexicon";
|
|
583
|
+
icon.innerHTML = LX.ICONS[ iconName ] ?? "";
|
|
584
|
+
return icon;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
LX.makeIcon = makeIcon;
|
|
588
|
+
|
|
506
589
|
/**
|
|
507
590
|
* @method registerCommandbarEntry
|
|
508
591
|
* @description Adds an extra command bar entry
|
|
@@ -772,12 +855,12 @@ function _createCommandbar( root )
|
|
|
772
855
|
if( LX.has('CodeEditor') )
|
|
773
856
|
{
|
|
774
857
|
const instances = LX.CodeEditor.getInstances();
|
|
775
|
-
if(!instances.length) return;
|
|
858
|
+
if( !instances.length ) return;
|
|
776
859
|
|
|
777
860
|
const languages = instances[ 0 ].languages;
|
|
778
861
|
|
|
779
|
-
for( let l of Object.keys( languages ) )
|
|
780
|
-
|
|
862
|
+
for( let l of Object.keys( languages ) )
|
|
863
|
+
{
|
|
781
864
|
const key = "Language: " + l;
|
|
782
865
|
const icon = instances[ 0 ]._getFileIcon( null, languages[ l ].ext );
|
|
783
866
|
|
|
@@ -785,9 +868,11 @@ function _createCommandbar( root )
|
|
|
785
868
|
"<img src='" + ( "https://raw.githubusercontent.com/jxarco/lexgui.js/master/" + icon ) + "'>";
|
|
786
869
|
|
|
787
870
|
value += key + " <span class='lang-ext'>(" + languages[ l ].ext + ")</span>";
|
|
788
|
-
if( key.toLowerCase().includes( filter ) )
|
|
871
|
+
if( key.toLowerCase().includes( filter ) )
|
|
872
|
+
{
|
|
789
873
|
_addElement( value, () => {
|
|
790
|
-
for( let i of instances )
|
|
874
|
+
for( let i of instances )
|
|
875
|
+
{
|
|
791
876
|
i._changeLanguage( l );
|
|
792
877
|
}
|
|
793
878
|
}, "", {} );
|
|
@@ -845,7 +930,19 @@ function init( options = { } )
|
|
|
845
930
|
this.container = document.getElementById( options.container );
|
|
846
931
|
}
|
|
847
932
|
|
|
848
|
-
|
|
933
|
+
this.usingStrictViewport = options.strictViewport ?? true;
|
|
934
|
+
document.documentElement.setAttribute( "data-strictVP", ( this.usingStrictViewport ) ? "true" : "false" );
|
|
935
|
+
|
|
936
|
+
if( !this.usingStrictViewport )
|
|
937
|
+
{
|
|
938
|
+
document.addEventListener( "scroll", e => {
|
|
939
|
+
// Get all active menuboxes
|
|
940
|
+
const mbs = document.body.querySelectorAll( ".lexmenubox" );
|
|
941
|
+
mbs.forEach( ( mb ) => {
|
|
942
|
+
mb._updatePosition();
|
|
943
|
+
} );
|
|
944
|
+
} );
|
|
945
|
+
}
|
|
849
946
|
|
|
850
947
|
this.commandbar = _createCommandbar( this.container );
|
|
851
948
|
|
|
@@ -860,6 +957,25 @@ function init( options = { } )
|
|
|
860
957
|
this.root = document.body;
|
|
861
958
|
}
|
|
862
959
|
|
|
960
|
+
// Notifications
|
|
961
|
+
{
|
|
962
|
+
const notifSection = document.createElement( "section" );
|
|
963
|
+
notifSection.className = "notifications";
|
|
964
|
+
this.notifications = document.createElement( "ol" );
|
|
965
|
+
this.notifications.className = "";
|
|
966
|
+
this.notifications.iWidth = 0;
|
|
967
|
+
notifSection.appendChild( this.notifications );
|
|
968
|
+
this.container.appendChild( notifSection );
|
|
969
|
+
|
|
970
|
+
this.notifications.addEventListener( "mouseenter", () => {
|
|
971
|
+
this.notifications.classList.add( "list" );
|
|
972
|
+
} );
|
|
973
|
+
|
|
974
|
+
this.notifications.addEventListener( "mouseleave", () => {
|
|
975
|
+
this.notifications.classList.remove( "list" );
|
|
976
|
+
} );
|
|
977
|
+
}
|
|
978
|
+
|
|
863
979
|
// Disable drag icon
|
|
864
980
|
root.addEventListener( 'dragover', function( e ) {
|
|
865
981
|
e.preventDefault();
|
|
@@ -1010,6 +1126,7 @@ LX.popup = popup;
|
|
|
1010
1126
|
function prompt( text, title, callback, options = {} )
|
|
1011
1127
|
{
|
|
1012
1128
|
options.modal = true;
|
|
1129
|
+
options.className = "prompt";
|
|
1013
1130
|
|
|
1014
1131
|
let value = "";
|
|
1015
1132
|
|
|
@@ -1024,7 +1141,9 @@ function prompt( text, title, callback, options = {} )
|
|
|
1024
1141
|
|
|
1025
1142
|
p.sameLine( 2 );
|
|
1026
1143
|
|
|
1027
|
-
p.addButton(
|
|
1144
|
+
p.addButton(null, "Cancel", () => {if(options.on_cancel) options.on_cancel(); dialog.close();} );
|
|
1145
|
+
|
|
1146
|
+
p.addButton( null, options.accept || "Continue", () => {
|
|
1028
1147
|
if( options.required && value === '' )
|
|
1029
1148
|
{
|
|
1030
1149
|
text += text.includes("You must fill the input text.") ? "": "\nYou must fill the input text.";
|
|
@@ -1038,8 +1157,6 @@ function prompt( text, title, callback, options = {} )
|
|
|
1038
1157
|
}
|
|
1039
1158
|
}, { buttonClass: "primary" });
|
|
1040
1159
|
|
|
1041
|
-
p.addButton(null, "Cancel", () => {if(options.on_cancel) options.on_cancel(); dialog.close();} );
|
|
1042
|
-
|
|
1043
1160
|
}, options );
|
|
1044
1161
|
|
|
1045
1162
|
// Focus text prompt
|
|
@@ -1053,6 +1170,101 @@ function prompt( text, title, callback, options = {} )
|
|
|
1053
1170
|
|
|
1054
1171
|
LX.prompt = prompt;
|
|
1055
1172
|
|
|
1173
|
+
/**
|
|
1174
|
+
* @method toast
|
|
1175
|
+
* @param {String} title
|
|
1176
|
+
* @param {String} description (Optional)
|
|
1177
|
+
* @param {*} options
|
|
1178
|
+
* action: Data of the custom action { name, callback }
|
|
1179
|
+
* closable: Allow closing the toast
|
|
1180
|
+
* timeout: Time in which the toast closed automatically, in ms. -1 means persistent. [3000]
|
|
1181
|
+
*/
|
|
1182
|
+
|
|
1183
|
+
function toast( title, description, options = {} )
|
|
1184
|
+
{
|
|
1185
|
+
if( !title )
|
|
1186
|
+
{
|
|
1187
|
+
throw( "The toast needs at least a title!" );
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
console.assert( this.notifications );
|
|
1191
|
+
|
|
1192
|
+
const toast = document.createElement( "li" );
|
|
1193
|
+
toast.className = "lextoast";
|
|
1194
|
+
toast.style.translate = "0 calc(100% + 30px)";
|
|
1195
|
+
this.notifications.prepend( toast );
|
|
1196
|
+
|
|
1197
|
+
doAsync( () => {
|
|
1198
|
+
|
|
1199
|
+
if( this.notifications.offsetWidth > this.notifications.iWidth )
|
|
1200
|
+
{
|
|
1201
|
+
this.notifications.iWidth = Math.min( this.notifications.offsetWidth, 480 );
|
|
1202
|
+
this.notifications.style.width = this.notifications.iWidth + "px";
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
toast.dataset[ "open" ] = true;
|
|
1206
|
+
}, 10 );
|
|
1207
|
+
|
|
1208
|
+
const content = document.createElement( "div" );
|
|
1209
|
+
content.className = "lextoastcontent";
|
|
1210
|
+
toast.appendChild( content );
|
|
1211
|
+
|
|
1212
|
+
const titleContent = document.createElement( "div" );
|
|
1213
|
+
titleContent.className = "title";
|
|
1214
|
+
titleContent.innerHTML = title;
|
|
1215
|
+
content.appendChild( titleContent );
|
|
1216
|
+
|
|
1217
|
+
if( description )
|
|
1218
|
+
{
|
|
1219
|
+
const desc = document.createElement( "div" );
|
|
1220
|
+
desc.className = "desc";
|
|
1221
|
+
desc.innerHTML = description;
|
|
1222
|
+
content.appendChild( desc );
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
if( options.action )
|
|
1226
|
+
{
|
|
1227
|
+
const panel = new Panel();
|
|
1228
|
+
panel.addButton(null, options.action.name ?? "Accept", options.action.callback.bind( this, toast ), { width: "auto", maxWidth: "150px", className: "right", buttonClass: "outline" });
|
|
1229
|
+
toast.appendChild( panel.root.childNodes[ 0 ] );
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
const that = this;
|
|
1233
|
+
|
|
1234
|
+
toast.close = function() {
|
|
1235
|
+
this.dataset[ "closed" ] = true;
|
|
1236
|
+
doAsync( () => {
|
|
1237
|
+
this.remove();
|
|
1238
|
+
if( !that.notifications.childElementCount )
|
|
1239
|
+
{
|
|
1240
|
+
that.notifications.style.width = "unset";
|
|
1241
|
+
that.notifications.iWidth = 0;
|
|
1242
|
+
}
|
|
1243
|
+
}, 500 );
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
if( options.closable ?? true )
|
|
1247
|
+
{
|
|
1248
|
+
const closeButton = document.createElement( "a" );
|
|
1249
|
+
closeButton.className = "fa fa-xmark lexicon closer";
|
|
1250
|
+
closeButton.addEventListener( "click", () => {
|
|
1251
|
+
toast.close();
|
|
1252
|
+
} );
|
|
1253
|
+
toast.appendChild( closeButton );
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
const timeout = options.timeout ?? 3000;
|
|
1257
|
+
|
|
1258
|
+
if( timeout != -1 )
|
|
1259
|
+
{
|
|
1260
|
+
doAsync( () => {
|
|
1261
|
+
toast.close();
|
|
1262
|
+
}, timeout );
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
LX.toast = toast;
|
|
1267
|
+
|
|
1056
1268
|
/**
|
|
1057
1269
|
* @method badge
|
|
1058
1270
|
* @param {String} text
|
|
@@ -1354,7 +1566,8 @@ class Area {
|
|
|
1354
1566
|
|
|
1355
1567
|
function inner_mousemove( e )
|
|
1356
1568
|
{
|
|
1357
|
-
switch( that.type )
|
|
1569
|
+
switch( that.type )
|
|
1570
|
+
{
|
|
1358
1571
|
case "right":
|
|
1359
1572
|
var dt = ( lastMousePosition[ 0 ] - e.x );
|
|
1360
1573
|
var size = ( that.root.offsetWidth + dt );
|
|
@@ -1549,7 +1762,8 @@ class Area {
|
|
|
1549
1762
|
|
|
1550
1763
|
// Listen resize event on first area
|
|
1551
1764
|
const resizeObserver = new ResizeObserver( entries => {
|
|
1552
|
-
for (const entry of entries)
|
|
1765
|
+
for ( const entry of entries )
|
|
1766
|
+
{
|
|
1553
1767
|
const bb = entry.contentRect;
|
|
1554
1768
|
area2.root.style.height = "calc(100% - " + ( bb.height + 4) + "px )";
|
|
1555
1769
|
}
|
|
@@ -1690,9 +1904,15 @@ class Area {
|
|
|
1690
1904
|
this.root.style.height = height;
|
|
1691
1905
|
}
|
|
1692
1906
|
|
|
1693
|
-
|
|
1907
|
+
if( this.onresize )
|
|
1908
|
+
{
|
|
1909
|
+
this.onresize( this.root.getBoundingClientRect() );
|
|
1910
|
+
}
|
|
1694
1911
|
|
|
1695
|
-
|
|
1912
|
+
doAsync( () => {
|
|
1913
|
+
this.size = [ this.root.clientWidth, this.root.clientHeight ];
|
|
1914
|
+
this.propagateEvent( "onresize" );
|
|
1915
|
+
}, 150 );
|
|
1696
1916
|
}
|
|
1697
1917
|
|
|
1698
1918
|
/**
|
|
@@ -1709,7 +1929,7 @@ class Area {
|
|
|
1709
1929
|
let [area1, area2] = this.sections;
|
|
1710
1930
|
this.splitExtended = true;
|
|
1711
1931
|
|
|
1712
|
-
if(this.type == "vertical")
|
|
1932
|
+
if( this.type == "vertical")
|
|
1713
1933
|
{
|
|
1714
1934
|
this.offset = area2.root.offsetHeight;
|
|
1715
1935
|
area2.root.classList.add("fadeout-vertical");
|
|
@@ -1723,7 +1943,6 @@ class Area {
|
|
|
1723
1943
|
this._moveSplit(-Infinity, true, 8);
|
|
1724
1944
|
}
|
|
1725
1945
|
|
|
1726
|
-
// Async resize in some ms...
|
|
1727
1946
|
doAsync( () => this.propagateEvent('onresize'), 150 );
|
|
1728
1947
|
}
|
|
1729
1948
|
|
|
@@ -1739,7 +1958,7 @@ class Area {
|
|
|
1739
1958
|
this.splitExtended = false;
|
|
1740
1959
|
let [area1, area2] = this.sections;
|
|
1741
1960
|
|
|
1742
|
-
if(this.type == "vertical")
|
|
1961
|
+
if( this.type == "vertical")
|
|
1743
1962
|
{
|
|
1744
1963
|
area2.root.classList.add("fadein-vertical");
|
|
1745
1964
|
this._moveSplit(this.offset);
|
|
@@ -1750,7 +1969,6 @@ class Area {
|
|
|
1750
1969
|
this._moveSplit(this.offset);
|
|
1751
1970
|
}
|
|
1752
1971
|
|
|
1753
|
-
// Async resize in some ms...
|
|
1754
1972
|
doAsync( () => this.propagateEvent('onresize'), 150 );
|
|
1755
1973
|
}
|
|
1756
1974
|
|
|
@@ -1784,11 +2002,15 @@ class Area {
|
|
|
1784
2002
|
|
|
1785
2003
|
propagateEvent( eventName ) {
|
|
1786
2004
|
|
|
1787
|
-
for(var i = 0; i < this.sections.length; i++)
|
|
2005
|
+
for( var i = 0; i < this.sections.length; i++ )
|
|
1788
2006
|
{
|
|
1789
|
-
const area = this.sections[i];
|
|
1790
|
-
|
|
2007
|
+
const area = this.sections[ i ];
|
|
2008
|
+
|
|
2009
|
+
if( area[ eventName ] )
|
|
2010
|
+
{
|
|
1791
2011
|
area[ eventName ].call( this, area.root.getBoundingClientRect() );
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1792
2014
|
area.propagateEvent( eventName );
|
|
1793
2015
|
}
|
|
1794
2016
|
}
|
|
@@ -1811,42 +2033,63 @@ class Area {
|
|
|
1811
2033
|
* @param {Function} callback Function to fill the menubar
|
|
1812
2034
|
* @param {*} options:
|
|
1813
2035
|
* float: Justify content (left, center, right) [left]
|
|
2036
|
+
* sticky: Fix menubar at the top [true]
|
|
1814
2037
|
*/
|
|
1815
2038
|
|
|
1816
2039
|
addMenubar( callback, options = {} ) {
|
|
1817
2040
|
|
|
1818
|
-
let menubar = new Menubar(options);
|
|
2041
|
+
let menubar = new Menubar( options );
|
|
1819
2042
|
|
|
1820
|
-
if(
|
|
2043
|
+
if( callback )
|
|
2044
|
+
{
|
|
2045
|
+
callback( menubar );
|
|
2046
|
+
}
|
|
1821
2047
|
|
|
1822
2048
|
LX.menubars.push( menubar );
|
|
1823
2049
|
|
|
1824
2050
|
const height = 48; // pixels
|
|
2051
|
+
const [ bar, content ] = this.split({ type: 'vertical', sizes: [height, null], resize: false, menubar: true });
|
|
2052
|
+
menubar.siblingArea = content;
|
|
1825
2053
|
|
|
1826
|
-
const [bar, content] = this.split({type: 'vertical', sizes: [height, null], resize: false, menubar: true});
|
|
1827
2054
|
bar.attach( menubar );
|
|
1828
|
-
bar.
|
|
2055
|
+
bar.isMenubar = true;
|
|
2056
|
+
|
|
2057
|
+
if( options.sticky ?? true )
|
|
2058
|
+
{
|
|
2059
|
+
bar.root.classList.add( "sticky" );
|
|
2060
|
+
}
|
|
2061
|
+
|
|
1829
2062
|
return menubar;
|
|
1830
2063
|
}
|
|
1831
2064
|
|
|
1832
2065
|
/**
|
|
1833
2066
|
* @method addSidebar
|
|
1834
2067
|
* @param {Function} callback Function to fill the sidebar
|
|
2068
|
+
* @param {Object} options: Sidebar options
|
|
2069
|
+
* width: Width of the sidebar [16rem]
|
|
1835
2070
|
*/
|
|
1836
2071
|
|
|
1837
2072
|
addSidebar( callback, options = {} ) {
|
|
1838
2073
|
|
|
1839
2074
|
let sidebar = new SideBar( options );
|
|
1840
2075
|
|
|
1841
|
-
if( callback )
|
|
2076
|
+
if( callback )
|
|
2077
|
+
{
|
|
2078
|
+
callback( sidebar );
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
// Generate DOM elements after adding all entries
|
|
2082
|
+
sidebar.update();
|
|
1842
2083
|
|
|
1843
2084
|
LX.menubars.push( sidebar );
|
|
1844
2085
|
|
|
1845
|
-
const width =
|
|
2086
|
+
const width = options.width ?? "16rem";
|
|
2087
|
+
const [ bar, content ] = this.split( { type: 'horizontal', sizes: [ width, null ], resize: false, sidebar: true } );
|
|
2088
|
+
sidebar.siblingArea = content;
|
|
1846
2089
|
|
|
1847
|
-
const [bar, content] = this.split( { type: 'horizontal', sizes: [ width, null ], resize: false, sidebar: true } );
|
|
1848
2090
|
bar.attach( sidebar );
|
|
1849
|
-
bar.
|
|
2091
|
+
bar.isSidebar = true;
|
|
2092
|
+
|
|
1850
2093
|
return sidebar;
|
|
1851
2094
|
}
|
|
1852
2095
|
|
|
@@ -2102,7 +2345,8 @@ class Area {
|
|
|
2102
2345
|
|
|
2103
2346
|
this.size = [ rect.width, rect.height ];
|
|
2104
2347
|
|
|
2105
|
-
for(var i = 0; i < this.sections.length; i++)
|
|
2348
|
+
for( var i = 0; i < this.sections.length; i++ )
|
|
2349
|
+
{
|
|
2106
2350
|
this.sections[i]._update();
|
|
2107
2351
|
}
|
|
2108
2352
|
}
|
|
@@ -2126,7 +2370,7 @@ class Tabs {
|
|
|
2126
2370
|
static TAB_SIZE = 28;
|
|
2127
2371
|
static TAB_ID = 0;
|
|
2128
2372
|
|
|
2129
|
-
constructor( area, options = {} )
|
|
2373
|
+
constructor( area, options = {} ) {
|
|
2130
2374
|
|
|
2131
2375
|
this.onclose = options.onclose;
|
|
2132
2376
|
|
|
@@ -2208,24 +2452,28 @@ class Tabs {
|
|
|
2208
2452
|
}
|
|
2209
2453
|
|
|
2210
2454
|
// debug
|
|
2211
|
-
if(folding)
|
|
2455
|
+
if( folding )
|
|
2212
2456
|
{
|
|
2213
2457
|
this.folded = true;
|
|
2214
2458
|
this.folding = folding;
|
|
2215
2459
|
|
|
2216
|
-
if(folding == "up"
|
|
2460
|
+
if( folding == "up" )
|
|
2461
|
+
{
|
|
2462
|
+
area.root.insertChildAtIndex(area.sections[1].root, 0);
|
|
2463
|
+
}
|
|
2217
2464
|
|
|
2218
2465
|
// Listen resize event on parent area
|
|
2219
2466
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
2220
|
-
for (const entry of entries)
|
|
2467
|
+
for (const entry of entries)
|
|
2468
|
+
{
|
|
2221
2469
|
const bb = entry.contentRect;
|
|
2222
|
-
const sibling = area.parentArea.sections[0].root;
|
|
2223
|
-
const
|
|
2224
|
-
sibling.style.height = "calc(100% - " + ((
|
|
2470
|
+
const sibling = area.parentArea.sections[ 0 ].root;
|
|
2471
|
+
const addOffset = true; // hardcoded...
|
|
2472
|
+
sibling.style.height = "calc(100% - " + ((addOffset ? 42 : 0) + bb.height) + "px )";
|
|
2225
2473
|
}
|
|
2226
2474
|
});
|
|
2227
2475
|
|
|
2228
|
-
resizeObserver.observe(this.area.root);
|
|
2476
|
+
resizeObserver.observe( this.area.root );
|
|
2229
2477
|
this.area.root.classList.add('folded');
|
|
2230
2478
|
}
|
|
2231
2479
|
}
|
|
@@ -2362,7 +2610,8 @@ class Tabs {
|
|
|
2362
2610
|
|
|
2363
2611
|
setTimeout( () => {
|
|
2364
2612
|
|
|
2365
|
-
if( options.onCreate )
|
|
2613
|
+
if( options.onCreate )
|
|
2614
|
+
{
|
|
2366
2615
|
options.onCreate.call(this, this.area.root.getBoundingClientRect());
|
|
2367
2616
|
}
|
|
2368
2617
|
|
|
@@ -2424,34 +2673,230 @@ LX.Tabs = Tabs;
|
|
|
2424
2673
|
|
|
2425
2674
|
class Menubar {
|
|
2426
2675
|
|
|
2427
|
-
constructor( options = {} )
|
|
2676
|
+
constructor( options = {} ) {
|
|
2428
2677
|
|
|
2429
|
-
this.root = document.createElement(
|
|
2678
|
+
this.root = document.createElement( "div" );
|
|
2430
2679
|
this.root.className = "lexmenubar";
|
|
2431
|
-
|
|
2680
|
+
|
|
2681
|
+
if( options.float )
|
|
2682
|
+
{
|
|
2432
2683
|
this.root.style.justifyContent = options.float;
|
|
2433
|
-
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
this.items = [ ];
|
|
2687
|
+
this.buttons = [ ];
|
|
2688
|
+
this.icons = { };
|
|
2689
|
+
this.shorts = { };
|
|
2690
|
+
}
|
|
2691
|
+
|
|
2692
|
+
_resetMenubar() {
|
|
2693
|
+
|
|
2694
|
+
// Menu entries are in the menubar..
|
|
2695
|
+
this.root.querySelectorAll(".lexmenuentry").forEach( _entry => {
|
|
2696
|
+
_entry.classList.remove( 'selected' );
|
|
2697
|
+
_entry.built = false;
|
|
2698
|
+
} );
|
|
2699
|
+
|
|
2700
|
+
// Menuboxes are in the root area!
|
|
2701
|
+
LX.root.querySelectorAll(".lexmenubox").forEach(e => e.remove());
|
|
2702
|
+
|
|
2703
|
+
// Next time we need to click again
|
|
2704
|
+
this.focused = false;
|
|
2705
|
+
}
|
|
2706
|
+
|
|
2707
|
+
_createSubmenu( o, k, c, d ) {
|
|
2708
|
+
|
|
2709
|
+
let menuElement = document.createElement('div');
|
|
2710
|
+
menuElement.className = "lexmenubox";
|
|
2711
|
+
menuElement.tabIndex = "0";
|
|
2712
|
+
c.currentMenu = menuElement;
|
|
2713
|
+
menuElement.parentEntry = c;
|
|
2714
|
+
|
|
2715
|
+
const isSubMenu = c.classList.contains( "lexmenuboxentry" );
|
|
2716
|
+
if( isSubMenu )
|
|
2717
|
+
{
|
|
2718
|
+
menuElement.dataset[ "submenu" ] = true;
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
menuElement._updatePosition = () => {
|
|
2722
|
+
|
|
2723
|
+
// Remove transitions for this change..
|
|
2724
|
+
const transition = menuElement.style.transition;
|
|
2725
|
+
menuElement.style.transition = "none";
|
|
2726
|
+
flushCss( menuElement );
|
|
2727
|
+
|
|
2728
|
+
doAsync( () => {
|
|
2729
|
+
let rect = c.getBoundingClientRect();
|
|
2730
|
+
rect.x += document.scrollingElement.scrollLeft;
|
|
2731
|
+
rect.y += document.scrollingElement.scrollTop;
|
|
2732
|
+
menuElement.style.left = ( isSubMenu ? ( rect.x + rect.width ) : rect.x ) + "px";
|
|
2733
|
+
menuElement.style.top = ( isSubMenu ? rect.y : ( ( rect.y + rect.height ) ) - 4 ) + "px";
|
|
2734
|
+
|
|
2735
|
+
menuElement.style.transition = transition;
|
|
2736
|
+
} );
|
|
2737
|
+
};
|
|
2738
|
+
|
|
2739
|
+
menuElement._updatePosition();
|
|
2740
|
+
|
|
2741
|
+
doAsync( () => {
|
|
2742
|
+
menuElement.dataset[ "open" ] = true;
|
|
2743
|
+
}, 10 );
|
|
2744
|
+
|
|
2745
|
+
LX.root.appendChild( menuElement );
|
|
2746
|
+
|
|
2747
|
+
for( var i = 0; i < o[ k ].length; ++i )
|
|
2748
|
+
{
|
|
2749
|
+
const subitem = o[ k ][ i ];
|
|
2750
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
2751
|
+
const hasSubmenu = subitem[ subkey ].length;
|
|
2752
|
+
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2753
|
+
let subentry = document.createElement('div');
|
|
2754
|
+
subentry.className = "lexmenuboxentry";
|
|
2755
|
+
subentry.className += (i == o[k].length - 1 ? " last" : "") + ( subitem.disabled ? " disabled" : "" );
|
|
2756
|
+
|
|
2757
|
+
if( subkey == '' )
|
|
2758
|
+
{
|
|
2759
|
+
subentry.className = " lexseparator";
|
|
2760
|
+
}
|
|
2761
|
+
else
|
|
2762
|
+
{
|
|
2763
|
+
subentry.id = subkey;
|
|
2764
|
+
let subentrycont = document.createElement('div');
|
|
2765
|
+
subentrycont.innerHTML = "";
|
|
2766
|
+
subentrycont.classList = "lexmenuboxentrycontainer";
|
|
2767
|
+
subentry.appendChild(subentrycont);
|
|
2768
|
+
const icon = this.icons[ subkey ];
|
|
2769
|
+
if( isCheckbox )
|
|
2770
|
+
{
|
|
2771
|
+
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2772
|
+
}
|
|
2773
|
+
else if( icon )
|
|
2774
|
+
{
|
|
2775
|
+
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2776
|
+
}
|
|
2777
|
+
else
|
|
2778
|
+
{
|
|
2779
|
+
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2780
|
+
subentrycont.classList.add( "noicon" );
|
|
2781
|
+
|
|
2782
|
+
}
|
|
2783
|
+
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2784
|
+
}
|
|
2785
|
+
|
|
2786
|
+
let checkboxInput = subentry.querySelector('input');
|
|
2787
|
+
if( checkboxInput )
|
|
2788
|
+
{
|
|
2789
|
+
checkboxInput.checked = subitem.checked ?? false;
|
|
2790
|
+
checkboxInput.addEventListener('change', e => {
|
|
2791
|
+
subitem.checked = checkboxInput.checked;
|
|
2792
|
+
const f = subitem[ 'callback' ];
|
|
2793
|
+
if( f )
|
|
2794
|
+
{
|
|
2795
|
+
f.call( this, subitem.checked, subkey, subentry );
|
|
2796
|
+
this._resetMenubar();
|
|
2797
|
+
}
|
|
2798
|
+
e.stopPropagation();
|
|
2799
|
+
e.stopImmediatePropagation();
|
|
2800
|
+
})
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2803
|
+
menuElement.appendChild( subentry );
|
|
2804
|
+
|
|
2805
|
+
// Nothing more for separators
|
|
2806
|
+
if( subkey == '' )
|
|
2807
|
+
{
|
|
2808
|
+
continue;
|
|
2809
|
+
}
|
|
2434
2810
|
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2811
|
+
menuElement.addEventListener('keydown', e => {
|
|
2812
|
+
e.preventDefault();
|
|
2813
|
+
let short = this.shorts[ subkey ];
|
|
2814
|
+
if(!short) return;
|
|
2815
|
+
// check if it's a letter or other key
|
|
2816
|
+
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2817
|
+
if( short == e.key )
|
|
2818
|
+
{
|
|
2819
|
+
subentry.click()
|
|
2820
|
+
}
|
|
2821
|
+
});
|
|
2822
|
+
|
|
2823
|
+
// Add callback
|
|
2824
|
+
subentry.addEventListener("click", e => {
|
|
2825
|
+
if( checkboxInput )
|
|
2826
|
+
{
|
|
2827
|
+
subitem.checked = !subitem.checked;
|
|
2828
|
+
}
|
|
2829
|
+
const f = subitem[ 'callback' ];
|
|
2830
|
+
if( f )
|
|
2831
|
+
{
|
|
2832
|
+
f.call( this, checkboxInput ? subitem.checked : subkey, checkboxInput ? subkey : subentry );
|
|
2833
|
+
this._resetMenubar();
|
|
2834
|
+
}
|
|
2835
|
+
e.stopPropagation();
|
|
2836
|
+
e.stopImmediatePropagation();
|
|
2837
|
+
});
|
|
2838
|
+
|
|
2839
|
+
// Add icon if has submenu, else check for shortcut
|
|
2840
|
+
if( !hasSubmenu)
|
|
2841
|
+
{
|
|
2842
|
+
if( this.shorts[ subkey ] )
|
|
2843
|
+
{
|
|
2844
|
+
let shortEl = document.createElement('div');
|
|
2845
|
+
shortEl.className = "lexentryshort";
|
|
2846
|
+
shortEl.innerText = this.shorts[ subkey ];
|
|
2847
|
+
subentry.appendChild( shortEl );
|
|
2848
|
+
}
|
|
2849
|
+
continue;
|
|
2850
|
+
}
|
|
2851
|
+
|
|
2852
|
+
let submenuIcon = document.createElement('a');
|
|
2853
|
+
submenuIcon.className = "fa-solid fa-angle-right fa-xs";
|
|
2854
|
+
subentry.appendChild( submenuIcon );
|
|
2855
|
+
|
|
2856
|
+
subentry.addEventListener("mouseover", e => {
|
|
2857
|
+
if( subentry.built )
|
|
2858
|
+
{
|
|
2859
|
+
return;
|
|
2860
|
+
}
|
|
2861
|
+
subentry.built = true;
|
|
2862
|
+
this._createSubmenu( subitem, subkey, subentry, ++d );
|
|
2863
|
+
e.stopPropagation();
|
|
2864
|
+
});
|
|
2865
|
+
|
|
2866
|
+
subentry.addEventListener("mouseleave", e => {
|
|
2867
|
+
if( subentry.currentMenu && ( subentry.currentMenu != e.toElement ) )
|
|
2868
|
+
{
|
|
2869
|
+
d = -1; // Reset depth
|
|
2870
|
+
delete subentry.built;
|
|
2871
|
+
subentry.currentMenu.remove();
|
|
2872
|
+
delete subentry.currentMenu;
|
|
2873
|
+
}
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2877
|
+
// Set final width
|
|
2878
|
+
menuElement.style.width = menuElement.offsetWidth + "px";
|
|
2438
2879
|
}
|
|
2439
2880
|
|
|
2440
2881
|
/**
|
|
2441
2882
|
* @method add
|
|
2442
|
-
* @param {
|
|
2883
|
+
* @param {Object} options:
|
|
2443
2884
|
* callback: Function to call on each item
|
|
2885
|
+
* icon: Entry icon
|
|
2886
|
+
* short: Entry shortcut name
|
|
2444
2887
|
*/
|
|
2445
2888
|
|
|
2446
2889
|
add( path, options = {} ) {
|
|
2447
2890
|
|
|
2448
|
-
if(options.constructor == Function)
|
|
2891
|
+
if( options.constructor == Function )
|
|
2892
|
+
{
|
|
2449
2893
|
options = { callback: options };
|
|
2894
|
+
}
|
|
2450
2895
|
|
|
2451
|
-
//
|
|
2452
|
-
const tokens = path.split("/");
|
|
2896
|
+
// Process path
|
|
2897
|
+
const tokens = path.split( "/" );
|
|
2453
2898
|
|
|
2454
|
-
//
|
|
2899
|
+
// Assign icons and shortcuts to last token in path
|
|
2455
2900
|
const lastPath = tokens[tokens.length - 1];
|
|
2456
2901
|
this.icons[ lastPath ] = options.icon;
|
|
2457
2902
|
this.shorts[ lastPath ] = options.short;
|
|
@@ -2459,211 +2904,119 @@ class Menubar {
|
|
|
2459
2904
|
let idx = 0;
|
|
2460
2905
|
let that = this;
|
|
2461
2906
|
|
|
2462
|
-
const
|
|
2463
|
-
if(token == undefined)
|
|
2907
|
+
const _insertEntry = ( token, list ) => {
|
|
2908
|
+
if( token == undefined )
|
|
2909
|
+
{
|
|
2910
|
+
return;
|
|
2911
|
+
}
|
|
2464
2912
|
|
|
2465
2913
|
let found = null;
|
|
2466
2914
|
list.forEach( o => {
|
|
2467
|
-
const keys = Object.keys(o);
|
|
2915
|
+
const keys = Object.keys( o );
|
|
2468
2916
|
const key = keys.find( t => t == token );
|
|
2469
|
-
if(key) found = o[ key ];
|
|
2917
|
+
if( key ) found = o[ key ];
|
|
2470
2918
|
} );
|
|
2471
2919
|
|
|
2472
|
-
if(found)
|
|
2473
|
-
|
|
2920
|
+
if( found )
|
|
2921
|
+
{
|
|
2922
|
+
_insertEntry( tokens[ idx++ ], found );
|
|
2474
2923
|
}
|
|
2475
|
-
else
|
|
2924
|
+
else
|
|
2925
|
+
{
|
|
2476
2926
|
let item = {};
|
|
2477
2927
|
item[ token ] = [];
|
|
2478
|
-
const
|
|
2928
|
+
const nextToken = tokens[ idx++ ];
|
|
2479
2929
|
// Check if last token -> add callback
|
|
2480
|
-
if(!
|
|
2930
|
+
if( !nextToken )
|
|
2931
|
+
{
|
|
2481
2932
|
item[ 'callback' ] = options.callback;
|
|
2933
|
+
item[ 'disabled' ] = options.disabled;
|
|
2482
2934
|
item[ 'type' ] = options.type;
|
|
2483
2935
|
item[ 'checked' ] = options.checked;
|
|
2484
2936
|
}
|
|
2485
2937
|
list.push( item );
|
|
2486
|
-
|
|
2938
|
+
_insertEntry( nextToken, item[ token ] );
|
|
2487
2939
|
}
|
|
2488
2940
|
};
|
|
2489
2941
|
|
|
2490
|
-
|
|
2942
|
+
_insertEntry( tokens[idx++], this.items );
|
|
2491
2943
|
|
|
2492
2944
|
// Create elements
|
|
2493
2945
|
|
|
2494
2946
|
for( let item of this.items )
|
|
2495
2947
|
{
|
|
2496
|
-
let key = Object.keys(item)[0];
|
|
2497
|
-
let pKey = key.replace(/\s/g, '').replaceAll('.', '');
|
|
2948
|
+
let key = Object.keys( item )[ 0 ];
|
|
2949
|
+
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
2498
2950
|
|
|
2499
2951
|
// Item already created
|
|
2500
|
-
if( this.root.querySelector("#" + pKey) )
|
|
2952
|
+
if( this.root.querySelector( "#" + pKey ) )
|
|
2953
|
+
{
|
|
2501
2954
|
continue;
|
|
2955
|
+
}
|
|
2502
2956
|
|
|
2503
2957
|
let entry = document.createElement('div');
|
|
2504
2958
|
entry.className = "lexmenuentry";
|
|
2505
2959
|
entry.id = pKey;
|
|
2506
2960
|
entry.innerHTML = "<span>" + key + "</span>";
|
|
2507
|
-
|
|
2961
|
+
entry.tabIndex = "1";
|
|
2962
|
+
|
|
2963
|
+
if( options.position == "left" )
|
|
2964
|
+
{
|
|
2508
2965
|
this.root.prepend( entry );
|
|
2509
2966
|
}
|
|
2510
|
-
else
|
|
2511
|
-
|
|
2967
|
+
else
|
|
2968
|
+
{
|
|
2969
|
+
if( options.position == "right" )
|
|
2970
|
+
{
|
|
2512
2971
|
entry.right = true;
|
|
2513
|
-
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
2975
|
+
{
|
|
2514
2976
|
this.root.lastChild.before( entry );
|
|
2515
2977
|
}
|
|
2516
|
-
else
|
|
2978
|
+
else
|
|
2979
|
+
{
|
|
2517
2980
|
this.root.appendChild( entry );
|
|
2518
2981
|
}
|
|
2519
2982
|
}
|
|
2520
2983
|
|
|
2521
|
-
const
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
const isSubMenu = c.classList.contains('lexcontextmenuentry');
|
|
2527
|
-
var rect = c.getBoundingClientRect();
|
|
2528
|
-
contextmenu.style.left = (isSubMenu ? rect.width : rect.left) + "px";
|
|
2529
|
-
// Entries use css to set top relative to parent
|
|
2530
|
-
contextmenu.style.top = (isSubMenu ? 0 : rect.bottom - 4) + "px";
|
|
2531
|
-
c.appendChild( contextmenu );
|
|
2532
|
-
|
|
2533
|
-
contextmenu.focus();
|
|
2534
|
-
|
|
2535
|
-
rect = contextmenu.getBoundingClientRect();
|
|
2536
|
-
|
|
2537
|
-
for( var i = 0; i < o[k].length; ++i )
|
|
2538
|
-
{
|
|
2539
|
-
const subitem = o[k][i];
|
|
2540
|
-
const subkey = Object.keys(subitem)[0];
|
|
2541
|
-
const hasSubmenu = subitem[ subkey ].length;
|
|
2542
|
-
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2543
|
-
let subentry = document.createElement('div');
|
|
2544
|
-
subentry.className = "lexcontextmenuentry";
|
|
2545
|
-
subentry.className += (i == o[k].length - 1 ? " last" : "");
|
|
2546
|
-
if(subkey == '')
|
|
2547
|
-
subentry.className = " lexseparator";
|
|
2548
|
-
else {
|
|
2549
|
-
|
|
2550
|
-
subentry.id = subkey;
|
|
2551
|
-
let subentrycont = document.createElement('div');
|
|
2552
|
-
subentrycont.innerHTML = "";
|
|
2553
|
-
subentrycont.classList = "lexcontextmenuentrycontainer";
|
|
2554
|
-
subentry.appendChild(subentrycont);
|
|
2555
|
-
const icon = that.icons[ subkey ];
|
|
2556
|
-
if(isCheckbox){
|
|
2557
|
-
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2558
|
-
}else if(icon) {
|
|
2559
|
-
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2560
|
-
}else {
|
|
2561
|
-
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2562
|
-
subentrycont.classList.add( "noicon" );
|
|
2563
|
-
|
|
2564
|
-
}
|
|
2565
|
-
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2566
|
-
}
|
|
2567
|
-
|
|
2568
|
-
let checkbox_input = subentry.querySelector('input');
|
|
2569
|
-
if(checkbox_input) {
|
|
2570
|
-
checkbox_input.checked = subitem.checked ?? false;
|
|
2571
|
-
checkbox_input.addEventListener('change', (e) => {
|
|
2572
|
-
subitem.checked = checkbox_input.checked;
|
|
2573
|
-
const f = subitem[ 'callback' ];
|
|
2574
|
-
if(f) {
|
|
2575
|
-
f.call( this, subitem.checked, subkey, subentry );
|
|
2576
|
-
that.root.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
2577
|
-
}
|
|
2578
|
-
e.stopPropagation();
|
|
2579
|
-
e.stopImmediatePropagation();
|
|
2580
|
-
})
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
|
-
contextmenu.appendChild( subentry );
|
|
2584
|
-
|
|
2585
|
-
// Nothing more for separators
|
|
2586
|
-
if(subkey == '') continue;
|
|
2587
|
-
|
|
2588
|
-
contextmenu.addEventListener('keydown', function(e) {
|
|
2589
|
-
e.preventDefault();
|
|
2590
|
-
let short = that.shorts[ subkey ];
|
|
2591
|
-
if(!short) return;
|
|
2592
|
-
// check if it's a letter or other key
|
|
2593
|
-
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2594
|
-
if(short == e.key) {
|
|
2595
|
-
subentry.click()
|
|
2596
|
-
}
|
|
2597
|
-
});
|
|
2598
|
-
|
|
2599
|
-
// Add callback
|
|
2600
|
-
subentry.addEventListener("click", e => {
|
|
2601
|
-
if(checkbox_input) {
|
|
2602
|
-
subitem.checked = !subitem.checked;
|
|
2603
|
-
}
|
|
2604
|
-
const f = subitem[ 'callback' ];
|
|
2605
|
-
if(f) {
|
|
2606
|
-
f.call( this, checkbox_input ? subitem.checked : subkey, checkbox_input ? subkey : subentry );
|
|
2607
|
-
that.root.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
2608
|
-
}
|
|
2609
|
-
e.stopPropagation();
|
|
2610
|
-
e.stopImmediatePropagation();
|
|
2611
|
-
});
|
|
2612
|
-
|
|
2613
|
-
// Add icon if has submenu, else check for shortcut
|
|
2614
|
-
if( !hasSubmenu)
|
|
2615
|
-
{
|
|
2616
|
-
if(that.shorts[ subkey ]) {
|
|
2617
|
-
let shortEl = document.createElement('div');
|
|
2618
|
-
shortEl.className = "lexentryshort";
|
|
2619
|
-
shortEl.innerText = that.shorts[ subkey ];
|
|
2620
|
-
subentry.appendChild( shortEl );
|
|
2621
|
-
}
|
|
2622
|
-
continue;
|
|
2623
|
-
}
|
|
2624
|
-
|
|
2625
|
-
let submenuIcon = document.createElement('a');
|
|
2626
|
-
submenuIcon.className = "fa-solid fa-angle-right fa-xs";
|
|
2627
|
-
subentry.appendChild( submenuIcon );
|
|
2628
|
-
|
|
2629
|
-
subentry.addEventListener("mouseover", e => {
|
|
2630
|
-
if(subentry.built)
|
|
2631
|
-
return;
|
|
2632
|
-
subentry.built = true;
|
|
2633
|
-
create_submenu( subitem, subkey, subentry, ++d );
|
|
2634
|
-
e.stopPropagation();
|
|
2635
|
-
});
|
|
2636
|
-
|
|
2637
|
-
subentry.addEventListener("mouseleave", () => {
|
|
2638
|
-
d = -1; // Reset depth
|
|
2639
|
-
delete subentry.built;
|
|
2640
|
-
contextmenu.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
2641
|
-
});
|
|
2642
|
-
}
|
|
2643
|
-
|
|
2644
|
-
// Set final width
|
|
2645
|
-
contextmenu.style.width = contextmenu.offsetWidth + "px";
|
|
2984
|
+
const _showEntry = () => {
|
|
2985
|
+
this._resetMenubar();
|
|
2986
|
+
entry.classList.add( "selected" );
|
|
2987
|
+
entry.built = true;
|
|
2988
|
+
this._createSubmenu( item, key, entry, -1 );
|
|
2646
2989
|
};
|
|
2647
2990
|
|
|
2648
2991
|
entry.addEventListener("click", () => {
|
|
2649
|
-
|
|
2650
2992
|
const f = item[ 'callback' ];
|
|
2651
|
-
if(f)
|
|
2993
|
+
if( f )
|
|
2994
|
+
{
|
|
2652
2995
|
f.call( this, key, entry );
|
|
2653
2996
|
return;
|
|
2654
2997
|
}
|
|
2655
2998
|
|
|
2656
|
-
|
|
2657
|
-
this.root.querySelectorAll(".lexmenuentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
2658
|
-
entry.classList.add( "selected" );
|
|
2999
|
+
_showEntry();
|
|
2659
3000
|
|
|
2660
|
-
this.
|
|
2661
|
-
create_submenu( item, key, entry, -1 );
|
|
3001
|
+
this.focused = true;
|
|
2662
3002
|
});
|
|
2663
3003
|
|
|
2664
|
-
entry.addEventListener("
|
|
2665
|
-
|
|
2666
|
-
this.
|
|
3004
|
+
entry.addEventListener( "mouseover", (e) => {
|
|
3005
|
+
|
|
3006
|
+
if( this.focused && !entry.built )
|
|
3007
|
+
{
|
|
3008
|
+
_showEntry();
|
|
3009
|
+
}
|
|
3010
|
+
});
|
|
3011
|
+
|
|
3012
|
+
entry.addEventListener("blur", (e) => {
|
|
3013
|
+
|
|
3014
|
+
if( e.relatedTarget && e.relatedTarget.classList.contains( "lexmenubox" ) )
|
|
3015
|
+
{
|
|
3016
|
+
return;
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
this._resetMenubar();
|
|
2667
3020
|
});
|
|
2668
3021
|
}
|
|
2669
3022
|
}
|
|
@@ -2682,20 +3035,24 @@ class Menubar {
|
|
|
2682
3035
|
* @param {Object} item: parent item
|
|
2683
3036
|
* @param {Array} tokens: split path strings
|
|
2684
3037
|
*/
|
|
2685
|
-
getSubitem(item, tokens) {
|
|
3038
|
+
getSubitem( item, tokens ) {
|
|
2686
3039
|
|
|
2687
3040
|
let subitem = null;
|
|
2688
|
-
let path = tokens[0];
|
|
2689
|
-
for(let i = 0; i < item.length; i++) {
|
|
2690
|
-
if(item[i][path]) {
|
|
3041
|
+
let path = tokens[ 0 ];
|
|
2691
3042
|
|
|
2692
|
-
|
|
2693
|
-
|
|
3043
|
+
for( let i = 0; i < item.length; i++ )
|
|
3044
|
+
{
|
|
3045
|
+
if( item[ i ][ path ] )
|
|
3046
|
+
{
|
|
3047
|
+
if( tokens.length == 1 )
|
|
3048
|
+
{
|
|
3049
|
+
subitem = item[ i ];
|
|
2694
3050
|
return subitem;
|
|
2695
3051
|
}
|
|
2696
|
-
else
|
|
2697
|
-
|
|
2698
|
-
|
|
3052
|
+
else
|
|
3053
|
+
{
|
|
3054
|
+
tokens.splice( 0, 1 );
|
|
3055
|
+
return this.getSubitem( item[ i ][ path ], tokens );
|
|
2699
3056
|
}
|
|
2700
3057
|
|
|
2701
3058
|
}
|
|
@@ -2722,11 +3079,12 @@ class Menubar {
|
|
|
2722
3079
|
setButtonIcon( title, icon, callback, options = {} ) {
|
|
2723
3080
|
|
|
2724
3081
|
const button = this.buttons[ title ];
|
|
2725
|
-
if(button)
|
|
2726
|
-
|
|
3082
|
+
if( button )
|
|
3083
|
+
{
|
|
2727
3084
|
button.querySelector('a').className = "fa-solid" + " " + icon + " lexicon";
|
|
2728
3085
|
}
|
|
2729
|
-
else
|
|
3086
|
+
else
|
|
3087
|
+
{
|
|
2730
3088
|
let button = document.createElement('div');
|
|
2731
3089
|
const disabled = options.disabled ?? false;
|
|
2732
3090
|
button.className = "lexmenubutton" + (disabled ? " disabled" : "");
|
|
@@ -2736,15 +3094,21 @@ class Menubar {
|
|
|
2736
3094
|
button.style.maxHeight = "calc(100% - 10px)";
|
|
2737
3095
|
button.style.alignItems = "center";
|
|
2738
3096
|
|
|
2739
|
-
if(options.float == "right")
|
|
3097
|
+
if( options.float == "right" )
|
|
3098
|
+
{
|
|
2740
3099
|
button.right = true;
|
|
2741
|
-
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
3103
|
+
{
|
|
2742
3104
|
this.root.lastChild.before( button );
|
|
2743
3105
|
}
|
|
2744
|
-
else if(options.float == "left")
|
|
2745
|
-
|
|
3106
|
+
else if( options.float == "left" )
|
|
3107
|
+
{
|
|
3108
|
+
this.root.prepend( button );
|
|
2746
3109
|
}
|
|
2747
|
-
else
|
|
3110
|
+
else
|
|
3111
|
+
{
|
|
2748
3112
|
this.root.appendChild( button );
|
|
2749
3113
|
}
|
|
2750
3114
|
|
|
@@ -2764,11 +3128,12 @@ class Menubar {
|
|
|
2764
3128
|
|
|
2765
3129
|
setButtonImage( title, src, callback, options = {} ) {
|
|
2766
3130
|
const button = this.buttons[ title ];
|
|
2767
|
-
if(button)
|
|
2768
|
-
|
|
3131
|
+
if( button )
|
|
3132
|
+
{
|
|
2769
3133
|
button.querySelector('a').className = "fa-solid" + " " + icon + " lexicon";
|
|
2770
3134
|
}
|
|
2771
|
-
else
|
|
3135
|
+
else
|
|
3136
|
+
{
|
|
2772
3137
|
let button = document.createElement('div');
|
|
2773
3138
|
const disabled = options.disabled ?? false;
|
|
2774
3139
|
button.className = "lexmenubutton" + (disabled ? " disabled" : "");
|
|
@@ -2777,15 +3142,21 @@ class Menubar {
|
|
|
2777
3142
|
button.style.padding = "5px";
|
|
2778
3143
|
button.style.alignItems = "center";
|
|
2779
3144
|
|
|
2780
|
-
if(options.float == "right")
|
|
3145
|
+
if( options.float == "right" )
|
|
3146
|
+
{
|
|
2781
3147
|
button.right = true;
|
|
2782
|
-
|
|
3148
|
+
}
|
|
3149
|
+
|
|
3150
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
3151
|
+
{
|
|
2783
3152
|
this.root.lastChild.before( button );
|
|
2784
3153
|
}
|
|
2785
|
-
else if(options.float == "left")
|
|
2786
|
-
|
|
3154
|
+
else if( options.float == "left" )
|
|
3155
|
+
{
|
|
3156
|
+
this.root.prepend( button );
|
|
2787
3157
|
}
|
|
2788
|
-
else
|
|
3158
|
+
else
|
|
3159
|
+
{
|
|
2789
3160
|
this.root.appendChild( button );
|
|
2790
3161
|
}
|
|
2791
3162
|
|
|
@@ -2898,90 +3269,323 @@ LX.Menubar = Menubar;
|
|
|
2898
3269
|
|
|
2899
3270
|
class SideBar {
|
|
2900
3271
|
|
|
2901
|
-
|
|
3272
|
+
/**
|
|
3273
|
+
* @param {Object} options
|
|
3274
|
+
* filter: Add search bar to filter entries [false]
|
|
3275
|
+
* skipHeader: Do not use sidebar header [false]
|
|
3276
|
+
* headerImg: Image to be shown as avatar
|
|
3277
|
+
* headerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3278
|
+
* headerTitle: Header title
|
|
3279
|
+
* headerSubtitle: Header subtitle
|
|
3280
|
+
* skipFooter: Do not use sidebar footer [false]
|
|
3281
|
+
* footerImg: Image to be shown as avatar
|
|
3282
|
+
* footerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3283
|
+
* footerTitle: Footer title
|
|
3284
|
+
* footerSubtitle: Footer subtitle
|
|
3285
|
+
* collapsable: Sidebar can toggle between collapsed/expanded [true]
|
|
3286
|
+
* collapseToIcons: When Sidebar collapses, icons remains visible [true]
|
|
3287
|
+
* onHeaderPressed: Function to call when header is pressed
|
|
3288
|
+
* onFooterPressed: Function to call when footer is pressed
|
|
3289
|
+
*/
|
|
3290
|
+
|
|
3291
|
+
constructor( options = {} ) {
|
|
2902
3292
|
|
|
2903
3293
|
this.root = document.createElement( 'div' );
|
|
2904
3294
|
this.root.className = "lexsidebar";
|
|
2905
3295
|
|
|
2906
|
-
this.
|
|
2907
|
-
this.
|
|
2908
|
-
this.
|
|
3296
|
+
this.collapsable = options.collapsable ?? true;
|
|
3297
|
+
this._collapseWidth = ( options.collapseToIcons ?? true ) ? "58px" : "0px";
|
|
3298
|
+
this.collapsed = false;
|
|
3299
|
+
|
|
3300
|
+
this.filterString = "";
|
|
3301
|
+
|
|
3302
|
+
doAsync( () => {
|
|
3303
|
+
|
|
3304
|
+
this.root.parentElement.ogWidth = this.root.parentElement.style.width;
|
|
3305
|
+
this.root.parentElement.style.transition = "width 0.25s ease-out";
|
|
3306
|
+
|
|
3307
|
+
this.resizeObserver = new ResizeObserver( entries => {
|
|
3308
|
+
for ( const entry of entries )
|
|
3309
|
+
{
|
|
3310
|
+
this.siblingArea.setSize( [ "calc(100% - " + ( entry.contentRect.width ) + "px )", null ] );
|
|
3311
|
+
}
|
|
3312
|
+
});
|
|
3313
|
+
|
|
3314
|
+
}, 10 );
|
|
3315
|
+
|
|
3316
|
+
// This account for header, footer and all inner paddings
|
|
3317
|
+
let contentOffset = 32;
|
|
3318
|
+
|
|
3319
|
+
// Header
|
|
3320
|
+
if( !( options.skipHeader ?? false ) )
|
|
3321
|
+
{
|
|
3322
|
+
this.header = document.createElement( 'div' );
|
|
3323
|
+
this.header.className = "lexsidebarheader";
|
|
3324
|
+
this.root.appendChild( this.header );
|
|
3325
|
+
|
|
3326
|
+
this.header.addEventListener( "click", e => {
|
|
3327
|
+
if( this.collapsed )
|
|
3328
|
+
{
|
|
3329
|
+
e.preventDefault();
|
|
3330
|
+
e.stopPropagation();
|
|
3331
|
+
this.toggleCollapsed();
|
|
3332
|
+
}
|
|
3333
|
+
else if( options.onHeaderPressed )
|
|
3334
|
+
{
|
|
3335
|
+
options.onHeaderPressed( e );
|
|
3336
|
+
}
|
|
3337
|
+
} );
|
|
3338
|
+
|
|
3339
|
+
const avatar = document.createElement( 'span' );
|
|
3340
|
+
avatar.className = "lexavatar";
|
|
3341
|
+
this.header.appendChild( avatar );
|
|
3342
|
+
|
|
3343
|
+
if( options.headerImage )
|
|
3344
|
+
{
|
|
3345
|
+
const avatarImg = document.createElement( 'img' );
|
|
3346
|
+
avatarImg.src = options.headerImage;
|
|
3347
|
+
avatar.appendChild( avatarImg );
|
|
3348
|
+
}
|
|
3349
|
+
else if( options.headerIcon )
|
|
3350
|
+
{
|
|
3351
|
+
const avatarIcon = LX.makeIcon( options.headerIcon );
|
|
3352
|
+
avatar.appendChild( avatarIcon );
|
|
3353
|
+
}
|
|
3354
|
+
|
|
3355
|
+
// Info
|
|
3356
|
+
{
|
|
3357
|
+
const info = document.createElement( 'div' );
|
|
3358
|
+
this.header.appendChild( info );
|
|
3359
|
+
|
|
3360
|
+
const infoText = document.createElement( 'span' );
|
|
3361
|
+
infoText.innerHTML = options.headerTitle ?? "";
|
|
3362
|
+
info.appendChild( infoText );
|
|
3363
|
+
|
|
3364
|
+
const infoSubtext = document.createElement( 'span' );
|
|
3365
|
+
infoSubtext.innerHTML = options.headerSubtitle ?? "";
|
|
3366
|
+
info.appendChild( infoSubtext );
|
|
3367
|
+
}
|
|
3368
|
+
|
|
3369
|
+
if( this.collapsable )
|
|
3370
|
+
{
|
|
3371
|
+
const icon = LX.makeIcon( "Sidebar", "Toggle Sidebar" );
|
|
3372
|
+
this.header.appendChild( icon );
|
|
3373
|
+
|
|
3374
|
+
icon.addEventListener( "click", (e) => {
|
|
3375
|
+
e.preventDefault();
|
|
3376
|
+
e.stopPropagation();
|
|
3377
|
+
this.toggleCollapsed();
|
|
3378
|
+
} );
|
|
3379
|
+
}
|
|
3380
|
+
|
|
3381
|
+
contentOffset += 52;
|
|
3382
|
+
}
|
|
3383
|
+
|
|
3384
|
+
// Entry filter
|
|
3385
|
+
if( !( options.filter ?? false ) )
|
|
3386
|
+
{
|
|
3387
|
+
const panel = new Panel();
|
|
3388
|
+
panel.addText(null, "", (value, event) => {
|
|
3389
|
+
this.filterString = value;
|
|
3390
|
+
this.update();
|
|
3391
|
+
}, { placeholder: "Search...", icon: "fa-solid fa-magnifying-glass" });
|
|
3392
|
+
this.filter = panel.root.childNodes[ 0 ];
|
|
3393
|
+
this.root.appendChild( this.filter );
|
|
3394
|
+
contentOffset += 31;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
// Content
|
|
3398
|
+
{
|
|
3399
|
+
this.content = document.createElement( 'div' );
|
|
3400
|
+
this.content.className = "lexsidebarcontent";
|
|
3401
|
+
this.root.appendChild( this.content );
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
// Footer
|
|
3405
|
+
if( !( options.skipFooter ?? false ) )
|
|
3406
|
+
{
|
|
3407
|
+
this.footer = document.createElement( 'div' );
|
|
3408
|
+
this.footer.className = "lexsidebarfooter";
|
|
3409
|
+
this.root.appendChild( this.footer );
|
|
3410
|
+
|
|
3411
|
+
this.footer.addEventListener( "click", e => {
|
|
3412
|
+
if( options.onFooterPressed )
|
|
3413
|
+
{
|
|
3414
|
+
options.onFooterPressed( e );
|
|
3415
|
+
}
|
|
3416
|
+
} );
|
|
3417
|
+
|
|
3418
|
+
const avatar = document.createElement( 'span' );
|
|
3419
|
+
avatar.className = "lexavatar";
|
|
3420
|
+
this.footer.appendChild( avatar );
|
|
3421
|
+
|
|
3422
|
+
if( options.footerImage )
|
|
3423
|
+
{
|
|
3424
|
+
const avatarImg = document.createElement( 'img' );
|
|
3425
|
+
avatarImg.src = options.footerImage;
|
|
3426
|
+
avatar.appendChild( avatarImg );
|
|
3427
|
+
}
|
|
3428
|
+
else if( options.footerIcon )
|
|
3429
|
+
{
|
|
3430
|
+
const avatarIcon = LX.makeIcon( options.footerIcon );
|
|
3431
|
+
avatar.appendChild( avatarIcon );
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
// Info
|
|
3435
|
+
{
|
|
3436
|
+
const info = document.createElement( 'div' );
|
|
3437
|
+
this.footer.appendChild( info );
|
|
3438
|
+
|
|
3439
|
+
const infoText = document.createElement( 'span' );
|
|
3440
|
+
infoText.innerHTML = options.footerTitle ?? "";
|
|
3441
|
+
info.appendChild( infoText );
|
|
3442
|
+
|
|
3443
|
+
const infoSubtext = document.createElement( 'span' );
|
|
3444
|
+
infoSubtext.innerHTML = options.footerSubtitle ?? "";
|
|
3445
|
+
info.appendChild( infoSubtext );
|
|
3446
|
+
}
|
|
3447
|
+
|
|
3448
|
+
const icon = LX.makeIcon( "MenuArrows" );
|
|
3449
|
+
this.footer.appendChild( icon );
|
|
3450
|
+
|
|
3451
|
+
contentOffset += 52;
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3454
|
+
// Set width depending on header/footer
|
|
3455
|
+
this.content.style.height = `calc(100% - ${ contentOffset }px)`;
|
|
2909
3456
|
|
|
2910
3457
|
this.items = [ ];
|
|
3458
|
+
this.icons = { };
|
|
3459
|
+
this.groups = { };
|
|
2911
3460
|
}
|
|
2912
3461
|
|
|
2913
3462
|
/**
|
|
2914
|
-
* @method
|
|
2915
|
-
* @param {
|
|
2916
|
-
* callback: Function to call on each item
|
|
2917
|
-
* bottom: Bool to set item at the bottom as helper button (not selectable)
|
|
2918
|
-
* className: Add class to the entry DOM element
|
|
3463
|
+
* @method toggleCollapsed
|
|
3464
|
+
* @param {Boolean} force: Force collapsed state
|
|
2919
3465
|
*/
|
|
2920
3466
|
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
if( options.constructor == Function )
|
|
2924
|
-
options = { callback: options };
|
|
3467
|
+
toggleCollapsed( force ) {
|
|
2925
3468
|
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
if( this.items.findIndex( (v, i) => v.key == pKey ) > -1 )
|
|
3469
|
+
if( !this.collapsable )
|
|
2929
3470
|
{
|
|
2930
|
-
console.warn( `'${key}' already created in Sidebar` );
|
|
2931
3471
|
return;
|
|
2932
3472
|
}
|
|
2933
3473
|
|
|
2934
|
-
|
|
2935
|
-
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
2936
|
-
entry.id = pKey;
|
|
3474
|
+
this.collapsed = force ?? !this.collapsed;
|
|
2937
3475
|
|
|
2938
|
-
if(
|
|
3476
|
+
if( this.collapsed )
|
|
2939
3477
|
{
|
|
2940
|
-
this.
|
|
3478
|
+
this.root.classList.add( "collapsing" );
|
|
3479
|
+
this.root.parentElement.style.width = this._collapseWidth;
|
|
2941
3480
|
}
|
|
2942
3481
|
else
|
|
2943
3482
|
{
|
|
2944
|
-
this.root.
|
|
3483
|
+
this.root.classList.remove( "collapsing" );
|
|
3484
|
+
this.root.classList.remove( "collapsed" );
|
|
3485
|
+
this.root.parentElement.style.width = this.root.parentElement.ogWidth;
|
|
2945
3486
|
}
|
|
2946
3487
|
|
|
2947
|
-
|
|
2948
|
-
|
|
3488
|
+
if( !this.resizeObserver )
|
|
3489
|
+
{
|
|
3490
|
+
throw( "Wait until ResizeObserver has been created!" );
|
|
3491
|
+
}
|
|
2949
3492
|
|
|
2950
|
-
|
|
2951
|
-
button.innerHTML = "<i class='"+ (options.icon ?? "") + "'></i>";
|
|
2952
|
-
entry.appendChild( button );
|
|
3493
|
+
this.resizeObserver.observe( this.root.parentElement );
|
|
2953
3494
|
|
|
2954
|
-
|
|
2955
|
-
desc.className = 'lexsidebarentrydesc';
|
|
2956
|
-
desc.innerHTML = key;
|
|
2957
|
-
entry.appendChild( desc );
|
|
3495
|
+
doAsync( () => {
|
|
2958
3496
|
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
desc.style.display = "unset";
|
|
2962
|
-
}, 100 );
|
|
2963
|
-
});
|
|
3497
|
+
this.root.classList.toggle( "collapsed", this.collapsed );
|
|
3498
|
+
this.resizeObserver.unobserve( this.root.parentElement );
|
|
2964
3499
|
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
desc.style.display = "none";
|
|
2968
|
-
}, 100 );
|
|
2969
|
-
});
|
|
3500
|
+
}, 250 );
|
|
3501
|
+
}
|
|
2970
3502
|
|
|
2971
|
-
|
|
3503
|
+
/**
|
|
3504
|
+
* @method separator
|
|
3505
|
+
*/
|
|
3506
|
+
|
|
3507
|
+
separator() {
|
|
2972
3508
|
|
|
2973
|
-
|
|
2974
|
-
if( f ) f.call( this, key, entry );
|
|
3509
|
+
this.currentGroup = null;
|
|
2975
3510
|
|
|
2976
|
-
|
|
2977
|
-
|
|
3511
|
+
this.add( "" );
|
|
3512
|
+
}
|
|
3513
|
+
|
|
3514
|
+
/**
|
|
3515
|
+
* @method group
|
|
3516
|
+
* @param {String} groupName
|
|
3517
|
+
* @param {Object} action: { icon, callback }
|
|
3518
|
+
*/
|
|
3519
|
+
|
|
3520
|
+
group( groupName, action ) {
|
|
3521
|
+
|
|
3522
|
+
this.currentGroup = groupName;
|
|
3523
|
+
|
|
3524
|
+
this.groups[ groupName ] = action;
|
|
3525
|
+
}
|
|
3526
|
+
|
|
3527
|
+
/**
|
|
3528
|
+
* @method add
|
|
3529
|
+
* @param {String} path
|
|
3530
|
+
* @param {Object} options:
|
|
3531
|
+
* callback: Function to call on each item
|
|
3532
|
+
* icon: Entry icon
|
|
3533
|
+
* collapsable: Add entry as a collapsable section
|
|
3534
|
+
* className: Add class to the entry DOM element
|
|
3535
|
+
*/
|
|
3536
|
+
|
|
3537
|
+
add( path, options = {} ) {
|
|
3538
|
+
|
|
3539
|
+
if( options.constructor == Function )
|
|
3540
|
+
{
|
|
3541
|
+
options = { callback: options };
|
|
3542
|
+
}
|
|
3543
|
+
|
|
3544
|
+
// Process path
|
|
3545
|
+
const tokens = path.split( "/" );
|
|
3546
|
+
|
|
3547
|
+
// Assign icons and shortcuts to last token in path
|
|
3548
|
+
const lastPath = tokens[tokens.length - 1];
|
|
3549
|
+
this.icons[ lastPath ] = options.icon;
|
|
3550
|
+
|
|
3551
|
+
let idx = 0;
|
|
3552
|
+
|
|
3553
|
+
const _insertEntry = ( token, list ) => {
|
|
3554
|
+
|
|
3555
|
+
if( token == undefined )
|
|
2978
3556
|
{
|
|
2979
|
-
|
|
2980
|
-
entry.classList.add( "selected" );
|
|
3557
|
+
return;
|
|
2981
3558
|
}
|
|
2982
|
-
});
|
|
2983
3559
|
|
|
2984
|
-
|
|
3560
|
+
let found = null;
|
|
3561
|
+
list.forEach( o => {
|
|
3562
|
+
const keys = Object.keys( o );
|
|
3563
|
+
const key = keys.find( t => t == token );
|
|
3564
|
+
if( key ) found = o[ key ];
|
|
3565
|
+
} );
|
|
3566
|
+
|
|
3567
|
+
if( found )
|
|
3568
|
+
{
|
|
3569
|
+
_insertEntry( tokens[ idx++ ], found );
|
|
3570
|
+
}
|
|
3571
|
+
else
|
|
3572
|
+
{
|
|
3573
|
+
let item = {};
|
|
3574
|
+
item[ token ] = [];
|
|
3575
|
+
const nextToken = tokens[ idx++ ];
|
|
3576
|
+
// Check if last token -> add callback
|
|
3577
|
+
if( !nextToken )
|
|
3578
|
+
{
|
|
3579
|
+
item[ 'callback' ] = options.callback;
|
|
3580
|
+
item[ 'group' ] = this.currentGroup;
|
|
3581
|
+
item[ 'options' ] = options;
|
|
3582
|
+
}
|
|
3583
|
+
list.push( item );
|
|
3584
|
+
_insertEntry( nextToken, item[ token ] );
|
|
3585
|
+
}
|
|
3586
|
+
};
|
|
3587
|
+
|
|
3588
|
+
_insertEntry( tokens[idx++], this.items );
|
|
2985
3589
|
}
|
|
2986
3590
|
|
|
2987
3591
|
/**
|
|
@@ -2998,7 +3602,267 @@ class SideBar {
|
|
|
2998
3602
|
if( !entry )
|
|
2999
3603
|
return;
|
|
3000
3604
|
|
|
3001
|
-
entry.
|
|
3605
|
+
entry.dom.click();
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
update() {
|
|
3609
|
+
|
|
3610
|
+
// Reset first
|
|
3611
|
+
|
|
3612
|
+
this.content.innerHTML = "";
|
|
3613
|
+
|
|
3614
|
+
for( let item of this.items )
|
|
3615
|
+
{
|
|
3616
|
+
delete item.dom;
|
|
3617
|
+
}
|
|
3618
|
+
|
|
3619
|
+
for( let item of this.items )
|
|
3620
|
+
{
|
|
3621
|
+
const options = item.options ?? { };
|
|
3622
|
+
|
|
3623
|
+
// Item already created
|
|
3624
|
+
if( item.dom )
|
|
3625
|
+
{
|
|
3626
|
+
continue;
|
|
3627
|
+
}
|
|
3628
|
+
|
|
3629
|
+
let key = Object.keys( item )[ 0 ];
|
|
3630
|
+
|
|
3631
|
+
if( this.filterString.length && !key.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3632
|
+
{
|
|
3633
|
+
continue;
|
|
3634
|
+
}
|
|
3635
|
+
|
|
3636
|
+
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3637
|
+
let currentGroup = null;
|
|
3638
|
+
|
|
3639
|
+
let entry = document.createElement( 'div' );
|
|
3640
|
+
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
3641
|
+
entry.id = item.name = pKey;
|
|
3642
|
+
|
|
3643
|
+
if( item.group )
|
|
3644
|
+
{
|
|
3645
|
+
const pGroupKey = item.group.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3646
|
+
currentGroup = this.content.querySelector( "#" + pGroupKey );
|
|
3647
|
+
|
|
3648
|
+
if( !currentGroup )
|
|
3649
|
+
{
|
|
3650
|
+
currentGroup = document.createElement( 'div' );
|
|
3651
|
+
currentGroup.id = pGroupKey;
|
|
3652
|
+
currentGroup.className = "lexsidebargroup";
|
|
3653
|
+
this.content.appendChild( currentGroup );
|
|
3654
|
+
|
|
3655
|
+
let groupEntry = document.createElement( 'div' );
|
|
3656
|
+
groupEntry.className = "lexsidebargrouptitle";
|
|
3657
|
+
currentGroup.appendChild( groupEntry );
|
|
3658
|
+
|
|
3659
|
+
let groupLabel = document.createElement( 'div' );
|
|
3660
|
+
groupLabel.innerHTML = item.group;
|
|
3661
|
+
groupEntry.appendChild( groupLabel );
|
|
3662
|
+
|
|
3663
|
+
if( this.groups[ item.group ] != null )
|
|
3664
|
+
{
|
|
3665
|
+
let groupAction = document.createElement( 'a' );
|
|
3666
|
+
groupAction.className = ( this.groups[ item.group ].icon ?? "" ) + " lexicon";
|
|
3667
|
+
groupEntry.appendChild( groupAction );
|
|
3668
|
+
groupAction.addEventListener( "click", (e) => {
|
|
3669
|
+
if( this.groups[ item.group ].callback )
|
|
3670
|
+
{
|
|
3671
|
+
this.groups[ item.group ].callback( item.group, e );
|
|
3672
|
+
}
|
|
3673
|
+
} );
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
}
|
|
3677
|
+
else if( !currentGroup.classList.contains( "lexsidebargroup" ) )
|
|
3678
|
+
{
|
|
3679
|
+
throw( "Bad id: " + item.group );
|
|
3680
|
+
}
|
|
3681
|
+
}
|
|
3682
|
+
|
|
3683
|
+
if( pKey == "" )
|
|
3684
|
+
{
|
|
3685
|
+
let separatorDom = document.createElement( 'div' );
|
|
3686
|
+
separatorDom.className = "lexsidebarseparator";
|
|
3687
|
+
this.content.appendChild( separatorDom );
|
|
3688
|
+
continue;
|
|
3689
|
+
}
|
|
3690
|
+
|
|
3691
|
+
if( this.collapseContainer )
|
|
3692
|
+
{
|
|
3693
|
+
this.collapseContainer.appendChild( entry );
|
|
3694
|
+
|
|
3695
|
+
this.collapseQueue--;
|
|
3696
|
+
if( !this.collapseQueue )
|
|
3697
|
+
{
|
|
3698
|
+
delete this.collapseContainer;
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
else if( currentGroup )
|
|
3702
|
+
{
|
|
3703
|
+
currentGroup.appendChild( entry );
|
|
3704
|
+
}
|
|
3705
|
+
else
|
|
3706
|
+
{
|
|
3707
|
+
this.content.appendChild( entry );
|
|
3708
|
+
}
|
|
3709
|
+
|
|
3710
|
+
let itemDom = document.createElement( 'div' );
|
|
3711
|
+
entry.appendChild( itemDom );
|
|
3712
|
+
item.dom = entry;
|
|
3713
|
+
|
|
3714
|
+
if( options.type == "checkbox" )
|
|
3715
|
+
{
|
|
3716
|
+
item.value = options.value ?? false;
|
|
3717
|
+
const panel = new Panel();
|
|
3718
|
+
item.checkbox = panel.addCheckbox(null, item.value, (value, event) => {
|
|
3719
|
+
event.preventDefault();
|
|
3720
|
+
event.stopPropagation();
|
|
3721
|
+
const f = options.callback;
|
|
3722
|
+
item.value = value;
|
|
3723
|
+
if( f ) f.call( this, key, value, event );
|
|
3724
|
+
}, { label: key, signal: ( "@checkbox_" + key ) });
|
|
3725
|
+
itemDom.appendChild( panel.root.childNodes[ 0 ] );
|
|
3726
|
+
}
|
|
3727
|
+
else
|
|
3728
|
+
{
|
|
3729
|
+
if( options.icon )
|
|
3730
|
+
{
|
|
3731
|
+
let itemIcon = document.createElement( 'i' );
|
|
3732
|
+
itemIcon.className = options.icon;
|
|
3733
|
+
itemDom.appendChild( itemIcon );
|
|
3734
|
+
}
|
|
3735
|
+
|
|
3736
|
+
let itemName = document.createElement( 'a' );
|
|
3737
|
+
itemName.innerHTML = key;
|
|
3738
|
+
itemDom.appendChild( itemName );
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3741
|
+
entry.addEventListener("click", ( e ) => {
|
|
3742
|
+
if( e.target && e.target.classList.contains( "lexcheckbox" ) )
|
|
3743
|
+
{
|
|
3744
|
+
return;
|
|
3745
|
+
}
|
|
3746
|
+
|
|
3747
|
+
if( options.collapsable )
|
|
3748
|
+
{
|
|
3749
|
+
itemDom.querySelector( ".collapser" ).click();
|
|
3750
|
+
}
|
|
3751
|
+
else
|
|
3752
|
+
{
|
|
3753
|
+
const f = options.callback;
|
|
3754
|
+
if( f ) f.call( this, key, item.value, e );
|
|
3755
|
+
|
|
3756
|
+
if( item.checkbox )
|
|
3757
|
+
{
|
|
3758
|
+
item.value = !item.value;
|
|
3759
|
+
item.checkbox.set( item.value, true );
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3762
|
+
|
|
3763
|
+
// Manage selected
|
|
3764
|
+
this.root.querySelectorAll(".lexsidebarentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
3765
|
+
entry.classList.add( "selected" );
|
|
3766
|
+
});
|
|
3767
|
+
|
|
3768
|
+
if( options.action )
|
|
3769
|
+
{
|
|
3770
|
+
const actionIcon = LX.makeIcon( options.action.icon ?? "MoreHorizontal", options.action.name );
|
|
3771
|
+
itemDom.appendChild( actionIcon );
|
|
3772
|
+
|
|
3773
|
+
actionIcon.addEventListener( "click", (e) => {
|
|
3774
|
+
e.preventDefault();
|
|
3775
|
+
e.stopImmediatePropagation();
|
|
3776
|
+
const f = options.action.callback;
|
|
3777
|
+
if( f ) f.call( this, key, e );
|
|
3778
|
+
} );
|
|
3779
|
+
}
|
|
3780
|
+
else if( options.collapsable )
|
|
3781
|
+
{
|
|
3782
|
+
const collapsableContent = document.createElement( 'div' );
|
|
3783
|
+
Object.assign( collapsableContent.style, { width: "100%", display: "none" } );
|
|
3784
|
+
LX.makeCollapsible( itemDom, collapsableContent, currentGroup ?? this.content );
|
|
3785
|
+
this.collapseQueue = options.collapsable;
|
|
3786
|
+
this.collapseContainer = collapsableContent;
|
|
3787
|
+
}
|
|
3788
|
+
|
|
3789
|
+
let desc = document.createElement( 'span' );
|
|
3790
|
+
desc.className = 'lexsidebarentrydesc';
|
|
3791
|
+
desc.innerHTML = key;
|
|
3792
|
+
entry.appendChild( desc );
|
|
3793
|
+
|
|
3794
|
+
itemDom.addEventListener("mouseenter", () => {
|
|
3795
|
+
setTimeout( () => {
|
|
3796
|
+
desc.style.display = "unset";
|
|
3797
|
+
}, 150 );
|
|
3798
|
+
});
|
|
3799
|
+
|
|
3800
|
+
itemDom.addEventListener("mouseleave", () => {
|
|
3801
|
+
setTimeout( () => {
|
|
3802
|
+
desc.style.display = "none";
|
|
3803
|
+
}, 150 );
|
|
3804
|
+
});
|
|
3805
|
+
|
|
3806
|
+
// Subentries
|
|
3807
|
+
if( !item[ key ].length )
|
|
3808
|
+
{
|
|
3809
|
+
continue;
|
|
3810
|
+
}
|
|
3811
|
+
|
|
3812
|
+
let subentryContainer = document.createElement( 'div' );
|
|
3813
|
+
subentryContainer.className = "lexsidebarsubentrycontainer";
|
|
3814
|
+
|
|
3815
|
+
if( currentGroup )
|
|
3816
|
+
{
|
|
3817
|
+
currentGroup.appendChild( subentryContainer );
|
|
3818
|
+
}
|
|
3819
|
+
else
|
|
3820
|
+
{
|
|
3821
|
+
this.content.appendChild( subentryContainer );
|
|
3822
|
+
}
|
|
3823
|
+
|
|
3824
|
+
for( let i = 0; i < item[ key ].length; ++i )
|
|
3825
|
+
{
|
|
3826
|
+
const subitem = item[ key ][ i ];
|
|
3827
|
+
const suboptions = subitem.options ?? {};
|
|
3828
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
3829
|
+
|
|
3830
|
+
if( this.filterString.length && !subkey.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3831
|
+
{
|
|
3832
|
+
continue;
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3835
|
+
let subentry = document.createElement( 'div' );
|
|
3836
|
+
subentry.innerHTML = `<span>${ subkey }</span>`;
|
|
3837
|
+
|
|
3838
|
+
if( suboptions.action )
|
|
3839
|
+
{
|
|
3840
|
+
const actionIcon = LX.makeIcon( suboptions.action.icon ?? "MoreHorizontal", suboptions.action.name );
|
|
3841
|
+
subentry.appendChild( actionIcon );
|
|
3842
|
+
|
|
3843
|
+
actionIcon.addEventListener( "click", (e) => {
|
|
3844
|
+
e.preventDefault();
|
|
3845
|
+
e.stopImmediatePropagation();
|
|
3846
|
+
const f = suboptions.action.callback;
|
|
3847
|
+
if( f ) f.call( this, subkey, e );
|
|
3848
|
+
} );
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
subentry.className = "lexsidebarentry";
|
|
3852
|
+
subentry.id = subkey;
|
|
3853
|
+
subentryContainer.appendChild( subentry );
|
|
3854
|
+
|
|
3855
|
+
subentry.addEventListener("click", (e) => {
|
|
3856
|
+
|
|
3857
|
+
const f = suboptions.callback;
|
|
3858
|
+
if( f ) f.call( this, subkey, subentry, e );
|
|
3859
|
+
|
|
3860
|
+
// Manage selected
|
|
3861
|
+
this.root.querySelectorAll(".lexsidebarentry").forEach( e => e.classList.remove( 'selected' ) );
|
|
3862
|
+
entry.classList.add( "selected" );
|
|
3863
|
+
});
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
3002
3866
|
}
|
|
3003
3867
|
};
|
|
3004
3868
|
|
|
@@ -3017,30 +3881,32 @@ class Widget {
|
|
|
3017
3881
|
static DROPDOWN = 4;
|
|
3018
3882
|
static CHECKBOX = 5;
|
|
3019
3883
|
static TOGGLE = 6;
|
|
3020
|
-
static
|
|
3021
|
-
static
|
|
3022
|
-
static
|
|
3023
|
-
static
|
|
3024
|
-
static
|
|
3025
|
-
static
|
|
3026
|
-
static
|
|
3027
|
-
static
|
|
3028
|
-
static
|
|
3029
|
-
static
|
|
3030
|
-
static
|
|
3031
|
-
static
|
|
3032
|
-
static
|
|
3033
|
-
static
|
|
3034
|
-
static
|
|
3035
|
-
static
|
|
3036
|
-
static
|
|
3037
|
-
static
|
|
3038
|
-
static
|
|
3039
|
-
static
|
|
3040
|
-
static
|
|
3041
|
-
static
|
|
3042
|
-
static
|
|
3043
|
-
static
|
|
3884
|
+
static RADIO = 7;
|
|
3885
|
+
static COLOR = 8;
|
|
3886
|
+
static RANGE = 9;
|
|
3887
|
+
static NUMBER = 10;
|
|
3888
|
+
static TITLE = 11;
|
|
3889
|
+
static VECTOR = 12;
|
|
3890
|
+
static TREE = 13;
|
|
3891
|
+
static PROGRESS = 14;
|
|
3892
|
+
static FILE = 15;
|
|
3893
|
+
static LAYERS = 16;
|
|
3894
|
+
static ARRAY = 17;
|
|
3895
|
+
static LIST = 18;
|
|
3896
|
+
static TAGS = 19;
|
|
3897
|
+
static CURVE = 20;
|
|
3898
|
+
static CARD = 21;
|
|
3899
|
+
static IMAGE = 22;
|
|
3900
|
+
static CONTENT = 23;
|
|
3901
|
+
static CUSTOM = 24;
|
|
3902
|
+
static SEPARATOR = 25;
|
|
3903
|
+
static KNOB = 26;
|
|
3904
|
+
static SIZE = 27;
|
|
3905
|
+
static PAD = 28;
|
|
3906
|
+
static FORM = 29;
|
|
3907
|
+
static DIAL = 30;
|
|
3908
|
+
static COUNTER = 31;
|
|
3909
|
+
static TABLE = 32;
|
|
3044
3910
|
|
|
3045
3911
|
static NO_CONTEXT_TYPES = [
|
|
3046
3912
|
Widget.BUTTON,
|
|
@@ -3068,7 +3934,9 @@ class Widget {
|
|
|
3068
3934
|
set( value, skipCallback = false, signalName = "" ) {
|
|
3069
3935
|
|
|
3070
3936
|
if( this.onSetValue )
|
|
3937
|
+
{
|
|
3071
3938
|
return this.onSetValue( value, skipCallback );
|
|
3939
|
+
}
|
|
3072
3940
|
|
|
3073
3941
|
console.warn("Can't set value of " + this.typeName());
|
|
3074
3942
|
}
|
|
@@ -3107,14 +3975,17 @@ class Widget {
|
|
|
3107
3975
|
|
|
3108
3976
|
typeName() {
|
|
3109
3977
|
|
|
3110
|
-
switch( this.type )
|
|
3978
|
+
switch( this.type )
|
|
3979
|
+
{
|
|
3111
3980
|
case Widget.TEXT: return "Text";
|
|
3112
3981
|
case Widget.TEXTAREA: return "TextArea";
|
|
3113
3982
|
case Widget.BUTTON: return "Button";
|
|
3114
3983
|
case Widget.DROPDOWN: return "Dropdown";
|
|
3115
3984
|
case Widget.CHECKBOX: return "Checkbox";
|
|
3116
3985
|
case Widget.TOGGLE: return "Toggle";
|
|
3986
|
+
case Widget.RADIO: return "Radio";
|
|
3117
3987
|
case Widget.COLOR: return "Color";
|
|
3988
|
+
case Widget.RANGE: return "Range";
|
|
3118
3989
|
case Widget.NUMBER: return "Number";
|
|
3119
3990
|
case Widget.VECTOR: return "Vector";
|
|
3120
3991
|
case Widget.TREE: return "Tree";
|
|
@@ -3192,11 +4063,12 @@ function ADD_CUSTOM_WIDGET( custom_widget_name, options = {} )
|
|
|
3192
4063
|
buttonName += "<a class='fa-solid " + (instance ? "fa-bars-staggered" : " ") + " menu' style='float:right; width:5%;'></a>";
|
|
3193
4064
|
|
|
3194
4065
|
let buttonEl = this.addButton(null, buttonName, (value, event) => {
|
|
3195
|
-
|
|
3196
|
-
|
|
4066
|
+
if( instance )
|
|
4067
|
+
{
|
|
3197
4068
|
element.querySelector(".lexcustomitems").toggleAttribute('hidden');
|
|
3198
4069
|
}
|
|
3199
|
-
else
|
|
4070
|
+
else
|
|
4071
|
+
{
|
|
3200
4072
|
addContextMenu(null, event, c => {
|
|
3201
4073
|
c.add("New " + custom_widget_name, () => {
|
|
3202
4074
|
instance = {};
|
|
@@ -3383,16 +4255,20 @@ class NodeTree {
|
|
|
3383
4255
|
|
|
3384
4256
|
// Add or remove
|
|
3385
4257
|
const idx = this.selected.indexOf( node );
|
|
3386
|
-
if( idx > -1 )
|
|
4258
|
+
if( idx > -1 )
|
|
4259
|
+
{
|
|
3387
4260
|
item.classList.remove( 'selected' );
|
|
3388
4261
|
this.selected.splice( idx, 1 );
|
|
3389
|
-
}
|
|
4262
|
+
}
|
|
4263
|
+
else
|
|
4264
|
+
{
|
|
3390
4265
|
item.classList.add( 'selected' );
|
|
3391
4266
|
this.selected.push( node );
|
|
3392
4267
|
}
|
|
3393
4268
|
|
|
3394
4269
|
// Only Show children...
|
|
3395
|
-
if( isParent && node.id.length > 1 /* Strange case... */)
|
|
4270
|
+
if( isParent && node.id.length > 1 /* Strange case... */)
|
|
4271
|
+
{
|
|
3396
4272
|
node.closed = false;
|
|
3397
4273
|
if( that.onevent )
|
|
3398
4274
|
{
|
|
@@ -3430,7 +4306,7 @@ class NodeTree {
|
|
|
3430
4306
|
|
|
3431
4307
|
e.preventDefault();
|
|
3432
4308
|
|
|
3433
|
-
if( that.onevent )
|
|
4309
|
+
if( !that.onevent )
|
|
3434
4310
|
{
|
|
3435
4311
|
return;
|
|
3436
4312
|
}
|
|
@@ -3486,7 +4362,8 @@ class NodeTree {
|
|
|
3486
4362
|
return;
|
|
3487
4363
|
}
|
|
3488
4364
|
|
|
3489
|
-
if( that.onevent )
|
|
4365
|
+
if( that.onevent )
|
|
4366
|
+
{
|
|
3490
4367
|
const event = new TreeEvent( TreeEvent.NODE_DELETED, node, e );
|
|
3491
4368
|
that.onevent( event );
|
|
3492
4369
|
}
|
|
@@ -3513,7 +4390,8 @@ class NodeTree {
|
|
|
3513
4390
|
if( e.key == "Delete" )
|
|
3514
4391
|
{
|
|
3515
4392
|
// Send event now so we have the info in selected array..
|
|
3516
|
-
if( that.onevent )
|
|
4393
|
+
if( that.onevent )
|
|
4394
|
+
{
|
|
3517
4395
|
const event = new TreeEvent( TreeEvent.NODE_DELETED, this.selected.length > 1 ? this.selected : node, e );
|
|
3518
4396
|
event.multiple = this.selected.length > 1;
|
|
3519
4397
|
that.onevent( event );
|
|
@@ -3544,22 +4422,24 @@ class NodeTree {
|
|
|
3544
4422
|
|
|
3545
4423
|
// Node rename
|
|
3546
4424
|
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
item.appendChild(
|
|
4425
|
+
const nameInput = document.createElement( "input" );
|
|
4426
|
+
nameInput.toggleAttribute( "hidden", !node.rename );
|
|
4427
|
+
nameInput.value = node.id;
|
|
4428
|
+
item.appendChild(nameInput);
|
|
3551
4429
|
|
|
3552
|
-
if(node.rename)
|
|
4430
|
+
if( node.rename )
|
|
4431
|
+
{
|
|
3553
4432
|
item.classList.add('selected');
|
|
3554
|
-
|
|
4433
|
+
nameInput.focus();
|
|
3555
4434
|
}
|
|
3556
4435
|
|
|
3557
|
-
|
|
3558
|
-
if(e.key ==
|
|
3559
|
-
|
|
4436
|
+
nameInput.addEventListener("keyup", function(e){
|
|
4437
|
+
if( e.key == "Enter" )
|
|
4438
|
+
{
|
|
3560
4439
|
this.value = this.value.replace(/\s/g, '_');
|
|
3561
4440
|
|
|
3562
|
-
if(that.onevent)
|
|
4441
|
+
if( that.onevent )
|
|
4442
|
+
{
|
|
3563
4443
|
const event = new TreeEvent(TreeEvent.NODE_RENAMED, node, this.value);
|
|
3564
4444
|
that.onevent( event );
|
|
3565
4445
|
}
|
|
@@ -3569,18 +4449,20 @@ class NodeTree {
|
|
|
3569
4449
|
that.frefresh( node.id );
|
|
3570
4450
|
list.querySelector("#" + node.id).classList.add('selected');
|
|
3571
4451
|
}
|
|
3572
|
-
if(e.key ==
|
|
4452
|
+
else if(e.key == "Escape")
|
|
4453
|
+
{
|
|
3573
4454
|
delete node.rename;
|
|
3574
4455
|
that.frefresh( node.id );
|
|
3575
4456
|
}
|
|
3576
4457
|
});
|
|
3577
4458
|
|
|
3578
|
-
|
|
4459
|
+
nameInput.addEventListener("blur", function(e){
|
|
3579
4460
|
delete node.rename;
|
|
3580
4461
|
that.refresh();
|
|
3581
4462
|
});
|
|
3582
4463
|
|
|
3583
|
-
if(this.options.draggable ?? true)
|
|
4464
|
+
if( this.options.draggable ?? true )
|
|
4465
|
+
{
|
|
3584
4466
|
// Drag nodes
|
|
3585
4467
|
if(parent) // Root doesn't move!
|
|
3586
4468
|
{
|
|
@@ -3606,29 +4488,32 @@ class NodeTree {
|
|
|
3606
4488
|
return;
|
|
3607
4489
|
let target = node;
|
|
3608
4490
|
// Can't drop to same node
|
|
3609
|
-
if(dragged.id == target.id)
|
|
4491
|
+
if( dragged.id == target.id )
|
|
4492
|
+
{
|
|
3610
4493
|
console.warn("Cannot parent node to itself!");
|
|
3611
4494
|
return;
|
|
3612
4495
|
}
|
|
3613
4496
|
|
|
3614
4497
|
// Can't drop to child node
|
|
3615
|
-
const isChild = function(
|
|
4498
|
+
const isChild = function( newParent, node ) {
|
|
3616
4499
|
var result = false;
|
|
3617
|
-
for( var c of node.children )
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
result |= isChild(
|
|
4500
|
+
for( var c of node.children )
|
|
4501
|
+
{
|
|
4502
|
+
if( c.id == newParent.id ) return true;
|
|
4503
|
+
result |= isChild( newParent, c );
|
|
3621
4504
|
}
|
|
3622
4505
|
return result;
|
|
3623
4506
|
};
|
|
3624
4507
|
|
|
3625
|
-
if(isChild(target, dragged))
|
|
4508
|
+
if( isChild( target, dragged ))
|
|
4509
|
+
{
|
|
3626
4510
|
console.warn("Cannot parent node to a current child!");
|
|
3627
4511
|
return;
|
|
3628
4512
|
}
|
|
3629
4513
|
|
|
3630
4514
|
// Trigger node dragger event
|
|
3631
|
-
if(that.onevent)
|
|
4515
|
+
if( that.onevent )
|
|
4516
|
+
{
|
|
3632
4517
|
const event = new TreeEvent(TreeEvent.NODE_DRAGGED, dragged, target);
|
|
3633
4518
|
that.onevent( event );
|
|
3634
4519
|
}
|
|
@@ -3644,7 +4529,8 @@ class NodeTree {
|
|
|
3644
4529
|
let handled = false;
|
|
3645
4530
|
|
|
3646
4531
|
// Show/hide children
|
|
3647
|
-
if(isParent)
|
|
4532
|
+
if( isParent )
|
|
4533
|
+
{
|
|
3648
4534
|
item.querySelector('a.hierarchy').addEventListener("click", function(e) {
|
|
3649
4535
|
|
|
3650
4536
|
handled = true;
|
|
@@ -3652,7 +4538,8 @@ class NodeTree {
|
|
|
3652
4538
|
e.stopPropagation();
|
|
3653
4539
|
|
|
3654
4540
|
node.closed = !node.closed;
|
|
3655
|
-
if(that.onevent)
|
|
4541
|
+
if( that.onevent )
|
|
4542
|
+
{
|
|
3656
4543
|
const event = new TreeEvent(TreeEvent.NODE_CARETCHANGED, node, node.closed);
|
|
3657
4544
|
that.onevent( event );
|
|
3658
4545
|
}
|
|
@@ -3672,7 +4559,8 @@ class NodeTree {
|
|
|
3672
4559
|
node.visible = node.visible === undefined ? false : !node.visible;
|
|
3673
4560
|
this.className = "itemicon fa-solid fa-eye" + (!node.visible ? "-slash" : "");
|
|
3674
4561
|
// Trigger visibility event
|
|
3675
|
-
if(that.onevent)
|
|
4562
|
+
if( that.onevent )
|
|
4563
|
+
{
|
|
3676
4564
|
const event = new TreeEvent(TreeEvent.NODE_VISIBILITY, node, node.visible);
|
|
3677
4565
|
that.onevent( event );
|
|
3678
4566
|
}
|
|
@@ -3681,9 +4569,10 @@ class NodeTree {
|
|
|
3681
4569
|
item.appendChild(visibility);
|
|
3682
4570
|
}
|
|
3683
4571
|
|
|
3684
|
-
if(node.actions)
|
|
4572
|
+
if( node.actions )
|
|
3685
4573
|
{
|
|
3686
|
-
for(var i = 0; i < node.actions.length; ++i)
|
|
4574
|
+
for( var i = 0; i < node.actions.length; ++i )
|
|
4575
|
+
{
|
|
3687
4576
|
let a = node.actions[i];
|
|
3688
4577
|
var actionEl = document.createElement('a');
|
|
3689
4578
|
actionEl.className = "itemicon " + a.icon;
|
|
@@ -3696,20 +4585,25 @@ class NodeTree {
|
|
|
3696
4585
|
}
|
|
3697
4586
|
}
|
|
3698
4587
|
|
|
3699
|
-
if(selectedId != undefined && node.id == selectedId)
|
|
3700
|
-
|
|
4588
|
+
if( selectedId != undefined && node.id == selectedId )
|
|
4589
|
+
{
|
|
4590
|
+
this.selected = [ node ];
|
|
3701
4591
|
item.click();
|
|
3702
4592
|
}
|
|
3703
4593
|
|
|
3704
|
-
if(node.closed )
|
|
4594
|
+
if( node.closed )
|
|
4595
|
+
{
|
|
3705
4596
|
return;
|
|
4597
|
+
}
|
|
3706
4598
|
|
|
3707
4599
|
for( var i = 0; i < node.children.length; ++i )
|
|
3708
4600
|
{
|
|
3709
|
-
let child = node.children[i];
|
|
4601
|
+
let child = node.children[ i ];
|
|
3710
4602
|
|
|
3711
|
-
if( this.options.onlyFolders && child.type != 'folder')
|
|
4603
|
+
if( this.options.onlyFolders && child.type != 'folder' )
|
|
4604
|
+
{
|
|
3712
4605
|
continue;
|
|
4606
|
+
}
|
|
3713
4607
|
|
|
3714
4608
|
this._create_item( node, child, level + 1 );
|
|
3715
4609
|
}
|
|
@@ -3748,12 +4642,12 @@ class Panel {
|
|
|
3748
4642
|
* style: CSS Style object to be applied to the panel
|
|
3749
4643
|
*/
|
|
3750
4644
|
|
|
3751
|
-
constructor( options = {} )
|
|
4645
|
+
constructor( options = {} ) {
|
|
3752
4646
|
var root = document.createElement('div');
|
|
3753
4647
|
root.className = "lexpanel";
|
|
3754
|
-
if(options.id)
|
|
4648
|
+
if( options.id )
|
|
3755
4649
|
root.id = options.id;
|
|
3756
|
-
if(options.className)
|
|
4650
|
+
if( options.className )
|
|
3757
4651
|
root.className += " " + options.className;
|
|
3758
4652
|
|
|
3759
4653
|
root.style.width = options.width || "calc( 100% - 6px )";
|
|
@@ -3830,23 +4724,31 @@ class Panel {
|
|
|
3830
4724
|
this.branches = [];
|
|
3831
4725
|
this.current_branch = null;
|
|
3832
4726
|
|
|
3833
|
-
for(let w in this.widgets)
|
|
3834
|
-
|
|
4727
|
+
for( let w in this.widgets )
|
|
4728
|
+
{
|
|
4729
|
+
if( this.widgets[w].options && this.widgets[w].options.signal )
|
|
4730
|
+
{
|
|
3835
4731
|
const signal = this.widgets[w].options.signal;
|
|
3836
|
-
for(let i = 0; i < LX.signals[signal].length; i++)
|
|
3837
|
-
|
|
4732
|
+
for( let i = 0; i < LX.signals[signal].length; i++ )
|
|
4733
|
+
{
|
|
4734
|
+
if( LX.signals[signal][i] == this.widgets[w] )
|
|
4735
|
+
{
|
|
3838
4736
|
LX.signals[signal] = [...LX.signals[signal].slice(0, i), ...LX.signals[signal].slice(i+1)];
|
|
3839
4737
|
}
|
|
3840
4738
|
}
|
|
3841
4739
|
}
|
|
3842
4740
|
}
|
|
3843
4741
|
|
|
3844
|
-
if(this.signals)
|
|
3845
|
-
|
|
4742
|
+
if( this.signals )
|
|
4743
|
+
{
|
|
4744
|
+
for( let w = 0; w < this.signals.length; w++ )
|
|
4745
|
+
{
|
|
3846
4746
|
let widget = Object.values(this.signals[w])[0];
|
|
3847
4747
|
let signal = widget.options.signal;
|
|
3848
|
-
for(let i = 0; i < LX.signals[signal].length; i++)
|
|
3849
|
-
|
|
4748
|
+
for( let i = 0; i < LX.signals[signal].length; i++ )
|
|
4749
|
+
{
|
|
4750
|
+
if( LX.signals[signal][i] == widget )
|
|
4751
|
+
{
|
|
3850
4752
|
LX.signals[signal] = [...LX.signals[signal].slice(0, i), ...LX.signals[signal].slice(i+1)];
|
|
3851
4753
|
}
|
|
3852
4754
|
}
|
|
@@ -3884,10 +4786,12 @@ class Panel {
|
|
|
3884
4786
|
|
|
3885
4787
|
this._inline_widgets_left = -1;
|
|
3886
4788
|
|
|
3887
|
-
if(!this._inlineContainer)
|
|
4789
|
+
if( !this._inlineContainer )
|
|
4790
|
+
{
|
|
3888
4791
|
this._inlineContainer = document.createElement('div');
|
|
3889
4792
|
this._inlineContainer.className = "lexinlinewidgets";
|
|
3890
|
-
|
|
4793
|
+
|
|
4794
|
+
if( justifyContent )
|
|
3891
4795
|
{
|
|
3892
4796
|
this._inlineContainer.style.justifyContent = justifyContent;
|
|
3893
4797
|
}
|
|
@@ -3901,7 +4805,7 @@ class Panel {
|
|
|
3901
4805
|
if(is_pair)
|
|
3902
4806
|
{
|
|
3903
4807
|
// eg. an array, inline items appended later to
|
|
3904
|
-
if(this._inline_queued_container)
|
|
4808
|
+
if( this._inline_queued_container)
|
|
3905
4809
|
this._inlineContainer.appendChild( item[0] );
|
|
3906
4810
|
// eg. a dropdown, item is appended to parent, not to inline cont.
|
|
3907
4811
|
else
|
|
@@ -3913,7 +4817,7 @@ class Panel {
|
|
|
3913
4817
|
|
|
3914
4818
|
if(!this._inline_queued_container)
|
|
3915
4819
|
{
|
|
3916
|
-
if(this.current_branch)
|
|
4820
|
+
if( this.current_branch)
|
|
3917
4821
|
this.current_branch.content.appendChild( this._inlineContainer );
|
|
3918
4822
|
else
|
|
3919
4823
|
this.root.appendChild( this._inlineContainer );
|
|
@@ -3952,7 +4856,7 @@ class Panel {
|
|
|
3952
4856
|
this.current_branch = branch;
|
|
3953
4857
|
|
|
3954
4858
|
// Append to panel
|
|
3955
|
-
if(this.branches.length == 0)
|
|
4859
|
+
if( this.branches.length == 0)
|
|
3956
4860
|
branch.root.classList.add('first');
|
|
3957
4861
|
|
|
3958
4862
|
// This is the last!
|
|
@@ -3963,7 +4867,8 @@ class Panel {
|
|
|
3963
4867
|
this.root.appendChild( branch.root );
|
|
3964
4868
|
|
|
3965
4869
|
// Add widget filter
|
|
3966
|
-
if(options.filter)
|
|
4870
|
+
if( options.filter )
|
|
4871
|
+
{
|
|
3967
4872
|
this._addFilter( options.filter, {callback: this._searchWidgets.bind(this, branch.name)} );
|
|
3968
4873
|
}
|
|
3969
4874
|
|
|
@@ -4080,14 +4985,18 @@ class Panel {
|
|
|
4080
4985
|
element.jsInstance = widget;
|
|
4081
4986
|
|
|
4082
4987
|
const insert_widget = el => {
|
|
4083
|
-
if(options.container)
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4988
|
+
if( options.container )
|
|
4989
|
+
{
|
|
4990
|
+
options.container.appendChild( el );
|
|
4991
|
+
}
|
|
4992
|
+
else if( !this.queuedContainer )
|
|
4993
|
+
{
|
|
4994
|
+
if( this.current_branch )
|
|
4088
4995
|
{
|
|
4089
|
-
if(!options.skipWidget)
|
|
4996
|
+
if( !options.skipWidget )
|
|
4997
|
+
{
|
|
4090
4998
|
this.current_branch.widgets.push( widget );
|
|
4999
|
+
}
|
|
4091
5000
|
this.current_branch.content.appendChild( el );
|
|
4092
5001
|
}
|
|
4093
5002
|
else
|
|
@@ -4097,40 +5006,47 @@ class Panel {
|
|
|
4097
5006
|
}
|
|
4098
5007
|
}
|
|
4099
5008
|
// Append content to queued tab container
|
|
4100
|
-
else
|
|
5009
|
+
else
|
|
5010
|
+
{
|
|
4101
5011
|
this.queuedContainer.appendChild( el );
|
|
4102
5012
|
}
|
|
4103
5013
|
};
|
|
4104
5014
|
|
|
4105
5015
|
const store_widget = el => {
|
|
4106
5016
|
|
|
4107
|
-
if(!this.queuedContainer)
|
|
5017
|
+
if( !this.queuedContainer )
|
|
5018
|
+
{
|
|
4108
5019
|
this._inlineWidgets.push( el );
|
|
4109
5020
|
}
|
|
4110
5021
|
// Append content to queued tab container
|
|
4111
|
-
else
|
|
5022
|
+
else
|
|
5023
|
+
{
|
|
4112
5024
|
this._inlineWidgets.push( [el, this.queuedContainer] );
|
|
4113
5025
|
}
|
|
4114
5026
|
};
|
|
4115
5027
|
|
|
4116
5028
|
// Process inline widgets
|
|
4117
|
-
if(this._inline_widgets_left > 0 && !options.skipInlineCount)
|
|
5029
|
+
if( this._inline_widgets_left > 0 && !options.skipInlineCount )
|
|
4118
5030
|
{
|
|
4119
|
-
if(!this._inlineWidgets)
|
|
5031
|
+
if( !this._inlineWidgets )
|
|
5032
|
+
{
|
|
4120
5033
|
this._inlineWidgets = [];
|
|
4121
5034
|
}
|
|
4122
5035
|
|
|
4123
5036
|
// Store widget and its container
|
|
4124
|
-
store_widget(element);
|
|
5037
|
+
store_widget( element );
|
|
4125
5038
|
|
|
4126
5039
|
this._inline_widgets_left--;
|
|
4127
5040
|
|
|
4128
5041
|
// Last widget
|
|
4129
|
-
if(!this._inline_widgets_left)
|
|
5042
|
+
if( !this._inline_widgets_left )
|
|
5043
|
+
{
|
|
4130
5044
|
this.endLine();
|
|
4131
5045
|
}
|
|
4132
|
-
}
|
|
4133
|
-
|
|
5046
|
+
}
|
|
5047
|
+
else
|
|
5048
|
+
{
|
|
5049
|
+
insert_widget( element );
|
|
4134
5050
|
}
|
|
4135
5051
|
|
|
4136
5052
|
return widget;
|
|
@@ -4167,15 +5083,20 @@ class Panel {
|
|
|
4167
5083
|
|
|
4168
5084
|
_searchWidgets(branchName, value) {
|
|
4169
5085
|
|
|
4170
|
-
for( let b of this.branches )
|
|
4171
|
-
|
|
4172
|
-
if(b.name !== branchName)
|
|
5086
|
+
for( let b of this.branches )
|
|
5087
|
+
{
|
|
5088
|
+
if( b.name !== branchName )
|
|
5089
|
+
{
|
|
4173
5090
|
continue;
|
|
5091
|
+
}
|
|
4174
5092
|
|
|
4175
5093
|
// remove all widgets
|
|
4176
|
-
for( let w of b.widgets )
|
|
4177
|
-
|
|
5094
|
+
for( let w of b.widgets )
|
|
5095
|
+
{
|
|
5096
|
+
if( w.domEl.classList.contains('lexfilter') )
|
|
5097
|
+
{
|
|
4178
5098
|
continue;
|
|
5099
|
+
}
|
|
4179
5100
|
w.domEl.remove();
|
|
4180
5101
|
}
|
|
4181
5102
|
|
|
@@ -4185,9 +5106,9 @@ class Panel {
|
|
|
4185
5106
|
const emptyFilter = !value.length;
|
|
4186
5107
|
|
|
4187
5108
|
// add widgets
|
|
4188
|
-
for( let w of b.widgets )
|
|
4189
|
-
|
|
4190
|
-
if(!emptyFilter)
|
|
5109
|
+
for( let w of b.widgets )
|
|
5110
|
+
{
|
|
5111
|
+
if( !emptyFilter )
|
|
4191
5112
|
{
|
|
4192
5113
|
if(!w.name) continue;
|
|
4193
5114
|
const filterWord = value.toLowerCase();
|
|
@@ -4281,7 +5202,7 @@ class Panel {
|
|
|
4281
5202
|
|
|
4282
5203
|
clearQueue() {
|
|
4283
5204
|
|
|
4284
|
-
if(this._queue && this._queue.length)
|
|
5205
|
+
if( this._queue && this._queue.length)
|
|
4285
5206
|
{
|
|
4286
5207
|
this.queuedContainer = this._queue.pop();
|
|
4287
5208
|
return;
|
|
@@ -4441,7 +5362,7 @@ class Panel {
|
|
|
4441
5362
|
|
|
4442
5363
|
var resolve = ( function( val, event ) {
|
|
4443
5364
|
|
|
4444
|
-
if( !widget.valid() )
|
|
5365
|
+
if( !widget.valid() || ( this._lastValueTriggered == val ) )
|
|
4445
5366
|
{
|
|
4446
5367
|
return;
|
|
4447
5368
|
}
|
|
@@ -4454,6 +5375,8 @@ class Panel {
|
|
|
4454
5375
|
this._trigger( new IEvent( name, val, event ), callback );
|
|
4455
5376
|
}
|
|
4456
5377
|
|
|
5378
|
+
this._lastValueTriggered = val;
|
|
5379
|
+
|
|
4457
5380
|
}).bind( this );
|
|
4458
5381
|
|
|
4459
5382
|
const trigger = options.trigger ?? 'default';
|
|
@@ -4507,7 +5430,8 @@ class Panel {
|
|
|
4507
5430
|
element.appendChild( container );
|
|
4508
5431
|
|
|
4509
5432
|
// Remove branch padding and margins
|
|
4510
|
-
if( !widget.name )
|
|
5433
|
+
if( !widget.name )
|
|
5434
|
+
{
|
|
4511
5435
|
element.className += " noname";
|
|
4512
5436
|
container.style.width = "100%";
|
|
4513
5437
|
}
|
|
@@ -4607,7 +5531,8 @@ class Panel {
|
|
|
4607
5531
|
element.appendChild(container);
|
|
4608
5532
|
|
|
4609
5533
|
// Remove branch padding and margins
|
|
4610
|
-
if(!widget.name)
|
|
5534
|
+
if( !widget.name )
|
|
5535
|
+
{
|
|
4611
5536
|
element.className += " noname";
|
|
4612
5537
|
container.style.width = "100%";
|
|
4613
5538
|
}
|
|
@@ -4712,11 +5637,12 @@ class Panel {
|
|
|
4712
5637
|
/**
|
|
4713
5638
|
* @method addComboButtons
|
|
4714
5639
|
* @param {String} name Widget name
|
|
4715
|
-
* @param {Array} values Each of the {value, callback} items
|
|
5640
|
+
* @param {Array} values Each of the {value, callback, selected, disabled} items
|
|
4716
5641
|
* @param {*} options:
|
|
4717
5642
|
* float: Justify content (left, center, right) [center]
|
|
4718
|
-
* selected: Selected item by default by value
|
|
5643
|
+
* @legacy selected: Selected item by default by value
|
|
4719
5644
|
* noSelection: Buttons can be clicked, but they are not selectable
|
|
5645
|
+
* toggle: Buttons can be toggled insted of selecting only one
|
|
4720
5646
|
*/
|
|
4721
5647
|
|
|
4722
5648
|
addComboButtons( name, values, options = {} ) {
|
|
@@ -4738,7 +5664,8 @@ class Panel {
|
|
|
4738
5664
|
let buttonsBox = document.createElement('div');
|
|
4739
5665
|
buttonsBox.className = "lexcombobuttonsbox ";
|
|
4740
5666
|
|
|
4741
|
-
|
|
5667
|
+
const shouldSelect = !( options.noSelection ?? false );
|
|
5668
|
+
const shouldToggle = shouldSelect && ( options.toggle ?? false );
|
|
4742
5669
|
|
|
4743
5670
|
for( let b of values )
|
|
4744
5671
|
{
|
|
@@ -4757,14 +5684,14 @@ class Panel {
|
|
|
4757
5684
|
buttonEl.classList.add( options.buttonClass );
|
|
4758
5685
|
}
|
|
4759
5686
|
|
|
4760
|
-
if( shouldSelect && options.selected == b.value )
|
|
5687
|
+
if( shouldSelect && ( b.selected || options.selected == b.value ) )
|
|
4761
5688
|
{
|
|
4762
5689
|
buttonEl.classList.add("selected");
|
|
4763
5690
|
}
|
|
4764
5691
|
|
|
4765
5692
|
buttonEl.innerHTML = ( b.icon ? "<a class='" + b.icon +"'></a>" : "" ) + "<span>" + ( b.icon ? "" : b.value ) + "</span>";
|
|
4766
5693
|
|
|
4767
|
-
if(
|
|
5694
|
+
if( b.disabled )
|
|
4768
5695
|
{
|
|
4769
5696
|
buttonEl.setAttribute( "disabled", true );
|
|
4770
5697
|
}
|
|
@@ -4772,8 +5699,15 @@ class Panel {
|
|
|
4772
5699
|
buttonEl.addEventListener("click", function( e ) {
|
|
4773
5700
|
if( shouldSelect )
|
|
4774
5701
|
{
|
|
4775
|
-
|
|
4776
|
-
|
|
5702
|
+
if( shouldToggle )
|
|
5703
|
+
{
|
|
5704
|
+
this.classList.toggle('selected');
|
|
5705
|
+
}
|
|
5706
|
+
else
|
|
5707
|
+
{
|
|
5708
|
+
container.querySelectorAll('button').forEach( s => s.classList.remove('selected'));
|
|
5709
|
+
this.classList.add('selected');
|
|
5710
|
+
}
|
|
4777
5711
|
}
|
|
4778
5712
|
|
|
4779
5713
|
that._trigger( new IEvent( name, b.value, e ), b.callback );
|
|
@@ -4783,7 +5717,7 @@ class Panel {
|
|
|
4783
5717
|
}
|
|
4784
5718
|
|
|
4785
5719
|
// Remove branch padding and margins
|
|
4786
|
-
if( !widget.name)
|
|
5720
|
+
if( !widget.name )
|
|
4787
5721
|
{
|
|
4788
5722
|
element.className += " noname";
|
|
4789
5723
|
container.style.width = "100%";
|
|
@@ -4957,7 +5891,8 @@ class Panel {
|
|
|
4957
5891
|
|
|
4958
5892
|
element.appendChild( container );
|
|
4959
5893
|
|
|
4960
|
-
if( !widget.name || options.hideName )
|
|
5894
|
+
if( !widget.name || options.hideName )
|
|
5895
|
+
{
|
|
4961
5896
|
element.className += " noname";
|
|
4962
5897
|
container.style.width = "100%";
|
|
4963
5898
|
}
|
|
@@ -5093,8 +6028,6 @@ class Panel {
|
|
|
5093
6028
|
|
|
5094
6029
|
const _placeOptions = ( parent ) => {
|
|
5095
6030
|
|
|
5096
|
-
console.log("Replacing container");
|
|
5097
|
-
|
|
5098
6031
|
const overflowContainer = parent.getParentArea();
|
|
5099
6032
|
const rect = selectedOption.getBoundingClientRect();
|
|
5100
6033
|
const nestedDialog = parent.parentElement.closest( "dialog" );
|
|
@@ -5378,15 +6311,16 @@ class Panel {
|
|
|
5378
6311
|
|
|
5379
6312
|
addCurve( name, values, callback, options = {} ) {
|
|
5380
6313
|
|
|
5381
|
-
if(!name)
|
|
5382
|
-
|
|
6314
|
+
if( !name )
|
|
6315
|
+
{
|
|
6316
|
+
throw( "Set Widget Name!" );
|
|
5383
6317
|
}
|
|
5384
6318
|
|
|
5385
6319
|
let that = this;
|
|
5386
|
-
let widget = this.create_widget(name, Widget.CURVE, options);
|
|
6320
|
+
let widget = this.create_widget( name, Widget.CURVE, options );
|
|
5387
6321
|
|
|
5388
6322
|
widget.onGetValue = () => {
|
|
5389
|
-
return JSON.parse(JSON.stringify(curveInstance.element.value));
|
|
6323
|
+
return JSON.parse(JSON.stringify( curveInstance.element.value ));
|
|
5390
6324
|
};
|
|
5391
6325
|
|
|
5392
6326
|
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
@@ -5531,7 +6465,8 @@ class Panel {
|
|
|
5531
6465
|
|
|
5532
6466
|
addLayers( name, value, callback, options = {} ) {
|
|
5533
6467
|
|
|
5534
|
-
if(!name)
|
|
6468
|
+
if( !name )
|
|
6469
|
+
{
|
|
5535
6470
|
throw("Set Widget Name!");
|
|
5536
6471
|
}
|
|
5537
6472
|
|
|
@@ -5573,7 +6508,8 @@ class Panel {
|
|
|
5573
6508
|
let binary = value.toString( 2 );
|
|
5574
6509
|
let nbits = binary.length;
|
|
5575
6510
|
// fill zeros
|
|
5576
|
-
for(var i = 0; i < (16 - nbits); ++i)
|
|
6511
|
+
for( var i = 0; i < (16 - nbits); ++i )
|
|
6512
|
+
{
|
|
5577
6513
|
binary = '0' + binary;
|
|
5578
6514
|
}
|
|
5579
6515
|
|
|
@@ -5626,8 +6562,9 @@ class Panel {
|
|
|
5626
6562
|
|
|
5627
6563
|
addArray( name, values = [], callback, options = {} ) {
|
|
5628
6564
|
|
|
5629
|
-
if(!name)
|
|
5630
|
-
|
|
6565
|
+
if( !name )
|
|
6566
|
+
{
|
|
6567
|
+
throw( "Set Widget Name!" );
|
|
5631
6568
|
}
|
|
5632
6569
|
|
|
5633
6570
|
let widget = this.create_widget(name, Widget.ARRAY, options);
|
|
@@ -5808,7 +6745,8 @@ class Panel {
|
|
|
5808
6745
|
widget.updateValues( values );
|
|
5809
6746
|
|
|
5810
6747
|
// Remove branch padding and margins
|
|
5811
|
-
if( !widget.name )
|
|
6748
|
+
if( !widget.name )
|
|
6749
|
+
{
|
|
5812
6750
|
element.className += " noname";
|
|
5813
6751
|
listContainer.style.width = "100%";
|
|
5814
6752
|
}
|
|
@@ -5895,7 +6833,7 @@ class Panel {
|
|
|
5895
6833
|
tagsContainer.appendChild( tagInput );
|
|
5896
6834
|
|
|
5897
6835
|
tagInput.onkeydown = function( e ) {
|
|
5898
|
-
const val = this.value.replace(/\s/g, '');
|
|
6836
|
+
const val = this.value.replace( /\s/g, '' );
|
|
5899
6837
|
if( e.key == ' ' || e.key == 'Enter' )
|
|
5900
6838
|
{
|
|
5901
6839
|
e.preventDefault();
|
|
@@ -5933,15 +6871,16 @@ class Panel {
|
|
|
5933
6871
|
* @param {Function} callback Callback function on change
|
|
5934
6872
|
* @param {*} options:
|
|
5935
6873
|
* disabled: Make the widget disabled [false]
|
|
6874
|
+
* label: Checkbox label
|
|
5936
6875
|
* suboptions: Callback to add widgets in case of TRUE value
|
|
5937
|
-
* className:
|
|
6876
|
+
* className: Extra classes to customize style
|
|
5938
6877
|
*/
|
|
5939
6878
|
|
|
5940
6879
|
addCheckbox( name, value, callback, options = {} ) {
|
|
5941
6880
|
|
|
5942
|
-
if( !name )
|
|
6881
|
+
if( !name && !options.label )
|
|
5943
6882
|
{
|
|
5944
|
-
throw( "Set Widget Name!" );
|
|
6883
|
+
throw( "Set Widget Name or at least a label!" );
|
|
5945
6884
|
}
|
|
5946
6885
|
|
|
5947
6886
|
let widget = this.create_widget( name, Widget.CHECKBOX, options );
|
|
@@ -5961,10 +6900,13 @@ class Panel {
|
|
|
5961
6900
|
let element = widget.domEl;
|
|
5962
6901
|
|
|
5963
6902
|
// Add reset functionality
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
Panel.
|
|
5967
|
-
|
|
6903
|
+
if( name )
|
|
6904
|
+
{
|
|
6905
|
+
Panel._add_reset_property( element.domName, function() {
|
|
6906
|
+
checkbox.checked = !checkbox.checked;
|
|
6907
|
+
Panel._dispatch_event( checkbox, "change" );
|
|
6908
|
+
});
|
|
6909
|
+
}
|
|
5968
6910
|
|
|
5969
6911
|
// Add widget value
|
|
5970
6912
|
|
|
@@ -5980,7 +6922,7 @@ class Panel {
|
|
|
5980
6922
|
|
|
5981
6923
|
let valueName = document.createElement( 'span' );
|
|
5982
6924
|
valueName.className = "checkboxtext";
|
|
5983
|
-
valueName.innerHTML = "On";
|
|
6925
|
+
valueName.innerHTML = options.label ?? "On";
|
|
5984
6926
|
|
|
5985
6927
|
container.appendChild( checkbox );
|
|
5986
6928
|
container.appendChild( valueName );
|
|
@@ -6118,6 +7060,96 @@ class Panel {
|
|
|
6118
7060
|
return widget;
|
|
6119
7061
|
}
|
|
6120
7062
|
|
|
7063
|
+
/**
|
|
7064
|
+
* @method addRadioGroup
|
|
7065
|
+
* @param {String} label Radio label
|
|
7066
|
+
* @param {Array} values Radio options
|
|
7067
|
+
* @param {Function} callback Callback function on change
|
|
7068
|
+
* @param {*} options:
|
|
7069
|
+
* disabled: Make the widget disabled [false]
|
|
7070
|
+
* className: Customize colors
|
|
7071
|
+
*/
|
|
7072
|
+
|
|
7073
|
+
addRadioGroup( label, values, callback, options = {} ) {
|
|
7074
|
+
|
|
7075
|
+
let widget = this.create_widget( null, Widget.RADIO, options );
|
|
7076
|
+
|
|
7077
|
+
widget.onGetValue = () => {
|
|
7078
|
+
const items = container.querySelectorAll( 'button' );
|
|
7079
|
+
for( let i = 0; i < items.length; ++i )
|
|
7080
|
+
{
|
|
7081
|
+
const optionItem = items[ i ];
|
|
7082
|
+
if( optionItem.checked )
|
|
7083
|
+
{
|
|
7084
|
+
return [ i, values[ i ] ];
|
|
7085
|
+
}
|
|
7086
|
+
}
|
|
7087
|
+
};
|
|
7088
|
+
|
|
7089
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
7090
|
+
const items = container.querySelectorAll( 'button' );
|
|
7091
|
+
for( let i = 0; i < items.length; ++i )
|
|
7092
|
+
{
|
|
7093
|
+
const optionItem = items[ i ];
|
|
7094
|
+
if( newValue == i )
|
|
7095
|
+
{
|
|
7096
|
+
Panel._dispatch_event( optionItem, "click", skipCallback );
|
|
7097
|
+
}
|
|
7098
|
+
}
|
|
7099
|
+
};
|
|
7100
|
+
|
|
7101
|
+
let element = widget.domEl;
|
|
7102
|
+
|
|
7103
|
+
// Add widget value
|
|
7104
|
+
var container = document.createElement( 'div' );
|
|
7105
|
+
container.className = "lexradiogroup " + ( options.className ?? "" );
|
|
7106
|
+
|
|
7107
|
+
let labelSpan = document.createElement( 'span' );
|
|
7108
|
+
labelSpan.innerHTML = label;
|
|
7109
|
+
container.appendChild( labelSpan );
|
|
7110
|
+
|
|
7111
|
+
const that = this;
|
|
7112
|
+
|
|
7113
|
+
for( let i = 0; i < values.length; ++i )
|
|
7114
|
+
{
|
|
7115
|
+
const optionItem = document.createElement( 'div' );
|
|
7116
|
+
optionItem.className = "lexradiogroupitem";
|
|
7117
|
+
container.appendChild( optionItem );
|
|
7118
|
+
|
|
7119
|
+
const optionButton = document.createElement( 'button' );
|
|
7120
|
+
optionButton.className = "lexbutton";
|
|
7121
|
+
optionButton.disabled = options.disabled ?? false;
|
|
7122
|
+
optionItem.appendChild( optionButton );
|
|
7123
|
+
|
|
7124
|
+
optionButton.addEventListener( "click", function( e ) {
|
|
7125
|
+
const skipCallback = ( e.detail?.constructor == Number ? null : e.detail );
|
|
7126
|
+
container.querySelectorAll( 'button' ).forEach( e => { e.checked = false; e.classList.remove( "checked" ) } );
|
|
7127
|
+
this.checked = !this.checked;
|
|
7128
|
+
this.classList.toggle( "checked" );
|
|
7129
|
+
if( !skipCallback ) that._trigger( new IEvent( null, [ i, values[ i ] ], e ), callback );
|
|
7130
|
+
} );
|
|
7131
|
+
|
|
7132
|
+
{
|
|
7133
|
+
const checkedSpan = document.createElement( 'span' );
|
|
7134
|
+
optionButton.appendChild( checkedSpan );
|
|
7135
|
+
}
|
|
7136
|
+
|
|
7137
|
+
const optionLabel = document.createElement( 'span' );
|
|
7138
|
+
optionLabel.innerHTML = values[ i ];
|
|
7139
|
+
optionItem.appendChild( optionLabel );
|
|
7140
|
+
}
|
|
7141
|
+
|
|
7142
|
+
if( options.selected )
|
|
7143
|
+
{
|
|
7144
|
+
console.assert( options.selected.constructor == Number );
|
|
7145
|
+
widget.set( options.selected, true );
|
|
7146
|
+
}
|
|
7147
|
+
|
|
7148
|
+
element.appendChild( container );
|
|
7149
|
+
|
|
7150
|
+
return widget;
|
|
7151
|
+
}
|
|
7152
|
+
|
|
6121
7153
|
/**
|
|
6122
7154
|
* @method addColor
|
|
6123
7155
|
* @param {String} name Widget name
|
|
@@ -6130,7 +7162,8 @@ class Panel {
|
|
|
6130
7162
|
|
|
6131
7163
|
addColor( name, value, callback, options = {} ) {
|
|
6132
7164
|
|
|
6133
|
-
if( !name )
|
|
7165
|
+
if( !name )
|
|
7166
|
+
{
|
|
6134
7167
|
throw( "Set Widget Name!" );
|
|
6135
7168
|
}
|
|
6136
7169
|
|
|
@@ -6168,7 +7201,8 @@ class Panel {
|
|
|
6168
7201
|
color.useRGB = options.useRGB ?? false;
|
|
6169
7202
|
color.value = color.iValue = value.constructor === Array ? rgbToHex( value ) : value;
|
|
6170
7203
|
|
|
6171
|
-
if( options.disabled )
|
|
7204
|
+
if( options.disabled )
|
|
7205
|
+
{
|
|
6172
7206
|
color.disabled = true;
|
|
6173
7207
|
}
|
|
6174
7208
|
|
|
@@ -6213,6 +7247,137 @@ class Panel {
|
|
|
6213
7247
|
return widget;
|
|
6214
7248
|
}
|
|
6215
7249
|
|
|
7250
|
+
/**
|
|
7251
|
+
* @method addRange
|
|
7252
|
+
* @param {String} name Widget name
|
|
7253
|
+
* @param {Number} value Default number value
|
|
7254
|
+
* @param {Function} callback Callback function on change
|
|
7255
|
+
* @param {*} options:
|
|
7256
|
+
* className: Extra classes to customize style
|
|
7257
|
+
* disabled: Make the widget disabled [false]
|
|
7258
|
+
* left: The slider goes to the left instead of the right
|
|
7259
|
+
* fill: Fill slider progress [true]
|
|
7260
|
+
* step: Step of the input
|
|
7261
|
+
* min, max: Min and Max values for the input
|
|
7262
|
+
*/
|
|
7263
|
+
|
|
7264
|
+
addRange( name, value, callback, options = {} ) {
|
|
7265
|
+
|
|
7266
|
+
let widget = this.create_widget( name, Widget.RANGE, options );
|
|
7267
|
+
|
|
7268
|
+
widget.onGetValue = () => {
|
|
7269
|
+
return +slider.value;
|
|
7270
|
+
};
|
|
7271
|
+
|
|
7272
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
7273
|
+
slider.value = newValue;
|
|
7274
|
+
Panel._dispatch_event( slider, "input", skipCallback );
|
|
7275
|
+
};
|
|
7276
|
+
|
|
7277
|
+
let element = widget.domEl;
|
|
7278
|
+
|
|
7279
|
+
// add reset functionality
|
|
7280
|
+
if( widget.name )
|
|
7281
|
+
{
|
|
7282
|
+
Panel._add_reset_property( element.domName, function() {
|
|
7283
|
+
this.style.display = "none";
|
|
7284
|
+
slider.value = slider.iValue;
|
|
7285
|
+
Panel._dispatch_event( slider, "input" );
|
|
7286
|
+
});
|
|
7287
|
+
}
|
|
7288
|
+
|
|
7289
|
+
// add widget value
|
|
7290
|
+
|
|
7291
|
+
var container = document.createElement( 'div' );
|
|
7292
|
+
container.className = "lexrange";
|
|
7293
|
+
container.style.width = options.inputWidth || "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
7294
|
+
|
|
7295
|
+
let slider = document.createElement( 'input' );
|
|
7296
|
+
slider.className = "lexrangeslider " + ( options.className ?? "" );
|
|
7297
|
+
slider.value = slider.iValue = value;
|
|
7298
|
+
slider.min = options.min;
|
|
7299
|
+
slider.max = options.max;
|
|
7300
|
+
slider.step = options.step ?? 1;
|
|
7301
|
+
slider.type = "range";
|
|
7302
|
+
slider.disabled = options.disabled ?? false;
|
|
7303
|
+
|
|
7304
|
+
if( options.left ?? false )
|
|
7305
|
+
{
|
|
7306
|
+
slider.classList.add( "left" );
|
|
7307
|
+
}
|
|
7308
|
+
|
|
7309
|
+
if( !( options.fill ?? true ) )
|
|
7310
|
+
{
|
|
7311
|
+
slider.classList.add( "no-fill" );
|
|
7312
|
+
}
|
|
7313
|
+
|
|
7314
|
+
slider.addEventListener( "input", e => {
|
|
7315
|
+
|
|
7316
|
+
if( isNaN( e.target.valueAsNumber ) )
|
|
7317
|
+
{
|
|
7318
|
+
return;
|
|
7319
|
+
}
|
|
7320
|
+
|
|
7321
|
+
const skipCallback = e.detail;
|
|
7322
|
+
|
|
7323
|
+
let val = e.target.value = clamp( +e.target.valueAsNumber, +slider.min, +slider.max );
|
|
7324
|
+
slider.value = val;
|
|
7325
|
+
|
|
7326
|
+
// Reset button (default value)
|
|
7327
|
+
if( !skipCallback )
|
|
7328
|
+
{
|
|
7329
|
+
let btn = element.querySelector( ".lexwidgetname .lexicon" );
|
|
7330
|
+
if( btn ) btn.style.display = val != slider.iValue ? "block": "none";
|
|
7331
|
+
}
|
|
7332
|
+
|
|
7333
|
+
if( options.left )
|
|
7334
|
+
{
|
|
7335
|
+
val = ( +slider.max ) - val + ( +slider.min );
|
|
7336
|
+
}
|
|
7337
|
+
|
|
7338
|
+
if( !skipCallback ) this._trigger( new IEvent( name, val, e ), callback );
|
|
7339
|
+
}, { passive: false });
|
|
7340
|
+
|
|
7341
|
+
slider.addEventListener( "mousedown", function( e ) {
|
|
7342
|
+
if( options.onPress )
|
|
7343
|
+
{
|
|
7344
|
+
options.onPress.bind( slider )( e, slider );
|
|
7345
|
+
}
|
|
7346
|
+
}, false );
|
|
7347
|
+
|
|
7348
|
+
slider.addEventListener( "mouseup", function( e ) {
|
|
7349
|
+
if( options.onRelease )
|
|
7350
|
+
{
|
|
7351
|
+
options.onRelease.bind( slider )( e, slider );
|
|
7352
|
+
}
|
|
7353
|
+
}, false );
|
|
7354
|
+
|
|
7355
|
+
// Method to change min, max, step parameters
|
|
7356
|
+
widget.setLimits = ( newMin, newMax, newStep ) => {
|
|
7357
|
+
slider.min = newMin ?? slider.min;
|
|
7358
|
+
slider.max = newMax ?? slider.max;
|
|
7359
|
+
slider.step = newStep ?? slider.step;
|
|
7360
|
+
Panel._dispatch_event( slider, "input", true );
|
|
7361
|
+
};
|
|
7362
|
+
|
|
7363
|
+
if( value.constructor == Number )
|
|
7364
|
+
{
|
|
7365
|
+
value = clamp( value, +slider.min, +slider.max );
|
|
7366
|
+
}
|
|
7367
|
+
|
|
7368
|
+
container.appendChild( slider );
|
|
7369
|
+
element.appendChild( container );
|
|
7370
|
+
|
|
7371
|
+
// Remove branch padding and margins
|
|
7372
|
+
if( !widget.name )
|
|
7373
|
+
{
|
|
7374
|
+
element.className += " noname";
|
|
7375
|
+
container.style.width = "100%";
|
|
7376
|
+
}
|
|
7377
|
+
|
|
7378
|
+
return widget;
|
|
7379
|
+
}
|
|
7380
|
+
|
|
6216
7381
|
/**
|
|
6217
7382
|
* @method addNumber
|
|
6218
7383
|
* @param {String} name Widget name
|
|
@@ -6245,7 +7410,8 @@ class Panel {
|
|
|
6245
7410
|
let element = widget.domEl;
|
|
6246
7411
|
|
|
6247
7412
|
// add reset functionality
|
|
6248
|
-
if( widget.name )
|
|
7413
|
+
if( widget.name )
|
|
7414
|
+
{
|
|
6249
7415
|
Panel._add_reset_property( element.domName, function() {
|
|
6250
7416
|
this.style.display = "none";
|
|
6251
7417
|
vecinput.value = vecinput.iValue;
|
|
@@ -6513,7 +7679,8 @@ class Panel {
|
|
|
6513
7679
|
return;
|
|
6514
7680
|
}
|
|
6515
7681
|
|
|
6516
|
-
for( let i = 0; i < inputs.length; ++i )
|
|
7682
|
+
for( let i = 0; i < inputs.length; ++i )
|
|
7683
|
+
{
|
|
6517
7684
|
let value = newValue[ i ];
|
|
6518
7685
|
inputs[ i ].value = round( value, options.precision ) ?? 0;
|
|
6519
7686
|
Panel._dispatch_event( inputs[ i ], "change", skipCallback );
|
|
@@ -6525,7 +7692,8 @@ class Panel {
|
|
|
6525
7692
|
// Add reset functionality
|
|
6526
7693
|
Panel._add_reset_property( element.domName, function() {
|
|
6527
7694
|
this.style.display = "none";
|
|
6528
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7695
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7696
|
+
{
|
|
6529
7697
|
v.value = v.iValue;
|
|
6530
7698
|
Panel._dispatch_event( v, "change" );
|
|
6531
7699
|
}
|
|
@@ -6537,8 +7705,8 @@ class Panel {
|
|
|
6537
7705
|
container.className = "lexvector";
|
|
6538
7706
|
container.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
6539
7707
|
|
|
6540
|
-
for( let i = 0; i < num_components; ++i )
|
|
6541
|
-
|
|
7708
|
+
for( let i = 0; i < num_components; ++i )
|
|
7709
|
+
{
|
|
6542
7710
|
let box = document.createElement( 'div' );
|
|
6543
7711
|
box.className = "vecbox";
|
|
6544
7712
|
box.innerHTML = "<span class='" + Panel.VECTOR_COMPONENTS[ i ] + "'></span>";
|
|
@@ -6614,7 +7782,8 @@ class Panel {
|
|
|
6614
7782
|
|
|
6615
7783
|
if( locker.locked )
|
|
6616
7784
|
{
|
|
6617
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7785
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7786
|
+
{
|
|
6618
7787
|
v.value = val;
|
|
6619
7788
|
value[ v.idx ] = val;
|
|
6620
7789
|
}
|
|
@@ -6672,7 +7841,8 @@ class Panel {
|
|
|
6672
7841
|
|
|
6673
7842
|
if( locker.locked )
|
|
6674
7843
|
{
|
|
6675
|
-
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7844
|
+
for( let v of element.querySelectorAll( ".vecinput" ) )
|
|
7845
|
+
{
|
|
6676
7846
|
v.value = round( +v.valueAsNumber + mult * dt, options.precision );
|
|
6677
7847
|
Panel._dispatch_event( v, "change" );
|
|
6678
7848
|
}
|
|
@@ -6798,7 +7968,7 @@ class Panel {
|
|
|
6798
7968
|
const value = [];
|
|
6799
7969
|
for( let i = 0; i < element.dimensions.length; ++i )
|
|
6800
7970
|
{
|
|
6801
|
-
value.push( element.dimensions[ i ].
|
|
7971
|
+
value.push( element.dimensions[ i ].value() );
|
|
6802
7972
|
}
|
|
6803
7973
|
return value;
|
|
6804
7974
|
};
|
|
@@ -6806,7 +7976,7 @@ class Panel {
|
|
|
6806
7976
|
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
6807
7977
|
for( let i = 0; i < element.dimensions.length; ++i )
|
|
6808
7978
|
{
|
|
6809
|
-
element.dimensions[ i ].
|
|
7979
|
+
element.dimensions[ i ].set( newValue[ i ], skipCallback );
|
|
6810
7980
|
}
|
|
6811
7981
|
};
|
|
6812
7982
|
|
|
@@ -6821,14 +7991,14 @@ class Panel {
|
|
|
6821
7991
|
{
|
|
6822
7992
|
element.dimensions[ i ] = this.addNumber( null, value[ i ], ( v ) => {
|
|
6823
7993
|
|
|
6824
|
-
const value = widget.
|
|
7994
|
+
const value = widget.value();
|
|
6825
7995
|
|
|
6826
7996
|
if( element.locked )
|
|
6827
7997
|
{
|
|
6828
7998
|
const ar = ( i == 0 ? 1.0 / element.aspectRatio : element.aspectRatio );
|
|
6829
7999
|
const index = ( 1 + i ) % 2;
|
|
6830
8000
|
value[ index ] = v * ar;
|
|
6831
|
-
element.dimensions[ index ].
|
|
8001
|
+
element.dimensions[ index ].set( value[ index ], true );
|
|
6832
8002
|
}
|
|
6833
8003
|
|
|
6834
8004
|
if( callback )
|
|
@@ -6871,7 +8041,7 @@ class Panel {
|
|
|
6871
8041
|
this.classList.remove( "fa-lock-open" );
|
|
6872
8042
|
|
|
6873
8043
|
// Recompute ratio
|
|
6874
|
-
const value = widget.
|
|
8044
|
+
const value = widget.value();
|
|
6875
8045
|
element.aspectRatio = value[ 0 ] / value[ 1 ];
|
|
6876
8046
|
}
|
|
6877
8047
|
else
|
|
@@ -7268,7 +8438,8 @@ class Panel {
|
|
|
7268
8438
|
let container = document.createElement('div');
|
|
7269
8439
|
container.className = "lextree";
|
|
7270
8440
|
|
|
7271
|
-
if(name)
|
|
8441
|
+
if( name )
|
|
8442
|
+
{
|
|
7272
8443
|
let title = document.createElement('span');
|
|
7273
8444
|
title.innerHTML = name;
|
|
7274
8445
|
container.appendChild(title);
|
|
@@ -7280,8 +8451,8 @@ class Panel {
|
|
|
7280
8451
|
toolsDiv.className += " notitle";
|
|
7281
8452
|
|
|
7282
8453
|
// Tree icons
|
|
7283
|
-
if(options.icons)
|
|
7284
|
-
|
|
8454
|
+
if( options.icons )
|
|
8455
|
+
{
|
|
7285
8456
|
for( let data of options.icons )
|
|
7286
8457
|
{
|
|
7287
8458
|
let iconEl = document.createElement('a');
|
|
@@ -7341,11 +8512,15 @@ class Panel {
|
|
|
7341
8512
|
let widget = new Widget( null, Widget.SEPARATOR );
|
|
7342
8513
|
widget.domEl = element;
|
|
7343
8514
|
|
|
7344
|
-
if(this.current_branch)
|
|
8515
|
+
if( this.current_branch )
|
|
8516
|
+
{
|
|
7345
8517
|
this.current_branch.content.appendChild( element );
|
|
7346
8518
|
this.current_branch.widgets.push( widget );
|
|
7347
|
-
}
|
|
7348
|
-
|
|
8519
|
+
}
|
|
8520
|
+
else
|
|
8521
|
+
{
|
|
8522
|
+
this.root.appendChild( element );
|
|
8523
|
+
}
|
|
7349
8524
|
}
|
|
7350
8525
|
|
|
7351
8526
|
/**
|
|
@@ -7670,6 +8845,12 @@ class Panel {
|
|
|
7670
8845
|
|
|
7671
8846
|
input.addEventListener( 'change', function() {
|
|
7672
8847
|
data.checkMap[ rowId ] = this.checked;
|
|
8848
|
+
|
|
8849
|
+
if( !this.checked )
|
|
8850
|
+
{
|
|
8851
|
+
const input = table.querySelector( "thead input[type='checkbox']" );
|
|
8852
|
+
input.checked = data.checkMap[ ":root" ] = false;
|
|
8853
|
+
}
|
|
7673
8854
|
});
|
|
7674
8855
|
|
|
7675
8856
|
row.appendChild( td );
|
|
@@ -7795,7 +8976,7 @@ class Branch {
|
|
|
7795
8976
|
root.appendChild( title );
|
|
7796
8977
|
|
|
7797
8978
|
var branchContent = document.createElement( 'div' );
|
|
7798
|
-
branchContent.id = name.replace(/\s/g, '');
|
|
8979
|
+
branchContent.id = name.replace( /\s/g, '' );
|
|
7799
8980
|
branchContent.className = "lexbranchcontent";
|
|
7800
8981
|
root.appendChild(branchContent);
|
|
7801
8982
|
this.content = branchContent;
|
|
@@ -7851,7 +9032,8 @@ class Branch {
|
|
|
7851
9032
|
|
|
7852
9033
|
const dialog = new Dialog(this.name, p => {
|
|
7853
9034
|
// add widgets
|
|
7854
|
-
for( let w of this.widgets )
|
|
9035
|
+
for( let w of this.widgets )
|
|
9036
|
+
{
|
|
7855
9037
|
p.root.appendChild( w.domEl );
|
|
7856
9038
|
}
|
|
7857
9039
|
});
|
|
@@ -7944,8 +9126,8 @@ class Branch {
|
|
|
7944
9126
|
var size = this.grabber.style.marginLeft;
|
|
7945
9127
|
|
|
7946
9128
|
// Update sizes of widgets inside
|
|
7947
|
-
for(var i = 0; i < this.widgets.length; i++)
|
|
7948
|
-
|
|
9129
|
+
for( var i = 0; i < this.widgets.length; i++ )
|
|
9130
|
+
{
|
|
7949
9131
|
let widget = this.widgets[ i ];
|
|
7950
9132
|
let element = widget.domEl;
|
|
7951
9133
|
|
|
@@ -7964,9 +9146,6 @@ class Branch {
|
|
|
7964
9146
|
case Widget.FILE:
|
|
7965
9147
|
padding = "10%";
|
|
7966
9148
|
break;
|
|
7967
|
-
case Widget.TEXT:
|
|
7968
|
-
padding = "8px";
|
|
7969
|
-
break;
|
|
7970
9149
|
};
|
|
7971
9150
|
|
|
7972
9151
|
value.style.width = "-moz-calc( 100% - " + size + " - " + padding + " )";
|
|
@@ -8105,7 +9284,7 @@ class Dialog {
|
|
|
8105
9284
|
modal = options.modal ?? false;
|
|
8106
9285
|
|
|
8107
9286
|
var root = document.createElement('dialog');
|
|
8108
|
-
root.className = "lexdialog " + (options.
|
|
9287
|
+
root.className = "lexdialog " + (options.className ?? "");
|
|
8109
9288
|
root.id = options.id ?? "dialog" + Dialog._last_id++;
|
|
8110
9289
|
LX.root.appendChild( root );
|
|
8111
9290
|
|
|
@@ -8263,15 +9442,15 @@ class Dialog {
|
|
|
8263
9442
|
|
|
8264
9443
|
root.style.width = size[ 0 ] ? (size[ 0 ]) : "25%";
|
|
8265
9444
|
root.style.height = size[ 1 ] ? (size[ 1 ]) : "auto";
|
|
9445
|
+
root.style.translate = options.position ? "unset" : "-50% -50%";
|
|
8266
9446
|
|
|
8267
9447
|
if( options.size )
|
|
8268
9448
|
{
|
|
8269
9449
|
this.size = size;
|
|
8270
9450
|
}
|
|
8271
9451
|
|
|
8272
|
-
|
|
8273
|
-
root.style.
|
|
8274
|
-
root.style.top = position[ 1 ] ? (position[ 1 ]) : "calc( 50% - " + ( rect.height * 0.5 ) + "px )";
|
|
9452
|
+
root.style.left = position[ 0 ] ?? "50%";
|
|
9453
|
+
root.style.top = position[ 1 ] ?? "50%";
|
|
8275
9454
|
|
|
8276
9455
|
panel.root.style.width = "calc( 100% - 30px )";
|
|
8277
9456
|
panel.root.style.height = title ? "calc( 100% - " + ( titleDiv.offsetHeight + 30 ) + "px )" : "calc( 100% - 51px )";
|
|
@@ -8288,7 +9467,7 @@ class Dialog {
|
|
|
8288
9467
|
this._oncreate.call(this, this.panel);
|
|
8289
9468
|
}
|
|
8290
9469
|
|
|
8291
|
-
setPosition(x, y) {
|
|
9470
|
+
setPosition( x, y ) {
|
|
8292
9471
|
|
|
8293
9472
|
this.root.style.left = x + "px";
|
|
8294
9473
|
this.root.style.top = y + "px";
|
|
@@ -8334,6 +9513,9 @@ class PocketDialog extends Dialog {
|
|
|
8334
9513
|
|
|
8335
9514
|
// Custom
|
|
8336
9515
|
this.root.classList.add( "pocket" );
|
|
9516
|
+
|
|
9517
|
+
this.root.style.translate = "none";
|
|
9518
|
+
this.root.style.top = "0";
|
|
8337
9519
|
this.root.style.left = "unset";
|
|
8338
9520
|
|
|
8339
9521
|
if( !options.position )
|
|
@@ -8349,6 +9531,11 @@ class PocketDialog extends Dialog {
|
|
|
8349
9531
|
this.minimized = false;
|
|
8350
9532
|
this.title.tabIndex = -1;
|
|
8351
9533
|
this.title.addEventListener("click", e => {
|
|
9534
|
+
if( this.title._eventCatched )
|
|
9535
|
+
{
|
|
9536
|
+
this.title._eventCatched = false;
|
|
9537
|
+
return;
|
|
9538
|
+
}
|
|
8352
9539
|
|
|
8353
9540
|
// Sized dialogs have to keep their size
|
|
8354
9541
|
if( this.size )
|
|
@@ -8431,12 +9618,12 @@ class ContextMenu {
|
|
|
8431
9618
|
constructor( event, title, options = {} ) {
|
|
8432
9619
|
|
|
8433
9620
|
// remove all context menus
|
|
8434
|
-
document.body.querySelectorAll(".
|
|
9621
|
+
document.body.querySelectorAll( ".lexcontextmenu" ).forEach( e => e.remove() );
|
|
8435
9622
|
|
|
8436
|
-
this.root = document.createElement(
|
|
8437
|
-
this.root.className = "
|
|
8438
|
-
this.root.style.left = (event.x - 48 + document.scrollingElement.scrollLeft) + "px";
|
|
8439
|
-
this.root.style.top = (event.y - 8 + document.scrollingElement.scrollTop) + "px";
|
|
9623
|
+
this.root = document.createElement( "div" );
|
|
9624
|
+
this.root.className = "lexcontextmenu";
|
|
9625
|
+
this.root.style.left = ( event.x - 48 + document.scrollingElement.scrollLeft ) + "px";
|
|
9626
|
+
this.root.style.top = ( event.y - 8 + document.scrollingElement.scrollTop ) + "px";
|
|
8440
9627
|
|
|
8441
9628
|
this.root.addEventListener("mouseleave", function() {
|
|
8442
9629
|
this.remove();
|
|
@@ -8449,13 +9636,13 @@ class ContextMenu {
|
|
|
8449
9636
|
{
|
|
8450
9637
|
const item = {};
|
|
8451
9638
|
item[ title ] = [];
|
|
8452
|
-
item[
|
|
8453
|
-
item[
|
|
9639
|
+
item[ "className" ] = "cmtitle";
|
|
9640
|
+
item[ "icon" ] = options.icon;
|
|
8454
9641
|
this.items.push( item );
|
|
8455
9642
|
}
|
|
8456
9643
|
}
|
|
8457
9644
|
|
|
8458
|
-
|
|
9645
|
+
_adjustPosition( div, margin, useAbsolute = false ) {
|
|
8459
9646
|
|
|
8460
9647
|
let rect = div.getBoundingClientRect();
|
|
8461
9648
|
|
|
@@ -8496,19 +9683,19 @@ class ContextMenu {
|
|
|
8496
9683
|
}
|
|
8497
9684
|
}
|
|
8498
9685
|
|
|
8499
|
-
|
|
9686
|
+
_createSubmenu( o, k, c, d ) {
|
|
8500
9687
|
|
|
8501
|
-
this.root.querySelectorAll(".
|
|
9688
|
+
this.root.querySelectorAll( ".lexcontextmenu" ).forEach( cm => cm.remove() );
|
|
8502
9689
|
|
|
8503
9690
|
let contextmenu = document.createElement('div');
|
|
8504
|
-
contextmenu.className = "
|
|
9691
|
+
contextmenu.className = "lexcontextmenu";
|
|
8505
9692
|
c.appendChild( contextmenu );
|
|
8506
9693
|
|
|
8507
9694
|
for( var i = 0; i < o[k].length; ++i )
|
|
8508
9695
|
{
|
|
8509
|
-
const subitem = o[k][i];
|
|
8510
|
-
const subkey = Object.keys(subitem)[0];
|
|
8511
|
-
this.
|
|
9696
|
+
const subitem = o[ k ][ i ];
|
|
9697
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
9698
|
+
this._createEntry(subitem, subkey, contextmenu, d);
|
|
8512
9699
|
}
|
|
8513
9700
|
|
|
8514
9701
|
var rect = c.getBoundingClientRect();
|
|
@@ -8516,29 +9703,32 @@ class ContextMenu {
|
|
|
8516
9703
|
contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
|
|
8517
9704
|
|
|
8518
9705
|
// Set final width
|
|
8519
|
-
this.
|
|
9706
|
+
this._adjustPosition( contextmenu, 6, true );
|
|
8520
9707
|
}
|
|
8521
9708
|
|
|
8522
|
-
|
|
9709
|
+
_createEntry( o, k, c, d ) {
|
|
8523
9710
|
|
|
8524
9711
|
const hasSubmenu = o[ k ].length;
|
|
8525
9712
|
let entry = document.createElement('div');
|
|
8526
|
-
entry.className = "
|
|
9713
|
+
entry.className = "lexmenuboxentry" + (o[ 'className' ] ? " " + o[ 'className' ] : "" );
|
|
8527
9714
|
entry.id = o.id ?? ("eId" + getSupportedDOMName( k ));
|
|
8528
9715
|
entry.innerHTML = "";
|
|
8529
9716
|
const icon = o[ 'icon' ];
|
|
8530
|
-
if(icon)
|
|
9717
|
+
if( icon )
|
|
9718
|
+
{
|
|
8531
9719
|
entry.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
8532
9720
|
}
|
|
8533
9721
|
const disabled = o['disabled'];
|
|
8534
9722
|
entry.innerHTML += "<div class='lexentryname" + (disabled ? " disabled" : "") + "'>" + k + "</div>";
|
|
8535
9723
|
c.appendChild( entry );
|
|
8536
9724
|
|
|
8537
|
-
if( this.colors[ k ] )
|
|
9725
|
+
if( this.colors[ k ] )
|
|
9726
|
+
{
|
|
8538
9727
|
entry.style.borderColor = this.colors[ k ];
|
|
8539
9728
|
}
|
|
8540
9729
|
|
|
8541
|
-
if( k == "" )
|
|
9730
|
+
if( k == "" )
|
|
9731
|
+
{
|
|
8542
9732
|
entry.className += " cmseparator";
|
|
8543
9733
|
return;
|
|
8544
9734
|
}
|
|
@@ -8551,7 +9741,8 @@ class ContextMenu {
|
|
|
8551
9741
|
if(disabled) return;
|
|
8552
9742
|
|
|
8553
9743
|
const f = o[ 'callback' ];
|
|
8554
|
-
if(f)
|
|
9744
|
+
if( f )
|
|
9745
|
+
{
|
|
8555
9746
|
f.call( this, k, entry );
|
|
8556
9747
|
this.root.remove();
|
|
8557
9748
|
}
|
|
@@ -8560,7 +9751,7 @@ class ContextMenu {
|
|
|
8560
9751
|
return;
|
|
8561
9752
|
|
|
8562
9753
|
if( LX.OPEN_CONTEXTMENU_ENTRY == 'click' )
|
|
8563
|
-
this.
|
|
9754
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
8564
9755
|
});
|
|
8565
9756
|
|
|
8566
9757
|
if( !hasSubmenu )
|
|
@@ -8576,20 +9767,19 @@ class ContextMenu {
|
|
|
8576
9767
|
if(entry.built)
|
|
8577
9768
|
return;
|
|
8578
9769
|
entry.built = true;
|
|
8579
|
-
this.
|
|
9770
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
8580
9771
|
e.stopPropagation();
|
|
8581
9772
|
});
|
|
8582
9773
|
}
|
|
8583
9774
|
|
|
8584
9775
|
entry.addEventListener("mouseleave", () => {
|
|
8585
9776
|
d = -1; // Reset depth
|
|
8586
|
-
|
|
8587
|
-
c.querySelectorAll(".lexcontextmenubox").forEach(e => e.remove());
|
|
9777
|
+
c.querySelectorAll(".lexcontextmenu").forEach(e => e.remove());
|
|
8588
9778
|
});
|
|
8589
9779
|
}
|
|
8590
9780
|
|
|
8591
9781
|
onCreate() {
|
|
8592
|
-
doAsync( () => this.
|
|
9782
|
+
doAsync( () => this._adjustPosition( this.root, 6 ) );
|
|
8593
9783
|
}
|
|
8594
9784
|
|
|
8595
9785
|
add( path, options = {} ) {
|
|
@@ -8617,22 +9807,25 @@ class ContextMenu {
|
|
|
8617
9807
|
if(key) found = o[ key ];
|
|
8618
9808
|
} );
|
|
8619
9809
|
|
|
8620
|
-
if(found)
|
|
8621
|
-
|
|
9810
|
+
if( found )
|
|
9811
|
+
{
|
|
9812
|
+
insert( tokens[ idx++ ], found );
|
|
8622
9813
|
}
|
|
8623
|
-
else
|
|
9814
|
+
else
|
|
9815
|
+
{
|
|
8624
9816
|
let item = {};
|
|
8625
9817
|
item[ token ] = [];
|
|
8626
|
-
const
|
|
9818
|
+
const nextToken = tokens[ idx++ ];
|
|
8627
9819
|
// Check if last token -> add callback
|
|
8628
|
-
if(!
|
|
9820
|
+
if( !nextToken )
|
|
9821
|
+
{
|
|
8629
9822
|
item[ 'id' ] = options.id;
|
|
8630
9823
|
item[ 'callback' ] = options.callback;
|
|
8631
9824
|
item[ 'disabled' ] = options.disabled ?? false;
|
|
8632
9825
|
}
|
|
8633
9826
|
|
|
8634
9827
|
list.push( item );
|
|
8635
|
-
insert(
|
|
9828
|
+
insert( nextToken, item[ token ] );
|
|
8636
9829
|
}
|
|
8637
9830
|
};
|
|
8638
9831
|
|
|
@@ -8642,13 +9835,15 @@ class ContextMenu {
|
|
|
8642
9835
|
|
|
8643
9836
|
const setParent = _item => {
|
|
8644
9837
|
|
|
8645
|
-
let key = Object.keys(_item)[0];
|
|
9838
|
+
let key = Object.keys( _item )[ 0 ];
|
|
8646
9839
|
let children = _item[ key ];
|
|
8647
9840
|
|
|
8648
|
-
if(!children.length)
|
|
9841
|
+
if( !children.length )
|
|
9842
|
+
{
|
|
8649
9843
|
return;
|
|
9844
|
+
}
|
|
8650
9845
|
|
|
8651
|
-
if(children.find( c => Object.keys(c)[0] == key ) == null)
|
|
9846
|
+
if( children.find( c => Object.keys(c)[0] == key ) == null )
|
|
8652
9847
|
{
|
|
8653
9848
|
const parent = {};
|
|
8654
9849
|
parent[ key ] = [];
|
|
@@ -8656,27 +9851,34 @@ class ContextMenu {
|
|
|
8656
9851
|
_item[ key ].unshift( parent );
|
|
8657
9852
|
}
|
|
8658
9853
|
|
|
8659
|
-
for( var child of _item[ key ] )
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
9854
|
+
for( var child of _item[ key ] )
|
|
9855
|
+
{
|
|
9856
|
+
let k = Object.keys( child )[ 0 ];
|
|
9857
|
+
for( var i = 0; i < child[ k ].length; ++i )
|
|
9858
|
+
{
|
|
9859
|
+
setParent( child );
|
|
9860
|
+
}
|
|
8663
9861
|
}
|
|
8664
9862
|
};
|
|
8665
9863
|
|
|
8666
9864
|
for( let item of this.items )
|
|
8667
|
-
|
|
9865
|
+
{
|
|
9866
|
+
setParent( item );
|
|
9867
|
+
}
|
|
8668
9868
|
|
|
8669
9869
|
// Create elements
|
|
8670
9870
|
|
|
8671
9871
|
for( let item of this.items )
|
|
8672
9872
|
{
|
|
8673
|
-
let key = Object.keys(item)[0];
|
|
9873
|
+
let key = Object.keys( item )[ 0 ];
|
|
8674
9874
|
let pKey = "eId" + getSupportedDOMName( key );
|
|
8675
9875
|
|
|
8676
9876
|
// Item already created
|
|
8677
|
-
const id = "#" + (item.id ?? pKey);
|
|
8678
|
-
if( !this.root.querySelector(id) )
|
|
8679
|
-
|
|
9877
|
+
const id = "#" + ( item.id ?? pKey );
|
|
9878
|
+
if( !this.root.querySelector( id ) )
|
|
9879
|
+
{
|
|
9880
|
+
this._createEntry( item, key, this.root, -1 );
|
|
9881
|
+
}
|
|
8680
9882
|
}
|
|
8681
9883
|
}
|
|
8682
9884
|
|
|
@@ -8787,7 +9989,7 @@ class Curve {
|
|
|
8787
9989
|
|
|
8788
9990
|
var r = [];
|
|
8789
9991
|
var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
|
|
8790
|
-
for(var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
9992
|
+
for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx )
|
|
8791
9993
|
{
|
|
8792
9994
|
r.push( element.getValueAt(i) );
|
|
8793
9995
|
}
|
|
@@ -8796,7 +9998,8 @@ class Curve {
|
|
|
8796
9998
|
|
|
8797
9999
|
element.addValue = function(v) {
|
|
8798
10000
|
|
|
8799
|
-
for(var i = 0; i < element.value; i++)
|
|
10001
|
+
for( var i = 0; i < element.value; i++ )
|
|
10002
|
+
{
|
|
8800
10003
|
var value = element.value[i];
|
|
8801
10004
|
if(value[0] < v[0]) continue;
|
|
8802
10005
|
element.value.splice(i,0,v);
|
|
@@ -8822,7 +10025,7 @@ class Curve {
|
|
|
8822
10025
|
|
|
8823
10026
|
var selected = -1;
|
|
8824
10027
|
|
|
8825
|
-
element.redraw = function( o = {} )
|
|
10028
|
+
element.redraw = function( o = {} ) {
|
|
8826
10029
|
|
|
8827
10030
|
if( o.value ) element.value = o.value;
|
|
8828
10031
|
if( o.xrange ) element.xrange = o.xrange;
|
|
@@ -8851,13 +10054,16 @@ class Curve {
|
|
|
8851
10054
|
ctx.moveTo( pos[ 0 ], pos[ 1 ] );
|
|
8852
10055
|
let values = [pos[ 0 ], pos[ 1 ]];
|
|
8853
10056
|
|
|
8854
|
-
for(var i in element.value)
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
values.push(pos[
|
|
8859
|
-
|
|
10057
|
+
for( var i in element.value )
|
|
10058
|
+
{
|
|
10059
|
+
var value = element.value[ i ];
|
|
10060
|
+
pos = convert( value );
|
|
10061
|
+
values.push( pos[ 0 ] );
|
|
10062
|
+
values.push( pos[ 1 ] );
|
|
10063
|
+
if( !element.smooth )
|
|
10064
|
+
{
|
|
8860
10065
|
ctx.lineTo( pos[ 0 ], pos[ 1 ] );
|
|
10066
|
+
}
|
|
8861
10067
|
}
|
|
8862
10068
|
|
|
8863
10069
|
pos = convert([ element.xrange[ 1 ], element.defaulty ]);
|
|
@@ -8874,7 +10080,8 @@ class Curve {
|
|
|
8874
10080
|
}
|
|
8875
10081
|
|
|
8876
10082
|
// Draw points
|
|
8877
|
-
for( var i = 0; i < element.value.length; i += 1 )
|
|
10083
|
+
for( var i = 0; i < element.value.length; i += 1 )
|
|
10084
|
+
{
|
|
8878
10085
|
var value = element.value[ i ];
|
|
8879
10086
|
pos = convert( value );
|
|
8880
10087
|
if( selected == i )
|
|
@@ -8886,10 +10093,11 @@ class Curve {
|
|
|
8886
10093
|
ctx.fill();
|
|
8887
10094
|
}
|
|
8888
10095
|
|
|
8889
|
-
if(element.show_samples)
|
|
10096
|
+
if( element.show_samples )
|
|
10097
|
+
{
|
|
8890
10098
|
var samples = element.resample(element.show_samples);
|
|
8891
10099
|
ctx.fillStyle = "#888";
|
|
8892
|
-
for(var i = 0; i < samples.length; i += 1)
|
|
10100
|
+
for( var i = 0; i < samples.length; i += 1)
|
|
8893
10101
|
{
|
|
8894
10102
|
var value = [ i * ((element.xrange[ 1 ] - element.xrange[ 0 ]) / element.show_samples) + element.xrange[ 0 ], samples[ i ] ];
|
|
8895
10103
|
pos = convert(value);
|
|
@@ -8912,7 +10120,8 @@ class Curve {
|
|
|
8912
10120
|
|
|
8913
10121
|
selected = computeSelected( mousex, canvas.height - mousey );
|
|
8914
10122
|
|
|
8915
|
-
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10123
|
+
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10124
|
+
{
|
|
8916
10125
|
var v = unconvert([ mousex, canvas.height - mousey ]);
|
|
8917
10126
|
element.value.push( v );
|
|
8918
10127
|
sortValues();
|
|
@@ -8960,7 +10169,8 @@ class Curve {
|
|
|
8960
10169
|
var dy = element.draggable_y ? last_mouse[ 1 ] - mousey : 0;
|
|
8961
10170
|
var delta = unconvert([ -dx, dy ]);
|
|
8962
10171
|
|
|
8963
|
-
if( selected != -1 )
|
|
10172
|
+
if( selected != -1 )
|
|
10173
|
+
{
|
|
8964
10174
|
var minx = element.xrange[ 0 ];
|
|
8965
10175
|
var maxx = element.xrange[ 1 ];
|
|
8966
10176
|
|
|
@@ -9117,7 +10327,7 @@ class Dial {
|
|
|
9117
10327
|
|
|
9118
10328
|
var r = [];
|
|
9119
10329
|
var dx = (element.xrange[1] - element.xrange[ 0 ]) / samples;
|
|
9120
|
-
for(var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
10330
|
+
for( var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
|
|
9121
10331
|
{
|
|
9122
10332
|
r.push( element.getValueAt(i) );
|
|
9123
10333
|
}
|
|
@@ -9126,15 +10336,16 @@ class Dial {
|
|
|
9126
10336
|
|
|
9127
10337
|
element.addValue = function(v) {
|
|
9128
10338
|
|
|
9129
|
-
for(var i = 0; i < element.value; i++)
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
10339
|
+
for( var i = 0; i < element.value; i++ )
|
|
10340
|
+
{
|
|
10341
|
+
var value = element.value[ i ];
|
|
10342
|
+
if(value[ 0 ] < v[ 0 ]) continue;
|
|
10343
|
+
element.value.splice( i, 0, v );
|
|
9133
10344
|
redraw();
|
|
9134
10345
|
return;
|
|
9135
10346
|
}
|
|
9136
10347
|
|
|
9137
|
-
element.value.push(v);
|
|
10348
|
+
element.value.push( v );
|
|
9138
10349
|
redraw();
|
|
9139
10350
|
}
|
|
9140
10351
|
|
|
@@ -9154,7 +10365,7 @@ class Dial {
|
|
|
9154
10365
|
|
|
9155
10366
|
var selected = -1;
|
|
9156
10367
|
|
|
9157
|
-
element.redraw = function( o = {} )
|
|
10368
|
+
element.redraw = function( o = {} ) {
|
|
9158
10369
|
|
|
9159
10370
|
if( o.value ) element.value = o.value;
|
|
9160
10371
|
if( o.xrange ) element.xrange = o.xrange;
|
|
@@ -9183,17 +10394,17 @@ class Dial {
|
|
|
9183
10394
|
ctx.moveTo( pos[ 0 ], pos[ 1 ] );
|
|
9184
10395
|
let values = [pos[ 0 ], pos[ 1 ]];
|
|
9185
10396
|
|
|
9186
|
-
for(var i in element.value)
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
values.push(pos[
|
|
9191
|
-
|
|
10397
|
+
for( var i in element.value)
|
|
10398
|
+
{
|
|
10399
|
+
var value = element.value[ i ];
|
|
10400
|
+
pos = convert( value );
|
|
10401
|
+
values.push( pos[ 0 ] );
|
|
10402
|
+
values.push( pos[ 1 ] );
|
|
9192
10403
|
}
|
|
9193
10404
|
|
|
9194
10405
|
pos = convert([ element.xrange[ 1 ], element.defaulty ]);
|
|
9195
|
-
values.push(pos[ 0 ]);
|
|
9196
|
-
values.push(pos[ 1 ]);
|
|
10406
|
+
values.push( pos[ 0 ] );
|
|
10407
|
+
values.push( pos[ 1 ] );
|
|
9197
10408
|
|
|
9198
10409
|
// Draw points
|
|
9199
10410
|
const center = [0,0];
|
|
@@ -9203,7 +10414,8 @@ class Dial {
|
|
|
9203
10414
|
ctx.arc( pos[ 0 ], pos[ 1 ], 3, 0, Math.PI * 2);
|
|
9204
10415
|
ctx.fill();
|
|
9205
10416
|
|
|
9206
|
-
for( var i = 0; i < element.value.length; i += 1 )
|
|
10417
|
+
for( var i = 0; i < element.value.length; i += 1 )
|
|
10418
|
+
{
|
|
9207
10419
|
var value = element.value[ i ];
|
|
9208
10420
|
pos = convert( value );
|
|
9209
10421
|
if( selected == i )
|
|
@@ -9215,10 +10427,11 @@ class Dial {
|
|
|
9215
10427
|
ctx.fill();
|
|
9216
10428
|
}
|
|
9217
10429
|
|
|
9218
|
-
if(element.show_samples)
|
|
10430
|
+
if( element.show_samples )
|
|
10431
|
+
{
|
|
9219
10432
|
var samples = element.resample(element.show_samples);
|
|
9220
10433
|
ctx.fillStyle = "#888";
|
|
9221
|
-
for(var i = 0; i < samples.length; i += 1)
|
|
10434
|
+
for( var i = 0; i < samples.length; i += 1)
|
|
9222
10435
|
{
|
|
9223
10436
|
var value = [ i * ((element.xrange[ 1 ] - element.xrange[ 0 ]) / element.show_samples) + element.xrange[ 0 ], samples[ i ] ];
|
|
9224
10437
|
pos = convert(value);
|
|
@@ -9241,7 +10454,8 @@ class Dial {
|
|
|
9241
10454
|
|
|
9242
10455
|
selected = computeSelected( mousex, canvas.height - mousey );
|
|
9243
10456
|
|
|
9244
|
-
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10457
|
+
if( e.button == LX.MOUSE_LEFT_CLICK && selected == -1 && element.allow_add_values )
|
|
10458
|
+
{
|
|
9245
10459
|
var v = unconvert([ mousex, canvas.height - mousey ]);
|
|
9246
10460
|
element.value.push( v );
|
|
9247
10461
|
sortValues();
|
|
@@ -9289,7 +10503,8 @@ class Dial {
|
|
|
9289
10503
|
var dy = element.draggable_y ? last_mouse[ 1 ] - mousey : 0;
|
|
9290
10504
|
var delta = unconvert([ -dx, dy ]);
|
|
9291
10505
|
|
|
9292
|
-
if( selected != -1 )
|
|
10506
|
+
if( selected != -1 )
|
|
10507
|
+
{
|
|
9293
10508
|
var minx = element.xrange[ 0 ];
|
|
9294
10509
|
var maxx = element.xrange[ 1 ];
|
|
9295
10510
|
|
|
@@ -9397,7 +10612,8 @@ class AssetViewEvent {
|
|
|
9397
10612
|
}
|
|
9398
10613
|
|
|
9399
10614
|
string() {
|
|
9400
|
-
switch(this.type)
|
|
10615
|
+
switch(this.type)
|
|
10616
|
+
{
|
|
9401
10617
|
case AssetViewEvent.NONE: return "assetview_event_none";
|
|
9402
10618
|
case AssetViewEvent.ASSET_SELECTED: return "assetview_event_selected";
|
|
9403
10619
|
case AssetViewEvent.ASSET_DELETED: return "assetview_event_deleted";
|
|
@@ -9751,8 +10967,8 @@ class AssetView {
|
|
|
9751
10967
|
icon: "fa-solid fa-arrows-rotate",
|
|
9752
10968
|
callback: domEl => { this._refreshContent(); }
|
|
9753
10969
|
}
|
|
9754
|
-
], { width: "
|
|
9755
|
-
this.rightPanel.addText(null, this.path.join('/'), null, { disabled: true, signal: "@on_folder_change", style: { fontWeight: "bolder", fontSize: "16px", color: "#aaa" } });
|
|
10970
|
+
], { width: "20%", minWidth: "164px", noSelection: true } );
|
|
10971
|
+
this.rightPanel.addText(null, this.path.join('/'), null, { width: "70%", maxWidth: "calc(70% - 64px)", minWidth: "164px", disabled: true, signal: "@on_folder_change", style: { fontWeight: "bolder", fontSize: "16px", color: "#aaa" } });
|
|
9756
10972
|
this.rightPanel.addText(null, "Page " + this.contentPage + " / " + ((((this.currentData.length - 1) / AssetView.MAX_PAGE_ELEMENTS )|0) + 1), null, {disabled: true, signal: "@on_page_change", width: "fit-content"})
|
|
9757
10973
|
this.rightPanel.endLine();
|
|
9758
10974
|
}
|
|
@@ -9878,8 +11094,8 @@ class AssetView {
|
|
|
9878
11094
|
title.innerText = item.id;
|
|
9879
11095
|
itemEl.appendChild( title );
|
|
9880
11096
|
|
|
9881
|
-
if( !that.skipPreview )
|
|
9882
|
-
|
|
11097
|
+
if( !that.skipPreview )
|
|
11098
|
+
{
|
|
9883
11099
|
let preview = null;
|
|
9884
11100
|
const hasImage = item.src && (['png', 'jpg'].indexOf( getExtension( item.src ) ) > -1 || item.src.includes("data:image/") ); // Support b64 image as src
|
|
9885
11101
|
|
|
@@ -9906,7 +11122,8 @@ class AssetView {
|
|
|
9906
11122
|
var newEmSize = charsPerLine / newLength;
|
|
9907
11123
|
var textBaseSize = 64;
|
|
9908
11124
|
|
|
9909
|
-
if(newEmSize < 1)
|
|
11125
|
+
if( newEmSize < 1 )
|
|
11126
|
+
{
|
|
9910
11127
|
var newFontSize = newEmSize * textBaseSize;
|
|
9911
11128
|
textEl.style.fontSize = newFontSize + "px";
|
|
9912
11129
|
preview.style.paddingTop = "calc(50% - " + (textEl.offsetHeight * 0.5 + 10) + "px)"
|
|
@@ -10135,7 +11352,8 @@ class AssetView {
|
|
|
10135
11352
|
|
|
10136
11353
|
this.currentData.push( item );
|
|
10137
11354
|
|
|
10138
|
-
if(i == (num_files - 1))
|
|
11355
|
+
if( i == (num_files - 1) )
|
|
11356
|
+
{
|
|
10139
11357
|
this._refreshContent();
|
|
10140
11358
|
if( !this.skipBrowser )
|
|
10141
11359
|
this.tree.refresh();
|
|
@@ -10187,7 +11405,7 @@ class AssetView {
|
|
|
10187
11405
|
this.currentData.splice( idx, 1 );
|
|
10188
11406
|
this._refreshContent( this.searchValue, this.filter );
|
|
10189
11407
|
|
|
10190
|
-
if(this.onevent)
|
|
11408
|
+
if( this.onevent)
|
|
10191
11409
|
{
|
|
10192
11410
|
const event = new AssetViewEvent( AssetViewEvent.ASSET_DELETED, item );
|
|
10193
11411
|
this.onevent( event );
|
|
@@ -10263,7 +11481,7 @@ Object.assign(LX, {
|
|
|
10263
11481
|
xhr.onload = function(load)
|
|
10264
11482
|
{
|
|
10265
11483
|
var response = this.response;
|
|
10266
|
-
if(this.status != 200)
|
|
11484
|
+
if( this.status != 200)
|
|
10267
11485
|
{
|
|
10268
11486
|
var err = "Error " + this.status;
|
|
10269
11487
|
if(request.error)
|
|
@@ -10311,7 +11529,7 @@ Object.assign(LX, {
|
|
|
10311
11529
|
var data = new FormData();
|
|
10312
11530
|
if( request.data )
|
|
10313
11531
|
{
|
|
10314
|
-
for(var i in request.data)
|
|
11532
|
+
for( var i in request.data)
|
|
10315
11533
|
data.append(i,request.data[i]);
|
|
10316
11534
|
}
|
|
10317
11535
|
|
|
@@ -10372,7 +11590,7 @@ Object.assign(LX, {
|
|
|
10372
11590
|
var size = total;
|
|
10373
11591
|
var loaded_scripts = [];
|
|
10374
11592
|
|
|
10375
|
-
for(var i in url)
|
|
11593
|
+
for( var i in url)
|
|
10376
11594
|
{
|
|
10377
11595
|
var script = document.createElement('script');
|
|
10378
11596
|
script.num = i;
|
|
@@ -10497,6 +11715,18 @@ Element.prototype.getParentArea = function() {
|
|
|
10497
11715
|
}
|
|
10498
11716
|
}
|
|
10499
11717
|
|
|
11718
|
+
LX.ICONS = {
|
|
11719
|
+
"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>`,
|
|
11720
|
+
"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>`,
|
|
11721
|
+
"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>`,
|
|
11722
|
+
"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>`,
|
|
11723
|
+
"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>`,
|
|
11724
|
+
"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>`,
|
|
11725
|
+
"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>`,
|
|
11726
|
+
"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>`,
|
|
11727
|
+
"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>`,
|
|
11728
|
+
}
|
|
11729
|
+
|
|
10500
11730
|
LX.UTILS = {
|
|
10501
11731
|
getTime() { return new Date().getTime() },
|
|
10502
11732
|
compareThreshold( v, p, n, t ) { return Math.abs(v - p) >= t || Math.abs(v - n) >= t },
|
|
@@ -10536,17 +11766,19 @@ LX.UTILS = {
|
|
|
10536
11766
|
drawSpline( ctx, pts, t ) {
|
|
10537
11767
|
|
|
10538
11768
|
ctx.save();
|
|
10539
|
-
var cp=[]; // array of control points, as x0,y0,x1,y1,...
|
|
10540
|
-
var n=pts.length;
|
|
11769
|
+
var cp = []; // array of control points, as x0,y0,x1,y1,...
|
|
11770
|
+
var n = pts.length;
|
|
10541
11771
|
|
|
10542
11772
|
// Draw an open curve, not connected at the ends
|
|
10543
|
-
for(var i=0;i<n-4;i+=2)
|
|
10544
|
-
|
|
11773
|
+
for( var i = 0; i < (n - 4); i += 2 )
|
|
11774
|
+
{
|
|
11775
|
+
cp = cp.concat(LX.UTILS.getControlPoints(pts[i],pts[i+1],pts[i+2],pts[i+3],pts[i+4],pts[i+5],t));
|
|
10545
11776
|
}
|
|
10546
11777
|
|
|
10547
|
-
for(var i=2;i<pts.length-5;i+=2)
|
|
11778
|
+
for( var i = 2; i < ( pts.length - 5 ); i += 2 )
|
|
11779
|
+
{
|
|
10548
11780
|
ctx.beginPath();
|
|
10549
|
-
ctx.moveTo(pts[i],pts[i+1]);
|
|
11781
|
+
ctx.moveTo(pts[i], pts[i+1]);
|
|
10550
11782
|
ctx.bezierCurveTo(cp[2*i-2],cp[2*i-1],cp[2*i],cp[2*i+1],pts[i+2],pts[i+3]);
|
|
10551
11783
|
ctx.stroke();
|
|
10552
11784
|
ctx.closePath();
|
|
@@ -10554,14 +11786,14 @@ LX.UTILS = {
|
|
|
10554
11786
|
|
|
10555
11787
|
// For open curves the first and last arcs are simple quadratics.
|
|
10556
11788
|
ctx.beginPath();
|
|
10557
|
-
ctx.moveTo(pts[0],pts[1]);
|
|
10558
|
-
ctx.quadraticCurveTo(cp[0],cp[1],pts[2],pts[3]);
|
|
11789
|
+
ctx.moveTo( pts[ 0 ], pts[ 1 ] );
|
|
11790
|
+
ctx.quadraticCurveTo( cp[ 0 ], cp[ 1 ], pts[ 2 ], pts[ 3 ]);
|
|
10559
11791
|
ctx.stroke();
|
|
10560
11792
|
ctx.closePath();
|
|
10561
11793
|
|
|
10562
11794
|
ctx.beginPath();
|
|
10563
|
-
ctx.moveTo(pts[n-2],pts[n-1]);
|
|
10564
|
-
ctx.quadraticCurveTo(cp[2*n-10],cp[2*n-9],pts[n-4],pts[n-3]);
|
|
11795
|
+
ctx.moveTo( pts[ n-2 ], pts[ n-1 ] );
|
|
11796
|
+
ctx.quadraticCurveTo( cp[ 2*n-10 ], cp[ 2*n-9 ], pts[ n-4 ], pts[ n-3 ]);
|
|
10565
11797
|
ctx.stroke();
|
|
10566
11798
|
ctx.closePath();
|
|
10567
11799
|
|