Re: [UndoManager] Re-introduce DOMTransaction interface?

On Fri, Jul 6, 2012 at 4:53 PM, Ryosuke Niwa <rniwa@webkit.org> wrote:
>
> On Jul 6, 2012 4:48 PM, "Jonas Sicking" <jonas@sicking.cc> wrote:
>>
>> On Fri, Jul 6, 2012 at 3:18 PM, Ryosuke Niwa <rniwa@webkit.org> wrote:
>> >
>> > On Jul 6, 2012 3:06 PM, "Boris Zbarsky" <bzbarsky@mit.edu> wrote:
>> >>
>> >> On 7/5/12 3:05 PM, Ryosuke Niwa wrote:
>> >>>
>> >>> Also, I think consistency matters a lot here. I'm not aware of any
>> >>> other
>> >>> Web-facing API that takes a pure object with callback functions.
>> >>
>> >>
>> >>
>> >>
>> >> http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html#Traversal-NodeFilter
>> >> (the acceptNode function).
>> >>
>> >> Or was the point about having multiple callback functions?
>> >
>> > Precisely about having multiple callback functions.
>> >
>> > Also to respond to some of earlier comments, I don't think most web
>> > developers think of passing objects when adding event listeners.
>>
>> Why does having one callback function rather than two make
>> implementation harder?
>
> Because we can implement it as a special event listener.

It seems to me that you could do this either way. Sure, it might take
some code modifications, but implementing any API will require code
modifications.

> But the difficulty in implementing it correctly in WebKit isn't main point.
> The inconsistency with other DOM API is.

I think we need to realize that a lot of the APIs that have been
designed in the past aren't terribly good APIs. The fact that people
almost more often than not wrap DOM APIs to create APIs more palatable
to them I think is something we should take as an indicator that we're
doing something wrong.

In other words, I think it's more important to focus on what makes a
good API, than what is consistent with other DOM APIs.

Something that I really liked about the old API was the fact that
using it created very intuitive code. Basically you just write a class
the way you normally would write a class, and then pass in your
object:

x = {
  someState: 0,
  apply: function() { this.someState++; this.modifyDOM(); },
  unapply: function() { this.subState--; this.modifyDOMOtherWay(); },
  ...
};
undoManager.transact(x);

You can even do things like

undoManager.transact(createParagraphTransaction(params));

This is an API which flows nicely with JS and what code *should* look like.

Using DOM Events you end up with much more awkward code:

(function() {
  var x = new DOMTransaction();
  var someState = 0;
  x.onapply = function(e) { someState++; modifyDOM(); }
  x.unapply = function(e) { someState--; modifyDOMOtherWay(); }
  ...
  undoManager.transact(x);
})();

You technically could set "expandos" on the returned DOM object like:
x = new DOMTransaction();
x.someState = 0;
x.onapply = function(e) { this.someState++;  this.modifyDOM(); }
x.onunapply = function(e) { this.someState--; this.modifyDOMOtherWay(); }
x... = ...;
undoManager.transact(x);

However that isn't recommended since it could break if we ever expand
the DOMTransaction API.

There's no way to subclass DOMTransaction directly to get anything
looking like real JS "class" syntax.

The fact that we have to choose between creating APIs that feel like
"DOM APIs" or "JS APIs" I think is an indication that "DOM APIs" are
doing things wrong. There should be no difference between "DOM APIs"
and "JS APIs".

/ Jonas

Received on Thursday, 12 July 2012 02:43:29 UTC