Project

General

Profile

Recommended approach to initialise a custom js library

Added by Dries Mys 4 months ago

What is the recommended approach to initialize a custom library once for each Wt::WApplication instance?

E.g.

class MyClass : public Wt::WContainerWidget
{
public:
  MyClass ()
  {
    require("myLibrary.js");

    doJavascript("initLibrary();"); // should be called once per Wapplication, not every time a MyClass object is created
  }
}

Sub questions:

  • Is it better to call wApp->doJavascript("initLibrary();"); to perform a global initialization or WWidget::doJavascript("initLibrary();");. Are WApplication::doJavascript js calls being executed before or after WWidget::doJavascript? Or is the execution order of the js code undefined?
  • Wt often uses WApplication::loadJavaScript instead of WApplication::require to load js library. Should we use that approach too? Advantage is that WApplication has a javaScriptLoaded which is f.ex. used by WTextEdit::initTinyMCE to perform the initialization only once for all WTextEdit's of the same application, but a similar function doesn't exist to check whether the library is already loaded using require.

Replies (3)

RE: Recommended approach to initialise a custom js library - Added by Matthias Van Ceulebroeck 2 months ago

Hello Dries,

I apologize for the delayed reply, I have been very busy, and I am going through my backlog now.

So, require is better used to add libraries that are required to make the application function, those will be added to a script tag, at the top of your DOM tree.
When you use loadJavaScript, this JS will be added to the JS preamble, which is executed just before the doJavaScript calls, but after the require scripts have been added.

Although there is no real convention, I would approach it like this:

  • use require if and only if the library is required everywhere, and makes the site function (like e.g. jQuery, Angular, Vue, ...), this indicates that it is a "framework"
  • use loadJavaScript for all other libraries (e.g. a library only necessary for certain pages). These libraries can then be indeed added to the widget that contains the functionality, so it isn't always loaded (and would take up resources)

A doJavaScript can then be called to initialize the library. If it is a require library, this can be done in the application constructor (or whatever function performs the first load), if it is a loadJavaScript, it can be called whenever the library is necessary (so often close to the loadJavaScript).

Now, to ensure that it is only called once, I suppose a very simple approach would be something like:

doJavaScript("if (window.isMyLibraryInitialised !== true) { initLibrary(); window.isMyLibraryInitialised = true; };");

Does that answer the question?

Best,
Matthias

RE: Recommended approach to initialise a custom js library - Added by Dries Mys 2 months ago

Dear Matthias,

Thanks for the clear information.

If loadJavascript is the/your preferred approach in certain cases, why isn't it documented?

In WApplication.h, it is stated that this function is for internal use only. The type of the second argument, i.e. WJavaScriptPreamble, seems to be an internal type too (in case of WT_DEBUG_JS is undefined).

Kind regards,
Dries

RE: Recommended approach to initialise a custom js library - Added by Matthias Van Ceulebroeck about 2 months ago

Hello Dries,

I do apologize, I always use Wt builds with nearly all possible flags, and debugging enabled. I sometimes forget what is public API and what is not. You can omit my remark about loadJavaScript. require is what we offer publicly, and functions as I said above.

Wt indeed uses loadJavaScript often, due to subtle difference in the way this works. This doesn't produce a script in the DOM, but allows the JS to be added to the response Wt server hands to the client. This enforces that the JS is only added once, and ensures that it is added right before the widgets can be used.

The remainder of my response is still valid. To recap:

  • use require to include the right JS file
  • call doJavaScript("if (window.isMyLibraryInitialised !== true) { initLibrary(); window.isMyLibraryInitialised = true; };"); to initialise the library.

Best,
Matthias

    (1-3/3)