[KSS-checkins] r44630 - kukit/docs/introducing_kss/trunk

reebalazs at codespeak.net reebalazs at codespeak.net
Fri Jun 29 22:11:36 CEST 2007


Author: reebalazs
Date: Fri Jun 29 22:11:36 2007
New Revision: 44630

Added:
   kukit/docs/introducing_kss/trunk/1-kss-architecture.png   (contents, props changed)
   kukit/docs/introducing_kss/trunk/1-kss-in-general.txt
   kukit/docs/introducing_kss/trunk/2-kss-on-the-zope-server.txt
   kukit/docs/introducing_kss/trunk/3-shipped-kss-plugins.txt
   kukit/docs/introducing_kss/trunk/4-kss-in-plone.txt
   kukit/docs/introducing_kss/trunk/5-extension-with-custom-plugins.txt
Log:
Add first draft chapters (chapter 1 is actually reviewed only)

Added: kukit/docs/introducing_kss/trunk/1-kss-architecture.png
==============================================================================
Binary file. No diff available.

Added: kukit/docs/introducing_kss/trunk/1-kss-in-general.txt
==============================================================================
--- (empty file)
+++ kukit/docs/introducing_kss/trunk/1-kss-in-general.txt	Fri Jun 29 22:11:36 2007
@@ -0,0 +1,1092 @@
+
+1. KSS in general
+=================
+
+1.1 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.
+
+
+We (the developers of KSS) did not want 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.
+
+1. JavaScript is difficult to develop with. Our development background
+is Python, and JavaScript talents are hard to
+find in that community. However, Web development projects need AJAX
+applications, so we designed KSS to help developers create sites with AJAX
+without requring them to know JavaScript at all.
+
+2. Browser incompatibility problems create difficult situations. Lots of
+resources are burned by making an application run in a limited set of
+supported browsers. We try to hide these details in our implementation. 
+
+3. We want to develop and debug our applications
+efficiently. Therefore we provide development tools with the
+framework, most importantly an efficient way of logging. The
+problem with JavaScript is that debugging applications is
+cumbersome and time consuming. The KSS framework is specifically
+designed to make debugging easier.
+
+4. 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. 
+
+5. 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. 
+
+If you are experienced with JavaScript and are just moving to Zope, you
+should find much of this architecture familiar. However, we do
+not require you to be a Javascript expert to understand this
+document. On the other hand, you'll find it comfortable if you're
+experienced in Python programming.
+
+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 (Python, Zope, Plone), 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. Some parts of
+the text assume that you can program in Python, and that you can build simple
+web applications with Zope or Plone. We do not (apart from the most advanced
+chapters) assume explicit knowledge of JavaScript. 
+
+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) In the current 
+  implementation, these "server actions" are
+  implemented in Python. 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.
+
+At the moment, KSS runs on standalone Zope platforms (including
+Zope2 and Zope3) and on Plone. However, since the main part of
+KSS is in JavaScript, we plan to provide KSS for other Pythonic
+and non-Pythonic web application frameworks as well.
+
+
+1.2 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. 
+
+.. image:: 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. Client actions can also execute locally,
+such as to support debugging.  It is also possible to execute
+multiple actions for the same event.
+
+If an event triggers a server action, control is passed through
+the request/response queue, which sends events
+events in the form of XMLHttpRequests to the server. 
+The main task of
+the request/response queue is to limit the maximum number of the
+pending requests to the server. The queue also perform request error and
+timeout handling. This functionality should really be
+carried out by the XMLHttpRequest stack itself, but at the moment this
+requirement is not fulfilled by the browser implementation, hence the
+need for a separate layer.
+
+Once the XMLHttpRequests are sent, they arrive on the server as
+special URL requests. One server action is designated to reply to each
+request. On Zope, this incarnates method calls on the server. 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 are 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.
+
+
+1.3 Syntax and semantics of the KSS resource file
+-------------------------------------------------
+
+In this section we detail what a KSS resource file contains and how to use it.
+
+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::
+
+    #title_save:click {
+        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.
+
+Another example::
+
+    #sportlet-main:timeout {
+        evt-timeout-delay:    5000;
+        action-server:        refreshRecentPortletBody;
+    }
+
+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 refreshRecentPortletBody is called every four seconds, and
+results in refreshing the "recent portlet" in a Plone 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), and
+
+- parameters for the "default action" (explained later)
+
+A rule follows the following syntax::
+
+    [<CSS> <CSS> <CSS> ...] <CSS_SELECTOR>:<KSS_EVENT_NAME> {
+
+        /* event parameters */
+        ...
+
+        /* actions (server or client) */
+        ...
+
+        /* default action */   
+        ...
+    }
+
+Consider the following example::
+
+    div#thisnode a:timeout {
+
+        /* event parameters */
+        evt-timeout-delay:  3000;
+
+        /* actions */
+
+        action-server:      updateInfo;
+        updateInfo-remark:  'Updating from timeout';
+        updateInfo-color:   red;
+
+        action-client:      log;
+        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. (There is no default action
+for this rule).
+
+There is a special type of rule where there is no real CSS
+selector; instead, a KSS special selector is used.
+
+**Remark**: Additional CSS rules for the same description block, separated with comma,
+are not supported at the moment.  
+
+
+Event selectors
+"""""""""""""""
+
+The event selector follows the css selector with a semicolon in
+the KSS rule::
+
+    :namespace-eventname
+
+Each event has a namespace. The exception is core events which are in the global namespace.
+
+Examples::
+
+    :click
+    :plone-submitCurrentForm
+
+In more advanced cases, the event can have an "event binder state
+identifier" after the name in parentheses::
+
+    :sdnd-sortable(originals)
+    :sdnd-sortable(inchart)
+
+The event binder identifier is useful for events that represent
+and store internal states. To specify an identifier explicitly,
+the internal state of the two events are separated from each
+other.  Consequently their rules are also not merged. (We cover
+this in more detail later.)
+
+Another way of thinking of the stateful events is that there are
+as many distinct event binder instances, as there are identifiers
+specified.
+
+(**Remark**: the sensible example above, with the drag and drop,
+currently lacks a working implementation, due to limitations in
+the source code that we reuse. Yet this is the best example at
+the moment.)
+
+
+The full event rule
+"""""""""""""""""""
+
+The name of the event follow the CSS selector after a comma::
+
+    div#recent-portlet:click { ... }
+    div.warehouse-item:sdnd-drag(originals) { ... }
+
+The event name in KSS must be preceded by a normal CSS selector.
+It cannot stand by itself. 
+
+Special KSS selectors
+"""""""""""""""""""""
+
+In addition to CSS style node selection, we have special KSS selectors
+to select the event. These are:
+
+document
+
+    The rule is matched exactly once for the whole document.
+    (The methods receive ``node=null`` as a parameter.) The
+    match is only done at the initial pageload, and not when the DOM
+    content is injected to a page.
+
+behavior
+
+    The rule will not match for any particular node. However, it is
+    possible to call this event method programmatically from the
+    plugin JavaScript code, and when this happens the given actions
+    and parameters are used. The behavior event's purpose
+    is to enable events to be triggered automatically by
+    other plugin components, not by the browser itself as normal events.
+
+General form::
+
+    document:namespace-method
+    behaviour:namespace-method(stateid)
+
+State IDs may be omitted. If state IDs are present, they must be existing
+IDs, or the selected rule will never execute. No warning is given.
+
+A full example for an event method rule is provided later in this document.
+
+Specifying parameters
+"""""""""""""""""""""
+
+The general schema for the parameter specification::
+
+    .... {
+        evt-<eventname>-<key1>: <descriptor1>;
+        evt-<eventname>-<key3>: <descriptor3>;
+        ...
+        default-<key1>: <descriptor1>;
+        default-<key2>: <descriptor2>;
+        ...
+        ...
+        action-[server|client]:  <actionname1>;
+        <actionname1>-kss<ActionParm1>: <descriptor1>;
+        <actionname1>-kss<ActionParm2>: <descriptor2>;
+        <actionname1>-<key1>: <descriptor3>;
+        <actionname1>-<key2>: <descriptor4>;
+        ...
+
+    }
+
+The keys themselves cannot contain a hyphen (-), as hyphens have
+a special semantics in KSS. Also, the action names cannot be
+"default" or "evt" as these are keywords. 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::
+
+    #thisnode:timeout {
+        evt-timeout-delay: 2000;
+    }
+
+The repetition of the event name after "evt-" has no semantics;
+it just increases readability.
+
+Event actions can be defined with their parameters. An event
+action must be a server or a client action. There is a
+restriction: only one event action with the same name can be
+executed within one rule::
+
+    #thisnode:timeout {
+        action-server:      updateInfo;
+        updateInfo-remark:  'Updating from timeout';
+        updateInfo-color:   red;
+
+        action-client:      log;
+        log-message:        'Updating from timeout';
+    }
+
+Events and their plugins may programatically declares a "default
+action" including parameters. Only the parameters can be set; the
+default action is always the same for a event name, and it is
+always on the client. The default action, if we think about the
+event binder as a class (as this is how it is actually implemented 
+too), corresponds to a method of the class::
+
+    #buttonupdate:bluekit-update {
+        default-url:      kssupdate.htm;
+        default-nodeid:   target;
+    }
+
+The default methods are designed to do the task themselves, but
+you can also specify client and server actions for the same
+node. In such cases, all these actions are executed.
+
+Parameter producer functions
+""""""""""""""""""""""""""""
+
+A value simply represents a value. Quotes are optional for single words. 
+And as seen in this example, both single and double quotes can be used
+to delimit string values that contain spaces::
+    
+    ... {
+        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::
+
+    ... {
+        node_id: nodeAttr(id);
+        rownum: kssAttr("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:
+
+kssSelector
+'''''''''''
+
+kssSelector can be a parameter of client actions. It modifies the scope
+of the action. The default execution scope is the same node where
+the event was triggered. With kssSelector, we can execute
+the action on a different or multiple nodes::
+    
+    ... {
+        action-client: actionName;
+        actionName-kssSelector: selector;
+    }
+
+
+The declaration can specify different selection methods, as seen in the following examples::
+
+    xxx-kssSelector: 'css_selector';
+    xxx-kssSelector: css('css_selector');
+    xxx-kssSelector: htmlid('id_selector');
+
+kssSubmitForm
+'''''''''''''
+
+kssSubmitForm transparently submits an entire
+form as a request of the KSS server action. It is global to the
+action: all field variables of the form are submitted with their
+name as they appear in the form. (This also assures that, for
+example, Zope multiform variables of the style :list, :record,
+:records will work as expected.)::
+    
+    ... {
+        action-server: actionName;
+        actionName-kssSubmitForm: 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::
+
+    xxx-kssSubmitForm: 'formname';
+    xxx-kssSubmitForm: form('formname');
+    xxx-kssSubmitForm: currentForm();
+
+
+Summarizing the rule definition basics
+""""""""""""""""""""""""""""""""""""""
+
+A complete example rule follows here::
+
+    div#portlet-recent:timeout {
+        evt-timeout-delay:          2000;
+        action-server:              replaceMacro;
+        replaceMacro-selector:      #portlet-recent;
+        replaceMacro-macropath:     portlet_recent/macros/portlet;
+    }
+
+Here, ``delay="2000"`` is used as a parameter for the binding of the
+timeout macro, and ``selector="div#portlet-recent"``,
+``macropath="portlet_recent/macros/portlet"`` are used for calling
+the "replaceMacro" method. In this example,
+``replaceMacro-selector`` is not a
+kss action method; it is a normal parameter passed to the
+server.
+
+Another example::
+
+    div.menu-item:load {
+        action-remote:                        replaceWithRenderedText;
+        replaceWithRenderedText-text:         nodeContent();
+        replaceWithRenderedText-size:         12pt;
+        replaceWithRenderedText-typeface:     "Bitstream Vera Sans";
+        replaceWithRenderedText-selector:     sameNode();
+    }
+
+
+How rule merging is done
+""""""""""""""""""""""""
+
+A very important characteristics of KSS is that, as in CSS,
+parameters with the same key can be overwritten in a selected
+node. So, it is possible to say::
+
+    div#portlet-recent:timeout {
+        evt-timeout-delay:          2000;
+        action-server:              replaceMacro;
+        replaceMacro-selector:      #portlet-recent;
+        replaceMacro-macropath:     portlet_recent/macros/portlet;
+    }
+
+    #portlet-recent:timeout {
+        evt--timeout-delay:    3000;
+    }
+
+...In which case the delay will be 3000 (on node(s) which are selected by both rules).
+
+The merging of the rules is similar to how you would think if you
+think in terms of CSS: the last section, the KSS selector, counts
+too. Simply, all rules with the same action name and same event ID are merged on the same node.
+
+This means that rules are not merged if:
+
+- Rules for two different events are not merged. For example,
+  "click" and "timeout" can be applied to the same node.
+
+- The two different events are in the same event binder
+  class. For example, a "drag" and a "drop" rule of the dnd event
+  binder can be applied to the same node.
+
+- The event state ID is different
+
+However, the kss-action is not significant from the viewpoint
+of the merge, and can be overwritten in a rule that follows
+if it applies to the same node.
+
+As just one example: You cannot specify two "timeout"
+events to the same node. They are simply merged, with only one
+timeout event. However, if you deliberately want two timeout
+events to be triggered by the presence of the same node, you can
+specify explicit event state IDs.
+
+Programmatic constructs
+"""""""""""""""""""""""
+
+There are constructions to support the building of more complex
+events. Typically, they are only useful for special event
+plugins.
+
+Using custom events with a default action
+'''''''''''''''''''''''''''''''''''''''''
+
+Custom events may have a default action which is wired into the
+event (and implemented in JavaScript directly). There is no KSS
+action name but the keyword "default" can be used to specify
+parameters to the default action.
+
+The behavior selector
+'''''''''''''''''''''
+
+"Behavior" is a special selector that enables events to be
+triggered automatically by other plugin components. These events
+can be triggered programmatically from an event plugin
+implementation. The rule is never triggered by any event,
+although it can be triggered automatically from other events.
+
+With events that are programmatic-only, the binding of parameters
+can be accomplished by using normal selectors. In such cases, the
+selection is applied for merging the actions and parameters,
+but the event does not listen to a physical browser event. Or, if
+there is no point in specifying different actions and parameters 
+on different nodes, you can use the behavior selector to specify
+actions and parameters globally for the event.
+
+The behavior selector is only legal for events that trigger
+programmatically. The current implementation does not check for
+this explicitly; this will be added in a later KSS version.
+
+Examples of complex events
+''''''''''''''''''''''''''
+
+As an example, consider the selective event type
+plugin. The plugin implements a special "click" event that can 
+be bound to any node just like an ordinary
+click event. However, the event instantiates itself and starts
+counting the incoming clicks. The action specified in the "doit"
+behavior rule is only executed every fifth time. For all the other
+clicks, the "miss" action is executed.
+
+The event selective-click has a default method as its
+implementation. (The dashes in the event name show that the event
+is looked up from the "selective" plugin namespace instead of the
+global one.) The click rule does not specify actions since the
+default action is supposed to do its work. It could have
+parameters to the default action though, which it does not have
+now.
+
+The special selectors ``behavior:selective-miss`` and
+``behavior:selective-doit`` will never select to any nodes by
+themselves; instead, they are called up from the default action,
+when the click event is triggered. Their role is to bind and
+specify parameters that are used for the action but they do
+not start listening to any real browser event.
+
+The behavior selectors can be parametrized in the same way, as the
+event selectors, but evt- keys (parameters for the
+event binder) are not allowed here. Also, "behavior" must stand
+by itself. It cannot be prefixed by another CSS selector (in the
+latter case, it would be actually interpreted as a regular CSS
+selector, not a special one)::
+
+    .clickable:selective-click {
+    }
+
+    behavior:selective-doit {
+        action-server:     clickedButton;
+        clickedButton-id:  nodeAttr(id);
+        action-client: log;
+        log-message: "Was here.";
+    }
+
+    behavior:selective-miss {
+        action-client:     alert;
+        alert-message:     "Missed it. (But just keep on trying...)";
+    }
+
+The previous example does not use an event state ID, as it is not
+necessary. We just bound by event class. But let's examine a
+variation of the same example in case we need to specify an event
+state ID. This would be necessary to instantiate different
+counters to operate on the same page and keep track of two
+different things. The state of these events must be distinct, two
+different event binder instances are required. In this example,
+each has a different ID in our selection, "mine" and "yours"::
+
+    #button-one:selective-click(mine) {
+    }
+
+    behavior:selective-doit:mine {
+        action-server:     clickedButton;
+        clickedButton-id:  nodeAttr(id);
+        action-client: log;
+        log-message: "Was here.";
+    }
+
+    behavior:selective-miss(mine) {
+        action-client:     alert;
+        alert-message:     "Keep trying until you get there";
+    }
+
+    #button-two:selective-click(yours) {
+        evt-click-count:         2;
+    }
+
+    behavior:selective-doit(yours) {
+        action-server:     clickedButton;
+        clickedButton-id:  nodeAttr(id);
+    }
+
+    behavior:selective-miss(yours) {
+        action-client:     alert;
+        alert-message:     "Keep trying until you get there, from the second button";
+    }
+
+
+Error handlers
+""""""""""""""
+
+It is possible to attach error handlers to a server action.
+As in an error handler, an error action can be specified. An error
+action is always a client action, as we cannot rely on error
+handling to the server::
+
+    #title_save click {
+        action-server:    saveTitle;
+        saveTitle-error:  handleError;
+    }
+
+The error action can accept parameters. Such parameters are specified in
+the same way as in other actions.
+
+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.  
+
+Cancelling an action with merging
+"""""""""""""""""""""""""""""""""
+
+It is possible to cancel an action::
+
+    ul.contentViews li a:click {
+        action-client: alert;
+    }
+
+    thisId#a:click {
+        action-cancel: alert;
+    }
+
+This example binds the alert action to the click event for the
+nodes selected in the first rule. The second rule cancels the
+alert action for the nodes it selects; in this example, that's
+the node with the ID thisId.
+
+Order is important for cancelling actions.
+
+Action names
+""""""""""""
+
+Action names are declared following the action-client or
+action-server keys in the rule definition.
+
+An action name is the name of either a server or client action,
+depending if action-client or 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 (other than a default action) is carried out.
+
+A rule definition can have multiple client and server actions
+defined, but each name must be unique. Definitions given the same
+action name will result in overriding the parameters for the
+original action; KSS does not attach a
+second action with the same name.
+
+
+1.4 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::
+
+    ... {
+        action-server: doIt;
+        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::
+
+    <div id='our-node'>The content</div>
+
+KSS::
+
+    div#our-node:click {
+        action-server: doIt;
+        doIt-id: nodeAttr(id);
+    }
+
+This server side action example is usable with Zope. 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'.
+
+Server action (Zope)::
+
+    @kssaction
+    def doIt(self, id):
+        # id == '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 special namespace
+attributes to achieve the same result. These namespace
+attributes can be acquired by the "kssAttr" parameter provider.
+
+HTML::
+
+    <div id='our-node' kssattr:marker='marker-id'>The content</div>
+
+KSS::
+
+    div#our-node:click {
+        action-server: doIt;
+        doIt-id: kssAttr(marker);
+    }
+
+The value 'marker-id' is marshalled to the doIt action. We can
+use any variable name, since they all become attributes within
+the kssattr HTML namespace.
+
+Unfortunately, we cannot use this capability in Zope or Plone.
+Zope and Plone use transitional XHTML syntax, and namespace
+attributes are only available in the real XHTML. Instead, we use
+a special encoding to fit the attributes into our HTML, which
+encodes the values into "class"::
+
+    <div id='our-node' class="kssattr-marker-marker-id">The content</div>
+
+The ``kssattr-marker-marker-id`` string takes the general form
+``kssattr-${key}-${value}``. There are some restrictions of what can
+be used as a key: dashes (-) are not allowed inside keys, and
+generic rules for HTML content must be respected.
+
+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 kssAttr if an event
+happens anywhere inside the widget.
+
+HTML::
+
+    <div id='our-node' class="kssattr-widgetid-widget2000">
+        <a class='link' href='firstpage.htm'>First page</a>
+        <a class='link' href='secondpage.htm'>Second page</a>
+    </div>
+
+KSS::
+
+    a.link:click {
+        action-server: doIt;
+        doIt-href: nodeAttr(href);
+        doIt-widgetid: kssAttr(widgetid, True);
+    }
+
+The second parameter in ``kssAttr(widgetid, True)`` tells KSS to look
+further in the parents of the node, until it finds the attribute.
+
+1.5 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 identfies the node or nodes on which the action needs
+  to execute. (Commands with a selector are called "selector"
+  commands, versus "global" commands that contain no selector.)
+
+Several commands are preimplemented in the KSS plugins.
+Practically, all the client actions are also defined as commands,
+ensuring that they 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, although a
+warning is entered into the client side logs.
+
+Only one part of the commands has a selector as described above. 
+Global commands have no selector, as they do operate on the page
+globally, and not on any of the nodes.
+
+Examples of global commands are "alert" and "log", both are used to help
+debugging, and have no concept of an actual "node" on which they execute.
+Commands are constructed on the server side. To demonstrate a complete
+example, let's examine an example usable with Zope. Look at the doIt action::
+
+    from kss.core import KSSView, kssaction
+
+    class MyView(KSSView):
+
+        @kssaction
+        def doIt(self, widgetid, href):
+            ksscore = self.getCommandSet('core')
+            selector = ksscore.getHtmlIdSelector('resultslot')
+            ksscore.replaceInnerHTML(selector, 
+                    '<h1>Parameters: %s, %s</h1>' % (widgetid, href))
+
+
+This Zope-specific example contains a few new things. We
+intentionally mention them in passing here, and will provide a
+deeper explanation in a later.
+
+- We implement the method in a Zope view. This is a special
+  browser view implemented from the ``KssView`` class which
+  contains a few utility methods.
+
+- The kssaction decorator forces the method to return the
+  payload of the set of commands upon return.
+
+- self.getCommandSet('core') looks up a commandset by name. This
+  adapts on the view and contains the commands that are defined
+  in the "core plugin".
+
+- For commands requiring a selector, the selector can be
+  specified by ``getHtmlIdSelector``, ``getHtmlSelector``, any
+  other selector defined in the plugin, or a string which is
+  implemented as a css selector.
+
+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
+marshalled in XML format. This is the raw result to be sent back
+to the client::
+
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+    <html xmlns="http://www.w3.org/1999/xhtml"
+          xmlns:kukit="http://www.kukit.org/commands/1.0"><body>
+    <kukit:commands>
+    <kukit:command selector="resultslot"
+                   name="replaceInnerHTML" selectorType="htmlid">
+        <kukit:param name="html"><h1>Parameters: , widget2000, firstpage.htm</h1></kukit:param>
+    </kukit:command>
+    </kukit:commands>
+    </body></html>
+
+

Added: kukit/docs/introducing_kss/trunk/2-kss-on-the-zope-server.txt
==============================================================================
--- (empty file)
+++ kukit/docs/introducing_kss/trunk/2-kss-on-the-zope-server.txt	Fri Jun 29 22:11:36 2007
@@ -0,0 +1,364 @@
+
+2. KSS on the Zope server
+=========================
+
+In this chapter we summarize how to write the application part that runs on
+the Zope server side: the server actions. 
+Many of this is also essential to work
+from Plone, although we will see later that Plone provides
+additional functionalities as well.
+
+We also advise you to look at the kss.demo package. This
+contains simple examples that cover all (or most) of the
+funtionality of kss. The demos are also used for automatize
+functional testing with Selenium.
+
+2.1. Installation
+-----------------
+
+For installing KSS on the Zope server side, please refer to
+the release notes of the KSS version you are using.
+Installation should be straightforward and consists of
+installing Python modules and ZCML "slugs" into your
+instance.
+
+2.2 Providing javascript code for the client
+--------------------------------------------
+
+First of all we need to serve the javascript code that is
+necessary for our application. This is done by the
+kss.concatresource package. The javascript code consists of several
+source files on the filesystem, this utility is able to
+concatenate them into a single javascript file. The file is
+then also compressed semantically to provide a smaller code size.
+
+Two resources are provided: the file "++resource++kukit.js"
+and "++resource++kukit-devel.js". They have to be used for
+production and development mode, respectively. One of these
+two resources must appear in the header of the html page.
+This javascript makes kss work.
+
+There is a preimplemented view that makes switching between
+these two resources: if "context/@@kss_devel_mode/isoff"
+evaluates to true, 
+the "++resource++kukit.js" resource, if
+"context/@@kss_devel_mode/ison" is true, then the
+"++resource++kukit-devel.js" resource should be used. There
+is also a view that contains a simple user interface,
+"context/@@kss_devel_mode/ui" to
+switch between development and production modes. The
+switching is done by client cookies so that no restart
+or reconfiguration of the server becomes necessary, when we
+want to change from production to development mode and back.
+
+The reason for having a differently optimized code for
+production and debug mode is, that in production mode the
+logging and informational parts are omitted, together with
+some runtime assertions. As a consequence you will get
+meaningless error messages with little or no information,
+but in return you get a slighly smaller and faster code size
+which is an advantage if everything works. For development
+and debugging it is inevitable to switch to development
+mode, though.
+
+In addition to the kukit javascript resources, the page also
+needs to include all the dependencies not directly contained
+by the
+concatenated code. This is necessary when components
+other then KSS want to use the same dependencies. At the
+moment you need the following zpt code in the header of the
+page to import the necessary javascript libraries::
+
+    <script type="text/javascript"
+      tal:attributes="src string:${context/@@absolute_url}/++resource++sarissa.js;"
+      src="++resource++sarissa.js">
+    </script>
+
+    <!-- Use original cssQuery -->
+    <script type="text/javascript"
+      tal:attributes="src string:${context/@@absolute_url}/++resource++cssQuery.js;"
+      src="++resource++cssQuery.js">
+    </script>
+
+THese third party modules are shipped with KSS and defined
+as resources to make the above imports work.
+
+The resources that contain KSS itself, can be included by the following zpt code that
+belongs to the header of the page after the dependencies::
+
+    <tal:block define="kss_devel_mode nocall:here/@@kss_devel_mode | nothing">
+
+        <script tal:condition="python: not kss_devel_mode or kss_devel_mode.isoff()" type="text/javascript"
+          tal:attributes="src string:${context/@@absolute_url}/++resource++kukit.js;"
+          src="++resource++kukit.js">
+        </script>
+
+        <script tal:condition="python: kss_devel_mode and kss_devel_mode.ison()" type="text/javascript"
+          tal:attributes="src string:${context/@@absolute_url}/++resource++kukit-devel.js;"
+          src="++resource++kukit-devel.js">
+        </script>
+
+    </tal:block>
+
+The kukit resource files, in addition to providing the KSS
+core itself, also collect all the KSS plugins that are
+installed on the server side. Installing plugins is a matter
+of including their configure.zcml. Plugins are placeless by
+rule, so they can be contained inside the Product to which
+they belong to, or can be placed and relocated anywhere
+without the need to touch any code that uses them.
+Installing a plugin this way thus will make its javascript
+transparently available on the client.
+
+Finally we have to mention, without much detail, another
+important thing: the kukit resource files are resources with
+different caching options provided. These options are set up
+to a sensible default and not likely that you need to change
+them. These settings are contained in the kss.core package,
+in the file concatresource.zcml. This file has a few
+comments that helps you learn about different caching
+options, in case it becomes necessarry to change them.
+
+2.2 Specifying stylesheets
+--------------------------
+
+Now that we have the javascript of KSS enabled in the pages, we 
+can start specifying one or more KSS stylesheets. The stylesheets, 
+(similarly to CSS stylesheets) should be referred to from the
+header of the page.
+
+For example to include the stylesheet "my_styles.kss", you would
+use the following definition::
+
+    <link rel="kinetic-stylesheet" type="text/kss"
+        tal:attributes="href string:${context/@@absolute_url}/my_sheet.kss" />
+
+A remarkable difference to those link definitions for CSS is,
+that the "rel" attribute of the link must be
+"kinetic-stylesheet". The browser will not handle this link,
+however if the KSS javascripr is active in the page, it will find
+these link definitions, fetch the stylesheets from the server,
+and starts processing them. 
+
+2.3 Debugging possibilities
+---------------------------
+
+Debuggability, as mentioned before, is a core feature of
+KSS. Besides the appearance of the server side errors in the
+Zope event.log (as usual), KSS offers client side logging
+that makes it possible to monitor the current activity and
+find the reasons for a possible error.
+
+There are more options for looking at this log file:
+
+- In FireFox browser, you need to install the FireBug
+  extension. If this is present, KSS will place its log
+  directly into the FireBug console. This is the most
+  developer friendly solution that is available so far.
+
+- In the Safari browser, Safari's console is directly used
+  for logging.
+
+- In the lack of any of the above two solution, MochiKit's
+  loggingPane can be utilized. In this case the page must
+  also include the "++resource++MochiKit.js" resource in the
+  headers, similarly to how we described above. Then, after
+  loading the page (and each time a new page is loaded and
+  reloaded), you need to enter the following as an URL to
+  activate the logging output::
+
+        javascript:void(createLoggingPane(true));
+
+
+The debugging will only happen if the development mode of
+KSS is activated.
+
+There is several practical tricks you need to learn in order to
+debug KSS efficiently. We don't go into details here, as 
+all the basic KSS tutorials will attempt to help you learn this.
+
+There is two particular thing to note here though. 
+
+First, being blunt: you need to restart the zope server
+*and* reload your pages from the browser in order to have
+any changes you made effective. Although in a given case,
+either the server restart or a page reload may be omitted,
+you save yourself from a lot of headache if you apply a
+disciplined restart and reload policy. Also note that in the
+browser you also need to switch off caching in order for the
+KSS files to refresh, and in some browsers you need to force
+this (by Control-Reload or similarly.)
+
+And finally, a useful hint: If you just receive a
+server side error which is reported in the client log, but
+the reason of the error is not indicated, you almost
+certainly need to look for the
+problem on the server side. In lots of cases, an unknown
+error indicates that a NotFound or Unauthorized exception
+has happened on the server. It
+helps if you make sure these exceptions are logged on the
+server and not filtered (by applying necessary settings to
+the error_log tool).
+
+2.4 The KSS command response
+----------------------------
+
+In this part we will work with browser views for
+implementing out server actions. According to the current
+state-of-the-art in Zope development, this is the most
+universal method. However to learn how to work TTW (Through
+The Web) only, you may skip to the next section.
+
+As briefly shown
+previously, we make our server actions as methods of a
+specialized browser view. Let's revisit the same example::
+
+  from kss.core import KSSView, kssaction
+
+    class MyView(KssView):
+
+        @kssaction
+        def doIt(self, widgetid, href):
+            ksscore = self.getCommandSet('core')
+            selector = ksscore.getHtmlIdSelector('resultslot')
+            ksscore.replaceInnerHTML(selector, 
+                    '<h1>Parameters: %s, %s</h1>' % (widgetid, href))
+
+
+In addition you also need to define this action as a Zope
+view (for, class and permission need to be changed according
+to the needs)::
+
+  <browser:page
+      for="*"
+      class=".my_view.MyView"
+      attribute="doIt"
+      name="doIt"
+      permission="zope.View"
+      />
+
+
+There are two important things. First, the server actions
+need to be decorated with the @kssaction decorator. If this
+is missing, the sender does not send back the rendered commands,
+and client will not receive a valid response.
+
+Second: every basic functionality is achieved by first
+calling up a "command set" and using some method of it. A
+commandset is a zope adapter that is looked up by the name
+of the plugin ("core" in our example). This makes it
+unnecessary to import the plugin commandsets and results in
+truly placeless plugins that just need their configure.zcml
+imported in order to activate them.
+
+The lookup of a given commandset is carried out by the
+"getCommandSet" method of the views. The commandsets diverge
+in functionality: some of them emit kss commands that will
+result the command to be sent to the client on return, some
+of them check or change the content of the ZODB and also
+emit KSS commands, while some of them are just methods in
+the traditional sense and do not change the KSS response.
+
+To see the methods of the commandset, you have to consult
+its documentation, or look at its accompanying interfaces.py
+file for hints. We will document the functionality of the
+commandsets of the core plugins later, and also document the
+commandsets shipped with the "plone" plugin.
+
+As an additional remark we mention that the kss parameters
+are passed to the method in the exact same way as it would
+happen with any normal zope method. That is, parameters that
+are mentioned in the method's signature (widgetid and href,
+in our example) will 
+
+2.5 How to work TTW
+-------------------
+
+Besides the above described method that involves the usage
+of Zope views to define server actions, KSS also provides a
+way to work Through The Web (TTW). This means that you can
+put your code in a python script and edit this script from
+the Zope Management Interface (ZMI) from your browser.
+
+While the basics are the same as with kss views, this method require 
+some extra quirks from you as a developer. This is because
+python scripts run in restricted execution mode, so we need
+to provide an aditional API called TTWAPI. The code
+implementing this is in the ttwapi.py file in kss.core.
+TTWAPI also cones with unittests that can be consulted for
+details in usage.
+
+You have to do explicit preparation by using the following 3
+methods:
+
+- Call startKSSCommands in the beginning of the script, to
+  set up the container that holds the commands payload.
+
+- Call getKSSCommandSet to get any commandset you need.
+  After this the commandset can be used in the same way as
+  from the views.
+
+- Do a return renderKSSCommands() in the end, to make sure
+  the response payload is returned.
+
+Have a look at the following simple example::
+
+    from kss.core.ttwapi import startKSSCommands
+    from kss.core.ttwapi import getKSSCommandSet
+    from kss.core.ttwapi import renderKSSCommands
+
+    startKSSCommands(context, context.REQUEST)
+
+    core = getKSSCommandSet('core')
+    core.replaceInnerHTML('#test', '<p>Done</p>')
+
+    return renderKSSCommands()
+
+
+2.6 Server side event handling
+------------------------------
+
+When we talk about server side event handling, it is
+important to note that we talk about "events" in the real
+Zope sense, and this is not in connection with the KSS
+events at all, or with how we use the word "event" in the
+rest of this document.
+
+The server side event handling can be implemented by any KSS
+component that needs it. The use case emerges, because, if
+we want to change something on the page (like, for example,
+edit the title of the content object), several other widgets
+may need to change too (like for example the recent, the
+navigation and the breadcrumbs portlets in a typical Plone
+page.) Instead of producing these changes as a consequence
+of the first change from programmatic method calls, each of
+these widgets can listen to the events it requires to, and
+"add" its own kss commands to the payload that will be sent
+back to the client.
+
+KSS provides the mechanism that these event listeners can
+access the original request context and also the original
+KSS view on which the server action is defined. This makes
+it possible that they can access the commands container and
+add their additional manipulation orders to the response. To
+do this KSS implements its own local site manager.
+
+An example of how to define a listener for automatically
+updating the globalnav portlet of Plone, when some content object has
+changed:
+
+    from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+    from kss.core.interfaces import IKSSView
+
+    @component.adapter(None, IKSSView, IObjectModifiedEvent)
+    def doReloadOfPortalTabs(obj, view, event):
+        # figure out if you need the change
+        # ...
+        # execute the change
+        ksscore = view.getCommandSet('core')
+        ksscore.replaceHTML(
+            ksscore.getHtmlIdSelector('portal-globalnav'),
+            view.macroContent('global_sections/macros/portal_tabs'),
+            )
+
+

Added: kukit/docs/introducing_kss/trunk/3-shipped-kss-plugins.txt
==============================================================================
--- (empty file)
+++ kukit/docs/introducing_kss/trunk/3-shipped-kss-plugins.txt	Fri Jun 29 22:11:36 2007
@@ -0,0 +1,778 @@
+
+
+3. Shipped KSS plugins
+======================
+
+KSS plugins, the ones that come with the system
+
+In case of the javascript methods, we give the parameters the plugins take. There are both mandatory
+and optional parameters (with default value). 
+
+The commandsets repeat the functionality of all the kss
+actions, with the same parameter. However since the
+signature is python, the parameters can be given in a
+positional way as well. In addition, the "selector" commands
+have an additional selector parameter, which is not present
+at "global" commands.
+
+3.1. The "core" plugins
+-----------------------
+
+Namespace: "core"
+
+Events
+""""""
+
+Native browser events
+'''''''''''''''''''''
+
+With all native browser events, the following event
+parameters are available. Additional parameters are marked
+at the corresponding event.
+
+    - evt-<eventname>-allowbubbling (default False)
+
+        By default, we only let an event triggered when it
+        happens on the exact node we bound the event to. If
+        the event happens in one of the contained nodes of
+        the bound node, the event is "bubbling up" and
+        occasionally reach the bound node. If this parameter
+        is set to True, all these events will trigger.
+
+        (The basic behaviour with bubbling in KSS is
+        different from that of javascript. in javascript,
+        bubbling events are default triggering. in kss the
+        default is that we suppress these events.)
+
+        At the moment this parameter is only available for
+        "click" events.
+        
+    - evt-<eventname>-preventdefault (default False)
+
+       If set to True, this disables the default behaviour
+       to happen upon succesful completion of an event.
+
+       For example, if we handle the click event on an <A>
+       node, we don't want to link followed as well as it
+       would be the default behaviour of the click.
+
+    - evt-<eventname>-preventbubbling (default False)
+
+        When used in combination with allowbubbling on an
+        outer node, this
+        can prevent the bubbling up of events from an inner
+        node that is contained by the outer node. This
+        property itself needs to be set on the inner node.
+        (If the outer node does not have allowbubbling, the
+        parameter has no effect.)
+
+
+The events themselves:
+
+blur
+
+    Triggers when leaving a form field.
+
+focus
+
+    Triggers when entering a form field.
+
+resize
+
+    Triggers when element is resized.
+
+click
+
+    Triggers when element is clicked with the mouse.
+
+dblclick
+
+    Triggers when element is double clicked with the mouse.
+
+mousedown
+
+    Triggers when mouse button is pressed.
+
+mouseup
+
+    Triggers when mouse button is released.
+    
+mousemove
+
+    Triggers when mouse moves over the element.
+    
+mouseover
+
+    Triggers when mouse enters the element.
+
+mouseout
+
+    Triggers when mouse leaves the element.
+
+change
+
+    Triggers when the form field value is changed.
+
+reset
+
+    Triggers when form is reset.
+
+select
+
+    Trigger when selection box's value is selected.
+
+submit
+
+    Trigger when form is submitted.
+
+keydown
+
+    Trigger when key is pressed down.
+    
+    - evt-keydown-keycodes (default empty)
+        
+        If specified, it needs to be a list of comma
+        separated keycodes (specified as a single string),
+        and only the keycodes in the list will trigger the
+        event.
+
+
+keypress
+
+    Trigger when key is pressed.
+
+    - evt-keypress-keycodes (default empty)
+
+        Same as with keydown.
+
+keyup
+
+    Trigger when key is released.
+
+    - evt-keyup-keycodes (default empty)
+
+        Same as with keydown.
+
+
+Special kss events
+''''''''''''''''''
+
+timeout
+
+    Implements a timer that triggers the event when the
+    given period expires.
+
+    - evt-timeout-delay:  delay period in milliseconds
+
+    - evt-timeout-repeat (default true):  If the event should
+      happen periodically. This is the default, but it can
+      be set to false to let the timeout event happen only
+      once.
+
+
+load
+
+    The event triggers when the bound node gets loaded. That
+    signifies the full loading of the DOM, and may preceed
+    the loading of images for the page.
+
+    The event triggers both on the original page load, and
+    when we dynamically insert content from KSS.
+
+    - evt-load-initial (default true): if the event should
+      trigger on the initial page load.
+
+    - evt-load-insert (default true): if the event should
+      trigger on dynamic insertions by KSS.
+
+
+iload
+
+    The event can only be bound to <IFRAME> node. It
+    triggers when the full content of the internal frame gets loaded. 
+
+    - evt-iload-autodetect: if set to true, the default
+      mechanism that observes the loading of the iframe will
+      be utilized. If set to false, it is required that the
+      template of the internal template has the
+      _kssReadyForLoadEvent attribute set on the document.
+      (Without this the event will never be triggered.) This
+      method may be more solid then the default one but
+      requires the cooperation of the internal contact.
+
+    - evt-iload-initial (default true): if the event should
+      trigger on the initial page load.
+
+    - evt-iload-insert (default true): if the event should
+      trigger on dynamic insertions by KSS.
+
+spinneron
+
+    This event triggers when the "loading..." spinner should
+    be activated.
+
+    - evt-spinneron-laziness (default 0): laziness of the
+      spinner in milliseconds.
+
+spinneroff
+
+    This event triggers when the "loading..." spinner should
+    be deactivated.
+
+    - evt-spinneroff-laziness (default 0): laziness of the
+      spinner in milliseconds.
+
+Actions
+"""""""
+
+HTML functions to insert content
+''''''''''''''''''''''''''''''''
+
+All these actions have an optional parameter:
+
+    - withKssSetup: if set to false, prohibits binding uthe
+      nodes in the inserted content. This is plain
+      optimization, normally ve want this wo leave on the
+      default true.
+
+replaceInnerHTML
+
+    Replace all children of the given node with the given
+    content.
+    
+    - html: the html to insert
+
+replaceHTML
+
+    Replace HTML including the given node with the given
+    content.
+
+    - html: the html to use as replacement (only the first node is used in the replace)
+    
+    - withKssSetup: if set to false, prohibits binding the
+      nodes in the inserted content.
+
+appendHTML
+
+    Add HTML after last child of given node.
+
+    - html: the html to insert
+
+insertHTMLBefore
+
+    add HTML before given node.      
+
+    - html: the html to insert
+
+insertHTMLAfter
+    
+    Add HTML after given node.
+
+    - html: the html to insert
+
+insertHTMLAsFirstChild
+
+    Add HTML inside the given node, at the beginning.
+          
+    - html: the html to insert
+    
+insertHTMLAsLastChild
+
+    add HTML inside the given node, at the end
+    
+    - html: the html to insert
+
+Deleting content
+''''''''''''''''
+
+deleteNode
+
+    Delete the node.
+
+clearChildNodes
+
+    Delete all the children of the node.
+
+deleteNodeAfter
+
+    Delete the next node.
+
+deleteNodeBefore
+
+    Delete the previous node.
+
+Moving content
+''''''''''''''
+
+moveNodeAfter
+
+    Move the node after the node with the given HTML id.
+
+    - html_id: the id of the second node
+
+moveNodeBefore
+
+    Move the node before the node with the given HTML id.
+
+    - html_id: the id of the second node
+
+moveNodeAsLastChild
+
+    Move the node as last child of the node with the given HTML id.
+
+    - html_id: the id of the second node
+
+copyChildNodesFrom
+
+    Copy the child nodes from the given HTML id, under the
+    current node.
+
+    - html_id: the id of the second node
+
+copyChildNodesTo
+
+    Copy the child nodes of the given node to the given HTML
+    id.
+
+    - html_id: the id of the second node
+
+Attributes
+''''''''''
+
+setAttribute
+
+    Sets a given HTML attribute of the node.
+
+    - name: the attribute name. "style" cannot be used.
+    
+    - value: the attribute value to set
+
+setKssAttribute
+
+    Sets a given KSS attribute of the node, available for reading with the kssAttr() parameter producer function.
+    
+    - name: the attribute name.
+    
+    - value: the attribute value to set
+
+setStyle
+
+    Sets a given style element on the node.
+    
+    - name: the name of the style element.
+    
+    - value: the style element value to set
+
+addClass
+
+     Add a class to the classes of the node, in case it it
+     not there.
+
+    - value: the name of the class
+
+removeClass
+
+     Remove a class from the classes of the node, in case it
+     is defined on it.
+
+    - value: the name of the class
+
+toggleClass
+
+     Add a class to the classes of the node if it's not
+     there, and remove it if it's there.
+
+    - value: the name of the class
+
+Miscellaneous
+'''''''''''''
+
+focus
+
+    Focus the given node that is a form input.
+
+setStateVar
+
+    Sets a variable that resides on the client, in a global
+    namespace. You can also use namespace-name to separate
+    namespaces.  This variable can be sent back to a server
+    action later, as a parameter.
+
+    - varname: the variable name
+    
+    - value: the value to set
+
+continueEvent
+
+    Trigger continuation event. Event will be triggered on the same node or
+    on all the nodes bound for the current event state.
+
+    - name: the event name
+
+    - allnodes (default false): if set to True, event is
+      triggered on all the nodes that are bound in the
+      current event binder.
+
+Debugging helpers
+'''''''''''''''''
+
+error
+    
+    Throws an exception, when executed.
+
+log
+
+    Logs an informational message.
+
+    - message: additional message to log
+
+logDebug
+
+    Logs a debug message.
+
+    - message: additional message to log
+
+alert
+
+    Pops up an alert box. Note that this is not meant to be
+    used for an applications, only for debugging.
+
+    - message: additional message to show in the alert box
+
+Parameter providers
+"""""""""""""""""""
+
+Fetching a given form variable
+''''''''''''''''''''''''''''''
+
+formVar(formname, varname)
+
+    Produces the value of a given variable within a given form.
+
+currentFormVar(varname)
+    
+    Produces the value of a given variable within the
+    current form, which is the one in which the selected
+    node is. The parameter varname is optional, and if it is
+    ommitted, the current node will be used (in this case it
+    must be a form variable itself).
+
+For submitting an entire form, see the kssSubmitForm action
+parameter below.
+
+
+Fetching content
+''''''''''''''''
+
+nodeAttr(attrname [, recurseParent])
+
+    Produces the value of a given html attribute of the
+    selected node. The optional second parameter is by
+    default false. If set to true, it tries to recursively
+    acquire the attribute from parent nodes as well.
+
+kssAttr(attrname [, recurseParent])
+
+    Produces the value of a given kss attribute of the
+    selected node. The optional second parameter is by
+    default false. If set to true, it tries to recursively
+    acquire the attribute from parent nodes as well. The kss
+    attribute may be encoded in the page as a namespace
+    attribute in the form of kssattr:key="value" (only in
+    case of real xhtml iow not for Plone) or in a class
+    emulation mode appended at the end of the existing class
+    attribute as class="... kssattr-key1-value1
+    kssattr-key2-value2 ... kssattr-keyN-valueN"
+
+nodeContent([recursive])
+
+    Produces the textual content of the node. Newlines are
+    converted to spaces. If the parameter is false
+    (default), then only the direct text nodes are
+    considered, if the parameter is true, texts are fetched
+    from the whole subtree.
+
+Miscellaneous
+'''''''''''''
+
+stateVar(varname)
+    
+    Produces the value of a state variable, that is, the
+    same that can be set via the setStateVar command.
+
+pass(key)
+
+    It passes the given parameter from defaultparms to the
+    request.
+
+    It is only used in advanced cases with specially
+    developed stateful event plugins. This enables the
+    plugin to set additional parameters in defaultparms, and
+    these values are made available for KSS.
+
+
+currentFormVarFromKssAttr(attrname [, recurseParent])
+
+    experimental, the two methods cascaded. First the
+    kssAttr is looked up, and then it is used as the name of
+    the form variable of whose value is to be fetched.
+
+Action parameters
+"""""""""""""""""
+
+There are special parameters that are associated with an
+action itself. They all start with kss  and consequently
+normal parameters cannot have a name starting with this
+prefix.
+
+For action-server
+'''''''''''''''''
+
+kssUrl
+
+    Can specify a different url then what would be the page
+    base url and the name of the action concatenated after
+    it. For example, views containing a @@ in the url can be
+    called this way.
+
+kssSubmitForm
+
+    Submits an entire form directly onto the request.
+    
+    The parameter value can be one of the followings:
+
+    - form(formname):  Produces the values of all the
+      variables in a given form.
+    
+    - currentForm(): Produces the values of all the
+      variables in the form that contains the current node.
+    
+    - <string>: equals to form(<string>).
+
+For action-client and the default action
+''''''''''''''''''''''''''''''''''''''''
+
+kssSelector
+
+    Changes the scope of execution. All selectors can be
+    used as if they were parameter providers. A string value can also 
+    be specified, this will be equivalent of css(<string>).
+
+    - htmlid(id)
+	
+Selector types
+''''''''''''''
+
+css(selector)
+
+    Selects node by the css selector.
+
+htmlid(id)
+
+    Selects (zero or) one element that has the givem HTML
+    id.
+
+
+samenode()
+
+    Selects the same node on which the event was triggered
+    originally.
+
+    If used with kssSelector, this is the default, so it has
+    the same effect as not using kssSelector at all.
+
+    If used in commands, it will cause the command to select
+    the same node on which the event was triggered.
+    
+parentnode(selector):
+
+    Return a list of all nodes that match the css expression
+    in the parent chain of the original node.
+
+passnode(key)
+
+    Similarly to passes the given parameter from defaultparms to the
+    request. 
+    
+    It is only used in advanced cases with specially
+    developed stateful event plugins. 
+    The event plugin puts a set of nodes as a
+    value on defaultparms, and this will be used as the
+    selection.
+
+
+Commandset
+""""""""""
+
+The following client action are added as "selector" commands
+(in addition of the action parameters, the first parameter
+should be the selector).
+
+    replaceInnerHTML, replaceHTML, 
+    setAttribute, setStyle, 
+    insertHTMLAfter, insertHTMLBefore,
+    insertHTMLAsFirstChild, insertHTMLAsLastChild,
+    clearChildNodes, deleteNode, 
+    deleteNodeAfter, deleteNodeBefore,
+    copyChildNodesFrom, copyChildNodesTo, moveNodeAfter,
+    toggleClass, addClass, removeClass, focus
+
+The following client action are added as "global" commands:
+
+    setStateVar, triggerEvent
+
+The following helpers are also on the commandset:
+
+getSelector(type, selector)
+        
+        Return a specific type of selector.
+
+        The type can be `css` or `htmlid` or any registered
+        selector type. The selector parameter must contain the value for the
+        selector.
+
+getCssSelector(selector)
+
+        Return a CSS selector with selector as the value.
+
+getHtmlIdSelector(selector)
+
+        Return a HTML id selector with selector as the
+        value.
+
+getSameNodeSelector()
+        
+        Returns the same node selector. This can be used to
+        select the same node where the original event was
+        triggered.
+
+getParentNodeSelector(selector)
+        
+        Return a all nodes in the parent chain which match
+        the given css selector.
+
+3.2 The "zope" plugins
+----------------------
+
+Namespace: "zope"
+
+Commandset
+""""""""""
+
+refreshProvider(selector, name)
+
+    Refresh a page provider with the given name at the
+    selected node.
+
+refreshViewlet(self, selector, manager, name)
+        
+    Refresh a viewlet with the given manager and name at the
+    selected node.
+
+
+3.3 The "plone" plugins
+-----------------------
+
+Namespace: "plone"
+
+Events
+""""""
+
+formProtectionChecked
+    
+    Programmatic event, that gets triggered from the
+    plone-formProtectionCheck action, in case the user's
+    answer to the popup query is yes.
+
+formProtectionFailed
+
+    Programmatic event, that gets triggered from the
+    plone-formProtectionCheck action, in case the user's
+    answer to the popup query is yes.
+
+Actions
+"""""""
+
+formProtectionCheck
+
+    Allow the form protection dialog to be triggered
+    programmatically from kss. The action checks if form
+    protection is needed, pops up the user dialog to let the
+    user decide if he wants to leave the page, and finally
+    trigger either the formProtectionChecked or
+    formProtectionFailed programmatic events, based on the
+    user's answer.
+
+
+removeLockProtection
+
+    Force to remove the locking protection.
+
+initLockingProtection
+
+    Initialize the locking protection.
+    Need to execute on form nodes, typically on load event.
+
+initKupu
+
+    Initialize kupu. This is needed to initialize kupu
+    editors inserted dynamically to the page.
+
+followLink
+
+    Should execute on an <A> node. Results in the link
+    followed as a new request.
+
+submitCurrentForm
+
+    Submit the current form.
+
+initFormTabs
+
+    Initialize javascript for forms that have form tabs.
+    Needs to execute on the form, typically on load event.
+
+--
+
+initFormProtection
+
+    Initialize the form protection that protects the user
+    from leaving the form withoug saving, in case he has
+    changed the form's content.
+    Need to execute on form nodes, typically on load event.
+
+initShiftDetection
+
+    Action used for the quick-edit implementation.
+    
+
+initCheckBoxSelection
+
+    XXX
+
+createCheckBoxSelection
+
+    XXX
+
+initDragAndDrop
+
+    XXX
+
+Commandset
+""""""""""
+
+issuePortalMessage(message, msgtype='info')
+
+    Issue a portal message to the orange message area.
+
+
+refreshPortlet(portlethash, **kw)
+
+    Refresh the portlet identified with the given portlet
+    hash. Additional parameters are passed to the request
+    while the portlet is rendered.
+
+refreshContentMenu()
+
+    Refresh the content menu.
+

Added: kukit/docs/introducing_kss/trunk/4-kss-in-plone.txt
==============================================================================
--- (empty file)
+++ kukit/docs/introducing_kss/trunk/4-kss-in-plone.txt	Fri Jun 29 22:11:36 2007
@@ -0,0 +1,88 @@
+
+
+
+4. KSS in Plone
+===============
+
+
+4.1 Setup of KSS in Plone
+-------------------------
+
+Earlier we learned what headers are needed to be put into the
+page headers for KSS. With Plone the setup is even easier, thanks
+to the support of Plone's ResourceRegistries.
+
+The first thing to observe, that upon installing Plone (that is,
+version 3.0 or higher), the "kukit" javascript resources have the
+necesary entries in the portal_javascript tool. This means kss
+will be activated in every page. Have a look at the additional
+conditions for the resources in portal_javascript. Originally
+they should be::
+
+- for ++resource++kukit.js: "python: here.restrictedTraverse('@@kss_devel_mode').isoff()"
+
+- for ++resource++kukit-devel.js: "python: here.restrictedTraverse('@@kss_devel_mode').ison()"
+
+In addition, certain Plone releases may combine these with other
+condition, to restrict the loading of KSS in certain pages where
+it is not needed, for performance reasons.
+
+For managing the .kss files, a portal_kss tool is available. This
+is similar to portal_css, but it forces the link rel tags to
+kinetic-stylesheet as needed for KSS to identify the resources.
+The .kss files Plone uses are contained here. In addition you can
+enter any additional .kss files your application uses. Although
+these files will be (just like css files) included for every page
+in the portal without restriction, this is not a problem, since
+the selection mechanism makes sure that only those KSS rules will
+activate for your page, that are really needed for it.
+
+To summarize: if the javascript and kss resources are properly
+registered in Plone's portal_javascript and portal_kss files,
+there is nothing more to do then to sit back and enjoy KSS's
+functionality everywhere in the portal.
+
+4.2 How to kssize existing widgets
+----------------------------------
+
+XXX
+
+4.3 What features are implemented with KSS in Plone
+---------------------------------------------------
+
+We try to give a non-exhaustive report about what features are
+implemented with kss:
+
+- Content tab switching (currently disabled because of the lack
+  of some supporting functions)
+
+  The content tabs act in a way that only the content region gets
+  updated if a tab is clicked.
+
+- Field validation
+
+  If the focus leaves a field, its content is automatically
+  validated, and in case of problems, a status message is shown
+  immediately.
+
+- Quick edit
+
+  While viewing a page's content, if a field is clicked, it
+  becomes editable and its content gets saved upon confirmation.
+  This works with several field types including the kupu rich
+  editor.
+
+- Action menus
+
+  Set default view, copypaste, and the changing of the publishing
+  state work without leaving the page.
+
+- Locking
+
+  Locking content types is handled through an ajax interface.
+
+As a consequence, the plone.app.ukss package contains the "plone"
+plugin, which provides support for custom application building,
+including handling portal messages, refreshing portlets and
+viewlets.
+

Added: kukit/docs/introducing_kss/trunk/5-extension-with-custom-plugins.txt
==============================================================================
--- (empty file)
+++ kukit/docs/introducing_kss/trunk/5-extension-with-custom-plugins.txt	Fri Jun 29 22:11:36 2007
@@ -0,0 +1,50 @@
+
+5. Extension with custom plugins
+================================
+
+KSS has a plugin architecture. Apart from the core that is
+parsing the .kss files and binding them to nodes, communicating
+with the server and executing the KSS commands, almost every
+component, incuding actions, events, parameter providers,
+selectors is designed to be pluggable.  
+
+The KSS plugin API makes it possible to create all these
+components and register them to KSS.
+
+The plugin development is a seldom needed and specialized task.
+To be able to do it, you must be familiar with javascript and
+KSS.
+
+5.1 wrapping javascript on the client side
+------------------------------------------
+
+If we write a new plugin, first we need to create a javascript
+file that will contain the code for our plugin.
+
+To start with, we need to create a javascript namespace for our
+new plugin::
+
+    kukit.myplugin = {};
+
+5.1.1. Creating an action
+"""""""""""""""""""""""""
+
+An action is a javascript method that is called when the action
+is executed. It receives the parameters in a given form and it
+has to check them.
+
+
+
+
+
+
+
+5.2 registering your plugin on the server and shipping with your product
+------------------------------------------------------------------------
+
+XXX
+
+5.3. Testing
+------------
+
+XXX


More information about the Kukit-checkins mailing list