lexgui 0.1.44 → 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lexgui.css +295 -101
- package/build/lexgui.js +406 -95
- package/build/lexgui.module.js +406 -95
- package/changelog.md +21 -2
- package/demo.js +70 -15
- package/package.json +1 -1
package/build/lexgui.module.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
var LX = {
|
|
11
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.45",
|
|
12
12
|
ready: false,
|
|
13
13
|
components: [], // specific pre-build components
|
|
14
14
|
signals: {} // events and triggers
|
|
@@ -60,6 +60,15 @@ function deepCopy( o )
|
|
|
60
60
|
|
|
61
61
|
LX.deepCopy = deepCopy;
|
|
62
62
|
|
|
63
|
+
function setTheme( colorScheme )
|
|
64
|
+
{
|
|
65
|
+
colorScheme = ( colorScheme == "light" ) ? "light" : "dark";
|
|
66
|
+
document.documentElement.setAttribute( "data-theme", colorScheme );
|
|
67
|
+
LX.emit( "@on_new_color_scheme", colorScheme );
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
LX.setTheme = setTheme;
|
|
71
|
+
|
|
63
72
|
function setThemeColor( colorName, color )
|
|
64
73
|
{
|
|
65
74
|
var r = document.querySelector( ':root' );
|
|
@@ -75,7 +84,9 @@ function getThemeColor( colorName )
|
|
|
75
84
|
|
|
76
85
|
if( value.includes( "light-dark" ) && window.matchMedia )
|
|
77
86
|
{
|
|
78
|
-
|
|
87
|
+
const currentScheme = r.getPropertyValue( "color-scheme" );
|
|
88
|
+
|
|
89
|
+
if( ( window.matchMedia( "(prefers-color-scheme: light)" ).matches ) || ( currentScheme == "light" ) )
|
|
79
90
|
{
|
|
80
91
|
return value.substring( value.indexOf( '(' ) + 1, value.indexOf( ',' ) ).replace( /\s/g, '' );
|
|
81
92
|
}
|
|
@@ -142,6 +153,23 @@ function simple_guidGenerator() {
|
|
|
142
153
|
|
|
143
154
|
LX.guidGenerator = simple_guidGenerator;
|
|
144
155
|
|
|
156
|
+
function buildTextPattern( options = {} ) {
|
|
157
|
+
let patterns = [];
|
|
158
|
+
if ( options.lowercase ) patterns.push("(?=.*[a-z])");
|
|
159
|
+
if ( options.uppercase ) patterns.push("(?=.*[A-Z])");
|
|
160
|
+
if ( options.digit ) patterns.push("(?=.*\\d)");
|
|
161
|
+
if ( options.specialChar ) patterns.push("(?=.*[@#$%^&+=!])");
|
|
162
|
+
if ( options.noSpaces ) patterns.push("(?!.*\\s)");
|
|
163
|
+
|
|
164
|
+
let minLength = options.minLength || 0;
|
|
165
|
+
let maxLength = options.maxLength || ""; // Empty means no max length restriction
|
|
166
|
+
|
|
167
|
+
let pattern = `^${ patterns.join("") }.{${ minLength },${ maxLength }}$`;
|
|
168
|
+
return options.asRegExp ? new RegExp( pattern ) : pattern;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
LX.buildTextPattern = buildTextPattern;
|
|
172
|
+
|
|
145
173
|
// Timer that works everywhere (from litegraph.js)
|
|
146
174
|
if (typeof performance != "undefined") {
|
|
147
175
|
LX.getTime = performance.now.bind(performance);
|
|
@@ -756,7 +784,7 @@ function prompt( text, title, callback, options = {} )
|
|
|
756
784
|
if( callback ) callback.call( this, value );
|
|
757
785
|
dialog.close();
|
|
758
786
|
}
|
|
759
|
-
}, { buttonClass: "
|
|
787
|
+
}, { buttonClass: "primary" });
|
|
760
788
|
|
|
761
789
|
p.addButton(null, "Cancel", () => {if(options.on_cancel) options.on_cancel(); dialog.close();} );
|
|
762
790
|
|
|
@@ -2205,18 +2233,18 @@ class Menubar {
|
|
|
2205
2233
|
entry.className = "lexmenuentry";
|
|
2206
2234
|
entry.id = pKey;
|
|
2207
2235
|
entry.innerHTML = "<span>" + key + "</span>";
|
|
2208
|
-
if(options.position == "left") {
|
|
2209
|
-
this.root.prepend( entry );
|
|
2210
|
-
}
|
|
2211
|
-
else {
|
|
2212
|
-
if(options.position == "right")
|
|
2213
|
-
entry.right = true;
|
|
2214
|
-
if(this.root.lastChild && this.root.lastChild.right) {
|
|
2215
|
-
this.root.lastChild.before( entry );
|
|
2216
|
-
}
|
|
2217
|
-
else {
|
|
2218
|
-
this.root.appendChild( entry );
|
|
2219
|
-
}
|
|
2236
|
+
if(options.position == "left") {
|
|
2237
|
+
this.root.prepend( entry );
|
|
2238
|
+
}
|
|
2239
|
+
else {
|
|
2240
|
+
if(options.position == "right")
|
|
2241
|
+
entry.right = true;
|
|
2242
|
+
if(this.root.lastChild && this.root.lastChild.right) {
|
|
2243
|
+
this.root.lastChild.before( entry );
|
|
2244
|
+
}
|
|
2245
|
+
else {
|
|
2246
|
+
this.root.appendChild( entry );
|
|
2247
|
+
}
|
|
2220
2248
|
}
|
|
2221
2249
|
|
|
2222
2250
|
const create_submenu = function( o, k, c, d ) {
|
|
@@ -2437,16 +2465,16 @@ class Menubar {
|
|
|
2437
2465
|
button.style.maxHeight = "calc(100% - 10px)";
|
|
2438
2466
|
button.style.alignItems = "center";
|
|
2439
2467
|
|
|
2440
|
-
if(options.float == "right")
|
|
2441
|
-
button.right = true;
|
|
2442
|
-
if(this.root.lastChild && this.root.lastChild.right) {
|
|
2443
|
-
this.root.lastChild.before( button );
|
|
2468
|
+
if(options.float == "right")
|
|
2469
|
+
button.right = true;
|
|
2470
|
+
if(this.root.lastChild && this.root.lastChild.right) {
|
|
2471
|
+
this.root.lastChild.before( button );
|
|
2444
2472
|
}
|
|
2445
2473
|
else if(options.float == "left") {
|
|
2446
2474
|
this.root.prepend(button);
|
|
2447
|
-
}
|
|
2448
|
-
else {
|
|
2449
|
-
this.root.appendChild( button );
|
|
2475
|
+
}
|
|
2476
|
+
else {
|
|
2477
|
+
this.root.appendChild( button );
|
|
2450
2478
|
}
|
|
2451
2479
|
|
|
2452
2480
|
const _b = button.querySelector('a');
|
|
@@ -2478,16 +2506,16 @@ class Menubar {
|
|
|
2478
2506
|
button.style.padding = "5px";
|
|
2479
2507
|
button.style.alignItems = "center";
|
|
2480
2508
|
|
|
2481
|
-
if(options.float == "right")
|
|
2482
|
-
button.right = true;
|
|
2483
|
-
if(this.root.lastChild && this.root.lastChild.right) {
|
|
2484
|
-
this.root.lastChild.before( button );
|
|
2485
|
-
}
|
|
2509
|
+
if(options.float == "right")
|
|
2510
|
+
button.right = true;
|
|
2511
|
+
if(this.root.lastChild && this.root.lastChild.right) {
|
|
2512
|
+
this.root.lastChild.before( button );
|
|
2513
|
+
}
|
|
2486
2514
|
else if(options.float == "left") {
|
|
2487
2515
|
this.root.prepend(button);
|
|
2488
2516
|
}
|
|
2489
|
-
else {
|
|
2490
|
-
this.root.appendChild( button );
|
|
2517
|
+
else {
|
|
2518
|
+
this.root.appendChild( button );
|
|
2491
2519
|
}
|
|
2492
2520
|
|
|
2493
2521
|
const _b = button.querySelector('a');
|
|
@@ -2507,44 +2535,75 @@ class Menubar {
|
|
|
2507
2535
|
|
|
2508
2536
|
addButtons( buttons, options = {} ) {
|
|
2509
2537
|
|
|
2510
|
-
if(!buttons)
|
|
2511
|
-
|
|
2538
|
+
if( !buttons )
|
|
2539
|
+
{
|
|
2540
|
+
throw( "No buttons to add!" );
|
|
2541
|
+
}
|
|
2512
2542
|
|
|
2513
|
-
if(!this.buttonContainer)
|
|
2543
|
+
if( !this.buttonContainer )
|
|
2514
2544
|
{
|
|
2515
|
-
this.buttonContainer = document.createElement(
|
|
2545
|
+
this.buttonContainer = document.createElement( "div" );
|
|
2516
2546
|
this.buttonContainer.className = "lexmenubuttons";
|
|
2517
|
-
this.buttonContainer.classList.add(options.float ??
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
this.
|
|
2522
|
-
}
|
|
2523
|
-
|
|
2524
|
-
|
|
2547
|
+
this.buttonContainer.classList.add( options.float ?? "center" );
|
|
2548
|
+
|
|
2549
|
+
if( options.position == "right" )
|
|
2550
|
+
{
|
|
2551
|
+
this.buttonContainer.right = true;
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
if( this.root.lastChild && this.root.lastChild.right )
|
|
2555
|
+
{
|
|
2556
|
+
this.root.lastChild.before( this.buttonContainer );
|
|
2557
|
+
}
|
|
2558
|
+
else
|
|
2559
|
+
{
|
|
2560
|
+
this.root.appendChild( this.buttonContainer );
|
|
2525
2561
|
}
|
|
2526
2562
|
}
|
|
2527
2563
|
|
|
2528
2564
|
for( let i = 0; i < buttons.length; ++i )
|
|
2529
2565
|
{
|
|
2530
|
-
let data = buttons[i];
|
|
2531
|
-
let button = document.createElement(
|
|
2566
|
+
let data = buttons[ i ];
|
|
2567
|
+
let button = document.createElement( "label" );
|
|
2532
2568
|
const title = data.title;
|
|
2533
2569
|
let disabled = data.disabled ?? false;
|
|
2534
2570
|
button.className = "lexmenubutton" + (disabled ? " disabled" : "");
|
|
2535
2571
|
button.title = title ?? "";
|
|
2536
|
-
button.innerHTML = "<a class='" + data.icon + " lexicon'></a>";
|
|
2537
2572
|
this.buttonContainer.appendChild( button );
|
|
2538
2573
|
|
|
2539
|
-
const
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2574
|
+
const icon = document.createElement( "a" );
|
|
2575
|
+
icon.className = data.icon + " lexicon";
|
|
2576
|
+
button.appendChild( icon );
|
|
2577
|
+
|
|
2578
|
+
let trigger = icon;
|
|
2579
|
+
|
|
2580
|
+
if( data.swap )
|
|
2581
|
+
{
|
|
2582
|
+
button.classList.add( "swap" );
|
|
2583
|
+
icon.classList.add( "swap-off" );
|
|
2584
|
+
|
|
2585
|
+
const input = document.createElement( "input" );
|
|
2586
|
+
input.type = "checkbox";
|
|
2587
|
+
button.prepend( input );
|
|
2588
|
+
trigger = input;
|
|
2589
|
+
|
|
2590
|
+
const swapIcon = document.createElement( "a" );
|
|
2591
|
+
swapIcon.className = data.swap + " swap-on lexicon";
|
|
2592
|
+
button.appendChild( swapIcon );
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
trigger.addEventListener("click", e => {
|
|
2596
|
+
if( data.callback && !disabled )
|
|
2597
|
+
{
|
|
2598
|
+
const swapInput = button.querySelector( "input" );
|
|
2599
|
+
data.callback.call( this, e, swapInput?.checked );
|
|
2600
|
+
}
|
|
2544
2601
|
});
|
|
2545
2602
|
|
|
2546
|
-
if(title)
|
|
2603
|
+
if( title )
|
|
2604
|
+
{
|
|
2547
2605
|
this.buttons[ title ] = button;
|
|
2606
|
+
}
|
|
2548
2607
|
}
|
|
2549
2608
|
}
|
|
2550
2609
|
};
|
|
@@ -2698,6 +2757,7 @@ class Widget {
|
|
|
2698
2757
|
static PAD = 26;
|
|
2699
2758
|
static FORM = 27;
|
|
2700
2759
|
static DIAL = 28;
|
|
2760
|
+
static COUNTER = 29;
|
|
2701
2761
|
|
|
2702
2762
|
static NO_CONTEXT_TYPES = [
|
|
2703
2763
|
Widget.BUTTON,
|
|
@@ -2787,6 +2847,7 @@ class Widget {
|
|
|
2787
2847
|
case Widget.PAD: return "Pad";
|
|
2788
2848
|
case Widget.FORM: return "Form";
|
|
2789
2849
|
case Widget.DIAL: return "Dial";
|
|
2850
|
+
case Widget.COUNTER: return "Counter";
|
|
2790
2851
|
case Widget.CUSTOM: return this.customName;
|
|
2791
2852
|
}
|
|
2792
2853
|
|
|
@@ -4017,7 +4078,9 @@ class Panel {
|
|
|
4017
4078
|
* @param {Function} callback Callback function on change
|
|
4018
4079
|
* @param {*} options:
|
|
4019
4080
|
* disabled: Make the widget disabled [false]
|
|
4081
|
+
* required: Make the input required
|
|
4020
4082
|
* placeholder: Add input placeholder
|
|
4083
|
+
* pattern: Regular expression that value must match
|
|
4021
4084
|
* trigger: Choose onchange trigger (default, input) [default]
|
|
4022
4085
|
* inputWidth: Width of the text input
|
|
4023
4086
|
* skipReset: Don't add the reset value button when value changes
|
|
@@ -4032,11 +4095,18 @@ class Panel {
|
|
|
4032
4095
|
widget.onGetValue = () => {
|
|
4033
4096
|
return wValue.value;
|
|
4034
4097
|
};
|
|
4098
|
+
|
|
4035
4099
|
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
4036
4100
|
this.disabled ? wValue.innerText = newValue : wValue.value = newValue;
|
|
4037
4101
|
Panel._dispatch_event( wValue, "focusout", skipCallback );
|
|
4038
4102
|
};
|
|
4039
4103
|
|
|
4104
|
+
widget.valid = () => {
|
|
4105
|
+
if( wValue.pattern == "" ) { return true; }
|
|
4106
|
+
const regexp = new RegExp( wValue.pattern );
|
|
4107
|
+
return regexp.test( wValue.value );
|
|
4108
|
+
};
|
|
4109
|
+
|
|
4040
4110
|
let element = widget.domEl;
|
|
4041
4111
|
|
|
4042
4112
|
// Add reset functionality
|
|
@@ -4071,14 +4141,33 @@ class Panel {
|
|
|
4071
4141
|
wValue.style.width = "100%";
|
|
4072
4142
|
wValue.style.textAlign = options.float ?? "";
|
|
4073
4143
|
|
|
4074
|
-
|
|
4075
|
-
|
|
4144
|
+
wValue.setAttribute( "placeholder", options.placeholder ?? "" );
|
|
4145
|
+
|
|
4146
|
+
if( options.required )
|
|
4147
|
+
{
|
|
4148
|
+
wValue.setAttribute( "required", options.required );
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
if( options.pattern )
|
|
4152
|
+
{
|
|
4153
|
+
wValue.setAttribute( "pattern", options.pattern );
|
|
4154
|
+
}
|
|
4076
4155
|
|
|
4077
4156
|
var resolve = ( function( val, event ) {
|
|
4157
|
+
|
|
4158
|
+
if( !widget.valid() )
|
|
4159
|
+
{
|
|
4160
|
+
return;
|
|
4161
|
+
}
|
|
4162
|
+
|
|
4078
4163
|
const skipCallback = event.detail;
|
|
4079
4164
|
let btn = element.querySelector( ".lexwidgetname .lexicon" );
|
|
4080
4165
|
if( btn ) btn.style.display = ( val != wValue.iValue ? "block" : "none" );
|
|
4081
|
-
if( !skipCallback )
|
|
4166
|
+
if( !skipCallback )
|
|
4167
|
+
{
|
|
4168
|
+
this._trigger( new IEvent( name, val, event ), callback );
|
|
4169
|
+
}
|
|
4170
|
+
|
|
4082
4171
|
}).bind( this );
|
|
4083
4172
|
|
|
4084
4173
|
const trigger = options.trigger ?? 'default';
|
|
@@ -4290,18 +4379,13 @@ class Panel {
|
|
|
4290
4379
|
|
|
4291
4380
|
var wValue = document.createElement( 'button' );
|
|
4292
4381
|
wValue.title = options.title ?? "";
|
|
4293
|
-
wValue.className = "lexbutton";
|
|
4382
|
+
wValue.className = "lexbutton " + ( options.buttonClass ?? "" );
|
|
4294
4383
|
|
|
4295
4384
|
if( options.selected )
|
|
4296
4385
|
{
|
|
4297
4386
|
wValue.classList.add( "selected" );
|
|
4298
4387
|
}
|
|
4299
4388
|
|
|
4300
|
-
if( options.buttonClass )
|
|
4301
|
-
{
|
|
4302
|
-
wValue.classList.add( options.buttonClass );
|
|
4303
|
-
}
|
|
4304
|
-
|
|
4305
4389
|
wValue.innerHTML =
|
|
4306
4390
|
(options.icon ? "<a class='" + options.icon + "'></a>" :
|
|
4307
4391
|
( options.img ? "<img src='" + options.img + "'>" : "<span>" + (value || "") + "</span>" ));
|
|
@@ -4540,7 +4624,7 @@ class Panel {
|
|
|
4540
4624
|
|
|
4541
4625
|
this.addLabel( entry, { textClass: "formlabel" } );
|
|
4542
4626
|
|
|
4543
|
-
this.addText( null, entryData.constructor == Object ? entryData.value : entryData, ( value ) => {
|
|
4627
|
+
entryData.textWidget = this.addText( null, entryData.constructor == Object ? entryData.value : entryData, ( value ) => {
|
|
4544
4628
|
container.formData[ entry ] = value;
|
|
4545
4629
|
}, entryData );
|
|
4546
4630
|
|
|
@@ -4550,11 +4634,22 @@ class Panel {
|
|
|
4550
4634
|
this.addBlank( );
|
|
4551
4635
|
|
|
4552
4636
|
this.addButton( null, options.actionName ?? "Submit", ( value, event ) => {
|
|
4637
|
+
|
|
4638
|
+
for( let entry in data )
|
|
4639
|
+
{
|
|
4640
|
+
let entryData = data[ entry ];
|
|
4641
|
+
|
|
4642
|
+
if( !entryData.textWidget.valid() )
|
|
4643
|
+
{
|
|
4644
|
+
return;
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
|
|
4553
4648
|
if( callback )
|
|
4554
4649
|
{
|
|
4555
4650
|
callback( container.formData, event );
|
|
4556
4651
|
}
|
|
4557
|
-
}, { buttonClass: "
|
|
4652
|
+
}, { buttonClass: "primary", width: "calc(100% - 10px)" } );
|
|
4558
4653
|
|
|
4559
4654
|
this.clearQueue();
|
|
4560
4655
|
|
|
@@ -4709,13 +4804,35 @@ class Panel {
|
|
|
4709
4804
|
delete list.unfocus_event;
|
|
4710
4805
|
return;
|
|
4711
4806
|
}
|
|
4712
|
-
|
|
4713
|
-
list.
|
|
4807
|
+
|
|
4808
|
+
list.toggleAttribute( "hidden" );
|
|
4809
|
+
list.classList.remove( "place-above" );
|
|
4810
|
+
|
|
4811
|
+
const listHeight = 26 * values.length;
|
|
4812
|
+
const rect = selectedOption.getBoundingClientRect();
|
|
4813
|
+
const topPosition = rect.y;
|
|
4814
|
+
|
|
4815
|
+
let maxY = window.innerHeight;
|
|
4816
|
+
|
|
4817
|
+
if( this.mainContainer )
|
|
4818
|
+
{
|
|
4819
|
+
const parentRect = this.mainContainer.getBoundingClientRect();
|
|
4820
|
+
maxY = parentRect.y + parentRect.height;
|
|
4821
|
+
}
|
|
4822
|
+
|
|
4823
|
+
list.style.top = ( topPosition + selectedOption.offsetHeight ) + 'px';
|
|
4824
|
+
|
|
4825
|
+
const showAbove = ( topPosition + listHeight ) > maxY;
|
|
4826
|
+
if( showAbove )
|
|
4827
|
+
{
|
|
4828
|
+
list.style.top = ( topPosition - listHeight ) + 'px';
|
|
4829
|
+
list.classList.add( "place-above" );
|
|
4830
|
+
}
|
|
4831
|
+
|
|
4714
4832
|
list.style.width = (event.currentTarget.clientWidth) + 'px';
|
|
4715
4833
|
list.style.minWidth = (_getMaxListWidth()) + 'px';
|
|
4716
|
-
list.toggleAttribute('hidden');
|
|
4717
4834
|
list.focus();
|
|
4718
|
-
}, { buttonClass:
|
|
4835
|
+
}, { buttonClass: "array", skipInlineCount: true });
|
|
4719
4836
|
|
|
4720
4837
|
this.clearQueue();
|
|
4721
4838
|
|
|
@@ -5361,40 +5478,45 @@ class Panel {
|
|
|
5361
5478
|
|
|
5362
5479
|
// Show tags
|
|
5363
5480
|
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5481
|
+
const tagsContainer = document.createElement('div');
|
|
5482
|
+
tagsContainer.className = "lextags";
|
|
5483
|
+
tagsContainer.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
5367
5484
|
|
|
5368
5485
|
const create_tags = () => {
|
|
5369
5486
|
|
|
5370
|
-
|
|
5487
|
+
tagsContainer.innerHTML = "";
|
|
5371
5488
|
|
|
5372
5489
|
for( let i = 0; i < value.length; ++i )
|
|
5373
5490
|
{
|
|
5374
|
-
|
|
5375
|
-
|
|
5491
|
+
const tagName = value[i];
|
|
5492
|
+
const tag = document.createElement('span');
|
|
5376
5493
|
tag.className = "lextag";
|
|
5377
|
-
tag.innerHTML =
|
|
5494
|
+
tag.innerHTML = tagName;
|
|
5378
5495
|
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5496
|
+
const removeButton = document.createElement('a');
|
|
5497
|
+
removeButton.className = "lextagrmb fa-solid fa-xmark lexicon";
|
|
5498
|
+
tag.appendChild( removeButton );
|
|
5499
|
+
|
|
5500
|
+
removeButton.addEventListener( 'click', e => {
|
|
5501
|
+
tag.remove();
|
|
5502
|
+
value.splice( value.indexOf( tagName ), 1 );
|
|
5382
5503
|
let btn = element.querySelector( ".lexwidgetname .lexicon" );
|
|
5383
5504
|
if( btn ) btn.style.display = ( value != defaultValue ? "block" : "none" );
|
|
5384
5505
|
that._trigger( new IEvent( name, value, e ), callback );
|
|
5385
|
-
});
|
|
5506
|
+
} );
|
|
5386
5507
|
|
|
5387
|
-
|
|
5508
|
+
tagsContainer.appendChild( tag );
|
|
5388
5509
|
}
|
|
5389
5510
|
|
|
5390
|
-
let
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5511
|
+
let tagInput = document.createElement( 'input' );
|
|
5512
|
+
tagInput.value = "";
|
|
5513
|
+
tagInput.placeholder = "Add tag...";
|
|
5514
|
+
tagsContainer.appendChild( tagInput );
|
|
5394
5515
|
|
|
5395
|
-
|
|
5516
|
+
tagInput.onkeydown = function( e ) {
|
|
5396
5517
|
const val = this.value.replace(/\s/g, '');
|
|
5397
|
-
if( e.key == ' ')
|
|
5518
|
+
if( e.key == ' ' || e.key == 'Enter' )
|
|
5519
|
+
{
|
|
5398
5520
|
e.preventDefault();
|
|
5399
5521
|
if( !val.length || value.indexOf( val ) > -1 )
|
|
5400
5522
|
return;
|
|
@@ -5406,18 +5528,19 @@ class Panel {
|
|
|
5406
5528
|
}
|
|
5407
5529
|
};
|
|
5408
5530
|
|
|
5409
|
-
|
|
5531
|
+
tagInput.focus();
|
|
5410
5532
|
}
|
|
5411
5533
|
|
|
5412
5534
|
create_tags();
|
|
5413
5535
|
|
|
5414
5536
|
// Remove branch padding and margins
|
|
5415
|
-
if(!widget.name)
|
|
5537
|
+
if( !widget.name )
|
|
5538
|
+
{
|
|
5416
5539
|
element.className += " noname";
|
|
5417
|
-
|
|
5540
|
+
tagsContainer.style.width = "100%";
|
|
5418
5541
|
}
|
|
5419
5542
|
|
|
5420
|
-
element.appendChild(
|
|
5543
|
+
element.appendChild( tagsContainer );
|
|
5421
5544
|
|
|
5422
5545
|
return widget;
|
|
5423
5546
|
}
|
|
@@ -6604,7 +6727,7 @@ class Panel {
|
|
|
6604
6727
|
progress.classList.add( "editable" );
|
|
6605
6728
|
progress.addEventListener( "mousedown", inner_mousedown );
|
|
6606
6729
|
|
|
6607
|
-
|
|
6730
|
+
const that = this;
|
|
6608
6731
|
|
|
6609
6732
|
function inner_mousedown( e )
|
|
6610
6733
|
{
|
|
@@ -6612,24 +6735,28 @@ class Panel {
|
|
|
6612
6735
|
doc.addEventListener( 'mousemove', inner_mousemove );
|
|
6613
6736
|
doc.addEventListener( 'mouseup', inner_mouseup );
|
|
6614
6737
|
document.body.classList.add( 'noevents' );
|
|
6738
|
+
progress.classList.add( "grabbing" );
|
|
6615
6739
|
e.stopImmediatePropagation();
|
|
6616
6740
|
e.stopPropagation();
|
|
6741
|
+
|
|
6742
|
+
const rect = progress.getBoundingClientRect();
|
|
6743
|
+
const newValue = round( remapRange( e.offsetX, 0, rect.width, progress.min, progress.max ) );
|
|
6744
|
+
that.setValue( name, newValue );
|
|
6617
6745
|
}
|
|
6618
6746
|
|
|
6619
6747
|
function inner_mousemove( e )
|
|
6620
6748
|
{
|
|
6621
|
-
let dt =
|
|
6749
|
+
let dt = e.movementX;
|
|
6622
6750
|
|
|
6623
6751
|
if ( dt != 0 )
|
|
6624
6752
|
{
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
that.setValue( name, v );
|
|
6753
|
+
const rect = progress.getBoundingClientRect();
|
|
6754
|
+
const newValue = round( remapRange( e.offsetX - rect.x, 0, rect.width, progress.min, progress.max ) );
|
|
6755
|
+
that.setValue( name, newValue );
|
|
6629
6756
|
|
|
6630
6757
|
if( options.callback )
|
|
6631
6758
|
{
|
|
6632
|
-
options.callback(
|
|
6759
|
+
options.callback( newValue, e );
|
|
6633
6760
|
}
|
|
6634
6761
|
}
|
|
6635
6762
|
|
|
@@ -6643,6 +6770,7 @@ class Panel {
|
|
|
6643
6770
|
doc.removeEventListener( 'mousemove', inner_mousemove );
|
|
6644
6771
|
doc.removeEventListener( 'mouseup', inner_mouseup );
|
|
6645
6772
|
document.body.classList.remove( 'noevents' );
|
|
6773
|
+
progress.classList.remove( "grabbing" );
|
|
6646
6774
|
}
|
|
6647
6775
|
}
|
|
6648
6776
|
|
|
@@ -6932,6 +7060,91 @@ class Panel {
|
|
|
6932
7060
|
|
|
6933
7061
|
this.addSeparator();
|
|
6934
7062
|
}
|
|
7063
|
+
|
|
7064
|
+
/**
|
|
7065
|
+
* @method addCounter
|
|
7066
|
+
* @param {String} name Widget name
|
|
7067
|
+
* @param {Number} value Counter value
|
|
7068
|
+
* @param {Function} callback Callback function on change
|
|
7069
|
+
* @param {*} options:
|
|
7070
|
+
* disabled: Make the widget disabled [false]
|
|
7071
|
+
* min, max: Min and Max values
|
|
7072
|
+
* step: Step for adding/substracting
|
|
7073
|
+
* label: Text to show below the counter
|
|
7074
|
+
*/
|
|
7075
|
+
|
|
7076
|
+
addCounter( name, value, callback, options = { } ) {
|
|
7077
|
+
|
|
7078
|
+
let widget = this.create_widget( name, Widget.COUNTER, options );
|
|
7079
|
+
|
|
7080
|
+
widget.onGetValue = () => {
|
|
7081
|
+
return counterText.count;
|
|
7082
|
+
};
|
|
7083
|
+
|
|
7084
|
+
widget.onSetValue = ( newValue, skipCallback ) => {
|
|
7085
|
+
_onChange( newValue, skipCallback );
|
|
7086
|
+
};
|
|
7087
|
+
|
|
7088
|
+
let element = widget.domEl;
|
|
7089
|
+
|
|
7090
|
+
const min = options.min ?? 0;
|
|
7091
|
+
const max = options.max ?? 100;
|
|
7092
|
+
const step = options.step ?? 1;
|
|
7093
|
+
|
|
7094
|
+
const _onChange = ( value, skipCallback, event ) => {
|
|
7095
|
+
value = clamp( value, min, max );
|
|
7096
|
+
counterText.count = value;
|
|
7097
|
+
counterText.innerHTML = value;
|
|
7098
|
+
if( !skipCallback )
|
|
7099
|
+
{
|
|
7100
|
+
this._trigger( new IEvent( name, value, event ), callback );
|
|
7101
|
+
}
|
|
7102
|
+
}
|
|
7103
|
+
|
|
7104
|
+
const container = document.createElement( 'div' );
|
|
7105
|
+
container.className = "lexcounter";
|
|
7106
|
+
element.appendChild( container );
|
|
7107
|
+
|
|
7108
|
+
this.queue( container );
|
|
7109
|
+
|
|
7110
|
+
this.addButton(null, "<a style='margin-top: 0px;' class='fa-solid fa-minus'></a>", (value, e) => {
|
|
7111
|
+
let mult = step ?? 1;
|
|
7112
|
+
if( e.shiftKey ) mult *= 10;
|
|
7113
|
+
_onChange( counterText.count - mult, false, e );
|
|
7114
|
+
}, { className: "micro", skipInlineCount: true, title: "Minus" });
|
|
7115
|
+
|
|
7116
|
+
this.clearQueue();
|
|
7117
|
+
|
|
7118
|
+
const containerBox = document.createElement( 'div' );
|
|
7119
|
+
containerBox.className = "lexcounterbox";
|
|
7120
|
+
container.appendChild( containerBox );
|
|
7121
|
+
|
|
7122
|
+
const counterText = document.createElement( 'span' );
|
|
7123
|
+
counterText.className = "lexcountervalue";
|
|
7124
|
+
counterText.innerHTML = value;
|
|
7125
|
+
counterText.count = value;
|
|
7126
|
+
containerBox.appendChild( counterText );
|
|
7127
|
+
|
|
7128
|
+
if( options.label )
|
|
7129
|
+
{
|
|
7130
|
+
const counterLabel = document.createElement( 'span' );
|
|
7131
|
+
counterLabel.className = "lexcounterlabel";
|
|
7132
|
+
counterLabel.innerHTML = options.label;
|
|
7133
|
+
containerBox.appendChild( counterLabel );
|
|
7134
|
+
}
|
|
7135
|
+
|
|
7136
|
+
this.queue( container );
|
|
7137
|
+
|
|
7138
|
+
this.addButton(null, "<a style='margin-top: 0px;' class='fa-solid fa-plus'></a>", (value, e) => {
|
|
7139
|
+
let mult = step ?? 1;
|
|
7140
|
+
if( e.shiftKey ) mult *= 10;
|
|
7141
|
+
_onChange( counterText.count + mult, false, e );
|
|
7142
|
+
}, { className: "micro", skipInlineCount: true, title: "Plus" });
|
|
7143
|
+
|
|
7144
|
+
this.clearQueue();
|
|
7145
|
+
|
|
7146
|
+
return widget;
|
|
7147
|
+
}
|
|
6935
7148
|
}
|
|
6936
7149
|
|
|
6937
7150
|
LX.Panel = Panel;
|
|
@@ -7167,6 +7380,104 @@ class Branch {
|
|
|
7167
7380
|
|
|
7168
7381
|
LX.Branch = Branch;
|
|
7169
7382
|
|
|
7383
|
+
/**
|
|
7384
|
+
* @class Footer
|
|
7385
|
+
*/
|
|
7386
|
+
|
|
7387
|
+
class Footer {
|
|
7388
|
+
/**
|
|
7389
|
+
* @param {*} options:
|
|
7390
|
+
* columns: Array with data per column { title, items: [ { title, link } ] }
|
|
7391
|
+
* credits: html string
|
|
7392
|
+
* socials: Array with data per item { title, link, iconHtml }
|
|
7393
|
+
*/
|
|
7394
|
+
constructor( options = {} ) {
|
|
7395
|
+
|
|
7396
|
+
const root = document.createElement( "footer" );
|
|
7397
|
+
root.className = "lexfooter";
|
|
7398
|
+
|
|
7399
|
+
const wrapper = document.createElement( "div" );
|
|
7400
|
+
wrapper.className = "wrapper";
|
|
7401
|
+
root.appendChild( wrapper );
|
|
7402
|
+
|
|
7403
|
+
if( options.columns && options.columns.constructor == Array )
|
|
7404
|
+
{
|
|
7405
|
+
const cols = document.createElement( "div" );
|
|
7406
|
+
cols.className = "columns";
|
|
7407
|
+
cols.style.gridTemplateColumns = "1fr ".repeat( options.columns.length );
|
|
7408
|
+
wrapper.appendChild( cols );
|
|
7409
|
+
|
|
7410
|
+
for( let col of options.columns )
|
|
7411
|
+
{
|
|
7412
|
+
const colDom = document.createElement( "div" );
|
|
7413
|
+
colDom.className = "col";
|
|
7414
|
+
cols.appendChild( colDom );
|
|
7415
|
+
|
|
7416
|
+
const colTitle = document.createElement( "h2" );
|
|
7417
|
+
colTitle.innerHTML = col.title;
|
|
7418
|
+
colDom.appendChild( colTitle );
|
|
7419
|
+
|
|
7420
|
+
if( !col.items || !col.items.length )
|
|
7421
|
+
{
|
|
7422
|
+
continue;
|
|
7423
|
+
}
|
|
7424
|
+
|
|
7425
|
+
const itemListDom = document.createElement( "ul" );
|
|
7426
|
+
colDom.appendChild( itemListDom );
|
|
7427
|
+
|
|
7428
|
+
for( let item of col.items )
|
|
7429
|
+
{
|
|
7430
|
+
const itemDom = document.createElement( "li" );
|
|
7431
|
+
itemDom.innerHTML = `<a class="" href="${ item.link }">${ item.title }</a>`;
|
|
7432
|
+
itemListDom.appendChild( itemDom );
|
|
7433
|
+
}
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
|
|
7437
|
+
if( options.credits || options.socials )
|
|
7438
|
+
{
|
|
7439
|
+
const hr = document.createElement( "hr" );
|
|
7440
|
+
wrapper.appendChild( hr );
|
|
7441
|
+
|
|
7442
|
+
const creditsSocials = document.createElement( "div" );
|
|
7443
|
+
creditsSocials.className = "credits-and-socials";
|
|
7444
|
+
wrapper.appendChild( creditsSocials );
|
|
7445
|
+
|
|
7446
|
+
if( options.credits )
|
|
7447
|
+
{
|
|
7448
|
+
const credits = document.createElement( "p" );
|
|
7449
|
+
credits.innerHTML = options.credits;
|
|
7450
|
+
creditsSocials.appendChild( credits );
|
|
7451
|
+
}
|
|
7452
|
+
|
|
7453
|
+
if( options.socials )
|
|
7454
|
+
{
|
|
7455
|
+
const socials = document.createElement( "div" );
|
|
7456
|
+
socials.className = "social";
|
|
7457
|
+
|
|
7458
|
+
for( let social of options.socials )
|
|
7459
|
+
{
|
|
7460
|
+
const itemDom = document.createElement( "a" );
|
|
7461
|
+
itemDom.title = social.title;
|
|
7462
|
+
itemDom.innerHTML = social.icon;
|
|
7463
|
+
itemDom.href = social.link;
|
|
7464
|
+
itemDom.target = "_blank";
|
|
7465
|
+
socials.appendChild( itemDom );
|
|
7466
|
+
}
|
|
7467
|
+
|
|
7468
|
+
creditsSocials.appendChild( socials );
|
|
7469
|
+
}
|
|
7470
|
+
}
|
|
7471
|
+
|
|
7472
|
+
// Append directly to body
|
|
7473
|
+
const parent = options.parent ?? document.body;
|
|
7474
|
+
parent.appendChild( root );
|
|
7475
|
+
}
|
|
7476
|
+
|
|
7477
|
+
}
|
|
7478
|
+
|
|
7479
|
+
LX.Footer = Footer;
|
|
7480
|
+
|
|
7170
7481
|
/**
|
|
7171
7482
|
* @class Dialog
|
|
7172
7483
|
*/
|
|
@@ -9312,7 +9623,7 @@ Object.assign(LX, {
|
|
|
9312
9623
|
//request.mimeType = "text/plain; charset=x-user-defined";
|
|
9313
9624
|
dataType = "arraybuffer";
|
|
9314
9625
|
request.mimeType = "application/octet-stream";
|
|
9315
|
-
}
|
|
9626
|
+
}
|
|
9316
9627
|
|
|
9317
9628
|
//regular case, use AJAX call
|
|
9318
9629
|
var xhr = new XMLHttpRequest();
|