Blog

All Blog Posts  |  Next Post  |  Previous Post

Extend TMS WEB Core with JS Libraries with Andrew:
Introduction

Tuesday, April 5, 2022

Photo of Andrew Simard
Welcome to the first post in a new series for the TMS Software Blog, "Extend TMS WEB Core with JS Libraries with Andrew ". In this ongoing series, we'll look at how to quickly and easily incorporate third-party JavaScript libraries into TMS WEB Core projects. Each week will typically focus on a particular JS library and the problem it is trying to solve.  A sample project will be included to showcase some of its key features and how they can be integrated into TMS WEB Core. And some additional commentary will offer insight as to what it is like to work with the particular JS library as most of those to be featured in this series are used regularly in my own projects. For those new to TMS WEB Core or new to JavaScript, we'll spend the rest of this first post covering the basics of what this is all about.  

TMS Software Delphi  Components


So. Many. JS Libraries.

It is quite possible to develop fantastic 100% pure JavaScript/HTML/CSS web applications using just TMS WEB Core and the included components, just as you would expect with other popular web frameworks. When it comes to extending a project with additional functionality beyond the included components, you've got options. You can of course write code yourself. You can use components from vendors like TMS Software and others that are specifically designed for TMS WEB Core. Or you can tap into the huge reservoir of both open-source and commercial JavaScript libraries. On GitHub for example there are at least several thousand such JavaScript libraries covering everything from the simplest little CSS tweaks to hugely complex and involved APIs for machine learning. 

If you've run into a problem developing your web application and need a bit of functionality that just isn't there, there's a pretty good chance someone has come along and made a JavaScript library to address it.  Here's a bit of an idea about the categories of JavaScript Libraries that are available.

  • Helpers. Provide developers with shortcuts for common tasks.  JQuery and Bootstrap fall into this category.
  • Assets. Icons, fonts, themes and so on that are likely to make a big impact on the look and feel of your web application. FontAwesome is an example. Bootstrap offers a set of icons as well.
  • Controls. Interactive UI elements that provide functionality roughly equivalent to what a Delphi component might offer. There are countless date/time pickers, for example FlatPickr.
  • Tools. Similar to Helpers, these are used to extend or otherwise enhance the component's core controls that you are already using. Interact.js adds drag+resize functionality to any element, for example.
  • Services. These include libraries for connecting to external services or communications, and libraries that help with sending e-mail and SMS messages, that sort of thing.
  • Devices. Typically these are APIs that allow for interacting with local devices or other hardware. Almost anything to do with Raspberry Pi, for example, would fall into this category.
In this series we're going to start out by focusing on those JS libraries that can help us craft better-looking and easier-to-use web applications, so typically the first four categories. While the last two categories, Services and Devices, are hugely popular and important, they're also very specific in nature.  Coverage of these would likely be far less about JavaScript and TMS Web Core and instead be focused entirely on the Service or Device in question, and thus somewhat different than what we're trying to do with this series.

Managing JavaScript Libraries.

Most often, JavaScript Libraries are added to a web application by adding entries to the <head> stanza of the main HTML page. Usually, it is just one or two lines. A reference to a JavaScript file and a corresponding CSS file in situations where there are visual elements to the library. These can be added by editing the main Project.html file directly, or by using the Manage JavaScript Libraries tool from within the Delphi IDE. TMS WEB Core v1.9.8 introduced the ability to add your own libraries to this managed list. So it can be as simple as that - select a JavaScript library from the list and you're done!

For the more adventurous, there are additional considerations. The first is about where the JavaScript library is actually hosted. When you create a TMS WEB Core project, the final output is a collection of HTML, JavaScript, and CSS files that are then uploaded to your web server. When the Project.html file is loaded into a visitor's web browser, it tells the browser where all the other JavaScript and CSS files are to be found. There are typically three places where a JavaScript library might ultimately reside, each with its own considerations.

  • CDN. A content delivery network like jsDelivr hosts many such libraries and is often the preferred choice. The main benefit is that you don't have to handle the traffic that comes from delivering the JavaScript library to the visitor's browser. For small libraries, or if you have a small number of visitors, this is likely not an issue. But if you have thousands of daily visitors and a JavaScript library that is several megabytes, it certainly can be. If your visitors are geographically spread out, the CDN may also be able to serve the content faster than you can by virtue of them having typically many more servers located strategically for explicitly this purpose.
  • JavaScript library Vendor. If the JavaScript library is popular enough (and commercially supported) the vendor may offer links to its own servers for you to use. This has many of the same benefits as a CDN. The delivery is handled by others. Some vendors may provide such functionality but may also have service limits to be aware of. Typically these are very high. Some might even require custom API keys or other means of authentication before the JS library can be used in this fashion. We'll cover more of this when we get to FontAwesome, which does all of these things.
  • Self-hosted. The JS library can also be downloaded and included directly in your project, living alongside the rest of your HTML, JavaScript, and CSS files. The very nature of the web means that if you can link to a JavaScript library at a CDN, you can also download it and include it directly in your project. This may also be needed if you're wanting to use a JavaScript library that isn't hosted by a CDN and isn't hosted by the vendor.  But there's another reason why you want to do this which we'll get to next.
Many JavaScript libraries, like most well-written software, are updated from time to time.  Due to the connected nature of web applications, many of these updates are security-related so there's a need to keep them, and the applications that rely upon them, up-to-date. You would be well-advised, particularly in the case of GitHub projects but others as well, to subscribe to notifications about the JavaScript libraries that you regularly use.  Especially if they are under active development. But like all software, any update of any kind has the potential to break functionality elsewhere in the application or introduce additional problems perhaps not foreseen by the developer of the JavaScript library. And as many Delphi developers are aware, keeping up with versions of different libraries in your projects can sometimes be a nightmare. Fortunately, here we're able to change versions often just by changing the one or two lines in our project that reference the JavaScript library. This makes it easy to upgrade or revert to an older version. But here again, we have some things to consider.

  • Either the CDN or the vendor will offer a link to the "latest" version of a JavaScript library. For non-critical web applications or those in active development, this is probably the best approach. Any updates are automatically included in your app without having to do anything at all. For JavaScript libraries that are responsibly supported, widely deployed, and that have been around for a long time, this is great. If something does break there are thousands of people that will let the developer know in short order.
  • If the developer routinely breaks things with each new build, then it may be an idea to use a specific version of a library instead, using any of the methods we've covered. CDNs and vendors typically don't take away prior versions specifically because of this. Some even offer some middle ground, like being able to have the latest updates for the current major release via the same link, but a different link when upgrading to a new major release. 
  • Finally, if your project is mission-critical, is behind a firewall, or is particularly sensitive to changes in the JavaScript libraries being used, then we're back to self-hosting the JavaScript library.  This means that you have the responsibility of updating it as well if there are security-related or other critical issues. The upside is that your application isn't going to fail due to newly introduced bugs in an obscure JavaScript library.  
One final topic about managing JS libraries: dependencies. If a JS library depends on another JS library, it will need to be added to your project as well. Most of the JavaScript libraries we're going to cover won't have any such dependencies, so this may be a non-issue for many. However, many popular JavaScript libraries do indeed have dependencies that we need to be aware of.  There are two that come up often.

  • JQuery. As a helper library, many, many other JavaScript libraries rely on its availability in their own projects.  This has become less of an issue in recent years, and many projects are actively working on removing dependencies on JQuery. 
  • Frameworks. Many JavaScript libraries are either crafted or customized for a particular JavaScript framework. In this context, by a framework, I mean the JavaScript environment that is used. React, Angular, and even TMS WEB Core are all frameworks in this context. There are many such frameworks. So if a JavaScript library has been crafted to work specifically within React, for example, that JavaScript library may not always work directly in TMS WEB Core. Often this just means there's a different version of the JavaScript library that is needed instead.

From our perspective, a dependency just means that the JavaScript library must come after whatever it is dependent on in the Project.html file. Fortunately, the Manage JavaScript Libraries tool allows you to change the order that JavaScript libraries are loaded.  So if something is dependent on JQuery, then make sure it appears after JQuery in the list. Note that it is rare, but some JavaScript libraries need to be loaded before JQuery.  Generally, this isn't something that you have to worry about too much. Put JQuery at the top and everything else follows.  If something is amiss there will likely be a console.log message about it and it won't be difficult to sort out.


It Looks the Same.

Alright. So you've got a JavaScript library loaded and.... everything looks the same? This is hopefully the case! Because you've not yet incorporated anything from the JavaScript library into the rest of your project. This is of course the topic of each of the blog posts to come: the specifics of how to use a given JavaScript library in your project. Generally speaking, this will involve one or more of the following.

  • Some JavaScript libraries just work by being present. Adding Bootstrap or FontAwesome, for example, means that you can style a TWebButton from the IDE. Adding "btn btn-primary" to its ElementClassName property, and "<i class='fas fa-flag'></i> Flag" to its caption, and a dramatically different-looking button will be the result, without having to change anything else at all.
  • A handful of components included in TMS WEB Core depend on a JavaScript library. For example, if you want to use the Ace Editor component, you'll need to be sure the relevant JavaScript library has been added. Then you can use the component as you do all the other IDE components, setting properties and so on, none the wiser that the JavaScript library is even there.
  • In order for a JavaScript library to be functional, it may need to be initialized. This is typically done through code, most often in the WebFormCreate method, inside of an "asm ... end" block 
  • Visual controls will often need to be linked to a <div> element or something similar that is included in your page. We'll cover the details separately for each JavaScript library. As an example, I'm fond of using a TWebHTMLDiv component and assigning it an ElementID property that is then passed to the JavaScript library when it is initialized.
  • Many JavaScript libraries offer the ability to customize what they do via some kind of property mechanism. This translates generally into what we're accustomed to in terms of Delphi IDE component properties. But as JavaScript doesn't have a native IDE, this is done in code and typically also done using something akin to JSON. We'll touch ever so briefly on JSON in a moment.
  • Perhaps less familiar, some properties can be passed as a JavaScript function reference or even in-line JavaScript code. So familiarity with JavaScript will be hugely beneficial for some JavaScript libraries.  


About that JS Coding. 

It is entirely possible to get functionality out of a JavaScript library without any JavaScript knowledge of any kind.  This is indeed the case with Bootstrap and FontAwesome. Other libraries may not be so kind in this regard. They are JavaScript libraries, after all, intended for use within a JavaScript environment. Of course, in TMS WEB Core, we've got the ability to directly include JavaScript by including it within "asm ... end" blocks. And this works fantastically well. But knowing what to put in those blocks is a tricky thing. So in each JavaScript library that needs it, some samples and commentary will be provided. Here, though, are a few tips for getting started with using this most powerful feature of TMS Web Core.

  1. Normally, using "asm ... end" works without the IDE complaining at all.
  2. Sometimes it helps to use "asm { ... } end" if the JavaScript code has bits that look like Delphi code that the compiler doesn't like.
  3. For the worst offenders, using "{$IFNDEF WIN32} asm { ... } end; {$ENDIF}" gives it the most separation and the IDE really won't care what you're doing. The pas2js compiler will still complain if you have egregious JavaScript errors, though.
  4. JavaScript is case-sensitive. Delphi is not case-sensitive. If you pass variables from Delphi to JavaScript, however, the Delphi declarations need to match the case of the JavaScript code in order to work properly.
  5. Many JavaScript libraries have 'callbacks' that can be used to call Delphi functions, and Delphi functions can call JavaScript functions as well. All good.
  6. Context is important. How to call a function or how to reference a variable in different scopes can be tricky.  The frequently used 'this' qualifier is anything but unambiguous.
  7. The JavaScript console is a hugely powerful tool even for debugging regular Delphi code, so do take advantage of it.


Choices. Choices. Choices.

TMS WEB Core offers tremendous flexibility when it comes to how a complete web application is crafted. The layout of the page (the actual HTML) can be generated directly from a form designed in the Delphi IDE. Or an HTML template can be used and the various fields and other elements within the template can be mapped back and forth using ElementID properties to fully separate the design and layout of the page from the logic of the application. Or a combination of both can be used. Theming (the actual CSS) can also be done either using properties in the components of the IDE or directly in CSS files, using ElementClassName and ElementID properties to provide a link between the two. Or components might just draw themselves into <canvas> elements much like they would in a VCL environment. These can all be intermixed to best suit whatever environment the developer finds themselves in.

JavaScript libraries add another dimension to all of this. They often bring along their own CSS. Sometimes they draw their own components into <canvas> tags. Sometimes they are really well-behaved and CSS can be used to override the appearance of virtually anything.  

And then ultimately the browser can come along and decide that IT wants to display an element in its own way, regardless of what anyone else might want. Mobile browsers tend to take over when displaying combo boxes for example.

All this to say that whatever you're designing, you'll need to test it in whatever environment your clients are most likely to be using. Some JavaScript libraries in fact can help facilitate a more uniform user experience across different browsers by abstracting away some of the differences between them.


It's all about JSON.

Finally, we can't talk about JavaScript libraries without at least touching upon the topic of JSON. JavaScript Object Notation. Sounds simple enough, right? I'm sure there are hundreds of books written about JSON and its many uses.  For our purposes, for now, at least, the main takeaway is that it is used heavily all over the place. From passing simple parameters to handling large datasets and everything in between. 

If you have a property that supports multiple choices, that list will most likely be formatted as some form of JSON.  When looking at the documentation for a particular JavaScript library, it is important to keep an eye out for this kind of thing. Usually, there are examples to follow and it isn't particularly difficult once you've seen it in use a few times. But it is a departure from what a Delphi developer might normally be accustomed to using. We'll be sure to cover more about JSON as it comes up in different JS libraries.


Wrap-Up.

Thanks for sticking with me this far! Next time we'll delve into one of the most popular JavaScript libraries - Bootstrap. We've got quite a number of other JavaScript libraries we're planning to cover in the coming weeks and months. Is there a JavaScript library you'd like to see covered? Tell us a bit about it and we'll consider adding it to the list. Do you have a TMS WEB Core problem that might be overcome with a JavaScript library? We'd love to hear about that as well. 


Follow Andrew on 𝕏 at @WebCoreAndMore or join our
𝕏
Web Core and More Community.


Andrew Simard




This blog post has received 8 comments.


1. Tuesday, April 5, 2022 at 2:10:37 PM

Andrew, thanks a lot for your blog post. I wait for Tabulator tips/tricks.

Borbor Mehmet Emin


2. Tuesday, April 5, 2022 at 2:51:12 PM

Ah, yes it will take a few blog posts to get through all of Tabulator. But well worth the trouble!

Simard Andrew


3. Tuesday, April 5, 2022 at 4:13:41 PM

Outstanding job - well written & easy to follow! I''m sitting on the edge of my, waiting for the next episode :)

Richard Hazell


4. Tuesday, April 5, 2022 at 8:26:53 PM

Thanks for the kind remarks! To give a bit of a taste of what is to come in the Tabulator department, here''s a little screenshot. Too many to be useful to any sane individual, but even the Widget Selector on the right is a Tabulator table. Going to be a lot of fun showing how this all works so very well..... https://www.500foods.com/screencaps/dashboard.png


Simard Andrew


5. Wednesday, April 6, 2022 at 11:07:55 AM

Maybe Leaflet is too a good coandidate. Excellent idea of blog.

Poullet Eddy


6. Wednesday, April 6, 2022 at 12:07:24 PM

Andrew, thanks a lot. Waiting for next blog post

Monterisi Stefano


7. Wednesday, April 6, 2022 at 8:12:42 PM

Just took a quick look at Leaflet. Looks good! Is this something you already use in a TMS WEB Core project? I''ll add it to the list.

Simard Andrew


8. Wednesday, April 6, 2022 at 8:33:08 PM

Just took a quick look at Leaflet. Looks good! Is this something you already use in a TMS WEB Core project? I''ll add it to the list.

Simard Andrew




Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.



All Blog Posts  |  Next Post  |  Previous Post