6. App Development

6.1 Technology Reference

RapidContext app development is mostly based on JavaScript, HTML and CSS. The apps execute in the web browsers, so care must therefore be taken to follow appropriate web standards to remain compatible with all browsers. The most important of these are listed below:

RapidContext also provides a number of JavaScript libraries that greatly simplify the development:

6.2 App Configuration

The app source code and resources are stored on the server, but will be transferred to the web browser upon launch. Each app has an app configuration (i.e. a manifest) that lists resources required for launch along with some meta-data. These can be inspected in the Admin app, as shown in the screenshot below.

Screenshot

The app configuration is placed in the plugin/local/app/ directory (or the app/ directory in your plug-in). The file name should follow normal storage rules (e.g. [app identifier].properties). In the file, app meta-data is specified with a list of URL resources required to launch the app. If an app is not properly declared in the configuration file, it will not be visible to the web browser. Below follows a simple example:

# General properties
name = Example App
description = A simple example app to play and experiment with.
className = ExampleApp

# Resources array
resources.0.type = code
resources.0.url = app/example/app.js
resources.1.type = ui
resources.1.url = app/example/ui.xml
resources.2.type = icon
resources.2.url = app/example/icon.png
  

In the example above, the three files app.js, ui.xml and icon.png are referenced and must be located at the specified URL. Any app resource of type code is dynamically loaded as a JavaScript file on the first app launch. Subsequent launches will reuse the previously loaded file, so web page must be reloaded to force an app to be updated.

The available app configuration parameters are as follows:

6.3 App Implementation

All apps are implemented as JavaScript objects with constructor function or a class. Normally a single code resource contains the source code for the app, but a module resource can be used as an alternative to import a Javascript module (ESM). By declaring multiple code resources, several files can be loaded (in the specified order). Upon launch, the app constructor function is called and a new app instance object should be created.

Notice

Apps should take their execution environment into consideration:

  • Function Names: Multiple apps run in the same web browser environment, so function and class names should be reasonably unique to avoid collitions.
  • State Variables: The user may launch multiple instances of an app, so all app state information should be kept with the instance, not in global variables (i.e. use this).

The JavaScript constructor function for an app must be named exactly as specified by the className property in the app configuration (if not using ESM). The app instance objects must also contain two methods — start() and stop() — that handle the app lifecycle. Below is an example JavaScript file that implements a minimal example app:

var ExampleApp = class {
    /**
     * Creates a new ExampleApp instance. Called once all app resources have
     * been loaded.
     */
    constructor() {
        // Constructor code. No UI or external calls here.
    }

    /**
     * Starts the app execution. This function is called when the
     * user interface has been successfully created.
     */
    start() {
        // this.ui -- a map of identifiers from the UI XML
        // this.ui.root -- the user interface parent widget
        // this.ui.overlay -- the overlay widget for the app
        // this.resource -- a map of resource URL:s
    }

    /**
     * Stops the app execution. This function is called when the
     * app should terminate, but before the user interface has
     * been destroyed. The app should kill running requests and
     * similar when this method is called.
     */
    stop() {
        // stop async requests and other pending actions
    }
}
  

The RapidContext.App.startApp() function is responsible for app loading, instance creation and calling the start() method once the user interface has been created. Each app instance will also inherit all properties from app config, with the following adjustments:

6.4 User Interface XML

The user interface for an app is normally contained inside an RapidContext.Widget.TabContainer widget. The app itself is assigned a RapidContext.Widget.Pane widget inside which it is responsible for creating and managing its own user interface.

The RapidContext platform simplifies the user interface creation by optionally building it from a serialized XML format. The user interface XML is normally stored in a ui.xml file in the same location as the app JavaScript source code and other resources. To use the automatic user interface creation, an app resource is specified as follows:

resources.#.type = ui
resources.#.url = example/ui.xml
  

The ui.xml file contains a mix of HTML (in XML form) and references to user interface widgets defined in the RapidContext.Widget namespace. The XML is processed by the RapidContext.UI.buildUI function. Here is a simple example:

<?xml version="1.0" encoding="UTF-8"?>

<ui>
  <Button id="test" icon="COMMENT">Press Me</Button>
</ui>
  

The root XML tag in a ui.xml file should always be <ui>. Inside this tag, all well-formed XML tags will be interpreted as follows:

6.5 User Interface Style

The platform user interface is default styled by two CSS files — css/style.css and css/widget.css. When the default styles are not sufficient, a number of options are available:

  1. Element style Attributes — The easiest way to modify the style of a widget or an HTML DOM node is by setting the style attribute. This can be done either in the ui.xml file or through the MochiKit.Style.setStyle() function.
  2. Inline <style> Tags — The ui.xml file may contain an additional <style> tag with CSS rules to add to the page. Care should be taken use proper class attributes to avoid restyling other apps.
  3. CSS Resource Files — CSS rules can also be loaded from an app resource URL, as explained previously. Again, care should be taken use proper class attributes to avoid restyling other apps.
  4. Edit Default CSS Files — The default CSS files are located in the system plug-in and can be replaced by any other loaded plug-in. Replacing the default styles or images is useful for creating new user interface themes for the whole platform, but is strongly discouraged for other purposes. The styles and images provided in the default CSS files may change without notice in future versions.

6.6 Web Listeners & Services

RapidContext provides a default web listener for HTTP requests. This is the web listener that launches the start app and handles the platform web requests. It is configured in the webservice/root.yaml file:

id: root
type: webservice/app
description: >-
    The root (default) web service. This launches the start app and provides
    access to the storage files.
path: /files/
app: start
header:
  ...
match:
  - path: /
  

Although the default web listener responds to all requests, it is easy to add a custom listener to handle requests for a specific host, path, etc. The example below shows a simple file web server:

id: www.test.com
type: webservice/file
description: A simple static web site service.
path: files/www.test.com/
match:
  - host: www.test.com
  - host: www.test.net
  - host: www.test.org
  

Web listeners configurations are placed in the plugin/local/webservice/ directory (or the webservice/ directory in your plug-in). The file name should follow normal storage rules (e.g. [identifier].properties). A number of web service types are available and custom ones can also be implemented in Java.

The available web service configuration parameters are as follows:

The webservice/file listener automatically maps directories to index.html files. If a requested file is missing, the parent directories are searched for the nearest 404.html or index.html file. This allows single-page apps to match any URL.

The webservice/file and webservice/app listeners support the following additional parameters:

The webservice/app listeners support the following additional parameters:

The webservice/procedure listeners support the following additional parameters: