|
|
|
Introduction
|
|
|
|
============
|
|
|
|
|
|
|
|
KSS is an acronym for Kinetic Style Sheets. KSS is a client side
|
|
|
|
framework for implementing rich user interfaces with AJAX
|
|
|
|
functionality.
|
|
|
|
|
|
|
|
In this document, we assume the reader understands AJAX and its
|
|
|
|
purpose: to make pages in a browser behave more like a desktop
|
|
|
|
application. A primary AJAX characteristic
|
|
|
|
is that, instead of the user loading or reloading a web page, the web client
|
|
|
|
can contact the server and recieve information from it, then can change the
|
|
|
|
page's content or appearance without leaving it. As a result, the user
|
|
|
|
experiences faster interactions and a more "desktop"-like interface.
|
|
|
|
Plus, several tasks can be implemented with AJAX that are normally not
|
|
|
|
possible to achieve with static HTML pages.
|
|
|
|
|
|
|
|
|
|
|
|
The intention was not to create another JavaScript
|
|
|
|
framework for AJAX. Rather, we wanted to reuse existing libraries.
|
|
|
|
However, we also identified a few major problems in our everyday life
|
|
|
|
as AJAX developers, and by creating KSS we are attempting to offer
|
|
|
|
better solutions.
|
|
|
|
|
|
|
|
In many use cases, the "thin client" approach provides the best
|
|
|
|
results. Instead of performing complex DOM
|
|
|
|
modifications from JavaScript, the client consults the server, and the
|
|
|
|
server sends back an HTML page which is simply used by the client to
|
|
|
|
replace a part of the page.
|
|
|
|
|
|
|
|
Developing a "fat client" should seldom be necessary. But for the
|
|
|
|
use cases when fat clients are desirable, the process should work in
|
|
|
|
a reusable way, by encapsulation of plugins.
|
|
|
|
|
|
|
|
Developers have different skills and interests: site design,
|
|
|
|
application programming, plug-in creation, and so forth. Designers,
|
|
|
|
for example, are largely interested in tools that help them style a
|
|
|
|
site's look-and-feel, while programmers want to focus on
|
|
|
|
implementing that user interface with responsive, desktop-like
|
|
|
|
efficiency. As a result,
|
|
|
|
throughout this documention we highlight information peculiar to the
|
|
|
|
interests of several types of KSS user:
|
|
|
|
|
|
|
|
- KSS designer. A completed application can be bound to a page by writing
|
|
|
|
a KSS resource file. This task can be achieved by a
|
|
|
|
designer or by a programmer without any JavaScript knowledge. The
|
|
|
|
similarity of the KSS format to CSS assures the stylesheet is
|
|
|
|
developer friendly.
|
|
|
|
|
|
|
|
- KSS application developer. A developer can create an
|
|
|
|
application by reusing several KSS "plugins" that contain the
|
|
|
|
JavaScript code necessary for most client tasks. A developer
|
|
|
|
needs to write KSS resource files, and also must create server
|
|
|
|
side methods that command the client. This activity requires
|
|
|
|
you to know server side programming, but
|
|
|
|
JavaScript knowledge is not required.
|
|
|
|
|
|
|
|
- KSS plugin developer. Creating a plugin is the most complex but least often
|
|
|
|
needed activity. Plug-in development requires an extensive
|
|
|
|
knowledge of both browser side JavaScript programming and the
|
|
|
|
browsers themselves. Knowledge of the KSS plugin API is also
|
|
|
|
needed.
|
|
|
|
|
|
|
|
In this document, we assume you are familiar with HTML and
|
|
|
|
how web pages are created. We also assume that you know CSS, and, in
|
|
|
|
particular, that you understand CSS selectors. We do
|
|
|
|
not require you to be a Javascript expert to understand this
|
|
|
|
document.
|
|
|
|
|
|
|
|
A typical KSS application has the following characteristics:
|
|
|
|
|
|
|
|
- There is no JavaScript code or event binding in the HTML itself
|
|
|
|
(although we include JavaScript that contains the necessary client
|
|
|
|
side software for KSS to work).
|
|
|
|
|
|
|
|
- The behaviour is defined by a KSS resource file. A resource file has a syntax
|
|
|
|
similar to CSS, and its functionality is similar too. But instead of
|
|
|
|
being a static stylesheet, a KSS resource file defines how the
|
|
|
|
browser events should be bound to the HTML page.
|
|
|
|
|
|
|
|
- The client calls server side code, called "server actions," if certain browser
|
|
|
|
events are triggered (such as a user clicking on a node).
|
|
|
|
This server side code assembles a response that
|
|
|
|
consists of "kss commands" which are sent back to the client and which execute the
|
|
|
|
required behaviour.
|
|
|
|
|
|
|
|
Our goal in KSS to avoid the need to write JavaScript. JavaScript
|
|
|
|
is still necessary for some use cases, but even such
|
|
|
|
circumstance, we advise you choose JavaScript only as a last
|
|
|
|
choice. That is, first develop a "thin client" solution, and turn
|
|
|
|
it in to a "fat client" later, when you can't find another way to
|
|
|
|
solve the programming problem or you decide to spend excess time
|
|
|
|
on optimization. Besides, this gives you a possibility to
|
|
|
|
deliver a working application, and thus to learn the application
|
|
|
|
domain sooner. But often, it turns out that the thin client is
|
|
|
|
"good enough" and the development of the fat client can be
|
|
|
|
omitted altogether.
|
|
|
|
|
|
|
|
|
|
|
|
Architectural overview
|
|
|
|
======================
|
|
|
|
|
|
|
|
In this section, we provide a high level overview of KSS' system
|
|
|
|
architecture.
|
|
|
|
|
|
|
|
The principal characteristics of the KSS process are:
|
|
|
|
|
|
|
|
1. Process control is embedded into the KSS resource file
|
|
|
|
(including how to bind browser events to the plugins, and how to
|
|
|
|
dispatch them to the server), and server action code (that decides
|
|
|
|
what commands to marshal in return). Thus, application control logic
|
|
|
|
is not implemented on the client side, but is the
|
|
|
|
responsibility of the server.
|
|
|
|
|
|
|
|
2. All JavaScript code (apart from the KSS core) is a KSS
|
|
|
|
plugin, in most cases an event binder plugin or a client
|
|
|
|
action plugin. Apart from this, no JavaScript code appears in
|
|
|
|
the system. In particular, no JavaScript
|
|
|
|
ever appears in the HTML pages.
|
|
|
|
|
|
|
|
![1-kss-architecture](/uploads/b6560aee9bf788a1fbab959c7575d6b9/1-kss-architecture.png)
|
|
|
|
|
|
|
|
This diagram shows the architecture of KSS. Magenta and yellow
|
|
|
|
identify the two different types of plugins, and red highlights
|
|
|
|
the controlling information that governs the actual AJAX
|
|
|
|
functionality.
|
|
|
|
|
|
|
|
A major intent of the architecture of KSS is to separate design
|
|
|
|
from implementation.
|
|
|
|
|
|
|
|
KSS provides the execution flow similar to a simple programming language,
|
|
|
|
however yet does not have a "program." A command language can
|
|
|
|
execute a set of parametrized commands.
|
|
|
|
|
|
|
|
You can start implementing a thin client solution by using the
|
|
|
|
built-in set of KSS plugins. If it becomes necessary, you can
|
|
|
|
gradually fatten your client by developing new custom plugins.
|
|
|
|
Doing the latter naturally requires JavaScript programming, but
|
|
|
|
even so the result should be a well-componentized implementation
|
|
|
|
wherein
|
|
|
|
the details are totally decoupled from the level of the skin design.
|
|
|
|
|
|
|
|
To understand the entire KSS process, contemplate the complete flow of events
|
|
|
|
of an AJAX action. First, all actions are triggered from the client browser by
|
|
|
|
browser events. These are the same events that a programmer normally would bind
|
|
|
|
to JavaScript functions. Some of these events are generated by the user's
|
|
|
|
interaction (such as clicking on the page) or are triggered in some other
|
|
|
|
way (e.g. timer events).
|
|
|
|
|
|
|
|
Normally, JavaScript code
|
|
|
|
on the page would handle these events; in KSS, however, the events are
|
|
|
|
handled by event binder plugins. These plugins control both how the
|
|
|
|
event is bound and the actual process that executes when the event is
|
|
|
|
triggered.
|
|
|
|
|
|
|
|
Several event binder plugins are built into the KSS system. The
|
|
|
|
simplest plugin binds to a browser event via a
|
|
|
|
CSS selector. Other event type plugins are built-in. It is also
|
|
|
|
possible to extend the system by writing a custom event binder
|
|
|
|
plugin.
|
|
|
|
|
|
|
|
Such event binder plugins can bind to additional browser events and perform
|
|
|
|
more complex functionality. The way to bind these event plugins to browser
|
|
|
|
events is specified by the KSS resource file, a static resource file that
|
|
|
|
accompanies the HTML page. The format of this resource is called KSS which is
|
|
|
|
similar to CSS in syntax and nature; however, while CSS specifies
|
|
|
|
the static style of the content, KSS binds the dynamic behaviour
|
|
|
|
to a page.
|
|
|
|
|
|
|
|
The binding code for the event binder plugins runs at page
|
|
|
|
loading time. Event binder plugins may also specify the code to
|
|
|
|
be executed when the event is triggered, but usually they pass
|
|
|
|
execution to the event rule action dispatcher. The dispatcher
|
|
|
|
uses the KSS rule to decide what action to take. When
|
|
|
|
the action is a server action (the most common), control is
|
|
|
|
passed to the server. But client actions can also execute locally.
|
|
|
|
It is also possible to execute multiple actions for the same event.
|
|
|
|
|
|
|
|
If an event triggers a server action, control is passed through
|
|
|
|
an RPC service or direct URL request, which sends
|
|
|
|
events in the form of XMLHttpRequests to the server.
|
|
|
|
|
|
|
|
Once the XMLHttpRequests are sent, they arrive on the server as
|
|
|
|
RPC or normal URL requests. One server action is designated to reply to each
|
|
|
|
request. The methods do whatever their designated task is, then command the
|
|
|
|
client to do something in return.
|
|
|
|
|
|
|
|
This is a principal point of KSS: at this point in the process the server actions
|
|
|
|
decide what should happen on the client. The server side event
|
|
|
|
handlers do this by assembling a sequence of commands with
|
|
|
|
parameters. This command calling sequence is sent back to the
|
|
|
|
client as a response.
|
|
|
|
|
|
|
|
The commands consist of a selector (typically) and a client
|
|
|
|
action that is called with parameters. When the command
|
|
|
|
marshaller receives this sequence of commands, it looks up the
|
|
|
|
nodes identified by the selector. The command marshaller calls
|
|
|
|
each assigned client action in the required order,
|
|
|
|
with the parameters supplied by the server. The client actions
|
|
|
|
continue the flow of execution on the client side; this may
|
|
|
|
result in manipulating the DOM content of the page, binding
|
|
|
|
further events, and as a consequence, the execution of further
|
|
|
|
actions. In the end, the change is visible for the user,
|
|
|
|
finishing the entire AJAX cycle.
|
|
|
|
|
|
|
|
The client actions, like the event binders, ship as "core" plugins
|
|
|
|
into the KSS system. The simplest and also most useful client action
|
|
|
|
(replaceInnerHTML) replaces a selected tag in the DOM with a
|
|
|
|
string value supplied by the server as a parameter of the command.
|
|
|
|
This covers the most important KSS use case: in response to a user
|
|
|
|
action, the browser replaces part of the page that is
|
|
|
|
completely rendered on the server side. This results in a thin
|
|
|
|
browser client where most tasks are delegated to the server;
|
|
|
|
in many AJAX use cases, this is also the proper solution.
|
|
|
|
|
|
|
|
However, additional
|
|
|
|
local actions can carry out other common tasks, and you can
|
|
|
|
extend the system for your needs with very complex actions. In
|
|
|
|
the more complex cases, you may even want the server to return a
|
|
|
|
set of data to be turned into more complex DOM manipulation by
|
|
|
|
the accompanying command plugin.
|
|
|
|
|
|
|
|
|
|
|
|
Syntax and semantics of the KSS resource file
|
|
|
|
=============================================
|
|
|
|
|
|
|
|
In this section we detail what a KSS resource file contains
|
|
|
|
and how to use it.
|
|
|
|
|
|
|
|
At-config rule
|
|
|
|
--------------
|
|
|
|
|
|
|
|
The main configuration is done within an @config rule:
|
|
|
|
|
|
|
|
```css
|
|
|
|
@config {
|
|
|
|
protocol: json-rpc;
|
|
|
|
date-encoding: iso8601;
|
|
|
|
timeout: 5000;
|
|
|
|
endpoint: /path/to/service;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
protocol
|
|
|
|
|
|
|
|
The protocol to use. A value of "json-rpc" (default), "json-rpc-v1",
|
|
|
|
"json-rpc-v2" (synonym for "json-rpc"), "xml-rpc" or "url-encoded".
|
|
|
|
The latter can be used if there is no RPC service available.
|
|
|
|
|
|
|
|
date-encoding
|
|
|
|
|
|
|
|
How dates should be encoded. A value of "iso8601" (default),
|
|
|
|
"@timestamp@", "class-hinting" or "asp.net".
|
|
|
|
|
|
|
|
timeout
|
|
|
|
|
|
|
|
The timeout for server actions (defaults to 10000).
|
|
|
|
|
|
|
|
endpoint
|
|
|
|
|
|
|
|
The endpoint url to the RPC service.
|
|
|
|
|
|
|
|
|
|
|
|
Simple cases
|
|
|
|
------------
|
|
|
|
|
|
|
|
KSS is a resource format similar to CSS. It contains "rules." A rule
|
|
|
|
selects a HTML element from the page, binds it to an event, and
|
|
|
|
specifies the "actions" to happen when this event occurs.
|
|
|
|
|
|
|
|
A simple example is this:
|
|
|
|
|
|
|
|
```css
|
|
|
|
#title_save:click {
|
|
|
|
kss-action-server: saveTitle;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
This binds the node selected by the CSS selector ``#title_save`` to the
|
|
|
|
``click`` event. If this node is clicked, we want an action to happen.
|
|
|
|
In this case, this is a "server action" executed on the server. A server
|
|
|
|
action must be the name of a remote RPC method.
|
|
|
|
|
|
|
|
Another example:
|
|
|
|
|
|
|
|
```css
|
|
|
|
#sportlet-main:timeout {
|
|
|
|
evt-timeout-delay: 5000;
|
|
|
|
kss-action-server: refreshPortlet;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
This binds the ``timeout`` event to the HTML node selected by the
|
|
|
|
CSS selector ``#portlet-main``. The ``evt-timeout-delay`` specifies a
|
|
|
|
parameter used during the binding of the event. In this example,
|
|
|
|
it specifies how often the timeout event should poll. Similar to
|
|
|
|
the previous case, we also execute a server action here. The
|
|
|
|
method ``refreshPortlet`` is called every five seconds, and
|
|
|
|
results in refreshing a portlet in a page.
|
|
|
|
|
|
|
|
Complex cases
|
|
|
|
-------------
|
|
|
|
|
|
|
|
The goal is to enable the creation of complex event types with
|
|
|
|
abstract events that are not equivalent to browser events. A
|
|
|
|
simple example is ``timeout``: this is not a
|
|
|
|
browser event, but it is relatively
|
|
|
|
simple to bind it. In even more complex cases, the plugin writer can freely
|
|
|
|
implement how the events should be bound. The key point to keep
|
|
|
|
in mind is that once the events are triggered, we handle them
|
|
|
|
within the system, as if they were normal browser events.
|
|
|
|
|
|
|
|
The ``timeout`` event is contained in the "core" plugins of KSS.
|
|
|
|
|
|
|
|
The KSS stylesheet rules resemble CSS rules, but
|
|
|
|
we attach a KSS event name at the end to designate the event
|
|
|
|
to be bound to the nodes selected by CSS. The event
|
|
|
|
name is prefixed with a colon.
|
|
|
|
|
|
|
|
The attributes inside the rule also follow a syntax very similar
|
|
|
|
to CSS, but with different semantics. We
|
|
|
|
explain more about the parametrizing semantics a bit later.
|
|
|
|
Overall, however, the rule contains different properties that
|
|
|
|
define:
|
|
|
|
|
|
|
|
- parameters for the event binding
|
|
|
|
|
|
|
|
- server and client actions, with parameters (there can be more of these)
|
|
|
|
|
|
|
|
A rule follows the following syntax:
|
|
|
|
|
|
|
|
```css
|
|
|
|
[<CSS> <CSS> <CSS> ...] <CSS_SELECTOR>:<KSS_EVENT_NAME> {
|
|
|
|
|
|
|
|
/* event parameters */
|
|
|
|
...
|
|
|
|
|
|
|
|
/* actions (server or client) */
|
|
|
|
...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Consider the following example:
|
|
|
|
|
|
|
|
```css
|
|
|
|
div#thisnode a:timeout {
|
|
|
|
|
|
|
|
/* event parameters */
|
|
|
|
evt-timeout-delay: 3000;
|
|
|
|
|
|
|
|
/* actions */
|
|
|
|
|
|
|
|
kss-action-server: updateInfo;
|
|
|
|
remark: 'Updating from timeout';
|
|
|
|
color: red;
|
|
|
|
|
|
|
|
kss-action-client: log;
|
|
|
|
message: 'Updating from timeout';
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
A ``timeout`` event is bound; in this case the ``div#thisnode a`` CSS
|
|
|
|
selector selects any nodes. The event is bound to the selected nodes, but in
|
|
|
|
case of the timeout event the node itself does not matter.
|
|
|
|
|
|
|
|
The parameter ``delay=3000`` specifies a 3000ms
|
|
|
|
timeout recurring tick. When the events are executed, two actions
|
|
|
|
(updateInfo and log) are executed, each one with the supplied
|
|
|
|
parameters. The remote action is executed on the server, and then
|
|
|
|
sends back its command response to the client. The "log" action
|
|
|
|
is a special client action that is
|
|
|
|
implemented as a JavaScript action plugin; this
|
|
|
|
particular one gives a log message.
|
|
|
|
|
|
|
|
|
|
|
|
Event selectors
|
|
|
|
---------------
|
|
|
|
|
|
|
|
The event selector follows the css selector with a colon in
|
|
|
|
the KSS rule:
|
|
|
|
|
|
|
|
:eventname
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
|
|
:click
|
|
|
|
:timeout
|
|
|
|
|
|
|
|
|
|
|
|
The full event rule
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
The name of the event follow the CSS selector after a colon:
|
|
|
|
|
|
|
|
```css
|
|
|
|
div#recent-portlet:click { ... }
|
|
|
|
div.banner:timeout { ... }
|
|
|
|
```
|
|
|
|
|
|
|
|
The event name in KSS must be preceded by a normal CSS selector.
|
|
|
|
It cannot stand by itself.
|
|
|
|
|
|
|
|
A full example for an event method rule is provided later in this document.
|
|
|
|
|
|
|
|
|
|
|
|
Specifying parameters
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
The general schema for the parameter specification:
|
|
|
|
|
|
|
|
```css
|
|
|
|
.... {
|
|
|
|
evt[-<eventname>]-preventdefault: [true|false];
|
|
|
|
evt[-<eventname>]-preventbubbling: [true|false];
|
|
|
|
evt[-<eventname>]-allowbubbling: [true|false];
|
|
|
|
evt-<eventname>-<key>: <value>;
|
|
|
|
kss-selector: <selector>;
|
|
|
|
kss-precondition: [true|false];
|
|
|
|
...
|
|
|
|
kss-action-[server|client]: <actionname>;
|
|
|
|
kss-selector: <selector>;
|
|
|
|
kss-precondition: [true|false];
|
|
|
|
kss-includeform: [<form_name>|@currentform];
|
|
|
|
<key1>: <value1>;
|
|
|
|
<key2>: <value2>;
|
|
|
|
...
|
|
|
|
kss-action-[server|client]: <actionname>;
|
|
|
|
kss-selector: <selector>;
|
|
|
|
kss-precondition: [true|false];
|
|
|
|
kss-includeform: [<form_name>|@currentform];
|
|
|
|
<key1>: <value1>;
|
|
|
|
<key2>: <value2>;
|
|
|
|
...
|
|
|
|
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The keys and action names can be in camelcase (CamelCase). Although
|
|
|
|
the original CSS disallows the usage of uppercase characters in the
|
|
|
|
identifier, they are allowed in KSS.
|
|
|
|
|
|
|
|
"Event parameters" mean that these are parameters to the event
|
|
|
|
binding itself. There are different possibilities to declare them:
|
|
|
|
|
|
|
|
```css
|
|
|
|
evt-preventdefault: true;
|
|
|
|
evt-preventdefault: false;
|
|
|
|
evt-click-preventdefault: true;
|
|
|
|
evt-submit-preventdefault: true;
|
|
|
|
```
|
|
|
|
|
|
|
|
Declarations with omitted event names are applied to all event types
|
|
|
|
of the selector (that could be more than one).
|
|
|
|
|
|
|
|
Event actions can be defined with their parameters. An event
|
|
|
|
action must be a server or a client action. It is possible to
|
|
|
|
have more than one event action within a rule:
|
|
|
|
|
|
|
|
```css
|
|
|
|
#thisnode:timeout {
|
|
|
|
kss-action-server: updateInfo;
|
|
|
|
remark: 'Updating from timeout';
|
|
|
|
color: red;
|
|
|
|
|
|
|
|
kss-action-client: log;
|
|
|
|
message: 'Updating from timeout';
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Parameter producer functions
|
|
|
|
----------------------------
|
|
|
|
|
|
|
|
A value simply represents a value. Quotes are optional, but as seen
|
|
|
|
in this example, both single and double quotes can be used also:
|
|
|
|
|
|
|
|
```css
|
|
|
|
... {
|
|
|
|
size: 12pt;
|
|
|
|
typeface: "Bitstream Vera Sans";
|
|
|
|
typeface: 'Bitstream Vera Sans';
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
It is possible to create extensions to acquire a parameter in another
|
|
|
|
way as a constant; these are called parameter producer functions.
|
|
|
|
When calculating a value, these preset functions can take the
|
|
|
|
event rules, the state of the event, and the page in
|
|
|
|
consideration. We show some examples here, and we will give the
|
|
|
|
complete list of the selectors, too, later:
|
|
|
|
|
|
|
|
```css
|
|
|
|
... {
|
|
|
|
node_id: nodeAttr(id);
|
|
|
|
rownum: dataAttr("rownum", true);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The parameter producer functions operate on the scope of the
|
|
|
|
node which triggered the current event.
|
|
|
|
|
|
|
|
KSS action parameters
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
KSS action parameters are special predefined parameters. Strictly
|
|
|
|
speaking, they are not really freely usable parameters to specify
|
|
|
|
a value for an event; rather, they modify the way the (client or
|
|
|
|
server) action works.
|
|
|
|
|
|
|
|
The action parameters are distinguishable from normal parameters
|
|
|
|
by their name: they have the KSS prefix. (Consequently, normal
|
|
|
|
parameters are not allowed to start with this prefix.)
|
|
|
|
|
|
|
|
Only a few action parameters are implemented, so we present them
|
|
|
|
all here:
|
|
|
|
|
|
|
|
### kss-selector
|
|
|
|
|
|
|
|
``kss-selector`` modifies the scope
|
|
|
|
of the action. The default execution scope is the same node where
|
|
|
|
the event was triggered. With ``kss-selector``, we can execute
|
|
|
|
the action on a different or multiple nodes:
|
|
|
|
|
|
|
|
```css
|
|
|
|
... {
|
|
|
|
kss-action-client: actionName;
|
|
|
|
kss-selector: selector;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### kss-precondition
|
|
|
|
|
|
|
|
``kss-precondition`` prevents the execution of all declared actions
|
|
|
|
in a rule if its value evaluates to ``false``:
|
|
|
|
|
|
|
|
```css
|
|
|
|
... {
|
|
|
|
kss-action-server: actionName;
|
|
|
|
kss-precondition: confirm('Are you sure?');
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### kss-includeform
|
|
|
|
|
|
|
|
``kss-includeform`` transparently adds an entire
|
|
|
|
form to the parameters of a KSS action. It is global to the
|
|
|
|
action: all field variables of the form are added with their
|
|
|
|
name as they appear in the form:
|
|
|
|
|
|
|
|
```css
|
|
|
|
... {
|
|
|
|
kss-action-server: actionName;
|
|
|
|
kss-includeform: formname;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The value of the declaration can specify to submit a given form
|
|
|
|
or the current form (in which the event has been triggered).
|
|
|
|
Variations can be seen in the next example:
|
|
|
|
|
|
|
|
```css
|
|
|
|
kss-includeform: formname;
|
|
|
|
kss-includeform: @currentform;
|
|
|
|
```
|
|
|
|
|
|
|
|
Summarizing the rule definition basics
|
|
|
|
--------------------------------------
|
|
|
|
|
|
|
|
A complete example rule follows here:
|
|
|
|
|
|
|
|
```css
|
|
|
|
div#portlet-recent:timeout {
|
|
|
|
evt-timeout-delay: 2000;
|
|
|
|
kss-action-server: replaceMacro;
|
|
|
|
selector: #portlet-recent;
|
|
|
|
macropath: portlet_recent/macros/portlet;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Here, ``delay="2000"`` is used as a parameter for the binding of the
|
|
|
|
timeout event, and ``selector="#portlet-recent"``,
|
|
|
|
``macropath="portlet_recent/macros/portlet"`` are used for calling
|
|
|
|
the "replaceMacro" method. In this example, ``selector`` is not a
|
|
|
|
kss action property; it is a normal parameter passed to the
|
|
|
|
server.
|
|
|
|
|
|
|
|
Another example:
|
|
|
|
|
|
|
|
```css
|
|
|
|
div.menu-item:load {
|
|
|
|
kss-action-server: replaceWithRenderedText;
|
|
|
|
text: textContent();
|
|
|
|
size: 12pt;
|
|
|
|
typeface: "Bitstream Vera Sans";
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
How rule merging is done
|
|
|
|
------------------------
|
|
|
|
|
|
|
|
In contrast to CSS and the original KSS implementation, in KSS-RPC
|
|
|
|
there is no rule merging done at all. So a declaration of two rules
|
|
|
|
in the context of the same node results in the binding of two events.
|
|
|
|
|
|
|
|
|
|
|
|
Error handlers
|
|
|
|
--------------
|
|
|
|
|
|
|
|
It is possible to attach error handlers to server actions.
|
|
|
|
This is implemented as an additional event type ``error``:
|
|
|
|
|
|
|
|
```css
|
|
|
|
body:error {
|
|
|
|
kss-action-client: alert;
|
|
|
|
message: errorAttr('message');
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The error actions can accept the special parameters provider ``errorAttr``
|
|
|
|
to access properties of the current error object.
|
|
|
|
|
|
|
|
In practice, the main reasons that an error will occur during a remote action
|
|
|
|
execution are server errors or timeouts. It is also possible
|
|
|
|
for a server method to raise an exception on purpose, with the expectation that
|
|
|
|
the error handler will address the case on the client side in a
|
|
|
|
designated way.
|
|
|
|
|
|
|
|
|
|
|
|
Action names
|
|
|
|
------------
|
|
|
|
|
|
|
|
Action names are declared following the kss-action-client or
|
|
|
|
kss-action-server keys in the rule definition.
|
|
|
|
|
|
|
|
An action name is the name of either a server or client action,
|
|
|
|
depending if kss-action-client or kss-action-server is applied. These are
|
|
|
|
the two choices we have: pass the control flow to the server
|
|
|
|
(the most common case), or handle an action locally on the
|
|
|
|
client (in which case, a JavaScript plugin will be called).
|
|
|
|
|
|
|
|
If an action key is missing from an event or method rule, no
|
|
|
|
action is carried out.
|
|
|
|
|
|
|
|
A rule definition can have multiple client and server actions
|
|
|
|
defined. Actions are executed in the declared order but server
|
|
|
|
actions are executed asynchronously.
|
|
|
|
|
|
|
|
|
|
|
|
Getting information from the DOM (parameter providers)
|
|
|
|
======================================================
|
|
|
|
|
|
|
|
Actions must be executed with parameters. Although static
|
|
|
|
parameters can be sufficient for some application, most of the
|
|
|
|
time a program expects to fetch some information from the DOM
|
|
|
|
(the page where the event executing the action has triggered).
|
|
|
|
This pattern is solved by the "parameter providers" that we
|
|
|
|
introduced earlier in chapter 1.3.
|
|
|
|
|
|
|
|
For those not familiar with the term, we mention that DOM stands
|
|
|
|
for the Document Object Model. This refers to the internal
|
|
|
|
representation of our HTML page. So when talking about the DOM,
|
|
|
|
we mean accessing information from our page from a program or as in
|
|
|
|
this case, from KSS. And this is the exact purpose of the
|
|
|
|
KSS parameter providers.
|
|
|
|
|
|
|
|
A parameter provider looks like a function with a number of
|
|
|
|
parameters, and can stand in place of the value of a parameter:
|
|
|
|
|
|
|
|
```css
|
|
|
|
... {
|
|
|
|
kss-action-server: doIt;
|
|
|
|
whatisit: parmProvider(arg1, arg2, ... argN);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
There are two standard examples used most often.
|
|
|
|
In the first case, we want to take an attribute of a node.
|
|
|
|
|
|
|
|
HTML:
|
|
|
|
|
|
|
|
```html
|
|
|
|
<div id='our-node'>The content</div>
|
|
|
|
```
|
|
|
|
|
|
|
|
KSS:
|
|
|
|
|
|
|
|
```css
|
|
|
|
div#our-node:click {
|
|
|
|
kss-action-server: doIt;
|
|
|
|
id: nodeAttr('id');
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
We won't examine this line-by-line, at this point, but the important
|
|
|
|
piece to look at is the parameter 'id' that is passed with the value
|
|
|
|
'our-node'.
|
|
|
|
|
|
|
|
In the other use case, we want to include special markup with our
|
|
|
|
HTML, but we can not use HTML attributes for that. Existing HTML
|
|
|
|
attributes already have a specific purpose; using an attribute
|
|
|
|
not contained in the HTML standard would result in non-validating
|
|
|
|
pages. To avoid this problem, we use the HTML5 data-* attributes
|
|
|
|
to achieve the same result. These attributes can be acquired by
|
|
|
|
the ``dataAttr`` parameter provider.
|
|
|
|
|
|
|
|
HTML:
|
|
|
|
|
|
|
|
```html
|
|
|
|
<div id='our-node' data-marker='marker-id'>The content</div>
|
|
|
|
```
|
|
|
|
|
|
|
|
KSS:
|
|
|
|
|
|
|
|
```css
|
|
|
|
div#our-node:click {
|
|
|
|
kss-action-server: doIt;
|
|
|
|
marker: dataAttr('marker');
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The value 'marker-id' is marshalled to the doIt action. We can
|
|
|
|
use any variable name, since they all become attributes within
|
|
|
|
the data-* attributes.
|
|
|
|
|
|
|
|
It is a further enhancement of this use case to acquire these
|
|
|
|
attributes in a recursive way. For example, let us consider
|
|
|
|
a widget we created. Using KSS attributes recursively lets us
|
|
|
|
mark up an entire widget with a single KSS attribute, and we can
|
|
|
|
access the value of the single attribute from ``dataAttr`` if an event
|
|
|
|
happens anywhere inside the widget.
|
|
|
|
|
|
|
|
HTML:
|
|
|
|
|
|
|
|
```html
|
|
|
|
<div id='our-node' data-widgetid="widget2000">
|
|
|
|
<a class='link' href='firstpage.htm'>First page</a>
|
|
|
|
<a class='link' href='secondpage.htm'>Second page</a>
|
|
|
|
</div>
|
|
|
|
```
|
|
|
|
|
|
|
|
KSS:
|
|
|
|
|
|
|
|
```css
|
|
|
|
a.link:click {
|
|
|
|
kss-action-server: doIt;
|
|
|
|
href: nodeAttr(href);
|
|
|
|
widgetid: dataAttr('widgetid', true);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The second parameter in ``dataAttr('widgetid', true)`` tells KSS to look
|
|
|
|
further in the parents of the node, until it finds the attribute.
|
|
|
|
|
|
|
|
|
|
|
|
Introduction to commands
|
|
|
|
========================
|
|
|
|
|
|
|
|
"KSS commands" serve a very important role in a KSS application.
|
|
|
|
They enable the application to use server-side code to instruct
|
|
|
|
what the browser should do on the client side. A command
|
|
|
|
specifies:
|
|
|
|
|
|
|
|
- A client action that the command will execute. This action
|
|
|
|
stands with parameters that travel in the command from the
|
|
|
|
server to the client.
|
|
|
|
|
|
|
|
- In the majority of commands this is accompanied by a "selector"
|
|
|
|
parameter which identifies the node or nodes on which the action needs
|
|
|
|
to be executed. If there is no selector specified, the action is
|
|
|
|
executed in the context of the node that triggered the event.
|
|
|
|
|
|
|
|
Several commands are preimplemented in the KSS plugins.
|
|
|
|
Practically, all the client actions can be executed both
|
|
|
|
from the client and from the server.
|
|
|
|
|
|
|
|
When a server action executes, it assembles a response which it
|
|
|
|
will send back to the client. This response consists of a set of
|
|
|
|
commands.
|
|
|
|
|
|
|
|
A command instructs KSS on the browser to execute a client action
|
|
|
|
combined with a selector that is applied to select nodes for the
|
|
|
|
execution. This means that the selector is executed first on the
|
|
|
|
page, and the client action is executed on the resulting nodes.
|
|
|
|
The execution may occur on zero or more nodes. Executing on zero
|
|
|
|
nodes is permitted and results in no error condition.
|
|
|
|
|
|
|
|
Commands are constructed on the server side. To demonstrate a complete
|
|
|
|
example, let's examine an example. Look at the doIt action:
|
|
|
|
|
|
|
|
```python
|
|
|
|
from kss import KSSResponse
|
|
|
|
|
|
|
|
@rpcmethod
|
|
|
|
def doIt(widgetid, href):
|
|
|
|
kss = KSSResponse()
|
|
|
|
kss.replaceInnerHTML('div#result',
|
|
|
|
html='<p>Parameters: %s, %s</p>' % (widgetid, href))
|
|
|
|
return kss.response
|
|
|
|
```
|
|
|
|
|
|
|
|
The doIt action, as implemented above, commits a single command
|
|
|
|
``replaceInnerHTML`` that causes the target node to be replaced
|
|
|
|
by the value of the single parameter 'html' of the action.
|
|
|
|
|
|
|
|
The commands, as the response given by the server action, are
|
|
|
|
returned in RPC format (either JSON or XML). This is the raw JSON
|
|
|
|
result to be sent back to the client:
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"commands": [
|
|
|
|
{
|
|
|
|
"selector": "div#result",
|
|
|
|
"action": "replaceInnerHTML",
|
|
|
|
"params": {
|
|
|
|
"html": "<p>Parameters: widget2000, firstpage.html<\/p>"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
``` |