B4J Question [ABMATERIAL] Using collapsable containers... issue...

Cableguy

Expert
Licensed User
Hy guys,

This is a continuation from my other thread related to collapsing containers.
It seems that the state of my container is unknown or set to open, even if in the browser it appears closed. Because of this, when I press the button responsible for expanding/closing the content, it only responds from the second click onwards.

So, am I misunderstanding how these things work, or should I make a "blank" fire of this button in code when loading the page, so that the correct state is set?
 

alwaysbusy

Expert
Licensed User
I've been looking all morning into this and there are a couple of things. First and foremost: there seems to be a reported bug in jQuery on opening something for the first time that never got fixed. ABM seems to have a workaround by setting this last parameter to True (Collapsed as initial state) in cont3.InitializeCollapsable(page, "cont3", "", "", "", True).

However: this approach may not give you the desired effect you try to make. The Open/Close is not caused by pressing the button, but by clicking on the underlying collapsible header, which is a Toggle. So clicking on Button1 does open the body, but clicking on button 2 (which Triggers the toggle on the same header) closes it again.

So, collapsible containers don't seem the way to go. They where more intended to be used like a card where one could Toggle by clicking on the header to see or hide some detailed information.

I will pounder how we could make this...

Alwaysbusy
 
Upvote 0

Cableguy

Expert
Licensed User
They where more intended to be used like a card where one could Toggle by clicking on the header to see or hide some detailed information.
Hi Alain,

Iget it now... So I guess my best approach to this is to, instead of using one collapsable container inside "cont2", the best will be to add a grid to "cont2" with 1row 3cells and place a collapsable container inside each "cont2" cell, and just trash the buttons altogether... Instead, a simple label will do the trick.
What do you think?
 
Upvote 0

alwaysbusy

Expert
Licensed User
That could maybe somehow mimick a menu (each collapsable header being the part of the horizontal menu, and each body its dropdown one). The question would be, would it be possible to close one on clicking the other.

If this is what you are looking for, I may have a look if I can't make CustomComponent from something like this: https://css-tricks.com/solved-with-css-dropdown-menus/
 
Upvote 0

Cableguy

Expert
Licensed User
Again, my aim was to achieve something similar to the www.efacec.pt menu... (although I have less sub menu items)
I will live without it, and use a more "established " solution...

Thanks
 
Upvote 0

alwaysbusy

Expert
Licensed User
This is about as close as I could get to what that page shows. The trick I'm using here is using the ExtraContent from the NavigationBar, but without showing the NavigationBar (your custom floating bar is over it).


B4X:
'Class module
Sub Class_Globals
    ...    
    Dim MenuOpen(10) As Boolean    
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    ' build the local structure IMPORTANT!
    BuildPage
End Sub

' we need some transparent themes
public Sub BuildTheme()
    ' start with the base theme defined in ABMShared
    theme.Initialize("pagetheme")
    theme.AddABMTheme(Main.MyTheme)
    
    ' the navigation bar theme, transparent
    theme.AddNavigationBarTheme("fake")
    theme.NavigationBar("fake").TopBarZDepth = ABM.ZDEPTH_REMOVE
    theme.NavigationBar("fake").TopBarBackColor = ABM.COLOR_TRANSPARENT
    
    ' extra content
    theme.AddContainerTheme("transparent")
    theme.Container("transparent").BackColor = ABM.COLOR_TRANSPARENT
    
    theme.AddContainerTheme("light")
    theme.Container("light").BackColor = ABM.COLOR_TEAL
    theme.Container("light").BackColorIntensity = ABM.INTENSITY_LIGHTEN4
    
    ' add page specific theme elements
    theme.AddContainerTheme("menu")
    theme.Container("menu").BackColor = ABM.COLOR_TEAL
    theme.Container("menu").BackColorIntensity = ABM.INTENSITY_ACCENT3
   
    theme.AddLabelTheme("white")
    theme.Label("white").ForeColor = ABM.COLOR_WHITE
End Sub

