On 7/2/2011 12:36 PM, Ryosuke Niwa wrote:
On Sat, Jul 2, 2011 at 10:46 AM, John J. Barton
<johnjbar...@johnjbarton.com> wrote:
1) break on mutation. In Firebug we add DOM mutation listeners to
implement graphical breakpoints. The replacement would work fine for
local, element observation breakpoints like add/remove attribute.
If my goal is to break on addition of elements with class="foo", then
I guess I have to listen for addChildlistChanged on all elements, and
add an additional addChildlistChanged listener for each new element?
So in general one would implement document observation by walking
the DOM and covering it with listeners?
I don't think we can support this use case in general. We're trying
to avoid invoking scripts synchronously and your use case requires
exactly that.
Are you talking about the algorithm described by Olli and Jonas:
http://www.mail-archive.com/public-webapps@w3.org/msg14008.html
? If I set a breakpoint in a listener in their algorithm I would expect
to halt the browser before the algorithm completed and especially before
another DOM change can occur. (An entirely separate issue is how the
debugger mutates the document).
The only part that is async in the Mutation Event replacement is further
DOM events.
2) element transformation. The replacement fires "after" a mutation.
Library or tools that want to transform the application dynamically want
to get notification "before" the mutation.
Why do you need to get notified before the mutation?
Because developers want to take actions before the mutation. Removing
mutations after they are committed is a kludge we should try to avoid.
Again, this is
exactly the sort of usage that causes us headaches and what we want to
avoid because scripts can then modify DOM before we make mutations.
A common solution then is to bracket changes:
"beforeChange" or "onModelChanging"
"afterChange" or "onModelChanged"
Of course element transformation may want to prevent the current
change and replace it. Some changes are reversible so the observed
change can be countered with a remove (at unknown cost to performance
and user experience).
I don't think we can address your use case here. Scripts'
intercepting and preventing mutations browser is about to make or
mutating DOM in the way browser doesn't expect is exactly what we want
to avoid.
The stated properties (goals) of the replacement are (rephased):
1. No script operation in the middle of mutation,
2. Callback in order of mutation,
3. No propagation chain,
Importantly the current proposal has an undesirable feature:
4. DOM modification in listeners is asynchronous.
Preventing mutation in a 'before' listener still allows all of the
properties as far as I know.
A "two-phase-commit" like solution can have all of these properties.
Copy Jonas' AttributeChanged algorithm from the page cited above.
Replace "...ed" with "...ing". Add a flag 'cancelChange' initially
false. Add step
8b. If cancelChange is true, abort these steps and the DOM
mutation. Fire event DOMMutationCanceled
The 'before' version would be more powerful.
The Mutation events replacement gains its advantages from property 3 and
especially 4. Whether you enter the callback algorithm before or after
the mutation does not change this. In fact I think from the API point of
view the 'before' version is clearer. If the developer knows that the
callback is 'before' the mutation, they are naturally set up to think
about the meaning of additional DOM mutations. The arguments in the
callback are known to be in flight.
In fact we could go one step further and eliminate the undesirable
feature #4: if notifyingCallbacks is true, all DOM write operations
fail. That way developers are never surprised by DOM functions that
fail as in the current version. Instead developers will explicitly have
to cascade modifications via separate events. This would be a much less
mysterious solution. In some places Firefox already works in the
mystery way and speaking from experience it is not fun to figure out why
your function calls have no effect.
If you have both a before and and after event and both events prevent
DOM write, then the programming paradigm could be clear:
before handlers cancel mutations and signal 'after' handlers to
stage alternatives
after handlers stage responses to mutation or alternatives to
canceled mutations.
jjb