More TMS WEB Core Tips & tricks

Today we want to bring to your attention two totally different TMS WEB Core features. These little tidbits that can bring your TMS WEB Core web client application from good to great. The first is about handling application termination and the second is about getting something more out of TWebStretchPanel.

Application termination

For long, handling web application termination was simple: it was not really handled. When there was a reason to handle it server side, software developers came up with the concept of sessions. In a nutshell, when a user first requests a HTML page from the server, a session is started and typically a session timer runs. If the users requests a page update or performs another request from the user, the session timer is reset. If the user does nothing or worse, closes the browser, the server timer runs and when it reaches a predefined time, for example 20 minutes, the session is considered closed and thus stopped. We have all experienced the consequences. You decide to go and grab a cup of coffee, meet a colleague in the coffee room, have an interesting talk that of course takes longer than expected and you return to your desk, want to continue using your web application and you are greeted with a session timeout and need to login again.

In the world of modern single-page web client applications with stateless REST backend, this is a lot less likely to occur as it is way less likely to have a reason for server side session management. An easy way to look at it, is that the session state is now kept in the client and the web client application will just perform stateless HTTP(s) requests to a backend when data update or retrieval is needed.

And still, even in this much more server resource friendly scenario, developers might have a reason to know when the user closes the web application to save something client or server side. To handle this, modern browsers expose the browser window “unload” and “onbeforeunload” JavaScript event. This event is triggered when the browser window is about to be closed or the user leaves the page via navigation. Other than just handling leaving the web client application, it can also be signalled to the user and a confirmation dialog shown to ask if the user really wants to leave.

In TMS WEB Core, taking advantage of this is really simple. In your TMS WEB Core web client application, handle the main form’s OnBeforeUnload event. If you wish to show a confirmation dialog, return the confirmation message text via the parameter AMessage. Note that in Google Chrome, a confirmation message will be shown when the message is not empty but it will contain the standard Google text. For the reason, see: https://bugs.chromium.org/p/chromium/issues/detail?id=587940

Here is a code extract that shows the concept. A simple string variable will determine whether some action is needed before closing or not. This string s is empty by default but during application execution can be set (here via a button click). When this string is not empty, it is used to show a prompt when the user wants to close the application via the form.OnBeforeUnload event and in the form.Unload event it can be effectively handled to do a last action before unloading.

type
  TForm1 = class(TWebForm)
  public
    { Public declarations }
    s: string;
  end;

procedure TForm1.WebFormCreate(Sender: TObject);
begin
  s := '';
end;

procedure TForm1.WebButton1Click(Sender: TObject);
begin
  s := 'Action needed before leaving';
end;

procedure TForm1.WebFormBeforeUnload(Sender: TObject; var AMessage: string);
begin
  AMessage := s;
end;

procedure TForm1.WebFormUnload(Sender: TObject);
begin
  if (s  '') then
    DoHandleUnloadHere;
end;

The result is this dialog when we try to leave the web application either by closing the browser or navigating away from it:

Stretching the use of the TWebStretchPanel

TWebStretchPanel was designed to show a fixed UI under a piece of UI with variable height. Think of a grid, list control with unknown number of rows, image with unknown size, … TWebStretchPanel comes in handy to automatically deal with this. It is actually a HTML DIV element with two child DIV elements, one with a variable size at the top and one with a fixed size at the bottom. Obviously, as the size of the upper DIV dynamically adapts to its content, the fixed size DIV moves downward automatically. In the Delphi form designer, any control with Top coordinate set to 0 is considered part of the upper DIV, the other controls part of the lower DIV.

To demonstrate this, we have at design-time a TWebListControl with WebListControl.Top = 0 on the TWebStretchPanel and two buttons. Note that the TWebListControl.HeightStyle is set to ssAuto as we want its size to automatically adapt to the number of items it contains. We did also set the WebListControl.ElementPosition to epRelative as we expect this control to be automatically layouted by the browser in this upper DIV. Then there are two buttons of the type TWebBitBtn that are placed in the bottom part of the TWebStretchPanel. Here we set WebBitBtn.ElementPosition also to epRelative as we leave it to the browser to control the position and layout of the buttons. In the button OnClick handler we add code to add or remove items from the list:

