- From: Jonas Sicking <jonas@sicking.cc>
- Date: Fri, 5 Aug 2011 13:59:11 -0700
>> Why is there a need for a 'reapply' action? How is it different from >> the 'apply' action? > > > In the case of collaborative editing apps, reapply is different from apply because the backend server may have a tree of transaction history and may need to consult on demand in order to determine exactly what mutations have to happen. Looking at your examples other emails in this thread I do understand the idea better I think. However, it seems to me that apply is the same as reapply plus some initialization. This leads me to two questions: 1. Would it be better make the split be init/apply/unapply rather than apply/unapply/reapply. The latter seems to cause a lot of code duplication between apply and reapply as can be seen in your examples. IMHO the former is also more understandable, but that might be a matter of taste. 2. If we do go with the init/apply/unapply approach, would it make sense to skip init and just ask people to do it manually before creating the transaction? Or at least make init optional? >> What is the purpose of the UndoManager.replace function and it's >> replaceGroup argument? In general I'm not sure I fully understand >> "transaction groups". Are they different from simply a set of >> transactions which have been merged together such that they are >> done/undone together? > > > Yeah, sorry about that. ?I should clarify that part of the design. > > UndoManager.replace > The key observation is that ManagedTransaction is constrained to work only with a "proper sequence of managed transactions". ?Whenever an app inserts a manual transaction or?directly?mutates the DOM under the same editing host, the UA won't be able to unapply/reapply the existing ManagedTransaction created by user editing actions; i.e. inserting a manual transaction breaks the existing managed transactions. Follow you so far... >?Without this constraint, however, the UA is required to keep track of all DOM mutations happening in the undo scope :( ...but now you lost me :) For the record, my vision was that the editor will keep track of the mutations *it* does to the DOM and inserts managed transactions for those into the UndoManager. Any other mutations to the DOM the editor completely ignores. If the page makes other mutations to the DOM, it should use the UndoManager and create a managed transaction for it. If it doesn't, the page is on its own. If the UndoManager is asked to undo or redo a managed transaction and the DOM doesn't look the same as it had expected, then it should do the best it can. In some cases this means that it won't produce useful mutations, but this only happens if the page has done BadThings (tm). > Given this constraint, the apps that do use managed transactions such as collaborative editing apps need to replace the managed transactions inserted by the UA by the corresponding manual transaction when user types text. The vision I had for how this is done is that the editor code should fire events before it makes any modifications to the DOM. The website should be able to cancel this event and instead perform it's own modifications to the DOM. Until the various editor implementations are there, the website can always undo the editor transaction and then create its own manual transaction and insert in the UndoManager. > Transaction Group > When a user types "hello", he isn't really typing all of "hello" at once but rather inserting character "h", "e", "l", "l", and "o", letting the UA insert each letter as a separate managed transaction in the order. ?However, when the user undoes or redoes this typing command, the entire "hello" needs to removed. ?This is accomplished as grouping 5 managed transactions for inserting "h", "e", "l", "l", and "o" as a transaction group. Cool, that matches my understanding. Is there a reason that you're not allowing manual transactions to be part of a transaction group though? >> Why expose explicit Transaction objects. What value does that provide? > > > I admit this is more of stylistic issue rather than the technical limitation but given a transaction already has label and apply "properties", it seemed more natural for it to be an object. ?That'll allow us to add more properties in the future. > > In particular, I really wanted to provide a mutation list as discussed on the mutation events replacement thread on public-webapps. ?This allows apps to determine which transaction did what without having to listening to each mutation event, and makes it easier to replace managed transactions by manual transactions as described above. Hmm.. this is indeed an interesting idea. Though I would imagine that it's even more interesting for the page to know the "semantics" of the modification rather than knowing what exact DOM modifications are performed. I.e. understand that a transaction means "break current text into two paragraphs" rather than "insert new element with name 'p'. Remove text from other element. Add text to newly inserted element". This in order to be able to reapply the transaction even if the page looks slightly differently due to other collaborators editing it. My idea is that the event that editor fires before modifying the DOM would essentially describe "inserting paragraph break at cursor". / Jonas
Received on Friday, 5 August 2011 13:59:11 UTC