SCXML: DOM Events I/O

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 Wednesday, 26 September 2012 11:17:52 UTC