B4J Library [Web][ABMaterial] Framework for WebApps

TIP: For absolute beginners with ABM, Get started with the Mini Template
TIP: Get started with 'ABMaterial For Dummies' by Harris here! (lessons)
TIP:
My mini course on Youtube by MichalK73

ABMaterial is a framework combining a tuned Materialize CSS with the free programming tool B4J. It allows creating WebApps that not only look great thanks to Googles Material Design, but can be programmed with the powerful free tool from Anywhere Software without any knowledge of HTML, CSS or Javascript.

ABMDragonfly4.00.png


ABMaterial has over 45 themeable controls and some useful helpers.

Components:

  • ABMActionButton
  • ABMAudioPlayer (1.08)
  • ABMBadge
  • ABMButton
  • ABMCanvas
  • ABMCalendar
  • ABMCard
  • ABMChart (Plugin support 2.00)
  • ABMChat (2.50)
  • ABMCheckbox
  • ABMChronologyList (2.00)
  • ABMCombo
  • ABMCustomControl (1.05)
  • ABMChip
  • ABMCodeLabel
  • ABMDivider
  • ABMDateTimeScroller (1.06)
  • ABMDateTimePicker (1.06)
  • ABMEditor (1.07)
  • ABMFileInput (1.20+)
  • ABMGoogleMap
  • ABMLabel
  • ABMList
  • ABMImage
  • ABMImageSlider
  • ABMInputField
  • ABMRadioGroup
  • ABMPagination (1.04)
  • ABMPatternLock (1.20+)
  • ABMPDFViewer (1.08)
  • ABMPercentSlider (2.50)
  • ABMPlanner (2.50)
  • ABMPivotTable (1.08)
  • ABMRange (1.05)
  • ABMSignaturePad
  • ABMTimeLine (1.10, depreciated in 4.00)
  • ABMSlider (1.05)
  • ABMSmartWizard (3.00)
  • ABMSocialShare (1.07)
  • ABMSocialOAuth
  • ABMSVGSurface (1.20+)
  • ABMSwitch
  • ABMTabs
  • ABMTreeTable (1.04)
  • ABMUpload
  • ABMVideo

Helpers:
  • ABMContainer
  • ABMFlexWall (1.10)
  • ABMGenerator (1.07)
  • ABMModalSheet
  • ABMNavigationBar
  • ABMPage
  • ABMParallax
  • ABMSideBar (2.00)
  • ABMTable
  • ABMTableMutable (1.20+)
Other:
  • Firebase Auth (1.20+)
  • Firebase Storage (1.20+)
  • Configurable App and Content folders (2.00)
  • Lorem Ipsum Generator (2.00)
  • Grid Builder (2.00+)
The Grid Builder:
With the Grid Builder you can build the responsive framework very easy. This has been the most difficult part for beginners to understand. But now with the builder, you have no reason to not use ABMaterial :)

gridbuilder1.png


There is an online demo at http://abmaterial.com
Alternative url: http://prd.one-two.com:51042/demo/

NEW: You can now support BANano and ABMaterial here too: https://www.patreon.com/alwaysbusy


This means it is free to use, but consider this: it took me already thousands of hours to program ABMaterial, all done in my free time early in the morning and deep into the night. Not only will a donation push me to continue developing ABMaterial , remember, you'll get a warm and fuzzy feeling doing it!

Download version 5.12 - for jServer 4.00 (open source, library only):

ALWAYS TAKE A BACKUP BEFORE USING A NEW VERSION!


ABMaterial 5.12 is now available on github and is open sourced :cool: (AS IS)! This version has been in heavy use (development and production) within our company for over a year now without major alterations, so I consider it very stable and ready to be open sourced.

I trust no one here will publish a clone or take credit for my work and I would consider it common courtesy if you find a bug/fix/new feature, you report back to me so I can make the same changes in the official library and everyone can benefit from it.


Note: next to downloading the library, you need also to download the accompanying www zip files from the same github (releases) containing the latest javascript/css/font files.

The procedure from Github for 5.12:

1. Download https://github.com/RealAlwaysbusy/A...eleases/download/v5.12/ABMaterial5.12-bin.zip
2. Download https://github.com/RealAlwaysbusy/A...r4.00/releases/download/v5.12-www/www5.12.zip
3. Unzip ABMaterial5.12-bin.zip and copy all .xml and .jar files to you B4J Libraries folder
4. Unzip www5.12.zip
5. In the projects you are working on (e.g. a for Dummies project) delete the following folders in \www
  • css
  • font
  • js
6. Copy from the unzipped www5.12.zip the 3 folder (css/font/js) to the \www folder where you just deleted these 3 folders.

Additional Resources:

Demo source code (for v4.51, not yet updated for 5.12, but still usefull to learn ABM): https://gorgeousapps.com/ABMExtras4.51.zip

I hope you enjoy it as much as I did creating it and I look forward to see the killer apps you will make with ABMaterial!

Also consider BANano if you are planning to write Websites/Apps in B4J!

Alain Bailleul
Alwaysbusy's Corner
 
Last edited:

MichalK73

