Banano one step ahead

How interested are you in developing WebApps?

  • Not at all

    Votes: 0 0.0%
  • Little

    Votes: 0 0.0%
  • Lot

    Votes: 0 0.0%
  • I am interested in additional libraries

    Votes: 0 0.0%
  • I would pay for new libraries

    Votes: 0 0.0%
  • I would donate a kidney to learn more

    Votes: 1 50.0%
  • What is banano?

    Votes: 1 50.0%

  • Total voters
    2

Star-Dust

Expert
Licensed User
Longtime User
I would title this post like this: I was on the edge of the precipice now I've taken a step forward

Premise

I have recently worked with WebApps, customers prefer them and above all the stores (Apple and mostly Google) are making life difficult for developers.
For a few years I have been using Banano (by @alwaysbusy ) with Vuetify (by @Mashiane ). The last project was large and took too long to compile. Once the project was finished I thought I'd take a step forward.

Questions
I asked myself why I have always used Banano with Vuetify (excellent library) and never without, perhaps using skeleton. Would he have been as attractive? It certainly would have been much lighter
I downloaded and studied some examples and the result seemed satisfactory to me. But it was missing some fancier components that I find with Vuetify.
What if I had created them myself? I downloaded other examples and read some tutorials.
I tried other frameworks (Alpine.JS, Bootstrap, svelte ...) creating test components.

One step forward
In the end I concluded that I didn't need frameworks to manage data, rotation, etc.. but only graphics... which you can get with CSS or other free js sources you find around...
I decided to create my own Banano library with the views I need and which is light.
In fact I went from 5/7 minutes of compilation to less than 40 seconds.... I have to add many components, little by little I will get there

The result? Here is a small example ... A WebApp for pizza delivery

1731865483713.png


1731865492368.png
 

Mashiane

Expert
Licensed User
Longtime User
In the end I concluded that I didn't need frameworks to manage data, rotation, etc..
Awesome news. Glad you worked something out. I love the UI, amazing work, congrats, and thanks for this feedback.

One of the best thing you can always do for your app is tree-shaking it with remove dead code transpiler options before production in BANano. With BVAD3, because its a VueJS based library unlike Skeleton or any simple library, this can only be done via the BVAD3 Package Manager. That is what I've used with client apps to speed them up as this ensures that only the components used in your app are available and not the whole b4xlib.

BVAD4 is coming in 2025 using Vue3 which will have a lot of improvements and whilst BANano was never built around VueJS, it has been kicking a punch, thanks to Alain.

I am still interested though, whether when it comes to more speed, what is much better between writing code or use layouts for the UI.

Enjoy!
 

Star-Dust

Expert
Licensed User
Longtime User
Project progress (or Working Progress)

There is still a lot of work to be done on the classes and graphics, but something is starting to show

 

alwaysbusy

Expert
Licensed User
Longtime User
In the end I concluded that I didn't need frameworks to manage data, rotation, etc.. but only graphics... which you can get with CSS or other free js sources you find around...
I 100% agree and in many of our projects we also move away from standard UI frameworks and just write the extra CSS/BANano code for components specific for that project.

And your WebApp looks great!
 

Star-Dust

Expert
Licensed User
Longtime User
To give a small example of how you can easily build a component, I will show you My Numeric Stepper.
You see in the image the result and also how it looks in the design, a single object.
Below you will find the code. Obviously this is just one of the components I'm creating. I hope it is useful for others to create components on their own

1731949500908.png


B4X:
#Event: Click (event As BANanoEvent)

