Re: SCXML: DOM Events I/O

Hi,

I'm the author of SCION, another js-based implementation of SCXML. You
raise a lot of interesting points, and I'd like to share my perspective.
I'll first give you some background on the decisions that went into SCION,
and then I'll attempt to address your points individually.

SCION is developed to be a portable, embeddable SCXML interpreter, and
should be runnable in any context where js can be embedded, so it works
well in the browser, node.js, rhino, and even inside of other programming
languages (currently, there are binding for Python, Java and C#).
Therefore, I developed a simple API that could be used across these various
contexts, and left it to the developer to understand how to use this API to
integrate SCXML with the DOM in the browser context (e.g. to send DOM event
from SCXML, receive DOM events from the browser, and anchor SCXML to DOM
elements, as you've described).

The SCION API is described here: https://github.com/jbeard4/SCION#api

The Quickstart provides a simple description of how SCXML can be applied in
the browser environment to receive events and script DOM content:
https://github.com/jbeard4/SCION#quickstart-and-simple-use-case
The live demo is hosted live here:
http://jbeard4.github.com/SCION/demos/drag-and-drop/drag-and-drop.html

The first three questions you pose have to do with integrating SCXML into
the browser environment: how does <send type="DOM"> work, how does the
statechart instance receive events, and how do you anchor it in DOM? These
are useful questions to ask, as the SCXML spec does include language about
using SCXML in the browser, and it would be better if it the spec was
unambiguous. However, I've had several opportunities to present SCION to
front-end developers recently, and they seem to be universally concerned
with the fact that SCXML uses an XML syntax. XML is still painful to deal
with for js devs for reasons that are by now well-documented, and I think
this is the primary issue blocking adoption of SCXML in front-end
development. For this reason, I'm considering rolling a JSON format for
SCXML. SCION already uses a JSON-serializable intermediate representation
internally, and so I'm thinking about simply fixing this up and exposing it
as an alternative document format that SCION can accept as input. From a
practical perspective, this work may be more important than refining the
spec.

I'll now address your suggestions.

I think the first point you proposed for sending events via <send
type="DOM"> is sensible, and I would agree that events should be sent via
CustomEvent, and that CSS selectors should be allowed as the target, as
these are more commonly used in front-end development.

Regarding your suggestion on anchoring, I agree that it should not be a
requirement to bind an SCXML instance to an element in a web page. This
does lead to the consequence that the CustomEvent objects sent by that
SCXML instance via <send type="DOM"> would not have a target property, and
I think that's fine, as I believe target can be set to "null", which would
semantically make sense in this case. I also feel that relative xpath paths
from <send type="DOM">  in a document that is not anchored in the DOM
should simply throw an error. This could be determined through static
analysis when the model is parsed.

I would furthermore suggest that one should abandon the idea of anchoring
the SCXML document itself in the DOM. In 2010, I was really optimistic
about the concept of inlining SCXML markup, and using it as a declarative
syntax for interactive behaviour. I made some
prototypes<http://commons.apache.org/sandbox/gsoc/2010/scxml-js/demo/drag-and-drop/drag-and-drop.html>to
this effect, and gave a
presentation<http://www.svgopen.org/2010/registration.php?section=conference_speakers#user_88>about
it at the SVG Open 2010 conference. This was really easy to do in SVG
and XHTML because, as XML documents, it's easy to mix in XML content in
other namespaces to form XML compound documents. HTML5, however, does not
support custom elements, and, to the best of my knowledge, there is not
currently a way to inline arbitrary XML content in an HTML5 document if
that XML content may contain <script> tags, which SCXML does. While it
would still be technically feasible to inline SCXML content in an SVG
document, it was expressed to me at this year's SVG Open conference that
the SVG working group is now focused on making SVG the graphical
counterpart to HTML, and thus mixing markup is unlikely to be
well-supported. To summarize, I don't believe it to be practical to insert
SCXML content directly into the markup of a page, and this has implications
regarding anchoring SCXML content in the DOM.

What would be practical, and I think useful in some cases, is binding an
instance of a particular SCXML document with a particular node in the DOM,
such that the SCXML instance can automatically consume the DOM events sent
to the bound DOM node, and events which the SCXML document sends to other
DOM nodes via <send type="DOM"> would seem to originate from the DOM node
to which the SCXML instance is bound. This could even be
expressed declaratively using a custom data attribute on the bound element,
e.g. <div data-scxml-href="document.scxml"/>, which would indicate that the
that the document at that href should be fetched, instantiated, and event
listeners created which would pass events received by that element to the
bound state machine instance.

Currently, SCION maps DOM events to SCXML events in the following simple
way:
* The SCXML event name is derived from the DOM event name.
* The SCXML event data is the DOM event itself

You can see an example of this in the Quickstart, and I think the same
mapping could be applied to SCXML instances that are bound to DOM elements.

I hope this is helpful, and I'm looking forward to seeing what you do with
your project. Best,

Jake


On Tue, Sep 25, 2012 at 4:41 PM, David Junger <tffy@free.fr> wrote:

> Hi. I'm the main developer for JSSCxml (https://github.com/Touffy/JSSCxml),
> a browser-based JavaScript implementation of SCXML.
> Here's my feedback on DOM interaction and an SCXML interpreter API.
>
> * Sending events with type="DOM":
>   - most properties of DOM Events are read-only in the browser. Those few
> properties that can be set, depend on the exact Event constructor (basic
> Event, MouseEvent, CustomEvent…), yet the SCXML recommendation does not
> recommend a way for SCXML authors to choose one.
>   One possible solution would be to pick CustomEvent as the only DOM Event
> sent by SCXML interpreters, and put any event data (including <content>, as
> a string) in the CustomEvent's "detail" property. Alternatively, the event
> type could be more specific (type="DOM_Mouse" for a MouseEvent, etc).
>   - the SCXML recommendation should define a default value for the
> "cancel" and "bubbles" Event properties. It should also state that DOM
> Events sent from SCXML are never cancellable (or else explain what
> cancelling such an event would mean for the interpreter). If it seems
> interesting to allow authors to choose the value of "bubbles", I would
> consider making it an attribute of the <event> element so it's structurally
> separated from the event data (namelist, <param>s, <content>).
>   - the meaning of the target attribute of <send type="DOM"> is not well
> defined. There are two main schemes for adressing an element: XPath and CSS
> selectors. While XPath is more familiar to XML authors in general, CSS
> selectors are way more familiar to HTML authors. Why not use both? either
> with an explicit indication of the target type, or (as is currently the
> case in JSSCxml) with some heuristics (which is quite accurate because
> XPath expressions and CSS selectors have incompatible syntax). Note that
> basic #fragment identifiers are valid CSS selectors.
>   - there should be a default target. See the third *


> * Receiving (DOM or other) events from the browser
>   - magically handling every Event received by the <scxml> element and
> only those that target it directly has several issues, detailed later. For
> now, let's just say it's not a good idea. Simply lifting the restriction
> about the <scxml> element being the intended target is not a good idea
> either.
>   - typically, authors may want to send custom data to the SCXML
> interpreter. That means defining an event listener for an automatic DOM
> Event (e.g. a "click") or some other trigger (e.g. a callback) and, in
> reaction, instantiating a new Event with some data, and dispatching it at
> the <scxml> element. That is, using the mechanism described by the current
> draft.
>   I don't see a way around using *some* JavaScript to bind the trigger to
> an SCXML interpreter and pick the data to send along. But it should be
> simpler and more flexible. The SCXML interpreter should have a method that
> external JavaScript (e.g. an HTML event listener) can use to add an
> external event to the queue, or could just send a name and data to it and
> the interpreter would generate a new event with that name and data. At the
> moment, I plan for JSSCxml to support the following methods (assuming sc is
> an SCxml interpreter instance):
> sc.extEvent(Event ev)
> sc.extEvent(SCxml.ExternalEvent ev)
> sc.extEvent(String name, mixed data, Element origin)
>   - the origin of those events can be converted from an actual instance of
> Element into an XPath or CSS selector, in order to avoid mixing the
> external DOM and the ideally self-contained SCXML, but passing the actual
> Element reference is more efficient and flexible.
>   - if there must be an automatic conversion of Events reaching the
> <scxml> element into SCXML events, then each type of event should be
> registered for that conversion, e.g.:
> sc.autoEvent("keydown")
> would put every future Event with the type "keydown" that passes through
> the <scxml> element in the SCXML external queue. Of course, there should be
> a call to stop handling events automatically.
>

 * DOM anchor of the SCXML interpreter:
>   - the SCXML interpreter may be represented by a JavaScript object with
> no DOM presence. The SCXML recommendation does not forbid that possibility,
> nor should it.
>   - moreover, an author may wish to treat <scxml> tags the same way they
> do <script>s instead of worrying about exactly where they should be in the
> DOM and how DOM events will reach them, or they may want to place them in
> the path of certain UI elements' events but that may be different from
> where the outgoing Events should originate.
>   - yet there should be a srcElement when the interpreter generates a DOM
> Event (not easy to implement, though, since you can't write that property),
> and a default target for sending those DOM Events.
>   - finally, relative XPath evaluation requires a reference node.
>   To address those issues, the interpreter could be given any Element in
> its parent document to use as an origin for sent events and default target,
> and resolving relative XPaths. Events would bubble up or trickle down from
> that origin (bubbling seems more useful to me at this point). That "anchor"
> may be different from the <scxml> element, if present.


> * JavaScript API and interpreter-related DOM Events
>   The SCXML interpreter will necessarily have JavaScript methods intended
> for API use and that should be standardized to some extent. Some of that
> API would also be present in implementations on other platforms.
>   - The interpreter might fire a "load" event, and generally, events about
> its status. The moment it sends these events, and their name, should be
> defined or at least reminded (when the DOM recommendation is clear enough)
> in the SCXML recommendation. Most importantly, there should be an event
> that says the SC is parsed and ready to be interpreted, to support (without
> writing extra SCXML) the use case where you want to load an SCXML document
> to have it ready, but not to start the interpretation as soon as possible.
>   Here is a summary of the minimal API I suggest for SCXML interpreter
> objects (not to be confused with <scxml> Elements):
>
> // constructor for SCXML interpreter (named SCxml here because I'm doing
> it in my implementation):
> SCxml SCxml(string source, Element anchor)
> // source can be a URI or an SCXML string, though implementations may
> support
> // additional types, e.g. a parsed SCXML Document or an <scxml> Element
>
> // if the interpreter doesn't start running ASAP, start it with
> undefined run()
>
> // registering event types to handle automatically:
> undefined autoEvent(String type, Boolean capture)
> undefined removeAutoEvent(String type)
>
> // receiving events through a method call:
> undefined extEvent(Event ev)
> undefined extEvent(SCxml.ExternalEvent ev)
> undefined extEvent(String name, mixed data, Element origin)
> // may warn if it can't process the event, but does not throw an exception
> // data defaults to null and origin to the enclosing document's root
>
> Aforementionned <scxml> Elements on the page, especially if they are to be
> automatically evaluated in the manner of <script>s, should have an
> "interpreter" property referencing the interpreter object that runs them.
>
> I don't think it's necessary to recommend anything about
> SCxml.ExternalEvent, but it wouldn't hurt either.
>
>                         David
>
>

Received on Thursday, 27 September 2012 02:27:53 UTC