Well-Known Member
Licensed User
Longtime User
And it doesn't work anymore?

I once did a project for one of the companies where they added attachments to the entry. It turned out that on Android, when pressing the upload button, the camera option appeared. They calmly took photos and added themselves to the entry. And once you have the server on your disk, you can continue to manipulate the photo.

Additionally, can't you create one subpage in Banano and attach it to the ABMaterial project? Then you have full possibilities because there are many components in the camera handling JS. For example, Tailwindcss B4X has such a component.
 

JackKirk

Well-Known Member
Licensed User
Longtime User
And it doesn't work anymore?
Michail, I don't know - but this post suggests it is not viewed positively by alwaysbusy:

https://www.b4x.com/android/forum/threads/abmaterial-mashplugins.86561/post-555252

I would like to avoid all such issues.

The point I am at is, while I think I have a good grasp of B4A/i/J I have no knowledge of ABMaterial.

It looks like it would be a significant investment in time to get on top of it - time I don't want to waste if I ultimately hit this fairly obvious roadblock.

Surely an ABMCamera component is a sensible addition to the ABMaterial library?

Thanks for your interest...
 
Last edited:

Harris

Expert
Licensed User
Longtime User
Michail, I don't know - but this post suggests it is not viewed positively by alwaysbusy:

https://www.b4x.com/android/forum/threads/abmaterial-mashplugins.86561/post-555252

I would like to avoid all such issues.

The point I am at is, while I think I have a good grasp of B4A/i/J I have no knowledge of ABMaterial.

It looks like it would be a significant investment in time to get on top of it - time I don't want to waste if I ultimately hit this fairly obvious roadblock.

Surely an ABMCamera component is a sensible addition to the ABMaterial library?

Thanks for your interest...
Start with my ABM for Dummies to get a grip on ABM. The knowledge and time invested is well worth it.
I know what he will say to the ABMCamera.... Use a ABM_Custom_Component and implement your own... Not that difficult once you know how ABM works. I have made several for my needs. Post your results when done so others may benefit as well. Thanks.
 

alwaysbusy

Expert
Licensed User
Longtime User
They were mainly bug fixes and refactoring of some internal code.

B4X:
1. [CHANGE] ABM.MakeRESTApiCall now returns a RESTAPIResult instead of just the Body as String. It contains a statusCode, the Body and and 'extra' field not currently in use but may get some functionality in the future.
2. [NEW] ABM.randomId22 generates a random string with length 22. Some method we needed specificaly for a client API
3. [CHANGE] the 'fa fa-database'icon  is now loaded by default and does not be needed to be loaded manually with page.NeedsIcons.Add().
4. [NEW] some methods to encode/decode urls:
ABM.EncodeURL(String input): uses the Java URLEncoder method
ABM.DecodeURL(String input): uses the URLDecoder method
ABM.escape(String input): escapes some common characters, like \n, \t, ... -> \\n, \\t, ...
ABM.unescape(String input): unescapes some common characters, like \\n, \\t, ... -> \n, \t, ...
5 [CHANGE]: the components now expose the EventHandler
This can be used so e.g. a container that is in a class can handle events within the class instead of where the class is defined.  Needs his own ParseEvent method then in this class.

' container in some B4J class
...
cont.EventHandler = Me
...

' his own ParseEvent method to redirect the events to the correct methods within this class
public Sub ParseEvent(params As Map)
    Dim eventName As String = params.Get("eventname")
    Dim eventParams() As String = Regex.Split(",",params.Get("eventparams"))
    If eventName.ToLowerCase.StartsWith(Name.ToLowerCase) Then
        eventName = eventName.SubString(Name.Length)
    End If

    If SubExists(Me, eventName) Then
        params.Remove("eventname")
        params.Remove("eventparams")
        Select Case params.Size
            Case 0
                CallSub(Me, eventName)
            Case 1
                CallSub2(Me, eventName, params.Get(eventParams(0)))
            Case 2
                If params.get(eventParams(0)) = "abmistable" Then
                    Dim PassedTables As List = ABM.ProcessTablesFromTargetName(params.get(eventParams(1)))
                    CallSub2(Me, eventName, PassedTables)
                Else
                    CallSub3(Me, eventName, params.Get(eventParams(0)), params.Get(eventParams(1)))
                End If
            Case Else
                ' cannot be called directly, to many param
                CallSub2(Me, eventName, params)
        End Select
    End If
End Sub

6. [NEW] page.ClearAllEventHandlers
Used together with point 5.  If the page expires for some reason, the EventHandlers are all cleared so you can reinitialize them.

e.g.
Sub Page_Expired()
    Log(ABMPageId & " was expired! Reloading")
    page.ClearAllEventHandlers
    If page.ws.Open Then
        ABMShared.NavigateToPage(ws, ABMPageId, "../", False)
        page.ws.Close
    End If
End Sub

7. [NEW] ABMReportBlock.SetColumnRaw2(int index): marks a column as RAW HTML without setting the actual RAW HTML (this is what ABMReportBlock.SetColumnRaw does). Was needed for a very specific case in a report we made for a client.
8. [FIX] ABMSvgSurface: when removed, the internal JavaScript was not cleaned up.
 
