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