public Sub BuildPage()
    ' initialize the theme
    BuildTheme
    
    ' initialize this page using our theme
    page.InitializeWithTheme(Name, "/ws/" & Main.Server.AppName & "/" & Name, False, Main.Server.SessionMaxInactiveIntervalSeconds, theme)
    
    ...                

    ' add a transparent NavigationBar
    page.NavigationBar.Initialize(page, "nav1", ABM.SIDEBAR_MANUAL_HIDEMEDIUMSMALL, "", True, True, 330, 48, Null, ABM.COLLAPSE_ACCORDION, "fake")
    ' change the height so it is the same as the Floating Container
    page.NavigationBar.TopBarHeightPx = 70
                
    ...
End Sub

public Sub ConnectPage()
    ' connecting the navigation bar
    page.NavigationBar.Clear
    
    ' Add the extra content, transparent
    page.NavigationBar.InitializeExtraContent("extracontent", True, "transparent")
    page.NavigationBar.ExtraContent.AddRowsM(1, False,0,0,"").AddCellsOS(1,0,0,1,12,12,10,"")
    page.NavigationBar.ExtraContent.BuildGrid
                
    page.NavigationBar.Refresh ' IMPORTANT
    
    ' create a floating container    
    BuildNavBar

    ' other stuff

    ' make some big text to show the floating container stays on top
    Dim biglabel As ABMLabel
    biglabel.Initialize(page, "biglabel", ABM.Util.paragraphs(5,True), ABM.SIZE_PARAGRAPH, True, "")
    biglabel.HTMLAddClass("backblack")
    page.Cell(2,1).AddComponent(biglabel)
    
    page.Refresh ' IMPORTANT!
     
    ' NEW, because we use ShowLoaderType=ABM.LOADER_TYPE_MANUAL
    page.FinishedLoading 'IMPORTANT

    ' restoring the navigation bar position
    page.RestoreNavigationBarPosition
End Sub

Sub BuildNavBar()
    Dim floatingcont1 As ABMContainer
    floatingcont1.Initialize(page, "floatingcont1", "")
    floatingcont1.AddRowsM(1,False,0,0, "").AddCellsOSMP(1,0,0,0,12,12,12,0,0,0,0,"")
    floatingcont1.BuildGrid ' IMPORTANT
    floatingcont1.SetFixedWidth("100%")
    floatingcont1.SetFixedPosition("0px","0px","0px","")
    floatingcont1.SetExtraStyle("z-index: 1000") ' IMPORTANT as it has to be OVER the normal Navigation Bar.
    page.AddFloatingContainer(floatingcont1, ABM.FLOATING_FROMTOP, "0px")
    
    ' get the floating container
    Dim floatingcont1 As ABMContainer
    floatingcont1 = page.FloatingContainer("floatingcont1")

    ' create menu container
    Dim cont2 As ABMContainer
    cont2.Initialize(page, "cont2", "menu")
    ' you have to take care yourself how it bahaves on the different devices
    cont2.AddRows(1,False,"").AddCellsOS(1,0,0,0,6,2,1,"").AddCellsOS(1,0,0,0,1,7,9,"").AddCellsOS(1,0,0,0,5,3,2,"")
    cont2.BuildGrid
   
    cont2.Cell(1,1).MarginLeft = "6px"
    cont2.Cell(1,1).Margintop = "6px"
   
    cont2.Cell(1,2).MarginLeft = "-6px"   ' to compensate for the +5px in cell 1
   
    cont2.Cell(1,3).Margintop = "10px"

    Dim img As ABMImage
    img.Initialize(page, "img", "../images/paulo.jpg",1)
    img.SetFixedSize(58,58)
    cont2.Cell(1,1).AddComponent(img)
   
    Dim lbl As ABMLabel
    lbl.Initialize(page, "lbl", "{NBSP}{I}Paulo Gomez{/I}", ABM.SIZE_H4, False, "white")
    lbl.Visibility = ABM.VISIBILITY_HIDE_ON_SMALL_ONLY ' hide the label on phones
    cont2.Cell(1,2).AddComponent(lbl)
   
    Dim HoverScript As String
   
    Dim img2 As ABMImage
    img2.Initialize(page, "img2", "../images/france_round_256.png",1)
    img2.SetFixedSize(48,48)
    img2.IsClickable = True
    cont2.Cell(1,3).AddComponent(img2)
    
    Dim img3 As ABMImage
    img3.Initialize(page, "img3", "../images/united_kingdom_round_icon_256.png",1)
    img3.SetFixedSize(48,48)
    img3.IsClickable = True
    cont2.Cell(1,3).AddComponent(img3)
   
    Dim img4 As ABMImage
    img4.Initialize(page, "img4", "../images/hungary_round_icon_256.png",1)
    img4.SetFixedSize(48,48)
    img4.IsClickable = True
    cont2.Cell(1,3).AddComponent(img4)
   
    ' add it to the floating container
    floatingcont1.Cell(1,1).AddComponent(cont2)
    
    ' top is height of floating container
    page.Cell(1,1).PaddingTop = "70px" 
    page.Refresh
    
    ' add a hover script to the 3 images
    HoverScript = $"
    $('#cont2-img2').mouseenter(function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'openmenu','eventparams':'whichmenu', 'whichmenu': 1});
    });
    $('#cont2-img3').mouseenter(function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'openmenu','eventparams':'whichmenu', 'whichmenu': 2});
    });
    $('#cont2-img4').mouseenter(function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'openmenu','eventparams':'whichmenu', 'whichmenu': 3});
    });    
    "$
    page.ws.Eval(HoverScript, Null)
    page.ws.Flush
