The front-end API is all the facilities that run on the browser.
This includes HTML, CSS, JavaScript, image files, etc. The Kiss
back-end does not produce or modify HTML or JavaScript code. These
files are served, unaltered, by the server as they are on the back-end
disk. The Kiss
model is that the browser receives these files
from the server, and that they include all the code that the browser
needs to perform its function. Besides these static files, all data
is communicated between the back-end and front-end via REST services.
Having all of the display logic running on the front-end or user’s browser makes a lot of sense for the following reasons:
All of this leads to the following:
The front-end API is documented in the file manual/jsdoc/index.html
.
On the front-end, the class Server
is what deals with the REST
communications between the front-end and back-end. In it, there are a
handful of methods that deal with the environment, such as the back-end
URL. All communications between the back-end and front-end are done
with JSON.
The way it works is the login service requires a username and password, and it returns a login token (UUID). That token is used in all future calls, and it gets automatically invalidated after a certain amount of non-use time. There is no state kept on the back-end. Each REST call must login to the back-end with the provided token in order to be authenticated to communicate.
The method used to communicate is named Server.call()
. It is passed the
path to the REST service, the REST service method name, and a JSON
object that is sent to the back-end method. A Promise
is
returned that is used to obtain the result of the call. This
can also be used with async/await
.
There is also a logout
method that simply erases the
login token so that future communications cannot occur.
The Server
class also includes a method (fileUploadSend
)
that makes it easy to upload files.
Although HTML provides what is needed for real applications, it provides those facilities at too low a level to be useful without a lot of custom code. Custom components (tags) allow you to encapsulate that advanced behavior into what is used as and appears as native functionality.
Kiss provides the ability to create your own custom HTML tags
or elements as well as use those provided by Kiss. There are
two principal user methods that make this work.
Utils.useComponent
is used to load either a Kiss defined
component or one you define yourself (there is no difference). This
loads the JavaScript file that defines the new tag. All of the
components that come with the Kiss system are under the
src/main/frontend/kiss/component
directory. You can see those
files for examples of how custom tags are defined.
New application pages are loaded with the Utils.loadPage
method. In addition to loading the HTML and JavaScript code
associated with that page, this method performs the processing
necessary to make the components work. It does this intelligently so
that, for example, one component can use another component without any
special loading order requirement.
Briefly, the code that describes the custom tag must describe what the tag is replaced with. Ultimately, it must boil down to straight HTML, CSS, and JavaScript code.
Let’s say you have a pop-up window that allows a user to search for employees, products, or whatever. The user gets a variety of search capabilities and the selected item is returned. Let’s further say that you need this functionality in several places within your application. These are tagless components. They aren’t placed with a custom tag. They are a response to an event like a button push. Tagless components allow you to encapsulate a block of functionality (including pop-up windows) into a neat package that can be reused in any number of places.
The method used to load tagless components is
Utils.useTaglessComponent
. Later, when the tagless component
is needed, one would execute Kiss.MyComponent.run(in_data, on_exit)
(where
MyComponent
is the name of your tagless component).
in_data
represents possible data passed to the component on entry.
on_exit
is a function that gets executed when the component exits.
Arguments passed to on_exit
are determined by the component.
Kiss supports draggable, modal popup windows. HTML is used to describe the layout of the popup, and JavaScript is used to control the appearance of the popup.
The HTML portion is represented as a top-level popup
tag
that represents the entire popup. Within the top-level popup
there must be two child tags named popup-title
and
popup-body
. The first represents the single line header, and
the second represents the body of the popup window.
The top-level popup
tag’s attribute section must contain the following:
id="my-popup"
an ID is needed to reference the popup
width="600px" height="300px"
Set the height and width of the popup
An example is as follows:
<popup id="my-popup" width="600px" height="300px"> <popup-title>The title</popup-title> <popup-body> The content <div style="display: inline-block; position: absolute; bottom: 20px; right: 20px;"> <push-button id="cancel" style="margin-left: 15px;">Cancel</push-button> <push-button id="ok" style="margin-left: 15px;">Ok</push-button> </div> </popup-body> </popup>
There are only two JavaScript functions used to control the popup.
Utils.popup_open(id [, focus-id])
open the popup indicated by the id
, and if focus-id
is present, set initial focus to that control
Utils.popup_close()
close the most recent popup
Your defined responses to the buttons on the popup determine your dealings with the data on the popup and when to close it.
Kiss includes facilities that make it easy to upload a file or multiple files. The way to use it is as follows:
The HTML would contain two controls: a file input and a button. The file input looks as follows:
<file-upload id="the-file">Upload File</file-upload>
The button is just a standard Kiss button. In this example, its ID is “upload”.
The file input control allows the user to select the file or files to
be uploaded. If multiple files are to be allowed the multiple
attribute should be added to the HTML.
The button is used to activate the upload process. Your code that sends the file(s) to the server should be attached to this button.
The file-upload
control contains the helper functions
numberOfUploadedFiles
and getFormData
, and the main
function used to send the files is fileUploadSend
in the
Server
class. The code would look like the following:
$$('upload').onclick(async () => { if ($$('the-file').numberOfUploadFiles() < 1) { Utils.showMessage('Error', 'You must first select a file to upload.'); return; } const fd = $$('the-file').getFormData(); let data = { var1: 22, // just some random data we want to send to the back-end var2: 33 } const r = await Server.fileUploadSend('theService', 'theMethod', fd, data); });
Back-end code would look like this:
public void theMethod(JSONObject inJson, JSONObject outJson, MainServlet servlet) throws Exception { String var1 = inJson.getString("var1"); String var2 = inJson.getString("var2"); if (servlet.getUploadFileCount() == 0) throw new Exception("No file specified."); String originalFileName = servlet.getUploadFileName(0); BufferedInputStream bis = servlet.getUploadBufferedInputStream(0); // do something with the file stream bis.close(); // or String localFileName = servlet.saveUploadFile(0); }
Kiss includes an ever-growing set of utilities to help deal with common tasks.
These utilities are located under the src/main/frontend/kiss
directory and have names such as
DateTimeUtils.js
, DateUtils.js
, TimeUtils.js
, Utils.js
, etc. These utilities
are documented in the front-end API documentation.
Browsers have a mind of their own in terms of deciding when to use their cache for a file and when to download a new one. This can cause no end of trouble when code gets changed. Some user files end up being old from the browser cache, and others are freshly downloaded. The old and new files don’t agree with each other and all sorts of errors occur.
Kiss includes a facility to assure that all files are
downloaded afresh whenever the application changes while still taking
maximal advantage of the browser cache when the files have not
changed. The only cost for this capability is the requirement
that the index.html
file always gets loaded afresh.
To that end, Kiss has code to ignore browser cache and always load
index.html
afresh.
index.html
contains two variables named SystemInfo.softwareVersion
and SystemInfo.controlCache
.
Assuming SystemInfo.controlCache
is true
, Kiss has code that forces the browser
to reload all files whenever SystemInfo.softwareVersion
changes. After the code is re-loaded,
the browser cache will work as normal to maximally cache the files until the next
SystemInfo.softwareVersion
change.
Although not a part of the Kiss system, there are some very valuable technologies and libraries that have been used with Kiss in order to create some very powerful solutions.
The first is the Lovefield library, which adds SQL capabilities on the browser side. Data is persisted on the user’s browser and remains through browser or machine reboots. The library is located at https://github.com/google/lovefield
A recent technology that has been used to enable browser applications
that run when there is no Internet connection is called Service
Workers. There is a package at
https://developers.google.com/web/tools/workbox that makes
working with service workers very easy.