#DesignerProperty: Key: Value, DisplayName: Start value, FieldType: Int, DefaultValue: 0, Description: Starter value
#DesignerProperty: Key: minValue, DisplayName: Min value, FieldType: Int, DefaultValue: 0, Description: Minimum value
#DesignerProperty: Key: maxValue, DisplayName: Max value, FieldType: Int, DefaultValue: 10, Description: Maximum value
#DesignerProperty: Key: TextColor, DisplayName: Number Color, FieldType: Color, DefaultValue: 0xFF000000, Description: Text Color
#DesignerProperty: Key: Background, DisplayName: Background Color, FieldType: Color, DefaultValue: 0x00FFFFFF, Description: Background Color
#DesignerProperty: Key: btnTextColor, DisplayName: Button text Color, FieldType: Color, DefaultValue: 0xFFFFFFFF, Description: Button Text Color
#DesignerProperty: Key: btnBackground, DisplayName: Button Background Color, FieldType: Color, DefaultValue: 0xFFA52A2A, Description: Button  Background Color
#DesignerProperty: Key: Classes, DisplayName: Classes, FieldType: String, DefaultValue: sd-stepper, Description: Classes added to the HTML tag.
#DesignerProperty: Key: Style, DisplayName: Style, FieldType: String, DefaultValue: , Description: Styles added to the HTML tag. Must be a json String.
#DesignerProperty: Key: MarginLeft, DisplayName: Margin Left, FieldType: String, DefaultValue: , Description: Margin Left
#DesignerProperty: Key: MarginRight, DisplayName: Margin Right, FieldType: String, DefaultValue: , Description: Margin Right
#DesignerProperty: Key: MarginTop, DisplayName: Margin Top, FieldType: String, DefaultValue: , Description: Margin Top
#DesignerProperty: Key: MarginBottom, DisplayName: Margin Bottom, FieldType: String, DefaultValue: , Description: Margin Bottom
#DesignerProperty: Key: PaddingLeft, DisplayName: Padding Left, FieldType: String, DefaultValue: , Description: Padding Left
#DesignerProperty: Key: PaddingRight, DisplayName: Padding Right, FieldType: String, DefaultValue: , Description: Padding Right
#DesignerProperty: Key: PaddingTop, DisplayName: Padding Top, FieldType: String, DefaultValue: , Description: Padding Top
#DesignerProperty: Key: PaddingBottom, DisplayName: Padding Bottom, FieldType: String, DefaultValue: , Description: Padding Bottom
#DesignerProperty: Key: Enabled, DisplayName: Enabled, FieldType: Boolean, DefaultValue: True, Description: If enabled.
#DesignerProperty: Key: Visible, DisplayName: Visible, FieldType: Boolean, DefaultValue: True, Description: If visible.
#DesignerProperty: Key: Type, DisplayName: Type, FieldType: String, DefaultValue: p, List: p|div|span|h1|h2|h3|h4|h5|h6, Description: Type of label
#DesignerProperty: Key: StringWithListExample, DisplayName: String With List, FieldType: String, DefaultValue: Sunday, List: Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday

Sub Class_Globals
    Private BANano As BANano 'ignore
    Private mName As String 'ignore
    Private mEventName As String 'ignore
    Private mCallBack As Object 'ignore
    Private mTarget As BANanoElement 'ignore
    Private mElement As BANanoElement 'ignore
    Private btnMeno As BANanoElement 'ignore
    Private btnPiu As BANanoElement 'ignore
    
    Private mValue As String = ""
    Private minValue As Int = 0
    Private maxValue As Int = 10
    Private mTextColor As String = ""
    Private mBackground As String = ""
    Private mbtnTextColor As String = ""
    Private mbtnBackground As String = ""
    Private mClasses As String = ""
    Private mStyle As String = ""
    Private mMarginLeft As String = ""
    Private mMarginRight As String = ""
    Private mMarginTop As String = ""
    Private mMarginBottom As String = ""
    Private mPaddingLeft As String = ""
    Private mPaddingRight As String = ""
    Private mPaddingTop As String = ""
    Private mPaddingBottom As String = ""
    Private mVisible As Boolean = True
    Private mEnabled As Boolean = True
    Private mType As String = "p"
    
    Private mTag As Object
End Sub

' initializes the component
Public Sub Initialize (CallBack As Object, Name As String, EventName As String)
    mName = Name
    mEventName = EventName.ToLowerCase
    mCallBack = CallBack
End Sub

' returns the BANanoElement
public Sub getElement() As BANanoElement
    Return mElement
End Sub

' returns the tag id
public Sub getID() As String
    Return mName
