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

alwaysbusy

Expert
Licensed User
Download the latest version here: https://www.b4x.com/android/forum/t...rogressive-web-app-library.99740/#post-627764

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.

 

Attachments

Last edited:

alwaysbusy

Expert
Licensed User
BANano 2.15

CHANGES:

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: https://www.b4x.com/android/forum/threads/banano-extending-event-driven-bananosql-with-own-callbacks.101920/#post-639714

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

IMPORTANT:
- BANanoSkeleton_Files.zip 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

Download: https://www.b4x.com/android/forum/t...rogressive-web-app-library.99740/#post-627764

Alwaysbusy
 
Last edited:

alwaysbusy

Expert
Licensed User
BANano 2.17

CHANGES:

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.

e.g.

Without Sender:
B4X:
   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:
B4X:
   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:

B4X:
   'Sub RadioTest_Change (event As BANanoEvent, radio As SKRadio)
   Sub RadioTest_Change (event As BANanoEvent)
       Dim radio As SKRadio = Sender
B4X:
   '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:

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

B4X:
   ' get the current url
   Dim url As String = BANano.GetCurrentUrl
   Log(url)

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

   ' 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

Download:

https://www.b4x.com/android/forum/threads/banano-progressive-web-app-library.99740/#post-627764

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
BANano 2.19

CHANGES:


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:

B4X:
   Dim myString As String = "Foo"
   If myString.ToLowerCase.Contains("foo") Or myString.ToLowerCase.Contains("bar") Then
       Log("!")
   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:
B4X:
   var myGraph = new Dygraph(div, data);
BANano:
B4X:
   DygraphObject.Initialize2("Dygraph", Array(div, data))
6. Support for BANanoPromise. See this tutorial: https://www.b4x.com/android/forum/threads/banano-working-with-promises.102413/

7. Other Transpiler fixes

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

.GetField
.SetField
.RunMethod

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

So you can do:

B4X:
Dim UploadedFiles() As String = BANano.GetElement("#fu").GetField("files").Result
instead of having to do (both still work):
B4X:
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.

Download:

https://www.b4x.com/android/forum/threads/banano-progressive-web-app-library.99740/#post-627764

Alwaysbusy
 
Last edited:

alwaysbusy

Expert
Licensed User
BANano 2.25

CHANGES:

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:

SCRIPTS_FOLDER
ASSETS_FOLDER
STYLES_FOLDER

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.

Demonstates:
- 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:

BANanoWindow
BANanoHistory
BANanoLocation
BANanoGeoLocation/BANanoGeoPosition (https only)
BANanoConsole
BANanoNavigator
BANanoScreen

Some are used in the examples in (4)

6. BANanoObject has been extended with:

AddEventListener
ClientLeft/Top/Width/Height
OffsetLeft/Top/Width/Height
ScrollLeft/Top/Width/Height

7. Other transpiler fixes.

Download: https://www.b4x.com/android/forum/threads/banano-a-sneak-peek-into-a-progressive-web-app-library.99740/#post-627764

Alwaysbusy
 
Last edited:

alwaysbusy

Expert
Licensed User
BANano 2.32

CHANGES:

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:

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

