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.



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



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.15 - for jServer 4.00 (open source, library only):

ALWAYS TAKE A BACKUP BEFORE USING A NEW VERSION!


ABMaterial 5.15 is now available on github and is open sourced (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.15:


ALTERNATIVE DOWNLOAD: Download the ABMMini project where everything is included (Library, www and a Template project):

Additional Resources:

Demo source code (for v4.51, not yet updated for 5.15, 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:

mwebim

New Member
Licensed User
Longtime User
Hi Alwaysbusy
This looks amazing.
I tried to run it in b4j and I get the following error. I previously upgraded java to version 8 update 66
I get it building ok but on running comes up with this error

java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: java.lang.UnsupportedClassVersionError: com/ab/abmaterial/ABMTheme : Unsupported major.minor version 52.0
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:114)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:90)
at abmaterial.ab.com.main.<clinit>(main.java:17)
Caused by: java.lang.UnsupportedClassVersionError: com/ab/abmaterial/ABMTheme : Unsupported major.minor version 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:190)
at anywheresoftware.b4a.shell.Shell.getCorrectClassName(Shell.java:485)
at anywheresoftware.b4a.shell.Shell.createObject(Shell.java:472)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:243)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:158)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
... 2 more
Exception in thread "main"


Any ideas

regards

mike
 

b4auser1

Well-Known Member
Licensed User
Longtime User
Wish: I believe that standard control to authenticate users with facebook and google accounts will be usefull to avoid own authentication in many cases.
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
Hello again!!!

How I can add items to a list at runtime and refresh the page every time ?

Right now I 'm doing with Page.Refresh after clickar on a table , element adds me on the list, but the page tables are me " rare " and stop behaving as usual. And you can not be ordered depending on the title of the column that you click , etc.

In addition are the colors of the table also changed.

Please. Look at this images:

Before refresh:


After refresh:
 

Attachments

  • BeforeRefreshPage.PNG
    13.5 KB · Views: 953
  • AfterRefreshPage.PNG
    13.1 KB · Views: 937

billyrudi

Active Member
Licensed User
Longtime User
the first question is:
if in login panel i click the buttom and i must wait a webserver to verify the username and password there is a way to lock the panel or the botton to prevent more than one click?
for the second how i can show the hourglass that you you show when navigate between pages.
 

Cableguy

Expert
Licensed User
Longtime User

About adding to the list, I can't help you there, but after you have added to the list, call "ABMShared.NavigateToPage" to reload the entire page
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
Hi alwaysbusy,
another question..
there is the way to add items to an ABMList programmatically and not in the BuildPage event?

I'm trying to do it in this way:

B4X:
Dim list1 As ABMList = page.Component("list1")

Sub tbl2_clicked(PassedRowsAndColumns As List)
    ' is the root table
    Dim tblCellInfo As ABMTableCell = PassedRowsAndColumns.Get(0)
    Dim tbl As ABMTable = page.Component(tblCellInfo.TableName)
    Dim StringSelect As String = tbl.GetString(tblCellInfo.Row, tblCellInfo.Column)
    Dim list1 As ABMList = page.Component("list1")
    list1.AddSubItem("H1", "S"&(myToastId+1), BuildSimpleItem("L1H1S"&(myToastId+1),"", StringSelect))
    list1.Refresh
    page.Refresh  

    myToastId = myToastId + 1   
    page.ShowToast("toast" & myToastId, "toastred", "Clicked " & tblCellInfo.TableName & " row " & tblCellInfo.Row & " column " & tblCellInfo.Column, 5000)
End Sub

But I've got 2 "problems":
  1. list1.refresh (apparently not work)
  2. page.refresh (works, but with the problems indicated in my previous post deforming the tables)
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
I've founded a abnormal behaviour using fixed size tables.

The footer band is putted twice:


When I click y any row and the page is refreshed, the aspect is:


And then, you can click in both rows with data...

Bye.
 

Attachments

  • Before.JPG
    22.2 KB · Views: 841
  • After.JPG
    23.5 KB · Views: 864

billyrudi

Active Member
Licensed User
Longtime User
Hi
alwaysbusy
there i a way to add to a listitem of ABMList component a tag to insert on object or srting value?
regards paolo
 

alwaysbusy

Expert
Licensed User
Longtime User
@billyrudi No, but I'll see what I can do. Making good progress on the bugs on the refresh of the table and list. There were some shortcuts I created when I started writing the framework that don't appear to work now that the framework is bigger. Quite some work to do but it looks you would not have to make any changes to your code once its done.
 

billyrudi

Active Member
Licensed User
Longtime User
hi with this code i'm able to load item perfectly.
B4X:
Private Sub WebSocket_Connected (WebSocket1 As WebSocket)
   Log("Connected")
   ws = WebSocket1   
   If ABMShared.NeedsAuthorization Then
     If ws.Session.GetAttribute2("IsAuthorized", "") = "" Then
       ABMShared.NavigateToPage(ws, "../")
       Return
     End If
   End If
   ' connect our page with the websocket   
   page.SetWebSocket(ws)
   ' Prepare the page IMPORTANT!
   page.Prepare
   CaricaGriglia
   
End Sub


Sub CaricaGriglia()
    Dim list1 As ABMList = page.Component(2,1,"list1")
    Dim ll As List
    Try
        ll = ws.Session.GetAttributesNames
    Dim ii As Int
    For ii = 0 To ll.Size -1
        Dim s As String
        s = ll.Get (ii)
        If s.StartsWith("$$") Then
            Dim lstmez As List = ws.Session.GetAttribute (s)
            Dim jj As Int
            For jj = 0 To lstmez.Size -1
                Dim sl() As String
                Dim tll As String
                tll = lstmez.Get (jj)
                sl = Regex.Split ("\|",tll)
                Dim quando As String
                quando = sl(8)
                '  20151117090830
                quando = quando.SubString2 (6 ,8) & "/" &  quando.SubString2(4,6) & "/" &  quando.SubString2(0,4)& " " & quando.SubString2(8,10) & ":" &  quando.SubString2(10,12)
                list1.AddSubItem("H1",  sl(2), BuildSimpleItem( sl(3),  "","{B}" & sl(2) & "{/B} - " & quando  & "{BR}{B}T1:{/B}" & Round2( sl(4),1) & "°C"  & " - {B}T2:{/B}:" & Round2(sl(5),1) & "°C" & " - {B}T3:{/B}:" & Round2(sl(6),1) & "°C" & " - {B}T4:{/B}:" & Round2(sl(7),1) & "°C"))
                Log(sl(2))   
            Next
           
           
        End If
    Next
        list1.Refresh
        page.Refresh

    Catch
       
        Log(LastException)
    End Try
End Sub
 

billyrudi

Active Member
Licensed User
Longtime User
Excuseme for my questions.... but working ...
there is a way to make a reverse geocoding using this instructions for example?

B4X:
function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 8,
    center: {lat: 40.731, lng: -73.997}
  });
  var geocoder = new google.maps.Geocoder;
  var infowindow = new google.maps.InfoWindow;

  document.getElementById('submit').addEventListener('click', function() {
    geocodeLatLng(geocoder, map, infowindow);
  });
}

function geocodeLatLng(geocoder, map, infowindow) {
  var input = document.getElementById('latlng').value;
  var latlngStr = input.split(',', 2);
  var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
  geocoder.geocode({'location': latlng}, function(results, status) {
    if (status === google.maps.GeocoderStatus.OK) {
      if (results[1]) {
        map.setZoom(11);
        var marker = new google.maps.Marker({
          position: latlng,
          map: map
        });
        infowindow.setContent(results[1].formatted_address);
        infowindow.open(map, marker);
      } else {
        window.alert('No results found');
      }
    } else {
      window.alert('Geocoder failed due to: ' + status);
    }
  });
}
?
 

Roberto P.

Well-Known Member
Licensed User
Longtime User
there is a problem: after some time, the application is disconnected and is no longer reachable. There is a timer that stops or after a little time?

thank you
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…