In order to get productive with LaxarJS, a basic understanding of a few core concepts is helpful.
A LaxarJS Application
To the visitor running a web browser, an application is a set of URLs and associated pages which are loaded by the browser to provide some information or functionality. An application may access web services or connect to database programs, which are not considered part of the LaxarJS application itself.
From a developer point of view, an application primarily consists of:
* a set of LaxarJS _widgets_ and _activities_ providing the functionality * the _pages_ and _layouts_ assembling these widgets and activities * a _flow_ that connects the individual pages * one or more _themes_ to define the look and feel of the application.
In order to run the application, there are additional secondary resources:
* the _LaxarJS runtime_ loads flow and pages, sets up the widgets and connects them to the _event bus_ * _controls_ which are used by the widgets to provide advanced user interface functionality, such as those provided by _LaxarJS UiKit_ * _libraries_ used by widgets and activities, such as _moment.js_, _jQuery_, and _LaxarJS Patterns_.
The following two sections first explain the primary application components, and then the underlying secondary components.
Primary Application Parts
A LaxarJS widget is a rectangular part of the browser viewport which allows the user to perform some task.
It usually consists of several HTML elements, but might in some cases use only a single element, for example a
canvas to provide a painting surface.
The important distinction between a LaxarJS widget and a plain HTML control (such as a
select box or an
input field) is that a widget is written with a specific user-goal in mind, whereas a control is general-purpose and its role in the application is up to the developer.
For example, while a control might allow a user to input some text (such as a name, or a password), a widget might combine these input controls in a box to allow the same user to log in to the application, and another widget might allow the user to register a new account.
So, both widgets and controls are parts of the user interface, but on different levels of abstraction.
To illustrate this with further examples, possible widgets with their specific goals include:
* a to-do list, _to check and plan what is to do_ * a shopping cart, _to review and edit purchase items_ * a route planner displayed as a map, _to plan a journey_ * a calendar displaying various events, _to schedule and check appointments_ * the details editor for a specific event, _to reschedule or cancel an appointment_ * a social buttons bar, _to share content_.
In contrast, these are controls:
* an input field, _to display/edit any text_ * a date picker, _to display/edit any date_ * a select box, _to choose from any list of options_ * an accordion control or a tab control, _to navigate any set of contents_.
A LaxarJS activity is a widget without a visual representation, performing a task for the user behind the scenes. To build upon the previous example, a login widget might talk to an authentication service itself, but it might also delegate this task to an authentication activity using the event bus. When the authentication mechanism changes (e.g. from a plain HTTPS login to OAuth) only the activity needs to be exchanged, while the widget might remain untouched. In contrast to libraries and regular AngularJS services, activities participate in the lifecycle of the page and are attached to the event bus, which allows them to communicate with other widgets using publish/subscribe.
Another possible example would be a web search widget offering a search box with a list of web search results. Instead of hard-wiring the widget to a specific search engine, one could implement multiple engine-specific activities and choose depending on user preference. Because the search widget does not know any of the activities (it just subscribes to the search results) one could even define a "proxy" activity to combine results from multiple searches without touching any of the other implementations.
A LaxarJS page combines and configures widgets and activities that should be displayed together by embedding them in an HTML skeleton (the layout). When navigated to, the runtime loads the page and puts the widgets referenced by the page into the associated layout to display them. The page also defines the publish/subscribe topics that the widget instance use to communicate resource state and user actions.
An individual widget is still somewhat generic in that it allows to perform a specific task in any context. For example, a social buttons bar might allow to share any content, and the specific list of social sites to share on might be configurable. The page establishes this context, for example by placing the social buttons below a news article (rendered from markdown by another widget), and by configuring that twitter and tumblr should be offered, but not LinkedIn. This does not mean that all widgets must be broadly reusable: a widget to manage the inventory in a video game would probably not be useful anywhere else. But it means that reuse is supported for those widgets where it makes sense.
LaxarJS layouts are skeleton HTML documents, which contain placeholders (called widget areas) within which widget instances can be placed. Each page specifies a layout that the LaxarJS runtime should use for it. A layout can contain all the scaffolding markup of your application (such as copyright footers and navigation), but you may also choose to implement these areas as widgets to allow for re-use and configuration.
For each widget areas, the layout defines a width in grid columns, and widgets within these areas may not exceed their available number of columns. The LaxarJS UiKit ships with Bootstrap to implement the grid layout in CSS. Like widgets, layouts are accompanied by CSS styles, for example to define a background color.
You might think of layouts as the opposite of activities: While activities are just widgets without a user interface, layouts are similar to widgets without the logic part – just HTML templates and CSS.
The flow defines URL patterns that may be used to navigate to the pages of an application, and relations between pages. It is comparable to the routing mechanisms found in many MVC web frameworks. Also, the flow defines semantic relations between pages, such as what is considered the next page from a given page in the application.
Widgets and their controls may be styled using CSS. For widgets with a broad applicability (such as a calendar, or a route planner) it can be very useful to adapt the visual appearance to various circumstances. This is achieved by overriding parts of the vanilla bootstrap CSS classes (shipping with LaxarJS UiKit) with user defined CSS styles. A theme may specify styles for any control and for any widget that it wants to modify. Where nothing else is specified, plain bootstrap is used.
The LaxarJS UiKit is based on Compass/SCSS to simplify the generation of user defined themes. However, any way to generate Bootstrap-like CSS styles is a valid way to create a theme.
Secondary Application Parts – Under the Hood
The LaxarJS Runtime
The runtime handles URL routing and loads the template associated with the current page definition. It instantiates all required widgets and activities, and tells them when everyone else is ready to receive their publish/subscribe-events. It also loads the corresponding templates and CSS files, or provides these assets from an optimized bundle in production. Once everything is set up, the runtime gets out of the way: it lets the widgets perform their tasks and communicate through the event bus as needed.
The LaxarJS Event Bus
The event bus allows widgets to talk about common topics, without knowing anything about each other (not even a service name, interface or super-class). Widgets may request actions (such as a navigation or saving the page state), and other widgets might be there to respond to these actions. Likewise, widgets might provide resources (JSON structures), or expect resources to be provided for them. Because each widget uses its own isolated copy of the relevant resources which is synchronized over the event bus at well defined instances, race conditions are effectively avoided.
Controls are (user-defined) HTML elements and attributes, usually implemented as AngularJS directives. They are available to widgets as reusable UI components, and are styled using Bootstrap 3.2 for interoperability and theme support. A useful set of controls to get started is provided by the Angular UI Bootstrap project.
To establish a useful common base vocabulary for use with the event bus, the LaxarJS Patterns library is provided. It contains helpers that make it easy for widgets to talk about user actions, common (REST) resources and boolean flags.
After this quick tour through the building blocks of a LaxarJS application, have a look at the manuals for in-depth information on individual topics.