lexgui 0.4.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/lexgui.css +29 -3
- package/build/lexgui.js +299 -216
- package/build/lexgui.min.css +1 -1
- package/build/lexgui.min.js +1 -1
- package/build/lexgui.module.js +299 -216
- package/build/lexgui.module.min.js +1 -1
- package/changelog.md +15 -1
- package/demo.js +4 -1
- 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.4.
|
|
11
|
+
version: "0.4.1",
|
|
12
12
|
ready: false,
|
|
13
13
|
components: [], // Specific pre-build components
|
|
14
14
|
signals: {}, // Events and triggers
|
|
@@ -20,13 +20,13 @@ LX.MOUSE_LEFT_CLICK = 0;
|
|
|
20
20
|
LX.MOUSE_MIDDLE_CLICK = 1;
|
|
21
21
|
LX.MOUSE_RIGHT_CLICK = 2;
|
|
22
22
|
|
|
23
|
-
LX.MOUSE_DOUBLE_CLICK
|
|
24
|
-
LX.MOUSE_TRIPLE_CLICK
|
|
23
|
+
LX.MOUSE_DOUBLE_CLICK = 2;
|
|
24
|
+
LX.MOUSE_TRIPLE_CLICK = 3;
|
|
25
25
|
|
|
26
|
-
LX.CURVE_MOVEOUT_CLAMP
|
|
26
|
+
LX.CURVE_MOVEOUT_CLAMP = 0;
|
|
27
27
|
LX.CURVE_MOVEOUT_DELETE = 1;
|
|
28
28
|
|
|
29
|
-
LX.DRAGGABLE_Z_INDEX
|
|
29
|
+
LX.DRAGGABLE_Z_INDEX = 101;
|
|
30
30
|
|
|
31
31
|
function clamp( num, min, max ) { return Math.min( Math.max( num, min ), max ); }
|
|
32
32
|
function round( number, precision ) { return precision == 0 ? Math.floor( number ) : +(( number ).toFixed( precision ?? 2 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' )); }
|
|
@@ -926,7 +926,19 @@ function init( options = { } )
|
|
|
926
926
|
this.container = document.getElementById( options.container );
|
|
927
927
|
}
|
|
928
928
|
|
|
929
|
-
|
|
929
|
+
this.usingStrictViewport = options.strictViewport ?? true;
|
|
930
|
+
document.documentElement.setAttribute( "data-strictVP", ( this.usingStrictViewport ) ? "true" : "false" );
|
|
931
|
+
|
|
932
|
+
if( !this.usingStrictViewport )
|
|
933
|
+
{
|
|
934
|
+
document.addEventListener( "scroll", e => {
|
|
935
|
+
// Get all active menuboxes
|
|
936
|
+
const mbs = document.body.querySelectorAll( ".lexmenubox" );
|
|
937
|
+
mbs.forEach( ( mb ) => {
|
|
938
|
+
mb._updatePosition();
|
|
939
|
+
} );
|
|
940
|
+
} );
|
|
941
|
+
}
|
|
930
942
|
|
|
931
943
|
this.commandbar = _createCommandbar( this.container );
|
|
932
944
|
|
|
@@ -2063,7 +2075,7 @@ class Area {
|
|
|
2063
2075
|
}
|
|
2064
2076
|
|
|
2065
2077
|
// Generate DOM elements after adding all entries
|
|
2066
|
-
sidebar.
|
|
2078
|
+
sidebar.update();
|
|
2067
2079
|
|
|
2068
2080
|
LX.menubars.push( sidebar );
|
|
2069
2081
|
|
|
@@ -2673,6 +2685,195 @@ class Menubar {
|
|
|
2673
2685
|
this.shorts = { };
|
|
2674
2686
|
}
|
|
2675
2687
|
|
|
2688
|
+
_resetMenubar() {
|
|
2689
|
+
|
|
2690
|
+
// Menu entries are in the menubar..
|
|
2691
|
+
this.root.querySelectorAll(".lexmenuentry").forEach( _entry => {
|
|
2692
|
+
_entry.classList.remove( 'selected' );
|
|
2693
|
+
_entry.built = false;
|
|
2694
|
+
} );
|
|
2695
|
+
|
|
2696
|
+
// Menuboxes are in the root area!
|
|
2697
|
+
LX.root.querySelectorAll(".lexmenubox").forEach(e => e.remove());
|
|
2698
|
+
|
|
2699
|
+
// Next time we need to click again
|
|
2700
|
+
this.focused = false;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
_createSubmenu( o, k, c, d ) {
|
|
2704
|
+
|
|
2705
|
+
let menuElement = document.createElement('div');
|
|
2706
|
+
menuElement.className = "lexmenubox";
|
|
2707
|
+
menuElement.tabIndex = "0";
|
|
2708
|
+
c.currentMenu = menuElement;
|
|
2709
|
+
menuElement.parentEntry = c;
|
|
2710
|
+
|
|
2711
|
+
const isSubMenu = c.classList.contains( "lexmenuboxentry" );
|
|
2712
|
+
if( isSubMenu )
|
|
2713
|
+
{
|
|
2714
|
+
menuElement.dataset[ "submenu" ] = true;
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
menuElement._updatePosition = () => {
|
|
2718
|
+
|
|
2719
|
+
// Remove transitions for this change..
|
|
2720
|
+
const transition = menuElement.style.transition;
|
|
2721
|
+
menuElement.style.transition = "none";
|
|
2722
|
+
flushCss( menuElement );
|
|
2723
|
+
|
|
2724
|
+
doAsync( () => {
|
|
2725
|
+
let rect = c.getBoundingClientRect();
|
|
2726
|
+
rect.x += document.scrollingElement.scrollLeft;
|
|
2727
|
+
rect.y += document.scrollingElement.scrollTop;
|
|
2728
|
+
menuElement.style.left = ( isSubMenu ? ( rect.x + rect.width ) : rect.x ) + "px";
|
|
2729
|
+
menuElement.style.top = ( isSubMenu ? rect.y : ( ( rect.y + rect.height ) ) - 4 ) + "px";
|
|
2730
|
+
|
|
2731
|
+
menuElement.style.transition = transition;
|
|
2732
|
+
} );
|
|
2733
|
+
};
|
|
2734
|
+
|
|
2735
|
+
menuElement._updatePosition();
|
|
2736
|
+
|
|
2737
|
+
doAsync( () => {
|
|
2738
|
+
menuElement.dataset[ "open" ] = true;
|
|
2739
|
+
}, 10 );
|
|
2740
|
+
|
|
2741
|
+
LX.root.appendChild( menuElement );
|
|
2742
|
+
|
|
2743
|
+
for( var i = 0; i < o[ k ].length; ++i )
|
|
2744
|
+
{
|
|
2745
|
+
const subitem = o[ k ][ i ];
|
|
2746
|
+
const subkey = Object.keys( subitem )[ 0 ];
|
|
2747
|
+
const hasSubmenu = subitem[ subkey ].length;
|
|
2748
|
+
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2749
|
+
let subentry = document.createElement('div');
|
|
2750
|
+
subentry.className = "lexmenuboxentry";
|
|
2751
|
+
subentry.className += (i == o[k].length - 1 ? " last" : "") + ( subitem.disabled ? " disabled" : "" );
|
|
2752
|
+
|
|
2753
|
+
if( subkey == '' )
|
|
2754
|
+
{
|
|
2755
|
+
subentry.className = " lexseparator";
|
|
2756
|
+
}
|
|
2757
|
+
else
|
|
2758
|
+
{
|
|
2759
|
+
subentry.id = subkey;
|
|
2760
|
+
let subentrycont = document.createElement('div');
|
|
2761
|
+
subentrycont.innerHTML = "";
|
|
2762
|
+
subentrycont.classList = "lexmenuboxentrycontainer";
|
|
2763
|
+
subentry.appendChild(subentrycont);
|
|
2764
|
+
const icon = this.icons[ subkey ];
|
|
2765
|
+
if( isCheckbox )
|
|
2766
|
+
{
|
|
2767
|
+
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2768
|
+
}
|
|
2769
|
+
else if( icon )
|
|
2770
|
+
{
|
|
2771
|
+
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2772
|
+
}
|
|
2773
|
+
else
|
|
2774
|
+
{
|
|
2775
|
+
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2776
|
+
subentrycont.classList.add( "noicon" );
|
|
2777
|
+
|
|
2778
|
+
}
|
|
2779
|
+
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2780
|
+
}
|
|
2781
|
+
|
|
2782
|
+
let checkboxInput = subentry.querySelector('input');
|
|
2783
|
+
if( checkboxInput )
|
|
2784
|
+
{
|
|
2785
|
+
checkboxInput.checked = subitem.checked ?? false;
|
|
2786
|
+
checkboxInput.addEventListener('change', e => {
|
|
2787
|
+
subitem.checked = checkboxInput.checked;
|
|
2788
|
+
const f = subitem[ 'callback' ];
|
|
2789
|
+
if( f )
|
|
2790
|
+
{
|
|
2791
|
+
f.call( this, subitem.checked, subkey, subentry );
|
|
2792
|
+
this._resetMenubar();
|
|
2793
|
+
}
|
|
2794
|
+
e.stopPropagation();
|
|
2795
|
+
e.stopImmediatePropagation();
|
|
2796
|
+
})
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
menuElement.appendChild( subentry );
|
|
2800
|
+
|
|
2801
|
+
// Nothing more for separators
|
|
2802
|
+
if( subkey == '' )
|
|
2803
|
+
{
|
|
2804
|
+
continue;
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2807
|
+
menuElement.addEventListener('keydown', e => {
|
|
2808
|
+
e.preventDefault();
|
|
2809
|
+
let short = this.shorts[ subkey ];
|
|
2810
|
+
if(!short) return;
|
|
2811
|
+
// check if it's a letter or other key
|
|
2812
|
+
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2813
|
+
if( short == e.key )
|
|
2814
|
+
{
|
|
2815
|
+
subentry.click()
|
|
2816
|
+
}
|
|
2817
|
+
});
|
|
2818
|
+
|
|
2819
|
+
// Add callback
|
|
2820
|
+
subentry.addEventListener("click", e => {
|
|
2821
|
+
if( checkboxInput )
|
|
2822
|
+
{
|
|
2823
|
+
subitem.checked = !subitem.checked;
|
|
2824
|
+
}
|
|
2825
|
+
const f = subitem[ 'callback' ];
|
|
2826
|
+
if( f )
|
|
2827
|
+
{
|
|
2828
|
+
f.call( this, checkboxInput ? subitem.checked : subkey, checkboxInput ? subkey : subentry );
|
|
2829
|
+
this._resetMenubar();
|
|
2830
|
+
}
|
|
2831
|
+
e.stopPropagation();
|
|
2832
|
+
e.stopImmediatePropagation();
|
|
2833
|
+
});
|
|
2834
|
+
|
|
2835
|
+
// Add icon if has submenu, else check for shortcut
|
|
2836
|
+
if( !hasSubmenu)
|
|
2837
|
+
{
|
|
2838
|
+
if( this.shorts[ subkey ] )
|
|
2839
|
+
{
|
|
2840
|
+
let shortEl = document.createElement('div');
|
|
2841
|
+
shortEl.className = "lexentryshort";
|
|
2842
|
+
shortEl.innerText = this.shorts[ subkey ];
|
|
2843
|
+
subentry.appendChild( shortEl );
|
|
2844
|
+
}
|
|
2845
|
+
continue;
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
let submenuIcon = document.createElement('a');
|
|
2849
|
+
submenuIcon.className = "fa-solid fa-angle-right fa-xs";
|
|
2850
|
+
subentry.appendChild( submenuIcon );
|
|
2851
|
+
|
|
2852
|
+
subentry.addEventListener("mouseover", e => {
|
|
2853
|
+
if( subentry.built )
|
|
2854
|
+
{
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2857
|
+
subentry.built = true;
|
|
2858
|
+
this._createSubmenu( subitem, subkey, subentry, ++d );
|
|
2859
|
+
e.stopPropagation();
|
|
2860
|
+
});
|
|
2861
|
+
|
|
2862
|
+
subentry.addEventListener("mouseleave", e => {
|
|
2863
|
+
if( subentry.currentMenu && ( subentry.currentMenu != e.toElement ) )
|
|
2864
|
+
{
|
|
2865
|
+
d = -1; // Reset depth
|
|
2866
|
+
delete subentry.built;
|
|
2867
|
+
subentry.currentMenu.remove();
|
|
2868
|
+
delete subentry.currentMenu;
|
|
2869
|
+
}
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
// Set final width
|
|
2874
|
+
menuElement.style.width = menuElement.offsetWidth + "px";
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2676
2877
|
/**
|
|
2677
2878
|
* @method add
|
|
2678
2879
|
* @param {Object} options:
|
|
@@ -2776,176 +2977,11 @@ class Menubar {
|
|
|
2776
2977
|
}
|
|
2777
2978
|
}
|
|
2778
2979
|
|
|
2779
|
-
const _resetMenubar = function() {
|
|
2780
|
-
// Menu entries are in the menubar..
|
|
2781
|
-
that.root.querySelectorAll(".lexmenuentry").forEach( _entry => {
|
|
2782
|
-
_entry.classList.remove( 'selected' );
|
|
2783
|
-
_entry.built = false;
|
|
2784
|
-
} );
|
|
2785
|
-
// Menuboxes are in the root area!
|
|
2786
|
-
LX.root.querySelectorAll(".lexmenubox").forEach(e => e.remove());
|
|
2787
|
-
// Next time we need to click again
|
|
2788
|
-
that.focused = false;
|
|
2789
|
-
};
|
|
2790
|
-
|
|
2791
|
-
const create_submenu = function( o, k, c, d ) {
|
|
2792
|
-
|
|
2793
|
-
let menuElement = document.createElement('div');
|
|
2794
|
-
menuElement.className = "lexmenubox";
|
|
2795
|
-
menuElement.tabIndex = "0";
|
|
2796
|
-
c.currentMenu = menuElement;
|
|
2797
|
-
const isSubMenu = c.classList.contains( "lexmenuboxentry" );
|
|
2798
|
-
if( isSubMenu ) menuElement.dataset[ "submenu" ] = true;
|
|
2799
|
-
var rect = c.getBoundingClientRect();
|
|
2800
|
-
menuElement.style.left = ( isSubMenu ? ( rect.x + rect.width ) : rect.left ) + "px";
|
|
2801
|
-
menuElement.style.top = ( isSubMenu ? rect.y : rect.bottom - 4 ) + "px";
|
|
2802
|
-
rect = menuElement.getBoundingClientRect();
|
|
2803
|
-
|
|
2804
|
-
doAsync( () => {
|
|
2805
|
-
menuElement.dataset[ "open" ] = true;
|
|
2806
|
-
}, 10 );
|
|
2807
|
-
|
|
2808
|
-
LX.root.appendChild( menuElement );
|
|
2809
|
-
|
|
2810
|
-
for( var i = 0; i < o[ k ].length; ++i )
|
|
2811
|
-
{
|
|
2812
|
-
const subitem = o[ k ][ i ];
|
|
2813
|
-
const subkey = Object.keys( subitem )[ 0 ];
|
|
2814
|
-
const hasSubmenu = subitem[ subkey ].length;
|
|
2815
|
-
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2816
|
-
let subentry = document.createElement('div');
|
|
2817
|
-
subentry.className = "lexmenuboxentry";
|
|
2818
|
-
subentry.className += (i == o[k].length - 1 ? " last" : "") + ( subitem.disabled ? " disabled" : "" );
|
|
2819
|
-
|
|
2820
|
-
if( subkey == '' )
|
|
2821
|
-
{
|
|
2822
|
-
subentry.className = " lexseparator";
|
|
2823
|
-
}
|
|
2824
|
-
else
|
|
2825
|
-
{
|
|
2826
|
-
subentry.id = subkey;
|
|
2827
|
-
let subentrycont = document.createElement('div');
|
|
2828
|
-
subentrycont.innerHTML = "";
|
|
2829
|
-
subentrycont.classList = "lexmenuboxentrycontainer";
|
|
2830
|
-
subentry.appendChild(subentrycont);
|
|
2831
|
-
const icon = that.icons[ subkey ];
|
|
2832
|
-
if( isCheckbox )
|
|
2833
|
-
{
|
|
2834
|
-
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2835
|
-
}
|
|
2836
|
-
else if( icon )
|
|
2837
|
-
{
|
|
2838
|
-
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2839
|
-
}
|
|
2840
|
-
else
|
|
2841
|
-
{
|
|
2842
|
-
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2843
|
-
subentrycont.classList.add( "noicon" );
|
|
2844
|
-
|
|
2845
|
-
}
|
|
2846
|
-
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2847
|
-
}
|
|
2848
|
-
|
|
2849
|
-
let checkboxInput = subentry.querySelector('input');
|
|
2850
|
-
if( checkboxInput )
|
|
2851
|
-
{
|
|
2852
|
-
checkboxInput.checked = subitem.checked ?? false;
|
|
2853
|
-
checkboxInput.addEventListener('change', e => {
|
|
2854
|
-
subitem.checked = checkboxInput.checked;
|
|
2855
|
-
const f = subitem[ 'callback' ];
|
|
2856
|
-
if( f )
|
|
2857
|
-
{
|
|
2858
|
-
f.call( this, subitem.checked, subkey, subentry );
|
|
2859
|
-
_resetMenubar();
|
|
2860
|
-
}
|
|
2861
|
-
e.stopPropagation();
|
|
2862
|
-
e.stopImmediatePropagation();
|
|
2863
|
-
})
|
|
2864
|
-
}
|
|
2865
|
-
|
|
2866
|
-
menuElement.appendChild( subentry );
|
|
2867
|
-
|
|
2868
|
-
// Nothing more for separators
|
|
2869
|
-
if( subkey == '' )
|
|
2870
|
-
{
|
|
2871
|
-
continue;
|
|
2872
|
-
}
|
|
2873
|
-
|
|
2874
|
-
menuElement.addEventListener('keydown', function(e) {
|
|
2875
|
-
e.preventDefault();
|
|
2876
|
-
let short = that.shorts[ subkey ];
|
|
2877
|
-
if(!short) return;
|
|
2878
|
-
// check if it's a letter or other key
|
|
2879
|
-
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2880
|
-
if( short == e.key )
|
|
2881
|
-
{
|
|
2882
|
-
subentry.click()
|
|
2883
|
-
}
|
|
2884
|
-
});
|
|
2885
|
-
|
|
2886
|
-
// Add callback
|
|
2887
|
-
subentry.addEventListener("click", e => {
|
|
2888
|
-
if( checkboxInput )
|
|
2889
|
-
{
|
|
2890
|
-
subitem.checked = !subitem.checked;
|
|
2891
|
-
}
|
|
2892
|
-
const f = subitem[ 'callback' ];
|
|
2893
|
-
if( f )
|
|
2894
|
-
{
|
|
2895
|
-
f.call( this, checkboxInput ? subitem.checked : subkey, checkboxInput ? subkey : subentry );
|
|
2896
|
-
_resetMenubar();
|
|
2897
|
-
}
|
|
2898
|
-
e.stopPropagation();
|
|
2899
|
-
e.stopImmediatePropagation();
|
|
2900
|
-
});
|
|
2901
|
-
|
|
2902
|
-
// Add icon if has submenu, else check for shortcut
|
|
2903
|
-
if( !hasSubmenu)
|
|
2904
|
-
{
|
|
2905
|
-
if( that.shorts[ subkey ] )
|
|
2906
|
-
{
|
|
2907
|
-
let shortEl = document.createElement('div');
|
|
2908
|
-
shortEl.className = "lexentryshort";
|
|
2909
|
-
shortEl.innerText = that.shorts[ subkey ];
|
|
2910
|
-
subentry.appendChild( shortEl );
|
|
2911
|
-
}
|
|
2912
|
-
continue;
|
|
2913
|
-
}
|
|
2914
|
-
|
|
2915
|
-
let submenuIcon = document.createElement('a');
|
|
2916
|
-
submenuIcon.className = "fa-solid fa-angle-right fa-xs";
|
|
2917
|
-
subentry.appendChild( submenuIcon );
|
|
2918
|
-
|
|
2919
|
-
subentry.addEventListener("mouseover", e => {
|
|
2920
|
-
if( subentry.built )
|
|
2921
|
-
{
|
|
2922
|
-
return;
|
|
2923
|
-
}
|
|
2924
|
-
subentry.built = true;
|
|
2925
|
-
create_submenu( subitem, subkey, subentry, ++d );
|
|
2926
|
-
e.stopPropagation();
|
|
2927
|
-
});
|
|
2928
|
-
|
|
2929
|
-
subentry.addEventListener("mouseleave", (e) => {
|
|
2930
|
-
if( subentry.currentMenu && ( subentry.currentMenu != e.toElement ) )
|
|
2931
|
-
{
|
|
2932
|
-
d = -1; // Reset depth
|
|
2933
|
-
delete subentry.built;
|
|
2934
|
-
subentry.currentMenu.remove();
|
|
2935
|
-
delete subentry.currentMenu;
|
|
2936
|
-
}
|
|
2937
|
-
});
|
|
2938
|
-
}
|
|
2939
|
-
|
|
2940
|
-
// Set final width
|
|
2941
|
-
menuElement.style.width = menuElement.offsetWidth + "px";
|
|
2942
|
-
};
|
|
2943
|
-
|
|
2944
2980
|
const _showEntry = () => {
|
|
2945
|
-
_resetMenubar();
|
|
2981
|
+
this._resetMenubar();
|
|
2946
2982
|
entry.classList.add( "selected" );
|
|
2947
2983
|
entry.built = true;
|
|
2948
|
-
|
|
2984
|
+
this._createSubmenu( item, key, entry, -1 );
|
|
2949
2985
|
};
|
|
2950
2986
|
|
|
2951
2987
|
entry.addEventListener("click", () => {
|
|
@@ -2976,7 +3012,7 @@ class Menubar {
|
|
|
2976
3012
|
return;
|
|
2977
3013
|
}
|
|
2978
3014
|
|
|
2979
|
-
_resetMenubar();
|
|
3015
|
+
this._resetMenubar();
|
|
2980
3016
|
});
|
|
2981
3017
|
}
|
|
2982
3018
|
}
|
|
@@ -3231,20 +3267,19 @@ class SideBar {
|
|
|
3231
3267
|
|
|
3232
3268
|
/**
|
|
3233
3269
|
* @param {Object} options
|
|
3234
|
-
*
|
|
3235
|
-
* filter: TODO
|
|
3270
|
+
* filter: Add search bar to filter entries [false]
|
|
3236
3271
|
* skipHeader: Do not use sidebar header [false]
|
|
3237
3272
|
* headerImg: Image to be shown as avatar
|
|
3238
3273
|
* headerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3239
|
-
* headerTitle
|
|
3240
|
-
* headerSubtitle
|
|
3274
|
+
* headerTitle: Header title
|
|
3275
|
+
* headerSubtitle: Header subtitle
|
|
3241
3276
|
* skipFooter: Do not use sidebar footer [false]
|
|
3242
3277
|
* footerImg: Image to be shown as avatar
|
|
3243
3278
|
* footerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3244
|
-
* footerTitle
|
|
3245
|
-
* footerSubtitle
|
|
3279
|
+
* footerTitle: Footer title
|
|
3280
|
+
* footerSubtitle: Footer subtitle
|
|
3246
3281
|
* collapsable: Sidebar can toggle between collapsed/expanded [true]
|
|
3247
|
-
* collapseToIcons: When Sidebar collapses, icons remains visible
|
|
3282
|
+
* collapseToIcons: When Sidebar collapses, icons remains visible [true]
|
|
3248
3283
|
* onHeaderPressed: Function to call when header is pressed
|
|
3249
3284
|
* onFooterPressed: Function to call when footer is pressed
|
|
3250
3285
|
*/
|
|
@@ -3254,12 +3289,12 @@ class SideBar {
|
|
|
3254
3289
|
this.root = document.createElement( 'div' );
|
|
3255
3290
|
this.root.className = "lexsidebar";
|
|
3256
3291
|
|
|
3257
|
-
window.sidebar = this;
|
|
3258
|
-
|
|
3259
3292
|
this.collapsable = options.collapsable ?? true;
|
|
3260
|
-
this.
|
|
3293
|
+
this._collapseWidth = ( options.collapseToIcons ?? true ) ? "58px" : "0px";
|
|
3261
3294
|
this.collapsed = false;
|
|
3262
3295
|
|
|
3296
|
+
this.filterString = "";
|
|
3297
|
+
|
|
3263
3298
|
doAsync( () => {
|
|
3264
3299
|
|
|
3265
3300
|
this.root.parentElement.ogWidth = this.root.parentElement.style.width;
|
|
@@ -3272,7 +3307,7 @@ class SideBar {
|
|
|
3272
3307
|
}
|
|
3273
3308
|
});
|
|
3274
3309
|
|
|
3275
|
-
},
|
|
3310
|
+
}, 10 );
|
|
3276
3311
|
|
|
3277
3312
|
// This account for header, footer and all inner paddings
|
|
3278
3313
|
let contentOffset = 32;
|
|
@@ -3342,6 +3377,19 @@ class SideBar {
|
|
|
3342
3377
|
contentOffset += 52;
|
|
3343
3378
|
}
|
|
3344
3379
|
|
|
3380
|
+
// Entry filter
|
|
3381
|
+
if( !( options.filter ?? false ) )
|
|
3382
|
+
{
|
|
3383
|
+
const panel = new Panel();
|
|
3384
|
+
panel.addText(null, "", (value, event) => {
|
|
3385
|
+
this.filterString = value;
|
|
3386
|
+
this.update();
|
|
3387
|
+
}, { placeholder: "Search...", icon: "fa-solid fa-magnifying-glass" });
|
|
3388
|
+
this.filter = panel.root.childNodes[ 0 ];
|
|
3389
|
+
this.root.appendChild( this.filter );
|
|
3390
|
+
contentOffset += 31;
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3345
3393
|
// Content
|
|
3346
3394
|
{
|
|
3347
3395
|
this.content = document.createElement( 'div' );
|
|
@@ -3409,21 +3457,22 @@ class SideBar {
|
|
|
3409
3457
|
|
|
3410
3458
|
/**
|
|
3411
3459
|
* @method toggleCollapsed
|
|
3460
|
+
* @param {Boolean} force: Force collapsed state
|
|
3412
3461
|
*/
|
|
3413
3462
|
|
|
3414
|
-
toggleCollapsed() {
|
|
3463
|
+
toggleCollapsed( force ) {
|
|
3415
3464
|
|
|
3416
3465
|
if( !this.collapsable )
|
|
3417
3466
|
{
|
|
3418
3467
|
return;
|
|
3419
3468
|
}
|
|
3420
3469
|
|
|
3421
|
-
this.collapsed = !this.collapsed;
|
|
3470
|
+
this.collapsed = force ?? !this.collapsed;
|
|
3422
3471
|
|
|
3423
3472
|
if( this.collapsed )
|
|
3424
3473
|
{
|
|
3425
3474
|
this.root.classList.add( "collapsing" );
|
|
3426
|
-
this.root.parentElement.style.width = this.
|
|
3475
|
+
this.root.parentElement.style.width = this._collapseWidth;
|
|
3427
3476
|
}
|
|
3428
3477
|
else
|
|
3429
3478
|
{
|
|
@@ -3432,6 +3481,11 @@ class SideBar {
|
|
|
3432
3481
|
this.root.parentElement.style.width = this.root.parentElement.ogWidth;
|
|
3433
3482
|
}
|
|
3434
3483
|
|
|
3484
|
+
if( !this.resizeObserver )
|
|
3485
|
+
{
|
|
3486
|
+
throw( "Wait until ResizeObserver has been created!" );
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3435
3489
|
this.resizeObserver.observe( this.root.parentElement );
|
|
3436
3490
|
|
|
3437
3491
|
doAsync( () => {
|
|
@@ -3490,7 +3544,6 @@ class SideBar {
|
|
|
3490
3544
|
const lastPath = tokens[tokens.length - 1];
|
|
3491
3545
|
this.icons[ lastPath ] = options.icon;
|
|
3492
3546
|
|
|
3493
|
-
|
|
3494
3547
|
let idx = 0;
|
|
3495
3548
|
|
|
3496
3549
|
const _insertEntry = ( token, list ) => {
|
|
@@ -3545,10 +3598,19 @@ class SideBar {
|
|
|
3545
3598
|
if( !entry )
|
|
3546
3599
|
return;
|
|
3547
3600
|
|
|
3548
|
-
entry.
|
|
3601
|
+
entry.dom.click();
|
|
3549
3602
|
}
|
|
3550
3603
|
|
|
3551
|
-
|
|
3604
|
+
update() {
|
|
3605
|
+
|
|
3606
|
+
// Reset first
|
|
3607
|
+
|
|
3608
|
+
this.content.innerHTML = "";
|
|
3609
|
+
|
|
3610
|
+
for( let item of this.items )
|
|
3611
|
+
{
|
|
3612
|
+
delete item.dom;
|
|
3613
|
+
}
|
|
3552
3614
|
|
|
3553
3615
|
for( let item of this.items )
|
|
3554
3616
|
{
|
|
@@ -3561,12 +3623,18 @@ class SideBar {
|
|
|
3561
3623
|
}
|
|
3562
3624
|
|
|
3563
3625
|
let key = Object.keys( item )[ 0 ];
|
|
3626
|
+
|
|
3627
|
+
if( this.filterString.length && !key.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3628
|
+
{
|
|
3629
|
+
continue;
|
|
3630
|
+
}
|
|
3631
|
+
|
|
3564
3632
|
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3565
3633
|
let currentGroup = null;
|
|
3566
3634
|
|
|
3567
3635
|
let entry = document.createElement( 'div' );
|
|
3568
3636
|
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
3569
|
-
entry.id = pKey;
|
|
3637
|
+
entry.id = item.name = pKey;
|
|
3570
3638
|
|
|
3571
3639
|
if( item.group )
|
|
3572
3640
|
{
|
|
@@ -3637,7 +3705,7 @@ class SideBar {
|
|
|
3637
3705
|
|
|
3638
3706
|
let itemDom = document.createElement( 'div' );
|
|
3639
3707
|
entry.appendChild( itemDom );
|
|
3640
|
-
item.dom =
|
|
3708
|
+
item.dom = entry;
|
|
3641
3709
|
|
|
3642
3710
|
if( options.type == "checkbox" )
|
|
3643
3711
|
{
|
|
@@ -3749,12 +3817,17 @@ class SideBar {
|
|
|
3749
3817
|
this.content.appendChild( subentryContainer );
|
|
3750
3818
|
}
|
|
3751
3819
|
|
|
3752
|
-
for(
|
|
3820
|
+
for( let i = 0; i < item[ key ].length; ++i )
|
|
3753
3821
|
{
|
|
3754
3822
|
const subitem = item[ key ][ i ];
|
|
3755
3823
|
const suboptions = subitem.options ?? {};
|
|
3756
3824
|
const subkey = Object.keys( subitem )[ 0 ];
|
|
3757
3825
|
|
|
3826
|
+
if( this.filterString.length && !subkey.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3827
|
+
{
|
|
3828
|
+
continue;
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3758
3831
|
let subentry = document.createElement( 'div' );
|
|
3759
3832
|
subentry.innerHTML = `<span>${ subkey }</span>`;
|
|
3760
3833
|
|
|
@@ -5285,7 +5358,7 @@ class Panel {
|
|
|
5285
5358
|
|
|
5286
5359
|
var resolve = ( function( val, event ) {
|
|
5287
5360
|
|
|
5288
|
-
if( !widget.valid() )
|
|
5361
|
+
if( !widget.valid() || ( this._lastValueTriggered == val ) )
|
|
5289
5362
|
{
|
|
5290
5363
|
return;
|
|
5291
5364
|
}
|
|
@@ -5298,6 +5371,8 @@ class Panel {
|
|
|
5298
5371
|
this._trigger( new IEvent( name, val, event ), callback );
|
|
5299
5372
|
}
|
|
5300
5373
|
|
|
5374
|
+
this._lastValueTriggered = val;
|
|
5375
|
+
|
|
5301
5376
|
}).bind( this );
|
|
5302
5377
|
|
|
5303
5378
|
const trigger = options.trigger ?? 'default';
|
|
@@ -9563,7 +9638,7 @@ class ContextMenu {
|
|
|
9563
9638
|
}
|
|
9564
9639
|
}
|
|
9565
9640
|
|
|
9566
|
-
|
|
9641
|
+
_adjustPosition( div, margin, useAbsolute = false ) {
|
|
9567
9642
|
|
|
9568
9643
|
let rect = div.getBoundingClientRect();
|
|
9569
9644
|
|
|
@@ -9604,7 +9679,7 @@ class ContextMenu {
|
|
|
9604
9679
|
}
|
|
9605
9680
|
}
|
|
9606
9681
|
|
|
9607
|
-
|
|
9682
|
+
_createSubmenu( o, k, c, d ) {
|
|
9608
9683
|
|
|
9609
9684
|
this.root.querySelectorAll( ".lexcontextmenu" ).forEach( cm => cm.remove() );
|
|
9610
9685
|
|
|
@@ -9616,7 +9691,7 @@ class ContextMenu {
|
|
|
9616
9691
|
{
|
|
9617
9692
|
const subitem = o[ k ][ i ];
|
|
9618
9693
|
const subkey = Object.keys( subitem )[ 0 ];
|
|
9619
|
-
this.
|
|
9694
|
+
this._createEntry(subitem, subkey, contextmenu, d);
|
|
9620
9695
|
}
|
|
9621
9696
|
|
|
9622
9697
|
var rect = c.getBoundingClientRect();
|
|
@@ -9624,10 +9699,10 @@ class ContextMenu {
|
|
|
9624
9699
|
contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
|
|
9625
9700
|
|
|
9626
9701
|
// Set final width
|
|
9627
|
-
this.
|
|
9702
|
+
this._adjustPosition( contextmenu, 6, true );
|
|
9628
9703
|
}
|
|
9629
9704
|
|
|
9630
|
-
|
|
9705
|
+
_createEntry( o, k, c, d ) {
|
|
9631
9706
|
|
|
9632
9707
|
const hasSubmenu = o[ k ].length;
|
|
9633
9708
|
let entry = document.createElement('div');
|
|
@@ -9672,7 +9747,7 @@ class ContextMenu {
|
|
|
9672
9747
|
return;
|
|
9673
9748
|
|
|
9674
9749
|
if( LX.OPEN_CONTEXTMENU_ENTRY == 'click' )
|
|
9675
|
-
this.
|
|
9750
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
9676
9751
|
});
|
|
9677
9752
|
|
|
9678
9753
|
if( !hasSubmenu )
|
|
@@ -9688,7 +9763,7 @@ class ContextMenu {
|
|
|
9688
9763
|
if(entry.built)
|
|
9689
9764
|
return;
|
|
9690
9765
|
entry.built = true;
|
|
9691
|
-
this.
|
|
9766
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
9692
9767
|
e.stopPropagation();
|
|
9693
9768
|
});
|
|
9694
9769
|
}
|
|
@@ -9700,7 +9775,7 @@ class ContextMenu {
|
|
|
9700
9775
|
}
|
|
9701
9776
|
|
|
9702
9777
|
onCreate() {
|
|
9703
|
-
doAsync( () => this.
|
|
9778
|
+
doAsync( () => this._adjustPosition( this.root, 6 ) );
|
|
9704
9779
|
}
|
|
9705
9780
|
|
|
9706
9781
|
add( path, options = {} ) {
|
|
@@ -9730,13 +9805,13 @@ class ContextMenu {
|
|
|
9730
9805
|
|
|
9731
9806
|
if( found )
|
|
9732
9807
|
{
|
|
9733
|
-
insert( tokens[idx++], found );
|
|
9808
|
+
insert( tokens[ idx++ ], found );
|
|
9734
9809
|
}
|
|
9735
9810
|
else
|
|
9736
9811
|
{
|
|
9737
9812
|
let item = {};
|
|
9738
9813
|
item[ token ] = [];
|
|
9739
|
-
const nextToken = tokens[idx++];
|
|
9814
|
+
const nextToken = tokens[ idx++ ];
|
|
9740
9815
|
// Check if last token -> add callback
|
|
9741
9816
|
if( !nextToken )
|
|
9742
9817
|
{
|
|
@@ -9756,13 +9831,15 @@ class ContextMenu {
|
|
|
9756
9831
|
|
|
9757
9832
|
const setParent = _item => {
|
|
9758
9833
|
|
|
9759
|
-
let key = Object.keys(_item)[0];
|
|
9834
|
+
let key = Object.keys( _item )[ 0 ];
|
|
9760
9835
|
let children = _item[ key ];
|
|
9761
9836
|
|
|
9762
|
-
if(!children.length)
|
|
9837
|
+
if( !children.length )
|
|
9838
|
+
{
|
|
9763
9839
|
return;
|
|
9840
|
+
}
|
|
9764
9841
|
|
|
9765
|
-
if(children.find( c => Object.keys(c)[0] == key ) == null)
|
|
9842
|
+
if( children.find( c => Object.keys(c)[0] == key ) == null )
|
|
9766
9843
|
{
|
|
9767
9844
|
const parent = {};
|
|
9768
9845
|
parent[ key ] = [];
|
|
@@ -9772,14 +9849,18 @@ class ContextMenu {
|
|
|
9772
9849
|
|
|
9773
9850
|
for( var child of _item[ key ] )
|
|
9774
9851
|
{
|
|
9775
|
-
let k = Object.keys(child)[0];
|
|
9776
|
-
for( var i = 0; i < child[k].length; ++i )
|
|
9777
|
-
|
|
9852
|
+
let k = Object.keys( child )[ 0 ];
|
|
9853
|
+
for( var i = 0; i < child[ k ].length; ++i )
|
|
9854
|
+
{
|
|
9855
|
+
setParent( child );
|
|
9856
|
+
}
|
|
9778
9857
|
}
|
|
9779
9858
|
};
|
|
9780
9859
|
|
|
9781
9860
|
for( let item of this.items )
|
|
9782
|
-
|
|
9861
|
+
{
|
|
9862
|
+
setParent( item );
|
|
9863
|
+
}
|
|
9783
9864
|
|
|
9784
9865
|
// Create elements
|
|
9785
9866
|
|
|
@@ -9789,9 +9870,11 @@ class ContextMenu {
|
|
|
9789
9870
|
let pKey = "eId" + getSupportedDOMName( key );
|
|
9790
9871
|
|
|
9791
9872
|
// Item already created
|
|
9792
|
-
const id = "#" + (item.id ?? pKey);
|
|
9793
|
-
if( !this.root.querySelector(id) )
|
|
9794
|
-
|
|
9873
|
+
const id = "#" + ( item.id ?? pKey );
|
|
9874
|
+
if( !this.root.querySelector( id ) )
|
|
9875
|
+
{
|
|
9876
|
+
this._createEntry( item, key, this.root, -1 );
|
|
9877
|
+
}
|
|
9795
9878
|
}
|
|
9796
9879
|
}
|
|
9797
9880
|
|