Reputation: 744
I'm developing a web application which uses the Google Drive Realtime API. The API is used to store the document's data and to synchronize all modifications between the active collaborators.
Now I want to add support for text boxes with rich text (only some basics like bold, underline and links) to this application. A text box should enable collaborative text editing similar to Google Docs. I searched and experimented for some days now but I can't find a proper solution in how to exchange the data or how to build a suitable data model that would work with the Drive Realtime API.
There are several ways that one can think of like exchanging HTML (or a similar markup) within a CollaborativeSting. But that wont work because it would probably break the markup sooner or later.
Another (probably much better) starting point is to use a more abstract data model as the Quill editor does. (I would like to use this editor later if it's possible, but that's no must have.)
The rich text model for "Hello! Here is a link." looks like this:
var doc = [
{ insert: "Hello!", attributes: { bold: true } },
{ insert: " Here is a " },
{ insert: "link.", attributes: { href: 'http://example.org' } }
];
I could transform the upper document example into "Hello! That's a link." with these instructions:
var operation = [
{ retain: 7 },
{ insert: "That's", attributes: { italic: true } },
{ delete: 1 }
];
But saving this model into a CollaborativeList seems to be no solution as well, if more collaborators are typing or formatting at the same time. Especially because I can't influence server side behavior.
Can someone think of a suitable model or data exchange process that would work with rich text? It does not have to be the best solution (if there is something in between). Exchanging plain text is unbelievable simple with this API but rich text seems to be impossible to me.
Thanks for any help!
I'm able to precise my question with the new information Sheryl Simon provided me below. By using IndexReferences I’m now able to isolate the plain text from the format information.
I have added some code that saves the local text selection of the user (that can be a single position or a range) and restores it after a text change. This works fine. I could also add support for multiple text selections of a single user - because every user is only able to change the own selection(s).
But I can’t figure out a model where several users can simultaneously add and remove ranges of e.g. bold text. If I use a CollaborativeList for bold text with several [start, end]
arrays in it, I'll get a broken data set if two users set an overlapping range at the same time or if two users want to edit the same range at the same time (by removing and reinserting ranges or by moving the range markers of an existing range).
The following is a bit of pseudo code. All indexes are stored as IndexReferences:
Model:
[ User1: makeBold([8,20])
[ 0, 10] => removeValue([0,10]), removeValue([15,36]), push([0,36])
[15, 36]
[77, 82] User2: removeBold([0,5])
] => removeValue([0,10]), push([6,10])
If both users start on the data set that is shown on the left and the actions of the first user are applied first, the second user is not able to remove [0,10]
anymore (because it had been replaced) so the text stays bold and pushing [6,10]
into the list leads into duplicate data. How can I prevent these problems?
Upvotes: 3
Views: 1164
Reputation: 46844
Check out IndexReferences. This is what those are designed for. You basically track a marker for the start and end of the region that should be bold, italic, etc. The IndexReference will automatically move around if text is added before or within the region so it should behave logically.
Upvotes: 7