On 7/20/11 12:11 PM, Ryosuke Niwa wrote:
On Wed, Jul 20, 2011 at 11:56 AM, Aryeh Gregor <simetrical+...@gmail.com <mailto:simetrical%2b...@gmail.com>> wrote:

    On Wed, Jul 20, 2011 at 1:43 AM, David Flanagan
    <dflana...@mozilla.com <mailto:dflana...@mozilla.com>> wrote:
    > Finally, I still think it is worth thinking about trying to
    model the
    > distinction between removing nodes from the document tree and
    moving them
    > (atomically) within the tree.

    I'll chip in that I think this is useful.  It makes things somewhat
    more complicated, but remove/insert and move are conceptually very
    different.


But internally, a node movement is a removal then an insertion. There's always possibility that a node gets removed then inserted again after mutation observers are invoked. Also, what happens if a function removed a bunch of nodes and then inserted back one of them?

My definition of moving a node atomically is taking a node that is already in the tree and passing it to appendChild() or insertBefore(). Everything else is regular node removal followed by node insertion.

If you get a mutation event that says that node A was removed from node B and inserted into node C, you know nothing about the state of node A, since it could have been mutated while it was outside of the tree and no mutation events would have been recorded. Its attributes, text and children all could have changed, so the mutation listener has to basically discard everything it knows about node A and treat it as a brand-new node.

If, on the other hand, there was some way for the listener to know that the node was moved atomically, then it would know that it hadn't missed any mutation events and it could retain whatever cached state it had for node A, changing only the parent.

Here's one possible way that the distinction between move and remove could be made: keep the added and removed lists of nodes exactly as they are now. But when a node is moved atomically, also add it to an array of moved nodes. Listeners that don't care about the move/remove distinction can just use the added and removed properties as in the current proposal. But listeners that do care can check any added or removed node against the moved array to see if it was an atomic move.

Another approach that might work: define a "reparent" or "move" mutation event type. So when node A is moved from parent B to parent C, the mutations would be:

[{target:A, type:"reparent"},
 {target:B, type:"childList", removed:[A]},
 {target:C, type:"childList", added:[B]}]

To make this work, if an atomic move was followed by a removal, the reparent mutation would have to be removed from the list of mutations.

    David

    e.g. say we have <div>hello<br>world<br>w3c<br></div>

    And we have a hypothetical function that does:

     1. Remove all children of div
     2. Inserts "w3c" back after div.

    Then what should the list of mutations contain?  Should it contain
    2 items one that says it removed "hello", "world", and 3 br's, and
    then another one saying "w3c" moved?  But then child nodes are not
    all consecutive and scripts won't be able to infer where these
    nodes were even if we provided offsets or before/after node.

    Should it contain 3 items, one that says "hello", "world" and the
    first 2 br's are removed, then one for moving "w3c", and then
    another one for removing the last br?  But then UAs have to keep
    reorganizing the list as the function modifies more DOM because
    there is no way to differentiate "w3c" until it's inserted back
    into DOM.


- Ryosuke

Reply via email to