End Sub

' this is the place where you create the view in html and run initialize javascript
Public Sub DesignerCreateView (Target As BANanoElement, Props As Map)
    mTarget = Target

    If Props <> Null Then
        mValue = Props.Get("Value")
        minValue = 1 * Props.Get("minValue")
        maxValue = 1 * Props.Get("maxValue")
        mTextColor = Props.Get("TextColor")
        mBackground = Props.Get("Background")
        mbtnTextColor = Props.Get("btnTextColor")
        mbtnBackground = Props.Get("btnBackground")
        mClasses = Props.Get("Classes")
        mStyle = Props.Get("Style")
        mMarginLeft = Props.Get("MarginLeft")
        mMarginRight = Props.Get("MarginRight")
        mMarginTop = Props.Get("MarginTop")
        mMarginBottom = Props.Get("MarginBottom")
        mPaddingLeft = Props.Get("PaddingLeft")
        mPaddingRight = Props.Get("PaddingRight")
        mPaddingTop = Props.Get("PaddingTop")
        mPaddingBottom = Props.Get("PaddingBottom")
        mVisible = Props.Get("Visible")
        mEnabled = Props.Get("Enabled")
        mType = Props.Get("Type")
    End If
    
    Dim exStyle As String = BuildExStyle
    
    mElement = mTarget.Append($"<div id="div${mName}" class="sd-label" style="width: 100%; ${exStyle}${mStyle}">
        <div style="width: 33%; height: 50px; text-align: center; line-height: 50px; ">
            <button id="meno-${mName}" Type="button" class="${mClasses}" style="border-radius: 50%;padding: 10px 15px;">-</button>
        </div>
        <div style="width: 33%; height: 50px; text-align: center; line-height: 50px; ">
            <${mType} id="${mName}">${mValue}</${mType}>
        </div>
        <div style="width: 33%; height: 50px; text-align: center; line-height: 50px; ">
            <button id="plus-${mName}" Type="button" class="${mClasses}" style="border-radius: 50%;padding: 10px 15px;">+</button>
        </div>
    </div>"$)
                
    btnMeno = mElement.Get($"#meno-${mName}"$)
    btnPiu = mElement.Get($"#plus-${mName}"$)
    btnMeno.HandleEvents("click", Me, "meno_click")
    btnPiu.HandleEvents("click", Me, "piu_click")
    
    setBackgroundColor(mBackground)
    setTextColor(mTextColor)
    setbtnBackgroundColor(mbtnBackground)
    setbtnTextColor(mbtnTextColor)
End Sub

' add the component to a parent tag
public Sub AddToParent(targetID As String)
    mTarget = BANano.GetElement("#" & targetID.ToLowerCase)
    DesignerCreateView(mTarget, Null)
End Sub

' removes the component from the parent tag
public Sub Remove()
    mTarget.Empty
    BANano.SetMeToNull
End Sub

#Region common shared properties and methods
' trigger an event
public Sub Trigger(event As String, params() As String)
    If mElement <> Null Then
        mElement.Trigger(event, params)
    End If
End Sub

' internal method to build the style
public Sub BuildExStyle() As String
    Dim sb As StringBuilder
    sb.Initialize
    If mMarginLeft <> "" Then sb.Append("margin-left: " & mMarginLeft & ";")
    If mMarginRight <> "" Then sb.Append("margin-right: " & mMarginRight & ";")
    If mMarginTop <> "" Then sb.Append("margin-top: " & mMarginTop & ";")
    If mMarginBottom <> "" Then sb.Append("margin-bottom: " & mMarginBottom & ";")
    If mPaddingLeft <> "" Then sb.Append("padding-left: " & mPaddingLeft & ";")
    If mPaddingRight <> "" Then sb.Append("padding-right: " & mPaddingRight & ";")
    If mPaddingTop <> "" Then sb.Append("padding-top: " & mPaddingTop & ";")
    If mPaddingBottom <> "" Then sb.Append("padding-bottom: " & mPaddingBottom & ";")
    Return sb.ToString
End Sub

' set css classes to the main tag
public Sub setClasses(Classes As String)
    If mElement <> Null Then
        mElement.AddClass(Classes)
    End If
    mClasses = Classes
End Sub

public Sub getClasses() As String
    Return mClasses
End Sub

' get/set the style of the main tag
public Sub setStyle(Style As String)
    Dim tmpStyle As String = Style
    If tmpStyle.StartsWith("{") = False Then
        Dim spl() As String = BANano.Split(";", Style)
        Dim m As Map
        m.Initialize
        For i = 0 To spl.Length - 1
            Dim spl2() As String = BANano.Split(":", spl(0))
            Dim key As String = spl2(0).Replace(Chr(34), "").trim
            Dim val As String = spl2(1).Replace(Chr(34), "").trim
            m.Put(key, val)
        Next
        Dim jsonG As BANanoJSONGenerator
        jsonG.Initialize(m)
        tmpStyle = jsonG.ToString
    End If
    If mElement <> Null Then
        mElement.SetStyle(Style)
    End If
    mStyle = Style
End Sub

public Sub getStyle() As String
    Return mStyle
End Sub

' get/set if the component is visible
public Sub setVisible(Visible As Boolean)
    If mElement <> Null Then
        If Visible Then
            mElement.RemoveClass("u-hide")
        Else
            mElement.AddClass("u-hide")
        End If
    End If
    mVisible=Visible
End Sub

public Sub getVisible() As Boolean
    mVisible = Not(mElement.HasClass("u-hide"))
    Return mVisible
End Sub

' get/set if the component is enabled
public Sub setEnabled(Enabled As Boolean)
    If mElement <> Null Then
        If Enabled Then
            mElement.RemoveAttr("disabled")
        Else
            mElement.SetAttr("disabled", True)
        End If
    End If
    mEnabled = Enabled
End Sub

public Sub getEnabled() As Boolean
    mEnabled = Not(mElement.hasAttr("disabled"))
    Return mEnabled
End Sub

' get/set the margin left of the main tag
public Sub setMarginLeft(mar As String)
    mMarginLeft = mar
End Sub

public Sub getMarginLeft() As String
    Return mMarginLeft
End Sub

' get/set the margin right of the main tag
public Sub setMarginRight(mar As String)
    mMarginRight = mar
End Sub

public Sub getMarginRight() As String
    Return mMarginRight
End Sub

' get/set the margin top of the main tag
public Sub setMarginTop(mar As String)
    mMarginTop = mar
End Sub

public Sub getMarginTop() As String
    Return mMarginTop
End Sub

' get/set the margin bottom of the main tag
public Sub setMarginBottom(mar As String)
    mMarginBottom = mar
End Sub

public Sub getMarginBottom() As String
    Return mMarginBottom
End Sub

' get/set the Padding left of the main tag
public Sub setPaddingLeft(pad As String)
    mPaddingLeft = pad
End Sub

public Sub getPaddingLeft() As String
    Return mPaddingLeft
End Sub

' get/set the Padding right of the main tag
public Sub setPaddingRight(pad As String)
    mPaddingRight = pad
End Sub

public Sub getPaddingRight() As String
    Return mPaddingRight
End Sub

' get/set the Padding top of the main tag
public Sub setPaddingTop(pad As String)
    mPaddingTop = pad
End Sub

public Sub getPaddingTop() As String
    Return mPaddingTop
End Sub

' get/set the Padding bottom of the main tag
public Sub setPaddingBottom(pad As String)
    mPaddingBottom = pad
End Sub

public Sub getPaddingBottom() As String
    Return mPaddingBottom
End Sub

' get/set attach any object to the component
public Sub setTag(t As Object)
    mTag = t
End Sub

public Sub getTag() As Object
    Return mTag
End Sub

public Sub setValue(t As String)
    If BANano.IsNumber(t) Then
        mValue = t
        Dim be As BANanoElement = BANano.GetElement("#" & mName)
        be.SetText(t)
    End If
End Sub

public Sub getValue() As String
    Return mValue
End Sub

Public Sub setBackgroundColor(Color As String)
    mBackground=Color
    BANano.GetElement("#" & mName).SetStyle($"{"background-color":"${Color}"}"$)
    BANano.GetElement("#div" & mName).SetStyle($"{"background-color":"${Color}"}"$)
End Sub

Public Sub getBackgroundColor As String
    Return mBackground
End Sub

Public Sub setTextColor(Color As String)
    mTextColor=Color
    Dim be As BANanoElement = BANano.GetElement("#" & mName)
    be.SetStyle($"{"color":"${Color}"}"$)
End Sub

Public Sub getTextgroundColor As String
    Return mTextColor
End Sub

Public Sub setbtnBackgroundColor(Color As String)
    mbtnBackground=Color
    btnMeno.SetStyle($"{"background-color":"${Color}"}"$)
    btnPiu.SetStyle($"{"background-color":"${Color}"}"$)
End Sub

Public Sub getbtnBackgroundColor As String
    Return mbtnBackground
End Sub

Public Sub setbtnTextColor(Color As String)
    mbtnTextColor=Color
    btnMeno.SetStyle($"{"color":"plus-${Color}"}"$)
    btnPiu.SetStyle($"{"color":"meno-${Color}"}"$)
End Sub

Public Sub getbtnTextgroundColor As String
    Return mbtnTextColor
End Sub

#End Region

#Region Internal Events

Private Sub meno_click
    mValue=Max(mValue-1,minValue)
    Dim be As BANanoElement = BANano.GetElement("#" & mName)
    be.SetText(mValue)
End Sub

private Sub piu_click
    mValue=Min(mValue+1,maxValue)
    Dim be As BANanoElement = BANano.GetElement("#" & mName)
    be.SetText(mValue)
End Sub

#End Region



#IF CSS
 /* -----------------------------  Stili per label */
    .sd-label {
      background-color: white;
      border: none;
      color: black;
      padding: 15px 32px;
      text-align: center;
      text-decoration: none;
      display: inline-flex; /* Utilizzo di flexbox per l'allineamento */
      justify-content: center; /* Centra il testo orizzontalmente */
      align-items: center; /* Centra il testo verticalmente */
      font-size: 16px;
      border-radius: 8px; /* Angoli arrotondati */
      cursor: pointer;
      transition: background-color 0.3s ease, transform 0.2s ease;
    }

    /* Effetto di focus (quando il bottone è selezionato) */
    .sd-label:focus {
      outline: none;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    }

 /* -----------------------------  Stili per stepper */
    .sd-stepper {
      background-color: #AAAAAA; /* Colore di sfondo grigio */
      border: none;
      color: white;
      padding: 15px 32px;
      text-align: center;
      text-decoration: none;
      display: inline-flex; /* Utilizzo di flexbox per l'allineamento */
      justify-content: center; /* Centra il testo orizzontalmente */
      align-items: center; /* Centra il testo verticalmente */
      font-size: 18px;
      border-radius: 10px; /* Angoli arrotondati */
      cursor: pointer;
      transition: background-color 0.3s ease, transform 0.2s ease;
    }

    /* Effetto hover */
    .sd-stepper:hover {
      background-color: #FF45A049; /* Colore di sfondo quando si passa sopra */
      color: black;
      transform: scale(1.1); /* Aumento dimensione al passaggio del mouse */
    }

    /* Effetto di focus (quando il bottone è selezionato) */
    .sd-stepper:focus {
      outline: none;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    }
#End If
 

Star-Dust

Expert
Licensed User
Longtime User
Interesting, mind to share...
Using SKColumn on some components did not respect the width, even if set to 1/12 it always went full screen. after days I realized it was the DIV. So I created my own Column and will also create my own Rows
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
I'm sure you will create very nice components for BANano, your creativity is incredible.
Thanks, but they don't believe they have creativity, the b4x tool makes it very easy to create views and components
 

rabbitBUSH

Well-Known Member
Licensed User
until I understood some of the problems generated by DIVs
such is life - as is said in france i believe.
i've struggled with all these ABMs and BANANOs and whatnot . . . . .myself.....Oi!
 
Top