procedure TForm1.WebButton2Click(Sender: TObject);
begin
  WebListControl1.Items.Add.Text := 'Item ' + WebListControl1.Items.Count.ToString;
end;

procedure TForm1.WebButton3Click(Sender: TObject);
var
  it: TListItem;
begin
  it := WebListControl1.Items[WebListControl1.Items.Count - 1];
  it.Free;
end;

Now, we want to introduce some extras:

Add Material icons

We add little icons from Google Material Icons to the buttons to have a visual for Add/Remove. Via the Delphi IDE project manager, choose “Manage JavaScript libraries” and add check “Material Icons”. Once checked, we can select the icon to use for the button via the WebBitBtn.MaterialGlyph property. The object inspector shows all possible material icons.


Add Bootstrap

To give the buttons some nicer style, we wish to use Bootstrap. Also via the Delphi IDE project manager, choose “Manage JavaScript libraries” and add check “Bootstrap 3.3.7”. We will use this one as it doesn’t have a dependency to jQuery like 4.3.1 has. Once we enabled Bootstrap, we can select a Bootstrap button style for the buttons by setting WebBitBtn.ElementClassName to ‘btn btn-primary’ for example.

Add custom CSS

To give the buttons in the lower part of the TWebStretchPanel a nicer layout, we’ll add some margin to the buttons, remove the focus border and make sure the buttons stay besides each other. To do this, we could have added the CSS in the project HTML file, but for clarify and to show the concept of dynamically adding CSS, it is done here in code:

procedure TForm1.WebFormCreate(Sender: TObject);
begin
  AddCSS('btnmargin','.btnmargin { margin:10px; float:left; outline:none; border:none;} .btnmargin:focus {outline: none;}');
  WebBitBtn1.ElementClassName := WebBitBtn1.ElementClassName + ' btnmargin';
  WebBitBtn2.ElementClassName := WebBitBtn2.ElementClassName + ' btnmargin';
end;

Note that we add the new introduced btnmargin CSS class to the ElementClassName as it contains already the Bootstrap class specifier.

Customize the TWebStretchPanel bottom color

Default the TWebStretchPanel are just two DIV containers within a DIV. We can access these DIV elements easily and therefore also customize these. Just to highlight one additional way TMS WEB Core web client applications can directly interact with any HTML element in the DOM, we have chosen here for educational purposes for yet another technique to set the color of the lower DIV. In the form’s OnShow event, when we are sure the HTML element is in the browser DOM, we access this DIV as the 2nd child of the TWebStretchPanel main DIV container (ElementHandle) and can directly access its style property in code:

procedure TForm1.WebFormShow(Sender: TObject);
var
  el: TJSHTMLElement;
begin
  el := TJSHTMLElement(WebStretchPanel1.ElementHandle.children.item(1));
  el.style.setProperty('background-color','silver');
end;

The result of these little customizations is:

Explorer the wonderful world of TMS WEB Core

Without a doubt, the modern browser has become extremely powerful in many ways and is almost as rich as an operating system by itself.
The possibilities of HTML/CSS are virtually unlimited for the most demanding UI needs and note that these strengths can also be applied to create installable mobile device applications (PWA) or cross-platform desktop applications via the Electron framework (or other ways we will reveal in the near future).

For Object Pascal developers, we have our beloved strongly typed and object oriented language available thanks to the pas2js compiler (with coming soon more powerful than ever Object Pascal language features) and TMS WEB Core adds RAD component based development. And finally, there is a freedom of choice what IDE to use with TMS WEB Core: Delphi, Lazarus or Visual Studio Code. Wanting to explore TMS WEB Core on your Windows, macOS or Linux machine, get the free Visual Studio Code IDE and install TMS WEB Core for Visual Studio Code for it!