End Sub

Sub CloseMenu() 'ignore
    page.NavigationBar.CloseExtraContent2(50)
    For i = 0 To MenuOpen.Length - 1
        MenuOpen(i) = False
    Next
End Sub

Sub OpenMenu(WhichMenu As Int) 'ignore
    page.NavigationBar.CloseExtraContent2(50)
    page.NavigationBar.ExtraContent.Row(1).RemoveAllComponents
    
    Dim menucont As ABMContainer
    menucont.Initialize(page, "menucont", "light")
    menucont.AddRows(1,False,"").AddCells12(1, "")
    menucont.BuildGrid
    
    Dim menulabel As ABMLabel
    menulabel.Initialize(page, "menulabel", ABM.Util.paragraphs(WhichMenu,True), ABM.SIZE_PARAGRAPH, True, "")
    menucont.Cell(1,1).AddComponent(menulabel)
    
    page.NavigationBar.ExtraContent.Cell(1,1).AddComponent(menucont)
    
    page.NavigationBar.ExtraContent.Refresh
    
    ' script to close the menu
    Dim Script As String = $"
    $('#extracontent').off('mouseleave').on('mouseleave', function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'closemenu','eventparams':''});       
    });
    $('#menucont-r1c1').off('mouseleave').on('mouseleave', function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'closemenu','eventparams':''});       
    });
    "$
    page.ws.Eval(Script, Null)
    page.ws.Flush
    
    page.NavigationBar.OpenExtraContent2(50)
    
    MenuOpen(WhichMenu) = True
End Sub

Sub img2_Clicked(Target As String)
    If MenuOpen(1) Then
        CloseMenu
    Else
        OpenMenu(1)
    End If    
End Sub

Sub img3_Clicked(Target As String)
    If MenuOpen(2) Then
        CloseMenu        
    Else
        OpenMenu(2)
    End If
End Sub

Sub img4_Clicked(Target As String)
    If MenuOpen(3) Then
        CloseMenu
    Else
        OpenMenu(3)
    End If
End Sub

Alwaysbusy
 
Upvote 0

Cableguy

Expert
Licensed User
This is about as close as I could get to what that page shows. The trick I'm using here is using the ExtraContent from the NavigationBar, but without showing the NavigationBar (your custom floating bar is over it).


B4X:
'Class module
Sub Class_Globals
    ...    
    Dim MenuOpen(10) As Boolean    
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    ' build the local structure IMPORTANT!
    BuildPage
End Sub

' we need some transparent themes
public Sub BuildTheme()
    ' start with the base theme defined in ABMShared
    theme.Initialize("pagetheme")
    theme.AddABMTheme(Main.MyTheme)
    
    ' the navigation bar theme, transparent
    theme.AddNavigationBarTheme("fake")
    theme.NavigationBar("fake").TopBarZDepth = ABM.ZDEPTH_REMOVE
    theme.NavigationBar("fake").TopBarBackColor = ABM.COLOR_TRANSPARENT
    
    ' extra content
    theme.AddContainerTheme("transparent")
    theme.Container("transparent").BackColor = ABM.COLOR_TRANSPARENT
    
    theme.AddContainerTheme("light")
    theme.Container("light").BackColor = ABM.COLOR_TEAL
    theme.Container("light").BackColorIntensity = ABM.INTENSITY_LIGHTEN4
    
    ' add page specific theme elements
    theme.AddContainerTheme("menu")
    theme.Container("menu").BackColor = ABM.COLOR_TEAL
    theme.Container("menu").BackColorIntensity = ABM.INTENSITY_ACCENT3
   
    theme.AddLabelTheme("white")
    theme.Label("white").ForeColor = ABM.COLOR_WHITE