Last edited:

walterf25

Expert
Licensed User
Longtime User
They were mainly bug fixes and refactoring of some internal code.

B4X:
1. [CHANGE] ABM.MakeRESTApiCall now returns a RESTAPIResult instead of just the Body as String. It contains a statusCode, the Body and and 'extra' field not currently in use but may get some functionality in the future.
2. [NEW] ABM.randomId22 generates a random string with length 22. Some method we needed specificaly for a client API
3. [CHANGE] the 'fa fa-database'icon  is now loaded by default and does not be needed to be loaded manually with page.NeedsIcons.Add().
4. [NEW] some methods to encode/decode urls:
ABM.EncodeURL(String input): uses the Java URLEncoder method
ABM.DecodeURL(String input): uses the URLDecoder method
ABM.escape(String input): escapes some common characters, like \n, \t, ... -> \\n, \\t, ...
ABM.unescape(String input): unescapes some common characters, like \\n, \\t, ... -> \n, \t, ...
5 [CHANGE]: the components now expose the EventHandler
This can be used so e.g. a container that is in a class can handle events within the class instead of where the class is defined.  Needs his own ParseEvent method then in this class.

' container in some B4J class
...
cont.EventHandler = Me
...

' his own ParseEvent method to redirect the events to the correct methods within this class
public Sub ParseEvent(params As Map)
    Dim eventName As String = params.Get("eventname")
    Dim eventParams() As String = Regex.Split(",",params.Get("eventparams"))
    If eventName.ToLowerCase.StartsWith(Name.ToLowerCase) Then
        eventName = eventName.SubString(Name.Length)
    End If

    If SubExists(Me, eventName) Then
        params.Remove("eventname")
        params.Remove("eventparams")
        Select Case params.Size
            Case 0
                CallSub(Me, eventName)
            Case 1
                CallSub2(Me, eventName, params.Get(eventParams(0)))
            Case 2
                If params.get(eventParams(0)) = "abmistable" Then
                    Dim PassedTables As List = ABM.ProcessTablesFromTargetName(params.get(eventParams(1)))
                    CallSub2(Me, eventName, PassedTables)
                Else
                    CallSub3(Me, eventName, params.Get(eventParams(0)), params.Get(eventParams(1)))
                End If
            Case Else
                ' cannot be called directly, to many param
                CallSub2(Me, eventName, params)
        End Select
    End If
End Sub

6. [NEW] page.ClearAllEventHandlers
Used together with point 5.  If the page expires for some reason, the EventHandlers are all cleared so you can reinitialize them.

e.g.
Sub Page_Expired()
    Log(ABMPageId & " was expired! Reloading")
    page.ClearAllEventHandlers
    If page.ws.Open Then
        ABMShared.NavigateToPage(ws, ABMPageId, "../", False)
        page.ws.Close
    End If
End Sub

7. [NEW] ABMReportBlock.SetColumnRaw2(int index): marks a column as RAW HTML without setting the actual RAW HTML (this is what ABMReportBlock.SetColumnRaw does). Was needed for a very specific case in a report we made for a client.
8. [FIX] ABMSvgSurface: when removed, the internal JavaScript was not cleaned up.
What is the paremeter method in the ABM.MakeRESTApiCall function, what should it be?
 

alwaysbusy

Expert
Licensed User
Longtime User
What is the paremeter method in the ABM.MakeRESTApiCall function, what should it be?
An example from my code:

B4X:
Dim jsonM as Map = CreateMap("body":"Hello there")

Dim jsonG As JSONGenerator
jsonG.Initialize(jsonM)
jsonB = jsonG.ToString
    
Dim headers As Map
headers.Initialize
headers.Put("Content-Type", "application/json")
    
Dim result As RESTAPIResult = ABM.MakeRESTApiCall("POST", "https://sync.onetwo.klanten.xxx.yyy/bouwsoft/tasks/create", jsonB, headers,200)
lblLog.Text = "Executors: " & result.body
lblLog.Refresh

The last parameter is the http status code you expect back. Normally this is 200 OK, but we had some REST API's that returned 201 OK too.
If the returned code is anything different than this code, the result.body will contain the result ErrorStream.

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
Longtime User
This is a snippet from some code in one of my apps (sometimes they have different parameters between apps). Your NavigateToPage may look different:

In this case I seem to have added an extra parameter to open it in a different tab, but did not use it (yet) at this point:
B4X:
Public Sub NavigateToPage(ws As WebSocket, PageId As String, TargetUrl As String, OpenInNewTab As Boolean)    
    If PageId.Length > 0 Then ABM.RemoveMeFromCache2(CachedPages, PageId, "manually removed from the Cache")
    
    Try
        If ws.Open Then
            ws.Eval("window.name='';window.location = arguments[0]", Array As Object(TargetUrl))
            ws.Flush
        Else
            Log("ws was closed: " & PageId & ", url: " & TargetUrl )    
        End If        
    Catch        
        Log(LastException.Message)        
    End Try        
End Sub

Alwaysbusy
 
Top