- From: mozer <xmlizer@gmail.com>
- Date: Thu, 4 Jun 2009 13:37:09 +0200
- To: Jonas Sicking <jonas@sicking.cc>
- Cc: Webapps WG <public-webapps@w3.org>
- Message-ID: <21d9ade60906040437p78a4f73ap1d1fa9bf6a033847@mail.gmail.com>
On Thu, Jun 4, 2009 at 12:07 PM, Jonas Sicking <jonas@sicking.cc> wrote: > Here's an API that might work: > > The following methods are added to the Document, Element and > DocumentFragment interfaces: > > addAttributeChangedListener(NodeDataCallback); > addSubtreeAttributeChangedListener(NodeDataCallback); > addChildlistChangedListener(NodeDataCallback); > addSubtreeChangedListener(NodeDataCallback); I would go for addSubtreeElementChangedListener for this one since a modification to an attribute in the subtree does not trigger it > > addTextDataChangedListener(NodeDataCallback); > removeAttributeChangedListener(NodeDataCallback); > removeSubtreeAttributeChangedListener(NodeDataCallback); > removeChildlistChangedListener(NodeDataCallback); > removeSubtreeChangedListener(NodeDataCallback); and removeSubtreeElementChangedListener... > > removeTextDataChangedListener(NodeDataCallback); > > And add the following interface: > [CallBack=FunctionOnly, NoInterfaceObject] > interface NodeDataCallback { > void handleEvent(in Node node); > }; > > These are *not* DOM-Event listeners. No DOM Events are created, there > are no capture phases or bubbling phases. Instead you register a > listener on the node you are interested in being notified about, and > will get a call after a mutation takes place. The listeners are called > as follows: > > 'AttributeChanged': Called when an attribute on the node is changed. > This can be either a attribute addition, removal, or change in value. > If setAttribute is called the 'AttributeChanged' listener is always > called, even if the attribute is given the same value as it already > had. This is because it may be expensive to compare if the old and new > value was the same, if the value is internally stored in a parsed > form. > > 'SubtreeAttributeChanged': As for 'AttributeChanged', but called not > just for attribute changes to the node, but also to any descendants of > the node. > > 'ChildlistChanged': Called if one or or mode children are added or > removed to the node. So for example when innerHTML is set, replacing > 10 existing nodes with 20 new ones, only one call is made to the > 'ChildlistChanged' listeners on that node. > > 'SubtreeChanged': Same as 'ChildlistChanged', but called not just for > children added/removed to the node, but also to any descendants of the > node. > > 'TextDataChanged': Called when the data in a Text, CDATASection or > ProcessingInstruction, is changed on the node or any of its > decendants. > > The exact algorithm would go something like this: > > The implementation contains a global list, pendingCallbacks. Each item > in pendingCallbacks is a tuple: <callback, node>. > The implementation also contains a flag, notifyingCallbacks, which > initially is set to false. > > If an attribute is changed on node N, perform the following steps: > > 1. For each 'AttributeChanged' callback, C, registered on N, add an > item to the end of pendingCallbacks with the value <C, N> > 2. For each 'SubtreeAttributeChanged' callback, C, registered on N, > add an item to the end of pendingCallbacks with the value <C, N> > 3. Set N to N's parentNode. > 4. If N is non-null, go to step 2. > 5. If notifyingCallbacks is set to true, or pendingCallbacks is empty, > abort these steps. > 6. Set notifyingCallbacks to true. > 7. Remove the first tuple from pendingCallbacks. > 8. Call the handleEvent function on the callback in the tuple, with > the 'node' argument set to the node from the tuple. > 9. If pendingCallbacks is not empty, go to step 7. > 10 Set notifyingCallbacks to false. > > A similar algorithm is run when children are added and/or removed from > an element/document/document-fragment, just replace 'AttributeChanged' > with 'ChildlistChanged', and 'SubtreeAttributeChanged', with > 'SubtreeChanged'. > > And when Text/CDATASection/ProcessingInstruction Please add "Comment" too > nodes have their > contents modified the same algorithm is run, but without step 1, and > with 'SubtreeAttributeChanged' replaced with 'TextDataChanged'. > > There's a few of properties here that are desirable, and one that is > sub-optimal. > > First of all no notifications are done until after the implementation > is done with the mutations. This significantly simplifies the > implementation since all critical work can be done without worrying > about script performing arbitrary operations in the middle. > > Second, all callbacks are notified in the order mutations happen in > the tree, even when another callback performs further mutations. So if > a callback for 'ChildlistChanged' sets a attribute on the newly > inserted node, the other callbacks are still going to get first > notified about the node being inserted, and then about it having an > attribute set. This is thanks to the notifyingCallbacks flag. > > Third, these notifications should be significantly faster. Since there > are no DOM Events, there is no need to build propagation chains. > There's also no need to recreated the old attribute value, or to fire > one event for each node if multiple nodes are added and removed. > > The only undesirable feature is that code that mutates the DOM from > inside a callback, say by calling setAttribute, can't rely on that by > the time that setAttribute returns, all callbacks have been notified. > This is unfortunately required if we want the second desirable > property listed above. Indeed... > > > > The only feature of mutation events that this doesn't provide is the > functionality that the > DOMNodeRemovedFromDocument/DOMNodeInsertedIntoDocument. I believe that > these are implemented in some browsers. I don't know how these > browsers would feel about dropping support without supplying some sort > of alternative. If needed we could add the following > > addInDocumentChangedDocumentListener(NodeDataCallback); > removeInDocumentChangedDocumentListener(NodeDataCallback); > > But I'm not sure that there is web-dependency on this, or good use cases. > > / Jonas > > Xmlizer
Received on Thursday, 4 June 2009 11:37:47 UTC