Share My Creation [BANano] Web App library with Abstract Designer support

Discussion in 'B4J Share Your Creations' started by alwaysbusy, Jan 16, 2019.

  1. alwaysbusy

    alwaysbusy Expert Licensed User

    Download the latest version here:

    BANano is a FREE B4J library to create websites/webapps with (offline) Progressive Web App support.

    Unlike its big brother ABMaterial, BANano does not rely on any particular framework like Materialize CSS.

    Why a second framework? Well, from the start ABMaterial was build with a back server in mind. B4J has great support to setup a very powerful jServer to handle web requests. Which does mean all intelligence is at the server side and you have the full power of B4J to do whatever you want (secure database access, serial communication, cache control etc). With B4JS, some of this intelligence could be transferred to the browser side, but the app still needs internet/intranet access so this is as far as it could go.

    BANano is a different animal. It can use a Service Worker to 'install' the web app in the browser, so it can also work when the user is offline. While ABMaterial builds the page from the server side, BANano builds it from the browser side. This means EVERYTHING you write in B4J is transpiled to Javascript, HTML and CSS.


    Attached Files:

    Last edited: Feb 11, 2019
  2. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.15


    1. Support for B4J Type e.g. Type Person(Name As String, Properties As Map, Scores(10) As Int)

    2. Support for NumberFormat and NumberFormat2

    3. BANano.Sleep() is now just B4Js normal Sleep(). BANano.Sleep() will be depreciated in the future.

    4. BANano.GetType() and BANano.TypeOf are now just B4Js normal GetType(). Both BAnano functions will be depreciated in the future.

    5. BANanoSQL new method .ExecuteCallBack(). See for more info:

    6. BANanoSkeleton added SKRange, SKRadio, SKSwitch and SKNaviagationBar.
    All views now have a Visibility property.

    - contains new files. If you use it already in a project, you must copy the new files in your projects Files folder.
    - Open all your layouts and save them so the new property Visible will be saved in the layout.

    7. Bug fixes in the Transpiler


    Last edited: Jan 27, 2019
  3. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.17


    1. NEW: support for Sender. @Kiffi had the brilliant insight on how I could implement the B4J Sender keyword. This gives BANano a huge potential boost.


    Without Sender:
    Sub MultiButton_Click (event As BANanoEvent)
    Dim Ret As Long = BANano.GetSuffixFromID(event.ID)

    Dim Allviews As Map = BANano.GetAllViewsFromLayoutArray("MultiLayout", Ret)
    If Allviews <> Null Then
    Dim mButton As SKButton = Allviews.Get("multibutton"' always lowercase
               mButton.Text = "Multi Button changed!"
    End If
    End Sub
    With Sender:
    Sub MultiButton_Click (event As BANanoEvent)
    Dim MultiButton As SKButton = Sender
           MultiButton.Text = 
    "Multi Button changed!"
    End Sub
    2. Because of the new Sender keyword support, the BANanoSkeleton library has been updated:

    These events definition have changed:

    'Sub RadioTest_Change (event As BANanoEvent, radio As SKRadio)
       Sub RadioTest_Change (event As BANanoEvent)
    Dim radio As SKRadio = Sender
    'Sub SKSwitch1_Change (event As BANanoEvent, switch As SKSwitch)
       Sub SKSwitch1_Change (event As BANanoEvent)
    Dim switch As SKSwitch = Sender
    3. New BANanoObject property which allows you to get the result of a GetField() or GetMethod() call:

    Dim myArray() As Int
       myArray = bObjekt.RunMethod(
    4. For getting the Url params I made a couple of new methods:

    ' get the current url
       Dim url As String = BANano.GetCurrentUrl

    ' gets a Map with all the params
       Dim m As Map = BANano.GetURLParams(url)
    For i = 0 To m.Size - 1
    Log(m.GetKeyAt(i) & " = " & m.GetValueAt(i))

    ' get one param: if not exists return the default value
       Log(BANano.GetURLParamDefault(BANano.GetCurrentUrl, "test""Alain"))
    5 NEW method BANano.Exists(target) which returns if the target exists in the html (can be an ID, class, tag)

    6. Fixes for Transpiling a String/StringBuilder in some rare cases


    José J. Aguilar, Cableguy and Erel like this.
  4. alwaysbusy

    alwaysbusy Expert Licensed User

    joulongleu and mindful like this.
  5. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.19


    1. Fix for bug in release mode for #if CSS commenting out all generated Javascript after it.

    2. Support for #ExcludeFromLibrary. Modules having this tag set to true will not be compiled into the BANano library.

    3. Fix for bug 'OR' between two String functions:

    e.g. previously failed:

    Dim myString As String = "Foo"
    If myString.ToLowerCase.Contains("foo"Or myString.ToLowerCase.Contains("bar"Then
    End If

    4. Fix for List AddAll(), AddAllTo()

    5. BANanoObject.Initialize2() second param can now also be an Array. This makes it possible to do this:

    In Javascript:
    var myGraph = new Dygraph(div, data);
    DygraphObject.Initialize2("Dygraph"Array(div, data))
    6. Support for BANanoPromise. See this tutorial:

    7. Other Transpiler fixes

    8. Oh and I forgot: I made 3 shortcut methods on the BANanoElement:


    All three are BANanoObject methods, now also available on BANanoElement as shortcuts.

    So you can do:

    Dim UploadedFiles() As String = BANano.GetElement("#fu").GetField("files").Result
    instead of having to do (both still work):
    Dim UploadedFiles() As String = BANano.GetElement("#fu").ToObject.GetField("files").Result
    I hope this will help confused users who do not always understand when to switch from BANanoElement to BANanoObject.


    Last edited: Feb 7, 2019
    joulongleu and Kiffi like this.
  6. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.25


    1. GetViewFromLayoutArray() and GetAllViewsFromLayoutArray() has now an extra first parameter to allow adding the B4J class where the layout was loaded.

    2. New params to config the paths for a build:


    3. BANanoSkeletonCSS added some properties. You will need to copy the new Library to your Additional Libraries folder if you have already used it.
    the CSS file was also changed.

    4. New example Website with multiple pages. I made two versions, one using a Router, one without a Router.
    IMPORTANT: they need to run on a real server (or e.g. the Chrome Server plugin!)
    It is a real world example I wrote for a friend of mine who ownes a B&B.

    - multi-pages
    - multilingual supports
    - browsers Back/Forward buttons support.
    - floating navigation bar

    It is ridiculous how little programming I had to do to make his site. Finished the whole thing in a morning. :)

    Both examples are heavily commented.

    5. The following Javascript DOM objects have been wrapped:

    BANanoGeoLocation/BANanoGeoPosition (https only)

    Some are used in the examples in (4)

    6. BANanoObject has been extended with:


    7. Other transpiler fixes.


    Last edited: Feb 18, 2019
  7. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.32


    1. Two ways to handle old browsers who are not ES6 compliant (like IE 11).

    a. Using the BANano.DetectNoES6Support = true switch

    When there is no ES6 support, an event BANano_NoES6Support is raised. You can then inform the user (e.g. with an alert) that he has to upgrade her/his browser

    b. Using the BANano.ShowWarningsUnsupportedForOldBrowsers = True switch

    In this case, this is more a help for you, the developer. On compilation, you get a warning that you are using some code which will not be usable in a non ES6 browser.
    You can then change this code to something which will run.

    For example if you set this switch to true, and you use the following code:

    If BANano.CheckInternetConnectionWait Then
    Log("on line")       
    End If
    You will get a warning in the log when you compile:

    [WARNING]: The method CheckInternetConnectionWait will not work in old browser!
    I have added some polyfills for unsupported code (like the string methods .StartsWith/EndsWith and promises), but some things like async/await are just not working in a non ES6 compatible browser.
    The ...Wait() methods use async/await, so hence the above warning.

    2. Better system for updating Service Worker.

    By using the version param in BANano.Initialize better, the system got a lot smarter in knowing when it has an update:

    BANano.Initialize("BANano""ChatNoir"DateTime.Now) '<----------
    BANano.JAVASCRIPT_NAME = "app" & DateTime.Now & ".js"
    3. New method GZipGeneratedWebsite() will GZip your html/css/js/json files on compilation. You can set a minimum filesize so small files are no compressed (it may take longer to decompress such files than the actual transfer).

    4. Some warnings and optimization reminders when you are using an excessive number of CSS/Javascript files. You may not think this is important, but tests have shown your website/webapp will loose the users interest EXPONENTIALLY.
    In almost all cases, you can merge, and even omit certain files because you do not use them anywhere in your code. This is especially the case for jQuery components where plugins or even whole components are loading a lot of javascript and aren't even used in your current website.

    Just think this: your website may look great, but nobody will ever see it as they are long gone because it takes to long to load.

    Some numbers for each one-second delay in page load time:

    11% fewer page views
    16% decrease in customer satisfaction
    7% loss in conversions

    If your website is > 1MB in CSS/Javascript files alone and takes > 2.5 seconds to load, you are probably in trouble. So these are just gentle reminders you should look into this :)

    I will furter look into these and by analysing the source code in the future give you more tips and tricks to make your website the fastest it can be.

    5. Other bug fixes in the transpiler.


    Kiffi and joulongleu like this.
  8. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.33

    1. Important fix for those who use the service worker. There was a bug in the generated html file.

    2. New param BANano.MinifyOnline = true

    This will use the online API of to compress the generated javascript file (normally the app.js file).

    Minify will only do it in Release mode, not in Debug mode (to speed things up while debugging).

    And, only the BANano.Build() command will perform it, NOT the BANano.BuildAsLibrary() command. The final app using the lib will compress it anyway if it uses this parameter.


    Last edited: Mar 14, 2019
  9. alwaysbusy

    alwaysbusy Expert Licensed User

  10. alwaysbusy

    alwaysbusy Expert Licensed User

  11. alwaysbusy

    alwaysbusy Expert Licensed User

    Kiffi likes this.
  12. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.38


    1. Fix for CallInlinePHPWait which was missing the CallAjaxWait method

    2. Fix for Bit functions where the first param was ignored

    3. New BANanoURL, a wrapper around the URL object

    4. Shortcut for URL's CreateObjectURL() and RevokeObjectURL() on the BANano object

    5. New BANanoLibrary BANanoMediaRecorder which allows WebCam/Microphone/Screen recording

    see for more info:

    6. Other small transpiler fixes


  13. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.39


    1. new methods AddEventListenerOpen() and CloseEventListener on many BANano objects (they do work as a pair!)

    All the code between these two lines will be transpiled as one block. See (2) for an example.

    2. new wrapper around the XMLHttpRequest.


    Dim aEvt As Object
    Dim request As BANanoXMLHttpRequest
    "onreadystatechange", aEvt)
    If request.ReadyState = 4 Then
    If request.Status = 200 Then
               Shared.Ajaxresult = request.ResponseText
    "#r4c1""contajax", request.ResponseText)
    Log("Error loading")
    End If
    End If
    3. New method BANano.UrlBase64ToUint8Array which converts a Base64 string to a Unsigned Int array.

    4. new Value and OtherField() on the BANanoEvent object

    5. other transpiler fixes


  14. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.44


    1. new method BANano.Join(list, delimiter): Makes a new string from the list where all items are seperated by the delimiter

    2. The resulting BANanoObject from the BANanoEvent.OtherField() is now chainable

    3. Multi-line Json in the abstract designer now allowed

    4. New BANanoJSONQuery: Query your JSON data like a database.

    Tip: The query itself runs only after a method returning a normal B4J object like a Int, Map or List:

    e.g. the methods All, First, Last, Pluck, Find, Count

    Example usage:
    Sub FillExData() 'ignore
       Dim aEvt As Object
    Dim request As BANanoXMLHttpRequest
    "onreadystatechange", aEvt)
    If request.ReadyState = 4 Then
    If request.Status = 200 Then           
    ' get number of records
    ' get the movie name in the first record
    ' get the movie name in the last record
    ' group all movies by rating
               Dim ratings As Map = JQ.GroupBy("rating").All
    ' list per rating how many movies
               For Each rat As String In ratings.Keys
    Dim Lst As List = ratings.Get(rat)
    Log(rat & " = " & Lst.Size)               
    ' get new records with only the actors name and the movie rating
               Dim Lst As List = JQ.SelectFields(Array("actor""rating")).All
    ' show from the first record the actor
    ' get a subset of the records (.toJQ)
               Dim tmpJQ As BANanoJSONQuery = JQ.Where($"{'actor.$eq': 'Al Pacino', 'year.$gt': 1970 }"$) _
    $"{'rating': 8.4}"$) _
    Array("name""runtime")) _
    "{'rating': 'desc'}") _
    ' show from the subset the name of the movie with a runtime of 126 minutes (it will show the first found)
    Log("Error loading")
    End If
    End If
    End Sub
    5. New BANanoMutationObserver and BANanoMutationRecord.

    Example 1: log everything that happens in the DOM on document level
    Dim Document As BANanoObject

    Dim DocumentObserver As BANanoMutationObserver

    DocumentObserver.ChildList = 
    DocumentObserver.Attributes = 
    DocumentObserver.AttributeOldValue = 
    DocumentObserver.CharacterData = 
    DocumentObserver.CharacterDataOldValue = 
    DocumentObserver.SubTree = 

    Sub DocumentObserver_CallBack(records() As BANanoMutationRecord, observer As BANanoMutationObserver)
    End Sub
    Example 2:

    On the keyup event of a textbox, change the backcolor to red
    Observer: if the background changes, change it to green
    Dim TextBox As BANanoElement
    Dim TextBoxObserver As BANanoMutationObserver
    TextBoxObserver.Attributes = 
    True ' style is an attribute
    TextBoxObserver.AttributeOldValue = True ' and we want to log the old value too

    ' on keyup make red
    Sub SKTextBox1_KeyUp (event As BANanoEvent)
       SKTextBox1.Style = 
    $"{"background-color": "red"}"$
    End Sub

    ' observer, log the old value and change to green
    Sub TextBoxObserver_CallBack(records() As BANanoMutationRecord, observer As BANanoMutationObserver)
    Dim record As BANanoMutationRecord = records(0)
    Select Case record.TypeRecord
    Case "attributes"
    Log("Previous value: " & record.OldValue)
    Dim tmpObj As BANanoElement
               tmpObj = BANano.ToElement(record.Target)
    Log("New value: " & tmpObj.GetAttr(record.AttributeName))
               SKTextBox1.Style = 
    $"{"background-color": "green"}"$
    End Select   
    End Sub
    In the console Log:
    app.js:96 Previous value:
    102 New value: background-color: red;
    96 Previous value: background-color: red;
    102 New value: background-color: green;
    6. other transpiler fixes


  15. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano 2.46


    1. Fix for tags like <br> in Umbrella JS. See for more info:

    2. New BANanoWebSocket: WebSocket client applications use the WebSocket API to communicate with WebSocket servers using the WebSocket protocol.
    This can for example be a B4J server, but also any other server that supports WebSocket connections.

    With WebSockets you have bi-directional communication (while connected, the server can send messages to the browser).

    This example uses a normal B4J jServer. For more info on how B4J jServers work see:
    BANano code:
    Sub Process_Globals
    Private BANano As BANano 'ignore           
       ' dim our websocket
       public ws As BANanoWebSocket
    End Sub


    Sub BANano_Ready()   
    ' does the browser support websockets?
       If ws.IsSupported Then
    ' last param true = use a Reconnecting WebSocket
    End If   
    End Sub

    public Sub BrowserWriteLog(message As String)
    ' here for example we'll get the response to our question further: "Who are you?"
    End Sub

    public Sub BrowserWriteLogWithResult(message As StringAs String
    ' the server is waiting for a response....
    Return message & " OK"
    End Sub

    Sub ws_OnOpen(event As BANanoEvent)
    Log("Websocket opened")   
    End Sub

    Sub ws_OnError(event As BANanoEvent)
    Log("Websocket error")
    End Sub

    Sub ws_OnMessage(event As BANanoEvent)
    Log("Websocket message " &   
    End Sub

    Sub ws_OnClose(event As BANanoEvent)
    Log("Websocket closed")
    End Sub

    Sub SKButton1_Click (event As BANanoEvent)
    ' special Send for B4J servers
       ' Use .Send for non-B4J servers
       ws.B4JSend("AServerFunction_BAN", CreateMap("message""Who are you?"))
    End Sub
    On the server:

    You can use all the B4J WebSocket methods/properties that don't use a JQueryElement:


    Also, Future can be used.

    B4J Server code:
    'WebSocket class
    Sub Class_Globals
    Private ws As WebSocket 'ignore   
    End Sub

    Public Sub Initialize
    End Sub

    Private Sub WebSocket_Connected (WebSocket1 As WebSocket)
       ws = WebSocket1   
    End Sub

    Private Sub WebSocket_Disconnected
    End Sub

    ' a method that can be called from the browser: must end with _BAN and have only one parameter: Params as Map
    public Sub AServerFunction_BAN(Params As Map)
    ' access to the UpgradeRequest object
    ' is the connection secure?
       Log("Is secure? " & ws.Secure)
    ' is the connection open?
       Log("Is open? " & ws.Open)
    ' run a function, no return value
       ws.RunFunction("BrowserWriteLog"Array("I'm server!"))
    ' running a method in the browser and expect a return value. It must be a method in Main.
       Dim res As Future = ws.RunFunctionWithResult("BrowserWriteLogWithResult"Array("TestWithResult"))
    ' flush to browser
    ' print the return value
    ' run a piece of javascript, no result expected
       Dim script As String = $"window.alert('Hello!');"$
    ' run a piece of javascript, with a result from the browser
       ' here we ask what the users browser is
       Dim script2 As String = $" var ua= navigator.userAgent, tem,
           M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
               tem=  /\brv[ :]+(\d+)/g.exec(ua) || [];
               return 'IE '+(tem[1] || '');
           if(M[1]=== 'Chrome'){
               tem= ua.match(/\b(OPR|Edge)\/(\d+)/);
               if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
           M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
           if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
           return M.join(' ');"$

    Dim res As Future = ws.EvalWithResult(script2, Null)
    ' access to the session
    ' show an alert
       ws.Alert("Alert from the server!")
    ' also supported
    End Sub
    3. Typo caused some "Needs" to be saved in the CSS.

    4. Other small fixes.


    Kiffi and José J. Aguilar like this.
  16. alwaysbusy

    alwaysbusy Expert Licensed User

    BANano v3.09



    1. NEW: BANano .b4xlib libraries

    The big change is the introduction of being able to make and use BANano libraries in the .b4xlib format.
    This has a couple of profound advantages over normal .jar libraries for BANano:

    a. Because the libraries are compiled at the same time as the app, BANano can remove classes that are not used in the app. This works best for libraries that use Custom Views.

    E.g. suppose you made a big library with a lot of components like DatePickers, Grids, etc. If you don't use a certain component, then that code is not included in your final app. This can reduce the size of the generated app considerably.

    I think the way BANano generates a build (very modular) is now paying off big time.
    But, this really depends on how modular the library builder has written his library.

    e.g. if a class is used in a method in a module, but this method is never called in your app, all the classes (and the DependsOnAsset, see 6) will still be included.

    b. As all the assets are included in the .b4xlib, you don't have to worry about adding them in your app anymore: they are copied and included automatically. This means less clutter in your Files tab and no more .AddCSSFile or .AddJavascriptFile that are just needed for a library. You just have to worry about the assets you use in your app.

    c. No more need to make a library in two steps (BuildAsLibrary + Compile to Library)

    As a Library Builder, there is nothing special you have to do, except using:
    I've tried it on all the libs and projects I have and it looks like it works, but maybe there are still some problems in it. I had to make a lot of changes to the core of BANano to make this possible, so the chance exists.

    In short: TAKE A BACKUP! :)

    2. NEW: The generated .js files are in Build (release) modus a lot smaller (tests showed sometimes 50% smaller)

    3. CHANGE: UseServiceWorker is now by default false. You will have to set it to True if you want to use a Service worker.

    4. NEW: MinifyOnline now also minifies CSS files

    5. NEW: MergeAllCSSFiles and MergeAllJavascript files: will create one CSS and one JS file by mergin them.

    6. NEW: DependsOnAsset

    When creating e.g. a Custom View, you can set if it Depends on certain CSS, Javascript or other asset files.
    For CSS and Javascript, you must still use the AddCSSFile & AddJavascriptFile in AppStart.

    7. Because the Transpiler gets more and more options, I created a new object BANano.TranspilerOptions that hosts those options.

    The old ones are marked DEPRECIATED (they still work, but will eventually be removed). A warning is shown.

    8. NEW options: ShowWarningsDeadCode & RemoveDeadCode

    Only works in Build

    Shows a warning in the log if the transpiler suspects some code is dead (never used).
    This is handy, especially in the final stage of development to remove code (or comment out) that is never used.

    Methods with a _ in their name are always considerd to be needed.

    You can then use the RemoveDeadCode property to prevent GENERATING dead javascript code.

    9. Added the Fetch API: see


    Kiffi and José J. Aguilar like this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice