Extend TMS WEB Core with JS Libraries with Andrew: introduction

 TMS Software Delphi  Components
Welcome to the first post in a new series for the TMS 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 a lot of 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 any 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 at least several thousand such JS 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 JS library to address it.  Here’s a bit of an idea about the categories of JS Libraries that are available.

  • Helpers.  Provide developers with shortcuts for common tasks.  JQuery and Bootstrap fall in 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 comes with 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 components core controls that you are already using.  Interact.js adds drag+resize functionality to any control, 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. 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 JS 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 JS Libraries.

Most often, JS Libraries are added to a web application by adding entries to the stanza of the main HTML page.  Usually it is just one or two lines.  A reference to a JS file and a corresponding CSS file in situations where there are visual elements to the library. These can be added by editing the 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  JS library from the list and you’re done!

For the more adventurous, there are some additional considerations.  The first is about where the JS Library is actually hosted.  When you create a TMS WEB Core project, the final output is a collection of HTML, JS 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 JS and CSS files are to be found.  There are typically three places where a JS 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 JS 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 JS 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.
  • JS library Vendor.  If the JS 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, JS and CSS files.  The very nature of the web means that if you can link to a JS 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 JS 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 JS 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 JS 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 JS 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 JS 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 JS 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 JS libraries that are responsibly supported, widely deployed, and that have been around 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 JS libraries being used, then we’re back to self-hosting the JS 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 JS 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 JS libraries we’re going to cover won’t have any such dependencies, so this may be a non-issue for many.  However, many popular JS 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 JS libraries rely on its availability in their own projects.  This has become less of an issue in more recent years, and many projects are actively working on removing dependencies on JQuery. 
  • Frameworks.  Many JS libraries are either crafted or customized for a particular JS framework.  In this context, by framework I mean the JS 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 JS library has been crafted to work specifically within React, for example, that JS library may not always work directly in TMS WEB Core.  Often this just means there’s a different version of the JS library that is needed instead.

From our perspective, a dependency just means that the JS 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 JS 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 JS 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 JS library loaded and…. everything looks the same?  This is hopefully the case!  Because you’ve not yet incorporated anything from the JS 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 JS library in your project.  Generally speaking, this will involve one or more of the following.

  • Some JS libraries just work by being present.  Adding Bootstrap or FontAwesome, for example,  mean that you can style a TWebButton from the IDE.  Adding btn btn-primary to its ClassName property, and 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 JS library.  For example, if you want to use the Ace Editor component, you’ll need to be sure the relevant JS 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 JS library is even there.
  • In order for a JS library to be functional, it may need to be initialized.  This is typically done through code, most often in the WebFormCreate procedure. 
  • Visual controls will often need to be linked a
    on your page.  We’ll cover the details separately for each JS library.  As an example, I’m fond of using a TWebHJTML component and assigning it an ElementID property that is then passed to the JS library when it is initialized.
  • Many JS 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 JS 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 passed a JS function reference or even in-line JS code.  So familiarity with JavaScript will be hugely beneficial for some JS libraries.  

About that JS Coding. 

It is entirely possible to get functionality out of a JS library without any JS 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 JS libraries after all, intended for use within a JS 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 JS library that needs it, some samples and commentary will be provided.  Here though are a few tips to getting started with using this most powerful feature of TMS Web Core.

  1. Sometimes, using asm … end works without the IDE complaining at all.
  2. Sometimes it helps to use asm { … } end if the JS 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 JS 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 JS code in order to work properly.
  5. Many JS libraries have ‘callbacks’ that can be used to call Delphi functions, and Delphi functions can call JS 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 JS 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 a template can be used and the various fields and other elements 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 ClassName properties to provide a link between the two.  Or components like FNC might just draw themselves into elements much like they would in a VCL environment.  These can all be intermixed to best suit whatever environment the developer finds themselves in.

JS libraries add another dimension to all of this.  They often bring along their own CSS.  Sometimes they draw their own components into 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 would 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 JS libraries in fact can help facilitate a more uniform user experience across different browsers by abstracting away some of the differences.

It’s all about JSON.

Finally, we can’t talk about JS 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 JS 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 JS libraries – Bootstrap.  We’ve got quite a number of other JS libraries we’re planning to cover in the coming weeks and months. Is there a JS 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 JS library? We’d love to hear about that as well. 

Andrew Simard