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.js
CHANGED
|
@@ -12,7 +12,7 @@ console.warn( 'Script _build/lexgui.js_ is depracated and will be removed soon.
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
var LX = {
|
|
15
|
-
version: "0.4.
|
|
15
|
+
version: "0.4.1",
|
|
16
16
|
ready: false,
|
|
17
17
|
components: [], // Specific pre-build components
|
|
18
18
|
signals: {}, // Events and triggers
|
|
@@ -24,13 +24,13 @@ LX.MOUSE_LEFT_CLICK = 0;
|
|
|
24
24
|
LX.MOUSE_MIDDLE_CLICK = 1;
|
|
25
25
|
LX.MOUSE_RIGHT_CLICK = 2;
|
|
26
26
|
|
|
27
|
-
LX.MOUSE_DOUBLE_CLICK
|
|
28
|
-
LX.MOUSE_TRIPLE_CLICK
|
|
27
|
+
LX.MOUSE_DOUBLE_CLICK = 2;
|
|
28
|
+
LX.MOUSE_TRIPLE_CLICK = 3;
|
|
29
29
|
|
|
30
|
-
LX.CURVE_MOVEOUT_CLAMP
|
|
30
|
+
LX.CURVE_MOVEOUT_CLAMP = 0;
|
|
31
31
|
LX.CURVE_MOVEOUT_DELETE = 1;
|
|
32
32
|
|
|
33
|
-
LX.DRAGGABLE_Z_INDEX
|
|
33
|
+
LX.DRAGGABLE_Z_INDEX = 101;
|
|
34
34
|
|
|
35
35
|
function clamp( num, min, max ) { return Math.min( Math.max( num, min ), max ); }
|
|
36
36
|
function round( number, precision ) { return precision == 0 ? Math.floor( number ) : +(( number ).toFixed( precision ?? 2 ).replace( /([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/, '$1' )); }
|
|
@@ -930,7 +930,19 @@ function init( options = { } )
|
|
|
930
930
|
this.container = document.getElementById( options.container );
|
|
931
931
|
}
|
|
932
932
|
|
|
933
|
-
|
|
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
|
+
}
|
|
934
946
|
|
|
935
947
|
this.commandbar = _createCommandbar( this.container );
|
|
936
948
|
|
|
@@ -2067,7 +2079,7 @@ class Area {
|
|
|
2067
2079
|
}
|
|
2068
2080
|
|
|
2069
2081
|
// Generate DOM elements after adding all entries
|
|
2070
|
-
sidebar.
|
|
2082
|
+
sidebar.update();
|
|
2071
2083
|
|
|
2072
2084
|
LX.menubars.push( sidebar );
|
|
2073
2085
|
|
|
@@ -2677,6 +2689,195 @@ class Menubar {
|
|
|
2677
2689
|
this.shorts = { };
|
|
2678
2690
|
}
|
|
2679
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
|
+
}
|
|
2810
|
+
|
|
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";
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2680
2881
|
/**
|
|
2681
2882
|
* @method add
|
|
2682
2883
|
* @param {Object} options:
|
|
@@ -2780,176 +2981,11 @@ class Menubar {
|
|
|
2780
2981
|
}
|
|
2781
2982
|
}
|
|
2782
2983
|
|
|
2783
|
-
const _resetMenubar = function() {
|
|
2784
|
-
// Menu entries are in the menubar..
|
|
2785
|
-
that.root.querySelectorAll(".lexmenuentry").forEach( _entry => {
|
|
2786
|
-
_entry.classList.remove( 'selected' );
|
|
2787
|
-
_entry.built = false;
|
|
2788
|
-
} );
|
|
2789
|
-
// Menuboxes are in the root area!
|
|
2790
|
-
LX.root.querySelectorAll(".lexmenubox").forEach(e => e.remove());
|
|
2791
|
-
// Next time we need to click again
|
|
2792
|
-
that.focused = false;
|
|
2793
|
-
};
|
|
2794
|
-
|
|
2795
|
-
const create_submenu = function( o, k, c, d ) {
|
|
2796
|
-
|
|
2797
|
-
let menuElement = document.createElement('div');
|
|
2798
|
-
menuElement.className = "lexmenubox";
|
|
2799
|
-
menuElement.tabIndex = "0";
|
|
2800
|
-
c.currentMenu = menuElement;
|
|
2801
|
-
const isSubMenu = c.classList.contains( "lexmenuboxentry" );
|
|
2802
|
-
if( isSubMenu ) menuElement.dataset[ "submenu" ] = true;
|
|
2803
|
-
var rect = c.getBoundingClientRect();
|
|
2804
|
-
menuElement.style.left = ( isSubMenu ? ( rect.x + rect.width ) : rect.left ) + "px";
|
|
2805
|
-
menuElement.style.top = ( isSubMenu ? rect.y : rect.bottom - 4 ) + "px";
|
|
2806
|
-
rect = menuElement.getBoundingClientRect();
|
|
2807
|
-
|
|
2808
|
-
doAsync( () => {
|
|
2809
|
-
menuElement.dataset[ "open" ] = true;
|
|
2810
|
-
}, 10 );
|
|
2811
|
-
|
|
2812
|
-
LX.root.appendChild( menuElement );
|
|
2813
|
-
|
|
2814
|
-
for( var i = 0; i < o[ k ].length; ++i )
|
|
2815
|
-
{
|
|
2816
|
-
const subitem = o[ k ][ i ];
|
|
2817
|
-
const subkey = Object.keys( subitem )[ 0 ];
|
|
2818
|
-
const hasSubmenu = subitem[ subkey ].length;
|
|
2819
|
-
const isCheckbox = subitem[ 'type' ] == 'checkbox';
|
|
2820
|
-
let subentry = document.createElement('div');
|
|
2821
|
-
subentry.className = "lexmenuboxentry";
|
|
2822
|
-
subentry.className += (i == o[k].length - 1 ? " last" : "") + ( subitem.disabled ? " disabled" : "" );
|
|
2823
|
-
|
|
2824
|
-
if( subkey == '' )
|
|
2825
|
-
{
|
|
2826
|
-
subentry.className = " lexseparator";
|
|
2827
|
-
}
|
|
2828
|
-
else
|
|
2829
|
-
{
|
|
2830
|
-
subentry.id = subkey;
|
|
2831
|
-
let subentrycont = document.createElement('div');
|
|
2832
|
-
subentrycont.innerHTML = "";
|
|
2833
|
-
subentrycont.classList = "lexmenuboxentrycontainer";
|
|
2834
|
-
subentry.appendChild(subentrycont);
|
|
2835
|
-
const icon = that.icons[ subkey ];
|
|
2836
|
-
if( isCheckbox )
|
|
2837
|
-
{
|
|
2838
|
-
subentrycont.innerHTML += "<input type='checkbox' >";
|
|
2839
|
-
}
|
|
2840
|
-
else if( icon )
|
|
2841
|
-
{
|
|
2842
|
-
subentrycont.innerHTML += "<a class='" + icon + " fa-sm'></a>";
|
|
2843
|
-
}
|
|
2844
|
-
else
|
|
2845
|
-
{
|
|
2846
|
-
subentrycont.innerHTML += "<a class='fa-solid fa-sm noicon'></a>";
|
|
2847
|
-
subentrycont.classList.add( "noicon" );
|
|
2848
|
-
|
|
2849
|
-
}
|
|
2850
|
-
subentrycont.innerHTML += "<div class='lexentryname'>" + subkey + "</div>";
|
|
2851
|
-
}
|
|
2852
|
-
|
|
2853
|
-
let checkboxInput = subentry.querySelector('input');
|
|
2854
|
-
if( checkboxInput )
|
|
2855
|
-
{
|
|
2856
|
-
checkboxInput.checked = subitem.checked ?? false;
|
|
2857
|
-
checkboxInput.addEventListener('change', e => {
|
|
2858
|
-
subitem.checked = checkboxInput.checked;
|
|
2859
|
-
const f = subitem[ 'callback' ];
|
|
2860
|
-
if( f )
|
|
2861
|
-
{
|
|
2862
|
-
f.call( this, subitem.checked, subkey, subentry );
|
|
2863
|
-
_resetMenubar();
|
|
2864
|
-
}
|
|
2865
|
-
e.stopPropagation();
|
|
2866
|
-
e.stopImmediatePropagation();
|
|
2867
|
-
})
|
|
2868
|
-
}
|
|
2869
|
-
|
|
2870
|
-
menuElement.appendChild( subentry );
|
|
2871
|
-
|
|
2872
|
-
// Nothing more for separators
|
|
2873
|
-
if( subkey == '' )
|
|
2874
|
-
{
|
|
2875
|
-
continue;
|
|
2876
|
-
}
|
|
2877
|
-
|
|
2878
|
-
menuElement.addEventListener('keydown', function(e) {
|
|
2879
|
-
e.preventDefault();
|
|
2880
|
-
let short = that.shorts[ subkey ];
|
|
2881
|
-
if(!short) return;
|
|
2882
|
-
// check if it's a letter or other key
|
|
2883
|
-
short = short.length == 1 ? short.toLowerCase() : short;
|
|
2884
|
-
if( short == e.key )
|
|
2885
|
-
{
|
|
2886
|
-
subentry.click()
|
|
2887
|
-
}
|
|
2888
|
-
});
|
|
2889
|
-
|
|
2890
|
-
// Add callback
|
|
2891
|
-
subentry.addEventListener("click", e => {
|
|
2892
|
-
if( checkboxInput )
|
|
2893
|
-
{
|
|
2894
|
-
subitem.checked = !subitem.checked;
|
|
2895
|
-
}
|
|
2896
|
-
const f = subitem[ 'callback' ];
|
|
2897
|
-
if( f )
|
|
2898
|
-
{
|
|
2899
|
-
f.call( this, checkboxInput ? subitem.checked : subkey, checkboxInput ? subkey : subentry );
|
|
2900
|
-
_resetMenubar();
|
|
2901
|
-
}
|
|
2902
|
-
e.stopPropagation();
|
|
2903
|
-
e.stopImmediatePropagation();
|
|
2904
|
-
});
|
|
2905
|
-
|
|
2906
|
-
// Add icon if has submenu, else check for shortcut
|
|
2907
|
-
if( !hasSubmenu)
|
|
2908
|
-
{
|
|
2909
|
-
if( that.shorts[ subkey ] )
|
|
2910
|
-
{
|
|
2911
|
-
let shortEl = document.createElement('div');
|
|
2912
|
-
shortEl.className = "lexentryshort";
|
|
2913
|
-
shortEl.innerText = that.shorts[ subkey ];
|
|
2914
|
-
subentry.appendChild( shortEl );
|
|
2915
|
-
}
|
|
2916
|
-
continue;
|
|
2917
|
-
}
|
|
2918
|
-
|
|
2919
|
-
let submenuIcon = document.createElement('a');
|
|
2920
|
-
submenuIcon.className = "fa-solid fa-angle-right fa-xs";
|
|
2921
|
-
subentry.appendChild( submenuIcon );
|
|
2922
|
-
|
|
2923
|
-
subentry.addEventListener("mouseover", e => {
|
|
2924
|
-
if( subentry.built )
|
|
2925
|
-
{
|
|
2926
|
-
return;
|
|
2927
|
-
}
|
|
2928
|
-
subentry.built = true;
|
|
2929
|
-
create_submenu( subitem, subkey, subentry, ++d );
|
|
2930
|
-
e.stopPropagation();
|
|
2931
|
-
});
|
|
2932
|
-
|
|
2933
|
-
subentry.addEventListener("mouseleave", (e) => {
|
|
2934
|
-
if( subentry.currentMenu && ( subentry.currentMenu != e.toElement ) )
|
|
2935
|
-
{
|
|
2936
|
-
d = -1; // Reset depth
|
|
2937
|
-
delete subentry.built;
|
|
2938
|
-
subentry.currentMenu.remove();
|
|
2939
|
-
delete subentry.currentMenu;
|
|
2940
|
-
}
|
|
2941
|
-
});
|
|
2942
|
-
}
|
|
2943
|
-
|
|
2944
|
-
// Set final width
|
|
2945
|
-
menuElement.style.width = menuElement.offsetWidth + "px";
|
|
2946
|
-
};
|
|
2947
|
-
|
|
2948
2984
|
const _showEntry = () => {
|
|
2949
|
-
_resetMenubar();
|
|
2985
|
+
this._resetMenubar();
|
|
2950
2986
|
entry.classList.add( "selected" );
|
|
2951
2987
|
entry.built = true;
|
|
2952
|
-
|
|
2988
|
+
this._createSubmenu( item, key, entry, -1 );
|
|
2953
2989
|
};
|
|
2954
2990
|
|
|
2955
2991
|
entry.addEventListener("click", () => {
|
|
@@ -2980,7 +3016,7 @@ class Menubar {
|
|
|
2980
3016
|
return;
|
|
2981
3017
|
}
|
|
2982
3018
|
|
|
2983
|
-
_resetMenubar();
|
|
3019
|
+
this._resetMenubar();
|
|
2984
3020
|
});
|
|
2985
3021
|
}
|
|
2986
3022
|
}
|
|
@@ -3235,20 +3271,19 @@ class SideBar {
|
|
|
3235
3271
|
|
|
3236
3272
|
/**
|
|
3237
3273
|
* @param {Object} options
|
|
3238
|
-
*
|
|
3239
|
-
* filter: TODO
|
|
3274
|
+
* filter: Add search bar to filter entries [false]
|
|
3240
3275
|
* skipHeader: Do not use sidebar header [false]
|
|
3241
3276
|
* headerImg: Image to be shown as avatar
|
|
3242
3277
|
* headerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3243
|
-
* headerTitle
|
|
3244
|
-
* headerSubtitle
|
|
3278
|
+
* headerTitle: Header title
|
|
3279
|
+
* headerSubtitle: Header subtitle
|
|
3245
3280
|
* skipFooter: Do not use sidebar footer [false]
|
|
3246
3281
|
* footerImg: Image to be shown as avatar
|
|
3247
3282
|
* footerIcon: Icon to be shown as avatar (from LX.ICONS)
|
|
3248
|
-
* footerTitle
|
|
3249
|
-
* footerSubtitle
|
|
3283
|
+
* footerTitle: Footer title
|
|
3284
|
+
* footerSubtitle: Footer subtitle
|
|
3250
3285
|
* collapsable: Sidebar can toggle between collapsed/expanded [true]
|
|
3251
|
-
* collapseToIcons: When Sidebar collapses, icons remains visible
|
|
3286
|
+
* collapseToIcons: When Sidebar collapses, icons remains visible [true]
|
|
3252
3287
|
* onHeaderPressed: Function to call when header is pressed
|
|
3253
3288
|
* onFooterPressed: Function to call when footer is pressed
|
|
3254
3289
|
*/
|
|
@@ -3258,12 +3293,12 @@ class SideBar {
|
|
|
3258
3293
|
this.root = document.createElement( 'div' );
|
|
3259
3294
|
this.root.className = "lexsidebar";
|
|
3260
3295
|
|
|
3261
|
-
window.sidebar = this;
|
|
3262
|
-
|
|
3263
3296
|
this.collapsable = options.collapsable ?? true;
|
|
3264
|
-
this.
|
|
3297
|
+
this._collapseWidth = ( options.collapseToIcons ?? true ) ? "58px" : "0px";
|
|
3265
3298
|
this.collapsed = false;
|
|
3266
3299
|
|
|
3300
|
+
this.filterString = "";
|
|
3301
|
+
|
|
3267
3302
|
doAsync( () => {
|
|
3268
3303
|
|
|
3269
3304
|
this.root.parentElement.ogWidth = this.root.parentElement.style.width;
|
|
@@ -3276,7 +3311,7 @@ class SideBar {
|
|
|
3276
3311
|
}
|
|
3277
3312
|
});
|
|
3278
3313
|
|
|
3279
|
-
},
|
|
3314
|
+
}, 10 );
|
|
3280
3315
|
|
|
3281
3316
|
// This account for header, footer and all inner paddings
|
|
3282
3317
|
let contentOffset = 32;
|
|
@@ -3346,6 +3381,19 @@ class SideBar {
|
|
|
3346
3381
|
contentOffset += 52;
|
|
3347
3382
|
}
|
|
3348
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
|
+
|
|
3349
3397
|
// Content
|
|
3350
3398
|
{
|
|
3351
3399
|
this.content = document.createElement( 'div' );
|
|
@@ -3413,21 +3461,22 @@ class SideBar {
|
|
|
3413
3461
|
|
|
3414
3462
|
/**
|
|
3415
3463
|
* @method toggleCollapsed
|
|
3464
|
+
* @param {Boolean} force: Force collapsed state
|
|
3416
3465
|
*/
|
|
3417
3466
|
|
|
3418
|
-
toggleCollapsed() {
|
|
3467
|
+
toggleCollapsed( force ) {
|
|
3419
3468
|
|
|
3420
3469
|
if( !this.collapsable )
|
|
3421
3470
|
{
|
|
3422
3471
|
return;
|
|
3423
3472
|
}
|
|
3424
3473
|
|
|
3425
|
-
this.collapsed = !this.collapsed;
|
|
3474
|
+
this.collapsed = force ?? !this.collapsed;
|
|
3426
3475
|
|
|
3427
3476
|
if( this.collapsed )
|
|
3428
3477
|
{
|
|
3429
3478
|
this.root.classList.add( "collapsing" );
|
|
3430
|
-
this.root.parentElement.style.width = this.
|
|
3479
|
+
this.root.parentElement.style.width = this._collapseWidth;
|
|
3431
3480
|
}
|
|
3432
3481
|
else
|
|
3433
3482
|
{
|
|
@@ -3436,6 +3485,11 @@ class SideBar {
|
|
|
3436
3485
|
this.root.parentElement.style.width = this.root.parentElement.ogWidth;
|
|
3437
3486
|
}
|
|
3438
3487
|
|
|
3488
|
+
if( !this.resizeObserver )
|
|
3489
|
+
{
|
|
3490
|
+
throw( "Wait until ResizeObserver has been created!" );
|
|
3491
|
+
}
|
|
3492
|
+
|
|
3439
3493
|
this.resizeObserver.observe( this.root.parentElement );
|
|
3440
3494
|
|
|
3441
3495
|
doAsync( () => {
|
|
@@ -3494,7 +3548,6 @@ class SideBar {
|
|
|
3494
3548
|
const lastPath = tokens[tokens.length - 1];
|
|
3495
3549
|
this.icons[ lastPath ] = options.icon;
|
|
3496
3550
|
|
|
3497
|
-
|
|
3498
3551
|
let idx = 0;
|
|
3499
3552
|
|
|
3500
3553
|
const _insertEntry = ( token, list ) => {
|
|
@@ -3549,10 +3602,19 @@ class SideBar {
|
|
|
3549
3602
|
if( !entry )
|
|
3550
3603
|
return;
|
|
3551
3604
|
|
|
3552
|
-
entry.
|
|
3605
|
+
entry.dom.click();
|
|
3553
3606
|
}
|
|
3554
3607
|
|
|
3555
|
-
|
|
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
|
+
}
|
|
3556
3618
|
|
|
3557
3619
|
for( let item of this.items )
|
|
3558
3620
|
{
|
|
@@ -3565,12 +3627,18 @@ class SideBar {
|
|
|
3565
3627
|
}
|
|
3566
3628
|
|
|
3567
3629
|
let key = Object.keys( item )[ 0 ];
|
|
3630
|
+
|
|
3631
|
+
if( this.filterString.length && !key.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3632
|
+
{
|
|
3633
|
+
continue;
|
|
3634
|
+
}
|
|
3635
|
+
|
|
3568
3636
|
let pKey = key.replace( /\s/g, '' ).replaceAll( '.', '' );
|
|
3569
3637
|
let currentGroup = null;
|
|
3570
3638
|
|
|
3571
3639
|
let entry = document.createElement( 'div' );
|
|
3572
3640
|
entry.className = "lexsidebarentry " + ( options.className ?? "" );
|
|
3573
|
-
entry.id = pKey;
|
|
3641
|
+
entry.id = item.name = pKey;
|
|
3574
3642
|
|
|
3575
3643
|
if( item.group )
|
|
3576
3644
|
{
|
|
@@ -3641,7 +3709,7 @@ class SideBar {
|
|
|
3641
3709
|
|
|
3642
3710
|
let itemDom = document.createElement( 'div' );
|
|
3643
3711
|
entry.appendChild( itemDom );
|
|
3644
|
-
item.dom =
|
|
3712
|
+
item.dom = entry;
|
|
3645
3713
|
|
|
3646
3714
|
if( options.type == "checkbox" )
|
|
3647
3715
|
{
|
|
@@ -3753,12 +3821,17 @@ class SideBar {
|
|
|
3753
3821
|
this.content.appendChild( subentryContainer );
|
|
3754
3822
|
}
|
|
3755
3823
|
|
|
3756
|
-
for(
|
|
3824
|
+
for( let i = 0; i < item[ key ].length; ++i )
|
|
3757
3825
|
{
|
|
3758
3826
|
const subitem = item[ key ][ i ];
|
|
3759
3827
|
const suboptions = subitem.options ?? {};
|
|
3760
3828
|
const subkey = Object.keys( subitem )[ 0 ];
|
|
3761
3829
|
|
|
3830
|
+
if( this.filterString.length && !subkey.toLowerCase().includes( this.filterString.toLowerCase() ) )
|
|
3831
|
+
{
|
|
3832
|
+
continue;
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3762
3835
|
let subentry = document.createElement( 'div' );
|
|
3763
3836
|
subentry.innerHTML = `<span>${ subkey }</span>`;
|
|
3764
3837
|
|
|
@@ -5289,7 +5362,7 @@ class Panel {
|
|
|
5289
5362
|
|
|
5290
5363
|
var resolve = ( function( val, event ) {
|
|
5291
5364
|
|
|
5292
|
-
if( !widget.valid() )
|
|
5365
|
+
if( !widget.valid() || ( this._lastValueTriggered == val ) )
|
|
5293
5366
|
{
|
|
5294
5367
|
return;
|
|
5295
5368
|
}
|
|
@@ -5302,6 +5375,8 @@ class Panel {
|
|
|
5302
5375
|
this._trigger( new IEvent( name, val, event ), callback );
|
|
5303
5376
|
}
|
|
5304
5377
|
|
|
5378
|
+
this._lastValueTriggered = val;
|
|
5379
|
+
|
|
5305
5380
|
}).bind( this );
|
|
5306
5381
|
|
|
5307
5382
|
const trigger = options.trigger ?? 'default';
|
|
@@ -9567,7 +9642,7 @@ class ContextMenu {
|
|
|
9567
9642
|
}
|
|
9568
9643
|
}
|
|
9569
9644
|
|
|
9570
|
-
|
|
9645
|
+
_adjustPosition( div, margin, useAbsolute = false ) {
|
|
9571
9646
|
|
|
9572
9647
|
let rect = div.getBoundingClientRect();
|
|
9573
9648
|
|
|
@@ -9608,7 +9683,7 @@ class ContextMenu {
|
|
|
9608
9683
|
}
|
|
9609
9684
|
}
|
|
9610
9685
|
|
|
9611
|
-
|
|
9686
|
+
_createSubmenu( o, k, c, d ) {
|
|
9612
9687
|
|
|
9613
9688
|
this.root.querySelectorAll( ".lexcontextmenu" ).forEach( cm => cm.remove() );
|
|
9614
9689
|
|
|
@@ -9620,7 +9695,7 @@ class ContextMenu {
|
|
|
9620
9695
|
{
|
|
9621
9696
|
const subitem = o[ k ][ i ];
|
|
9622
9697
|
const subkey = Object.keys( subitem )[ 0 ];
|
|
9623
|
-
this.
|
|
9698
|
+
this._createEntry(subitem, subkey, contextmenu, d);
|
|
9624
9699
|
}
|
|
9625
9700
|
|
|
9626
9701
|
var rect = c.getBoundingClientRect();
|
|
@@ -9628,10 +9703,10 @@ class ContextMenu {
|
|
|
9628
9703
|
contextmenu.style.marginTop = 3.5 - c.offsetHeight + "px";
|
|
9629
9704
|
|
|
9630
9705
|
// Set final width
|
|
9631
|
-
this.
|
|
9706
|
+
this._adjustPosition( contextmenu, 6, true );
|
|
9632
9707
|
}
|
|
9633
9708
|
|
|
9634
|
-
|
|
9709
|
+
_createEntry( o, k, c, d ) {
|
|
9635
9710
|
|
|
9636
9711
|
const hasSubmenu = o[ k ].length;
|
|
9637
9712
|
let entry = document.createElement('div');
|
|
@@ -9676,7 +9751,7 @@ class ContextMenu {
|
|
|
9676
9751
|
return;
|
|
9677
9752
|
|
|
9678
9753
|
if( LX.OPEN_CONTEXTMENU_ENTRY == 'click' )
|
|
9679
|
-
this.
|
|
9754
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
9680
9755
|
});
|
|
9681
9756
|
|
|
9682
9757
|
if( !hasSubmenu )
|
|
@@ -9692,7 +9767,7 @@ class ContextMenu {
|
|
|
9692
9767
|
if(entry.built)
|
|
9693
9768
|
return;
|
|
9694
9769
|
entry.built = true;
|
|
9695
|
-
this.
|
|
9770
|
+
this._createSubmenu( o, k, entry, ++d );
|
|
9696
9771
|
e.stopPropagation();
|
|
9697
9772
|
});
|
|
9698
9773
|
}
|
|
@@ -9704,7 +9779,7 @@ class ContextMenu {
|
|
|
9704
9779
|
}
|
|
9705
9780
|
|
|
9706
9781
|
onCreate() {
|
|
9707
|
-
doAsync( () => this.
|
|
9782
|
+
doAsync( () => this._adjustPosition( this.root, 6 ) );
|
|
9708
9783
|
}
|
|
9709
9784
|
|
|
9710
9785
|
add( path, options = {} ) {
|
|
@@ -9734,13 +9809,13 @@ class ContextMenu {
|
|
|
9734
9809
|
|
|
9735
9810
|
if( found )
|
|
9736
9811
|
{
|
|
9737
|
-
insert( tokens[idx++], found );
|
|
9812
|
+
insert( tokens[ idx++ ], found );
|
|
9738
9813
|
}
|
|
9739
9814
|
else
|
|
9740
9815
|
{
|
|
9741
9816
|
let item = {};
|
|
9742
9817
|
item[ token ] = [];
|
|
9743
|
-
const nextToken = tokens[idx++];
|
|
9818
|
+
const nextToken = tokens[ idx++ ];
|
|
9744
9819
|
// Check if last token -> add callback
|
|
9745
9820
|
if( !nextToken )
|
|
9746
9821
|
{
|
|
@@ -9760,13 +9835,15 @@ class ContextMenu {
|
|
|
9760
9835
|
|
|
9761
9836
|
const setParent = _item => {
|
|
9762
9837
|
|
|
9763
|
-
let key = Object.keys(_item)[0];
|
|
9838
|
+
let key = Object.keys( _item )[ 0 ];
|
|
9764
9839
|
let children = _item[ key ];
|
|
9765
9840
|
|
|
9766
|
-
if(!children.length)
|
|
9841
|
+
if( !children.length )
|
|
9842
|
+
{
|
|
9767
9843
|
return;
|
|
9844
|
+
}
|
|
9768
9845
|
|
|
9769
|
-
if(children.find( c => Object.keys(c)[0] == key ) == null)
|
|
9846
|
+
if( children.find( c => Object.keys(c)[0] == key ) == null )
|
|
9770
9847
|
{
|
|
9771
9848
|
const parent = {};
|
|
9772
9849
|
parent[ key ] = [];
|
|
@@ -9776,14 +9853,18 @@ class ContextMenu {
|
|
|
9776
9853
|
|
|
9777
9854
|
for( var child of _item[ key ] )
|
|
9778
9855
|
{
|
|
9779
|
-
let k = Object.keys(child)[0];
|
|
9780
|
-
for( var i = 0; i < child[k].length; ++i )
|
|
9781
|
-
|
|
9856
|
+
let k = Object.keys( child )[ 0 ];
|
|
9857
|
+
for( var i = 0; i < child[ k ].length; ++i )
|
|
9858
|
+
{
|
|
9859
|
+
setParent( child );
|
|
9860
|
+
}
|
|
9782
9861
|
}
|
|
9783
9862
|
};
|
|
9784
9863
|
|
|
9785
9864
|
for( let item of this.items )
|
|
9786
|
-
|
|
9865
|
+
{
|
|
9866
|
+
setParent( item );
|
|
9867
|
+
}
|
|
9787
9868
|
|
|
9788
9869
|
// Create elements
|
|
9789
9870
|
|
|
@@ -9793,9 +9874,11 @@ class ContextMenu {
|
|
|
9793
9874
|
let pKey = "eId" + getSupportedDOMName( key );
|
|
9794
9875
|
|
|
9795
9876
|
// Item already created
|
|
9796
|
-
const id = "#" + (item.id ?? pKey);
|
|
9797
|
-
if( !this.root.querySelector(id) )
|
|
9798
|
-
|
|
9877
|
+
const id = "#" + ( item.id ?? pKey );
|
|
9878
|
+
if( !this.root.querySelector( id ) )
|
|
9879
|
+
{
|
|
9880
|
+
this._createEntry( item, key, this.root, -1 );
|
|
9881
|
+
}
|
|
9799
9882
|
}
|
|
9800
9883
|
}
|
|
9801
9884
|
|