B4J Question [BANano] [SOLVED ]How to trap the 'readychange' event of the document to get the 'readystate'?

Mashiane

Expert
Licensed User
Longtime User
Ola

I need a way to execute code during the ready change event of the document.

I have added this call in banano_ready

B4X:
Dim cb As BANanoObject = BANano.callback(Me, "readychange", Null)
    BANano.Window.GetField("document").AddEventListener("readystatechange", cb, True)

I am trapping this with

B4X:
'the state of the document is changing
Sub readychange
    Log("readystate...")
    Dim rs As String = BANano.Window.GetField("document").GetField("readyState").Result
    Log(rs)
    'read the state
End Sub

I seem to only pick a readyState of "complete" and none of these states discussed here.


I have set Network > Online > Slow Connection and none of the states are reported except complete.

Can you please advise?

Thanks

PS: I am trying to achieve the same effect discussed here, https://www.geeksforgeeks.org/how-to-show-page-loading-div-until-the-page-has-finished-loading/
 
Last edited:

alwaysbusy

Expert
Licensed User
Longtime User
The interactive state is the first one available in BANano (this is the BANano_Ready() method). At this point the core javascript/css is loaded and one can start using BANano functions (and any other Javascript library that you are using). Before that, one can only use pure Vanilla Javascript and no styles from .css files (only inline CSS from a style tag in the <head> tag)

Demo:
B4X:
Sub BANano_Ready()   
    Log(BANano.Window.GetField("document").GetField("readyState").Result) ' interactive   
    BANano.Window.GetField("document").AddEventListener("readystatechange", BANano.callback(Me, "BANano_Loaded", Null), True)
    ...

End Sub

Sub BANano_Loaded
    Log(BANano.Window.GetField("document").GetField("readyState").Result) ' complete
End Sub

What you want is the 'loading' state because you want to show something to the user while loading all your javascript/css files. However, this is a state that is never raised, and can only be queried (the onreadystatechange is ancient and is rarely used nowadays. One uses DOMContentLoaded instead) . And as said, at this point you can not use anything BANano, nor any functions or styles from the frameworks you are using (you are still loading them).

The styles we can fix using the #If CSS statements because they are written in the .html file as a <style> tag in the header.
B4X:
#if CSS
.mystyle {
   background-color: red;
}
#End If

As for the Javascript:

I've checked your VueCore demo (could not load your extensions demo) and I see why you would want such a system, although I would consider it being a bandage. Loading the core libs takes about 4 seconds (which is an eternity in Web terms), but then loading the pages takes another 10 seconds at which point you've lost about 95% of your visitors. The 10 seconds is because you preload all pages in the AddPages method. Finding a way to load only the first page, and then dynamically (buffer) loading the additional pages when the user clicks on another page could save you a lot of loading time. I would certainly have a look into that if I was you.

I can write a header option where you could append some pure javascript that uses the DOMContentLoaded event before loading any css/js. This could bridge your first 4 seconds gab to show something to the user as soon as the DOM is loaded (which is generally almost immidiately in a BANano WebApp). As for the next 10 seconds, I'm sure you can find a solution to dynamically load your pages as it would be weird if Vue didn't anticipate that. If you can solve this, then maybe an optimization cycle in the VueCore lib can also reduce the 4 seconds gab (getting it under 1 second is seen as 'acceptable' for most visitors). For example the new BANanoSkeleton library I wrote for BANano v5 (which contains about 85% of the components you have in Vue) takes 220ms to fully load.

But to temporary fix your load issue, I could add a new Property to the Header so you could do something like this in Appstart().
B4X:
BANano.Header.OnDOMContentLoaded=$"console.log("DOM ready!");document.getElementById("body").innerHTML+="loading...";"$

Alwaysbusy
 
Upvote 0

Mashiane

Expert
Licensed User
Longtime User
Phew... you are a star! Thanks a lot for the clarity and also for what you will implement with DOMContentLoaded , I'm soooooo glad I asked.

Thank you also for your interest in VueCore, your critical eye on the project and valuable advise is very much appreciated.

In my plans is to add routers for page management to take advantage of that space. To inject HTML like how its done now will be "optional". Secondly is the issue of components, which will ensure that an app is broken down into smaller parts for consolidation, just like how VueJS works.

Truth be told, wrapping VueJS with BANano is rather abnormal because VueJS is on the same league as React and Angular and other re-active frameworks out there. I know that the performance gains on just doing pure VueJS via the nodejs CLI are far more better, but then again, I enjoy BANano-ing stuff around and also learn how stuff work, besides BANAnoVue... is not pure Vue, we all know this and we can never expect the same performance from a "hybrid". :D Unless of course your wizardly could prove me wrong. Ha ha ha.

You know what, i've been staring at your "import" method and thought to myself. Vue in most cases works with imports for as and when you need components loaded. Just like...

B4X:
import BaseInput from './BaseInput.vue'

Still mind boggling...

Ta!
 
Upvote 0
Top