DOM2 Event gripes

   I'm trying to implement an SVG editor (Gill) as much as possible
based on the relevant W3C standards, and I'm running into some
problems with DOM2 events. I'm trying to use DOM as the document
model, and use the Event/Listener mechanism to implement _all_ views,
including the primary window of the application.

   First, is there any source available for DOM2 events? Mozilla seems
to implement a subset (no mutation events, very limited capture
semantics). My usual reaction when confronted with vague docs is to
RTFS, but in this case I'm having trouble finding FS to R.

   Here are some points that are not clear to me:

1) subtreeModified "can be used instead of the more specific events
   listed below." I assume "used" refers to the listener side. Also,
   regarding the batching, this assumes that there is a mechanism for
   making modifications to the DOM in a batch, currently not defined
   in any W3C DOM standard.

2) what is the difference between nodeInsertedIntoSubtree and
   nodeInsertedOntoParent? I assume a DOM implementation would
   generally have to serve both events when a node is inserted.

3) what events get generated when you do a splitText()?
   characterDataModified on the original node and nodeInserted* on the
   new node? Implementation-defined?


   The exact algorithm for event processing is not clear to me. Below
is pseudocode that I _think_ follows the spec. If not, I'd love to
hear about it!

processEvent (Event event, Node node,
   boolean postProcess, boolean bubbles, boolean cancellable) {
   /* Find potential capturers */
   List chainDown = [];
   Node n;

   event.returnValue = true;

   for (n = node; n != null; n = n.parentNode) {
      chainDown = [n] + chainDown;
      /* or, chainDown = cons (n, ChainDown); for Lisp'ers */
   }

   /* chainDown contains a list of all nodes from the document root
      down to node, inclusive */

   event.cancelCapture = false;
   for n in chainDown {
      for listener in n.listeners {
         if (listener.postProcess == postProcess &&
             listener.useCapture &&
	     listener.type == event.type) {
            listener.handleEvent (event);
         }
      }
      if (event.cancelCapture) goto captureCancelled;
   }
captureCancelled:

   event.cancelBubble = false;
   /* now bubble event up */
   for (n = node; n != null; n = n.parentNode) {
      for listener in n.listeners {
         if (listener.postProcess == postProcess &&
             !listener.useCapture &&
	     listener.type == event.type) {
         listener.handleEvent (event);
      }
      if (!bubbles || event.cancelBubble) goto bubbleCancelled;
   }
bubbleCancelled:

   if (!cancellable || event.returnValue) {
      "execute DOM implementation's default actions"
   }
}

   Lastly, I see the bubbling mechanism and multiple listeners as
having infelicitous interactions. Suppose for a minute that I have a
single view implemented through the Event/Listener mechanism. Now I
have a good, generic way of doing incremental changes to the view, or,
when the view of a node does not support incremental rendering,
allowing the change to bubble up to a container that does. In this
case, the container can delete the view that's changed, and re-render
a new one. As soon as an event reaches a node that knows how to handle
it, the bubbling is cancelled.

   However, this obviously fails when there are multiple views. The
cancellation of the bubbling in one view also causes the other views
to be cancelled. It looks like what I really want to do here is
implement my own event propagation in each view. Other ideas are
welcome, or perhaps the draft should be changed to support this
architecture more directly.

Raph

P.S. http://www.levien.com/svg/ for more information about Gill.

Received on Thursday, 24 June 1999 07:28:28 UTC