B4X:
[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:

B4X:
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.

Download: https://www.b4x.com/android/forum/t...library-with-abstract-designer-support.99740/

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
BANano 2.33

CHANGES:
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 https://javascript-minifier.com 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.

Download: https://www.b4x.com/android/forum/threads/banano-website-app-wpa-library-with-abstract-designer-support.99740/

Alwaysbusy
 
Last edited:

alwaysbusy

Expert
Licensed User
BANano 2.38

CHANGES:

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: https://www.b4x.com/android/forum/threads/banano-capture-webcam-microphone-screen.104504

6. Other small transpiler fixes

Download: https://www.b4x.com/android/forum/threads/banano-website-app-wpa-library-with-abstract-designer-support.99740/

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
BANano 2.39

CHANGES:

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.

Usage:

B4X:
Dim aEvt As Object
Dim request As BANanoXMLHttpRequest
request.Initialize
request.Open("GET", "https://reqres.in/api/users?page=1")
request.AddEventListenerOpen("onreadystatechange", aEvt)
   If request.ReadyState = 4 Then
       If request.Status = 200 Then
           Shared.Ajaxresult = request.ResponseText
           MiniCSS.Content("#r4c1", "contajax", request.ResponseText)
       Else
           Log("Error loading")
       End If
   End If
request.CloseEventListener
request.Send
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

Download: https://www.b4x.com/android/forum/t...library-with-abstract-designer-support.99740/

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
BANano 2.44

CHANGES:

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:
B4X:
Sub FillExData() 'ignore
   Dim aEvt As Object
   Dim request As BANanoXMLHttpRequest
   request.Initialize
   request.Open("GET", "assets/movies.json")
   request.AddEventListenerOpen("onreadystatechange", aEvt)
   If request.ReadyState = 4 Then
       If request.Status = 200 Then           
           JQ.Initialize2(request.ResponseText)
           ' get number of records
           Log(JQ.Count)
           ' get the movie name in the first record
           Log(JQ.First.Get("name"))
           ' get the movie name in the last record
           Log(JQ.Last.Get("name"))
           
           ' 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)               
           Next
           ' 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
           Log(JQ.SelectFields(Array("actor", "rating")).First.Get("actor"))
           
           ' get a subset of the records (.toJQ)
           Dim tmpJQ As BANanoJSONQuery = JQ.Where($"{'actor.$eq': 'Al Pacino', 'year.$gt': 1970 }"$) _
                   .OrWhere($"{'rating': 8.4}"$) _
                   .SelectFields(Array("name", "runtime")) _
                   .Order("{'rating': 'desc'}") _
                   .toJQ
           ' show from the subset the name of the movie with a runtime of 126 minutes (it will show the first found)
           Log(tmpJQ.Find("runtime", 126).Get("name"))
           
       Else
           Log("Error loading")
       End If
   End If
   request.CloseEventListener
   request.Send
End Sub
5. New BANanoMutationObserver and BANanoMutationRecord.

Example 1: log everything that happens in the DOM on document level
B4X:
Dim Document As BANanoObject
Document.Initialize("document")

Dim DocumentObserver As BANanoMutationObserver
DocumentObserver.Initialize("DocumentObserver")

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

DocumentObserver.Observe(Document)
...
Sub DocumentObserver_CallBack(records() As BANanoMutationRecord, observer As BANanoMutationObserver)
   Log(records)
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
B4X:
Dim TextBox As BANanoElement
TextBox.Initialize("#sktextbox1")
   
Dim TextBoxObserver As BANanoMutationObserver
TextBoxObserver.Initialize("TextBoxObserver")
TextBoxObserver.Attributes = True ' style is an attribute
TextBoxObserver.AttributeOldValue = True ' and we want to log the old value too
       
TextBoxObserver.Observe(TextBox.ToObject)
...

' 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:
B4X:
app.js:96 Previous value:
app.js:102 New value: background-color: red;
app.js:96 Previous value: background-color: red;
app.js:102 New value: background-color: green;
6. other transpiler fixes

Download: https://www.b4x.com/android/forum/t...library-with-abstract-designer-support.99740/

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
BANano 2.46

CHANGES:

1. Fix for tags like <br> in Umbrella JS. See for more info: https://www.b4x.com/android/forum/threads/banano-odd-br-handling.105595/

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: https://www.b4x.com/android/forum/threads/webapp-web-apps-overview.39811/
BANano code:
B4X:
Sub Process_Globals
   Private BANano As BANano 'ignore           
   ' dim our websocket
   public ws As BANanoWebSocket
End Sub

...

Sub BANano_Ready()   
   BANano.LoadLayout("#body","test")
   
   ' does the browser support websockets?
   If ws.IsSupported Then
       ' last param true = use a Reconnecting WebSocket
       ws.Initialize("ws", "ws://localhost:51042/login", "", True)
   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?"
   Log(message)
End Sub

public Sub BrowserWriteLogWithResult(message As String) As String
   ' the server is waiting for a response....
   Log(message)
   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 " & event.data)   
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:

.UpgradeRequest
.Secure
.Open
.RunFunction
.RunFunctionWithResult
.Eval
.EvalWithResult
.Flush
.Session
.Alert
.Close

Also, Future can be used.

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

Public Sub Initialize
   
End Sub

Private Sub WebSocket_Connected (WebSocket1 As WebSocket)
   Log("Connected")
   ws = WebSocket1   
End Sub

Private Sub WebSocket_Disconnected
   Log("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
   Log(ws.UpgradeRequest.FullRequestURI)
   
   ' is the connection secure?
   Log("Is secure? " & ws.Secure)
   
   ' is the connection open?
   Log("Is open? " & ws.Open)
   
   Log(Params.Get("message"))
   ' run a function, no return value
   ws.RunFunction("BrowserWriteLog", Array("I'm server!"))
   ws.Flush
   
   ' 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
   ws.Flush
   ' print the return value
   Log(res.Value)
   
   ' run a piece of javascript, no result expected
   Dim script As String = $"window.alert('Hello!');"$
   ws.Eval(script, Null)
   ws.Flush
   
   ' 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) || [];
       if(/trident/i.test(M[1])){
           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)
   ws.Flush
   Log(res.Value)
   
   ' access to the session
   Log(ws.Session.CreationTime)
   
   ' show an alert
   ws.Alert("Alert from the server!")
   
   ' also supported
   'ws.Close
End Sub
3. Typo caused some "Needs" to be saved in the CSS.

4. Other small fixes.

Download: https://www.b4x.com/android/forum/threads/banano-website-app-wpa-library-with-abstract-designer-support.99740

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
BANano v3.09

TAKE A BACKUP!

CHANGES:

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:
B4X:
BANano.BuildAsB4Xlib("1.01")
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 https://www.b4x.com/android/forum/threads/banano-the-fetch-api.106666/

Download: https://www.b4x.com/android/forum/threads/banano-website-app-wpa-library-with-abstract-designer-support.99740/#post-627764

Alwaysbusy
 

alwaysbusy

Expert
Licensed User
BANano v4.07

TAKE A BACKUP! <----

CHANGES:

1. [NEW] Besides the build-in Base64, there is an extra library based on another framework you can use in case you have problems with e.g. Chinese characters.

B4X:
Dim b64 As Base64
b64.Initialize
Log(b64.ToBase64("dankogai"))  ' ZGFua29nYWk=
Log(b64.Tobase64("小飼弾"))    ' 5bCP6aO85by+
Log(b64.ToBase64URI("小飼弾"))  ' 5bCP6aO85by-

Log(b64.FromBase64("ZGFua29nYWk="))  ' dankogai
Log(b64.FromBase64("5bCP6aO85by+"))  ' 小飼弾
Log(b64.FromBase64URI("5bCP6aO85by-"))  ' 小飼弾

Dim pngBase64 As String = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
Dim b() As Byte = b64.FromBase64Bytes(pngBase64)
' because the Log() method of B4J does not support printing a byte array
BANano.Console.Log(b)
2. [NEW] Added polyfills for the Fetch and AbortController APIs. They will be injected if you set the parameter BANano.TranspilerOptions.ShowWarningsUnsupportedForOldBrowsers = true

3. [FIX] Chained methods sometimes wrongly transpiled

4. [NEW] you are now able to use additional parameters using an Array in the WaitFor method

B4X:
BANano.WaitFor(PromiseResult, Me, "secondAsyncWait", Array(20))
Log("secondAsyncWait result:" & PromiseResult)
5. [NEW] I have added a warning in the B4J log if the method does not exist in a WaitFor call

B4X:
[WARNING]: The method WaitFor in banano_ready can not find '"DoesNotExist"'!
6. [FIX] Bad transpiling with BANano.Iif()

B4X:
Dim x As Object = Null
Dim xIsNull as Boolean = BANano.Iif(x = null, true, false) ' -> results in false because of (_x = null) instead of ==
7. [NEW] Try Catch can now also use the Javascript Finally keyword. See the example for what the difference is.

B4X:
Dim num As Int = 10
Dim divider As Int = 0
Try
   If divider = 0 Then
      BANano.Throw("You can not divide by 0!")
   Else
      Log(num/divider)
   End If  
Catch
   Log(LastException)
   ' will still do the Finally part, but not the "After the Try" log.
   Return
BANano.Finally 'ignore
   Log("Always doing this")          
End Try

Log("After the Try")
8. [NEW] Finally keyword also on Promise and Fetch

9. [CHANGE] BANanoEvent.CurrentTarget and RelatedTarget are now of the type Object

10. [CHANGE] BANanoElement.Last, First, Closest do now not return an Array anymore but directly the Element

11. [FIX] promise didn't bubble if BANano.CallBack is not called inside a sub. The

e.g.
B4X:
Private Sub Sub1() 'ignore
   Dim result, response, error as object
   Dim promise As BANanoPromise
   promise.CallSub(Me, "Sub2", Null)
   promise.Then(response)
       result = response
   promise.Else(error)
       result = error
   promise.Finally
       Log(result)
   promise.End
End Sub

'didn't work as _BANp,_B aren't passed to Sub3 as additional arguments, so calling BANano.ReturnThen() didn't work in Sub3
Private Sub Sub2()
   Sub3
End Sub

Private Sub Sub3()
   BANano.ReturnThen(True)
End Sub
12. [NEW] The Fetch API does now also have ...Wait methods like a Promise already has

B4X:
Dim fetch As BANanoFetch
Dim response As BANanoFetchResponse
Dim json As Object
fetch.Initialize("https://jsonplaceholder.typicode.com/todos/1", Null)
fetch.Then(response) ' not a wait
   Log("1")
   Return response.Json 'ignore
fetch.ThenWait(json) 'a wait
   Log("2")
   BANano.Sleep(1000)
   Log(json)
fetch.ElseWait(response) ' a wait
   Log("3")
   BANano.Sleep(1000)
   Log(response)
fetch.FinallyWait ' a wait
   Log("4")
   BANano.Sleep(1000)
   Log("Finally")
fetch.end
13. [FIX] Trasnpiler problem with BANanoElement.Last

14. [FIX] I fixed some problems where a method without parameters and written with () e.g. Initialize() was badly transpiled.
There are problably more methods that don't accept parameters where the () can give a problem. I will need to fix them as we discover them. General rule is, no params, don't use ().

15. [NEW] Support for importing an ES6 module.

IMPORTANT: Adding an ES6 module must use the BANano.Header.AddJavascriptES6File("math.js") method instead of the normal BANano.Header.AddJavascriptFile()!
This is because in Javascript a module is loaded differenly than a normal javascript file.

Content of math.js
B4X:
let sumAll = (a, b) => {return a + b;}
let subtractAll = (a, b) => {return a - b;}
let divideAll = (a, b) => {return a / b;}
let multiplyAll = (a, b) => {return a * b;}
let findModulus = (a, b) => {return a % b;}

export {sumAll, subtractAll, divideAll, multiplyAll, findModulus};
Example usage in B4J:
B4X:
Dim math As BANanoObject
Dim mathProm As BANanoPromise
mathProm = BANano.Import("math.js") ' <--- is an ES6 module
mathProm.Then(math)
   Log(math.RunMethod("sumAll", Array(5,6)))
mathProm.End
I also added a BANano.ImportWait() method, which directly returns the ES6 module as a BANanoObject.

16. [NEW] Support for nested b4xlib libraries.

IMPORTANT: There is currently a bug in B4J that prevents you to use them in Release mode. Erel has already fixed this bug and it will be possible in the next release of B4J.

17. [FIX] HandleEvents and On now converts the method parameter to lowercase

18. [NEW] The throw statement allows you to create a custom error.

Technically you can throw an exception (throw an error).

e.g.
B4X:
BANano.Throw("This number is not valid")
BANano.Throw(500)
19. [NEW] New methods on the BANano object that cover the 'Is' in B4J:

B4X:
BANano.IsBoolean(var)
BANano.IsDate(var)
BANano.IsDomelement(var)
BANano.IsFunction(var)
BANano.IsNull(var)
BANano.IsNumber(var)
BANano.IsObject(var)
BANano.IsMap(var)
BANano.IsList(var)
BANano.IsJson(var)
BANano.IsString(var)
BANano.IsUndefined(var)
BANano.IsError(var)
BANano.IsEmpty(var)
BANano.Existy(var)
BANano.IsCapitalzed(var)
BANano.IsDecimal(var)
BANano.IsInteger(var)
20. [FIX] LastMessageExeception does now not automatically append .Message (sometimes errors did not have a message and hence were not printed)

21. [NEW] BANanoObject.GetFunction and BANanoObject.Execute. Gets a function and then you can directly call the Execute method on it.

22. [REMOVED] DetectNoES6, ShowWarningsUnsupportedForOldBrowsers and the event are removed. They are replaced with a new system, see 24

23. [FIX] The callback in BANano.Window.SetTimeOut and BANano.Window.SetInterval was wrongly transpiled.

24. [NEW] new BANano controlword: BANano_OLDBROWSER

Must be used like this (the if can NOT contain extra conditions!):
B4X:
if BANano.OLDBROWSER then
   ' your old browser compatible stuff
else
   ' your ES6 stuff
end if
Example (here old browsers do not support wait methods or sleep):
B4X:
Dim promise As BANanoPromise
' the results from the promise
Dim Result As Map
Dim Error As String
                
' call the UploadAll method  
promise.CallSub(Me, "UploadAllFiles", Array(UploadedFiles))
  
If BANano.OLDBROWSER Then
      ' when it is done, we can use whatever the UploadAll has returned in its BANano.ReturnThen call
      ' we use can't use ThenWait here
      promise.Then(Result)
          ' let's show all our urls
          For i = 0 To Result.Size - 1
              Log(Result.GetKeyAt(i) & "=" & Result.GetValueAt(i))
          Next
      promise.Then(Null)
          ' now how about next we make a HTTP request after we got all files
          DoHTTP("assets/product.json")
          promise.Else(Error)
          Log("Error: " & Error)
      promise.End
Else
      ' when it is done, we can use whatever the UploadAll has returned in its BANano.ReturnThen call
      ' we use the ThenWait here because we use ...Wait functions or in this case a Sleep
      promise.ThenWait(Result)
          Log("Done, going to sleep for 2 seconds just to demonstrate ThenWait()...")
          Sleep(2000)
          Log("Printing result after 2 seconds")
          ' let's show all our urls
          For i = 0 To Result.Size - 1
              Log(Result.GetKeyAt(i) & "=" & Result.GetValueAt(i))
          Next
      promise.Then(Null)
          ' now how about next we make a HTTP request after we got all files
          DoHTTP("assets/product.json")
          promise.Else(Error)
          Log("Error: " & Error)
      promise.End
End If
a. two js files are created: one normal app.js for new browsers, one ES5_app.js for old browsers
b. In the html file, the scripts are no longer loaded with the <script> tags, but with a loadjs script. A check is done if the browser does support ES6 stuff. If it does the normal app.js is loaded, else the ES5_app.js.
c. all your own Wait methods will NOT be generated in the ES5_app.js

25. [NEW] a new polyfill was used for the Promise in old browsers which appears to be better than the old one.

26. [NEW] nested Promises are now allowed

27. [FIX] Transpiler error in GetAllResponseHeaders

28. [FIX] Consts on XMLHttpRequest: DONE, HEADERS_RECEIVED, LOADING, OPENED, UNSENT were not transpiled

30. [FIX] Transpiler error in BANanoXMLHttpRequest.SetWithCredentials()

31. [FIX] BANano.Window.RequestAnimationFrame now uses a callback syntax for its parameters. Also BANano.Window.CancelAnimationFrame was added.

32. [FIX] Datetime.DateFormat and BANano.Timeformat fix used in a condition or log()

33. [NEW] Conditional loading of assets.

Use the BANano.Header.AddCSSFileForLater, BANano.Header.AddJavascriptFileForLater and BANano.Header.AddJavascriptES6FileForLater to 'declare' which assets will be used.
Other assets like pictures, json or fonts this is not needed as they will be copied automatically if they are in the /Files folder.

* Check if bundle has already been defined
B4X:
BANano.AssetsIsDefined(bundleName as String) As Boolean
* Loads a bundle of assets and returns a promise.
If the asset is a CSS or JS file, it must have been Added with the BANano.header.Add...ForLater() methods
B4X:
' in Sub AppStart()
BANano.Header.AddCSSFileForLater("mini-nord.min.css")
...
' in Sub BANano_Ready()
Dim pathsNotFound() as String
If BANano.AssetIsDefined("Loader") = False then
   Dim prom as BANanoPromise = BANano.AssetsLoad("Loader", Array("./assets/1.jpg", "./styles/mini-nord.min.css"))
   prom.Then(Null)
       Log("Loader has been loaded!")
   prom.Else(pathsNotFound)
       Log("Doh! Loader has not been loaded completely!")
       For Each path As String In pathsNotFound
           Log(path)
       Next
   prom.End
End if
* Loads a bundle of assets and uses the BANano bundleEventName_AssetsLoaded() event
If the asset is a CSS or JS file, it must have been Added with the BANano.header.Add...ForLater() methods
The bundle name and eventName is the same.
B4X:
 ' in Sub AppStart()
 BANano.Header.AddCSSFileForLater("mini-nord.min.css")
 ...
 ' in Sub BANano_Ready()
 BANano.AssetsLoadEvent(Me, "Loader", Array("./assets/1.jpg", "./styles/mini-nord.min.css"))
 ...
 Sub loader_AssetsLoaded(pathsNotFound() As String)
   If BANano.IsNull(pathsNotFound) = False Then
       Log("Doh! Loader has not been loaded completely!")
       For Each path As String In pathsNotFound
           Log(path)
       Next
   Else
       Log("Loader has been loaded!")  
   End If
 End Sub
* Loads a bundle of assets and waits until it is loaded. Returns a String array containing the paths that failed.
If the asset is a CSS or JS file, it must have been Added with the BANano.header.Add...ForLater() methods
B4X:
 ' in Sub AppStart()
 BANano.Header.AddCSSFileForLater("mini-nord.min.css")
 ...
 ' in Sub BANano_Ready()
 Dim pathsNotFound() as String
 If BANano.AssetIsDefined("Loader") = False then
   pathsNotFound = BANano.AssetsLoadWait("Loader", Array("./assets/1.jpg", "./styles/mini-nord.min.css"))
   If BANano.IsNull(pathsNotFound) = False Then
       Log("Doh! Loader has not been loaded completely!")
       For Each path As String In pathsNotFound
           Log(path)
       Next
   Else
       Log("Loader has been loaded!")  
   End If
 end if
* Reset the dependency trackers
B4X:
BANano.AssetsReset
34. [NEW] In case CSS/JS assets are locale files in your /Files folder (not URLs), you can use the * wildcard:

e.g.

B4X:
BANano.Header.AddJavascriptFile("dayjs-locale*.js")' will load all javascript files starting with dayjs-locale
35. [NEW] Support for the Promise.All, Promise.AllSettled (only newer browsers) and Promise.Race

e.g.
B4X:
Sub BANano_Ready()
   ' All
   Dim ResultsAll() As Object  
   Dim pAll1 As BANanoPromise = 3 'ignore
   Dim pAll2 As BANanoPromise = 42 'ignore
   Dim pAll3 As BANanoPromise
   pAll3.CallSub(Me, "TheCallDelayed", Array("foo", 100, True))
  
   Dim AllProm As BANanoPromise = BANano.PromiseAll(Array(pAll1, pAll2, pAll3))
   AllProm.Then(ResultsAll)
       ' expected output: Array [3, 42, "foo"]
       Log(ResultsAll)
   AllProm.end
  
   ' AllSettled (not supported in old browsers yet!)
   Dim ResultsAllSettled() As BANanoObject
   Dim pAllSettled1 As BANanoPromise = 3 'ignore
   Dim pAllSettled2 As BANanoPromise
   pAllSettled2.CallSub(Me, "TheCallDelayed", Array(42, 100, False))
   Dim pAllSettled() As BANanoPromise = Array(pAllSettled1, pAllSettled2) 'ignore
   Dim AllSettledProm As BANanoPromise = BANano.PromiseAllSettled(pAllSettled)
   AllSettledProm.Then(ResultsAllSettled)
       ' expected output: fulfilled, rejected
       For i = 0 To ResultsAllSettled.Length - 1
           Log(ResultsAllSettled(i).GetField("status"))          
       Next
   AllSettledProm.end
  
   ' Race
   Dim ResultRace As Object
   Dim pRace1 As BANanoPromise
   pRace1.CallSub(Me, "TheCallDelayed", Array(3, 500, True))
   Dim pRace2 As BANanoPromise
   pRace2.CallSub(Me, "TheCallDelayed", Array("foo", 100, True))
   Dim RaceProm As BANanoPromise = BANano.PromiseRace(Array(pRace1, pRace2))
   RaceProm.Then(ResultRace)
       ' both resolved, but pRace2 is faster so
       ' expected output: foo
       Log(ResultRace)
   RaceProm.end
End Sub

Private Sub TheCallDelayed(ret As Object, ms As Long, DoResolve As Boolean) 'ignore
   BANano.Window.SetTimeout(BANano.CallBack(Me, "ResolveOrReject", Array(ret, DoResolve)), ms)
End Sub

private Sub ResolveOrReject(var As Object, DoResolve As Boolean) 'ignore
   If DoResolve Then
       BANano.ReturnThen(var)
   Else
       BANano.ReturnElse(var)
   End If      
End Sub
36. [NEW] New Initialize4 on BANanoObject

Can be used e.g. to connect a BANanoObject to a JavaScript object, with parameters.
This is basically the .Initialize, but with parameters. It does NOT do a New like the Initialize2 method!

37. Other minor Transpiler fixes and optimisations

Download: https://www.b4x.com/android/forum/threads/banano-website-app-wpa-library-with-abstract-designer-support.99740/#post-627764

Alwaysbusy
 
Last edited:
Top