End Sub

public Sub BuildPage()
    ' initialize the theme
    BuildTheme
    
    ' initialize this page using our theme
    page.InitializeWithTheme(Name, "/ws/" & Main.Server.AppName & "/" & Name, False, Main.Server.SessionMaxInactiveIntervalSeconds, theme)
    
    ...                

    ' add a transparent NavigationBar
    page.NavigationBar.Initialize(page, "nav1", ABM.SIDEBAR_MANUAL_HIDEMEDIUMSMALL, "", True, True, 330, 48, Null, ABM.COLLAPSE_ACCORDION, "fake")
    ' change the height so it is the same as the Floating Container
    page.NavigationBar.TopBarHeightPx = 70
                
    ...
End Sub

public Sub ConnectPage()
    ' connecting the navigation bar
    page.NavigationBar.Clear
    
    ' Add the extra content, transparent
    page.NavigationBar.InitializeExtraContent("extracontent", True, "transparent")
    page.NavigationBar.ExtraContent.AddRowsM(1, False,0,0,"").AddCellsOS(1,0,0,1,12,12,10,"")
    page.NavigationBar.ExtraContent.BuildGrid
                
    page.NavigationBar.Refresh ' IMPORTANT
    
    ' create a floating container    
    BuildNavBar

    ' other stuff

    ' make some big text to show the floating container stays on top
    Dim biglabel As ABMLabel
    biglabel.Initialize(page, "biglabel", ABM.Util.paragraphs(5,True), ABM.SIZE_PARAGRAPH, True, "")
    biglabel.HTMLAddClass("backblack")
    page.Cell(2,1).AddComponent(biglabel)
    
    page.Refresh ' IMPORTANT!
     
    ' NEW, because we use ShowLoaderType=ABM.LOADER_TYPE_MANUAL
    page.FinishedLoading 'IMPORTANT

    ' restoring the navigation bar position
    page.RestoreNavigationBarPosition
End Sub

Sub BuildNavBar()
    Dim floatingcont1 As ABMContainer
    floatingcont1.Initialize(page, "floatingcont1", "")
    floatingcont1.AddRowsM(1,False,0,0, "").AddCellsOSMP(1,0,0,0,12,12,12,0,0,0,0,"")
    floatingcont1.BuildGrid ' IMPORTANT
    floatingcont1.SetFixedWidth("100%")
    floatingcont1.SetFixedPosition("0px","0px","0px","")
    floatingcont1.SetExtraStyle("z-index: 1000") ' IMPORTANT as it has to be OVER the normal Navigation Bar.
    page.AddFloatingContainer(floatingcont1, ABM.FLOATING_FROMTOP, "0px")
    
    ' get the floating container
    Dim floatingcont1 As ABMContainer
    floatingcont1 = page.FloatingContainer("floatingcont1")

    ' create menu container
    Dim cont2 As ABMContainer
    cont2.Initialize(page, "cont2", "menu")
    ' you have to take care yourself how it bahaves on the different devices
    cont2.AddRows(1,False,"").AddCellsOS(1,0,0,0,6,2,1,"").AddCellsOS(1,0,0,0,1,7,9,"").AddCellsOS(1,0,0,0,5,3,2,"")
    cont2.BuildGrid
   
    cont2.Cell(1,1).MarginLeft = "6px"
    cont2.Cell(1,1).Margintop = "6px"
   
    cont2.Cell(1,2).MarginLeft = "-6px"   ' to compensate for the +5px in cell 1
   
    cont2.Cell(1,3).Margintop = "10px"

    Dim img As ABMImage
    img.Initialize(page, "img", "../images/paulo.jpg",1)
    img.SetFixedSize(58,58)
    cont2.Cell(1,1).AddComponent(img)
   
    Dim lbl As ABMLabel
    lbl.Initialize(page, "lbl", "{NBSP}{I}Paulo Gomez{/I}", ABM.SIZE_H4, False, "white")
    lbl.Visibility = ABM.VISIBILITY_HIDE_ON_SMALL_ONLY ' hide the label on phones
    cont2.Cell(1,2).AddComponent(lbl)
   
    Dim HoverScript As String
   
    Dim img2 As ABMImage
    img2.Initialize(page, "img2", "../images/france_round_256.png",1)
    img2.SetFixedSize(48,48)
    img2.IsClickable = True
    cont2.Cell(1,3).AddComponent(img2)
    
    Dim img3 As ABMImage
    img3.Initialize(page, "img3", "../images/united_kingdom_round_icon_256.png",1)
    img3.SetFixedSize(48,48)
    img3.IsClickable = True
    cont2.Cell(1,3).AddComponent(img3)
   
    Dim img4 As ABMImage
    img4.Initialize(page, "img4", "../images/hungary_round_icon_256.png",1)
    img4.SetFixedSize(48,48)
    img4.IsClickable = True
    cont2.Cell(1,3).AddComponent(img4)
   
    ' add it to the floating container
    floatingcont1.Cell(1,1).AddComponent(cont2)
    
    ' top is height of floating container
    page.Cell(1,1).PaddingTop = "70px" 
    page.Refresh
    
    ' add a hover script to the 3 images
    HoverScript = $"
    $('#cont2-img2').mouseenter(function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'openmenu','eventparams':'whichmenu', 'whichmenu': 1});
    });
    $('#cont2-img3').mouseenter(function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'openmenu','eventparams':'whichmenu', 'whichmenu': 2});
    });
    $('#cont2-img4').mouseenter(function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'openmenu','eventparams':'whichmenu', 'whichmenu': 3});
    });    
    "$
    page.ws.Eval(HoverScript, Null)
    page.ws.Flush
End Sub

Sub CloseMenu() 'ignore
    page.NavigationBar.CloseExtraContent2(50)
    For i = 0 To MenuOpen.Length - 1
        MenuOpen(i) = False
    Next
End Sub

Sub OpenMenu(WhichMenu As Int) 'ignore
    page.NavigationBar.CloseExtraContent2(50)
    page.NavigationBar.ExtraContent.Row(1).RemoveAllComponents
    
    Dim menucont As ABMContainer
    menucont.Initialize(page, "menucont", "light")
    menucont.AddRows(1,False,"").AddCells12(1, "")
    menucont.BuildGrid
    
    Dim menulabel As ABMLabel
    menulabel.Initialize(page, "menulabel", ABM.Util.paragraphs(WhichMenu,True), ABM.SIZE_PARAGRAPH, True, "")
    menucont.Cell(1,1).AddComponent(menulabel)
    
    page.NavigationBar.ExtraContent.Cell(1,1).AddComponent(menucont)
    
    page.NavigationBar.ExtraContent.Refresh
    
    ' script to close the menu
    Dim Script As String = $"
    $('#extracontent').off('mouseleave').on('mouseleave', function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'closemenu','eventparams':''});       
    });
    $('#menucont-r1c1').off('mouseleave').on('mouseleave', function() {
       b4j_raiseEvent('page_parseevent',{'eventname':'closemenu','eventparams':''});       
    });
    "$
    page.ws.Eval(Script, Null)
    page.ws.Flush
    
    page.NavigationBar.OpenExtraContent2(50)
    
    MenuOpen(WhichMenu) = True
End Sub

Sub img2_Clicked(Target As String)
    If MenuOpen(1) Then
        CloseMenu
    Else
        OpenMenu(1)
    End If    
End Sub

Sub img3_Clicked(Target As String)
    If MenuOpen(2) Then
        CloseMenu        
    Else
        OpenMenu(2)
    End If
End Sub

Sub img4_Clicked(Target As String)
    If MenuOpen(3) Then
        CloseMenu
    Else
        OpenMenu(3)
    End If
End Sub

Alwaysbusy
Awesome!!!
 
Upvote 0

Cableguy

Expert
Licensed User
Dim MenuOpen(10) As Boolean

Hi Alain, I just add a bit of time and gave your code a better look, and i have just one question.... the above declaration, the array should be equal to number of items in the menu container only or also in the "extraContent"?
 
Upvote 0
Top