Om and contentEditable - there be dragons?

543 views
Skip to first unread message

Paul Butcher

unread,
Apr 22, 2014, 6:58:38 AM4/22/14
to clojur...@googlegroups.com
After working my way through the various samples and tutorials out there, I’m about to start on my first Om app (yay!).

Possibly foolishly, I’m planning to make heavy use of contentEditable. In essence, what I need to do is replicate something similar to Word’s “track changes” functionality. Ideally, I’d like to get this to play nicely with Om’s undo - the complication being that as well as changes made by the app, I’d also need to undo changes made by the user (ideally wrapping changes made by both into a single logical undo).

I’ve done quite a bit of searching, and getting React to play nicely with contentEditable seems to be a largely unexplored area? Chas Emerick’s message on the React mailing list seems to capture the current state of the art:


Although this looks promising:


Is there anything else that I should be aware of? Any words of wisdom or advice before I dive into this (including “don’t use Om for this - it’s the wrong tool for the job” :-)?

--
paul.butcher->msgCount++

Silverstone, Brands Hatch, Donington Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
Skype: paulrabutcher

Author of Seven Concurrency Models in Seven Weeks: When Threads Unravel

David Nolen

unread,
Apr 22, 2014, 8:02:54 AM4/22/14
to clojur...@googlegroups.com
contentEditable in regular JavaScript is challenging / difficult - https://vimeo.com/76219173. Getting it to work under React / Om is like to be even more challenging / difficult.

I would probably spend quite a bit of time prototyping / testing before making any assumptions that it can be accomplished in a reasonable amount of time.

David


--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.

deliminator

unread,
Apr 22, 2014, 9:46:02 AM4/22/14
to clojur...@googlegroups.com
In the aloha project we are experimenting with new ways to deal with the contentEditable problem that you may find interesting:

* state-based, serializable, replayable change tracking for contentEditable (as opposed to command-based the way it is usually done) using MutationObservers where available: https://github.com/alohaeditor/Aloha-Editor/blob/howling-mad/src/undo.js

* React-like virtual-DOM, where a javascript-object tree can be updated without actually touching the DOM (in a referentially-transparent and optionally lazy fashion), and coupled with a very simple difference algorithm can be used to update the dom with a single function call: https://github.com/alohaeditor/Aloha-Editor/blob/howling-mad/src/boromir.js

Paul Butcher

unread,
Apr 22, 2014, 9:46:54 AM4/22/14
to David Nolen, clojur...@googlegroups.com
Yeah, I’m aware of the various challenges of contentEditable. I was hoping that I might be able to leverage ClojureScript/React/Om to make them at least slightly more palatable. 

Consider me suitably warned ;-)

--
paul.butcher->msgCount++

Silverstone, Brands Hatch, Donington Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
Skype: paulrabutcher

Author of Seven Concurrency Models in Seven Weeks: When Threads Unravel

ts

unread,
Apr 22, 2014, 9:50:52 AM4/22/14
to clojur...@googlegroups.com


--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to a topic in the Google Groups "ClojureScript" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojurescript/1jeSLRdSmGU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojurescrip...@googlegroups.com.

To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.



--
We create value through sharing and collaboration.

Tobias Steiner
Tech-lead & Co-founder

tobias....@wikidocs.com
Gonzagagasse 11/25
A-1010 Vienna, Austria
+43 699 15191890
https://wikidocs.com

This e-mail is private, confidential, privileged and is intended
only for the use of the above mentioned addressee. If you receive
this e-mail in error, please advise us immediately and delete the
message. Unless confirmed in writing, duly signed by an authorized
representative of Girigiri Software GmbH, any liability our
company, its partners or employees for e-mails or their content
is excluded. Although taking according measures, complete safety
from viruses cannot be guaranteed. Any liability for damages
resulting from or in connection with virus infections is
excluded. Forum for all disputes out of or in connection with our
services is the competent court for the First District, City of
Vienna, Austria. Any agreements and all services are governed to
the extent or as permitted by Austrian law.

Paul Butcher

unread,
Apr 22, 2014, 10:17:39 AM4/22/14
to deliminator, clojur...@googlegroups.com
Wow. That looks really interesting. It also looks like a lot of code :-) Is there any introductory documentation/blog posts that might help me distill the “essence”? 

--
paul.butcher->msgCount++

Silverstone, Brands Hatch, Donington Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
Skype: paulrabutcher

Author of Seven Concurrency Models in Seven Weeks: When Threads Unravel

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.

deliminator

unread,
Apr 22, 2014, 10:32:42 AM4/22/14
to clojur...@googlegroups.com, deliminator
The tests are the only kind of documentation we can offer at the moment ;-)

Dave Della Costa

unread,
Apr 22, 2014, 10:54:04 AM4/22/14
to clojur...@googlegroups.com
Hi Paul, we've built a Content Editable widget in Om (and while it needs
some more polish I'm hoping we can release it soon). For now I can only
tell you about my experiences:

The first iteration I wrote had contenteditable getting turned on and
off using local state updates. This worked well enough but gave us some
trouble with focus on IE8 and IE9 if I recall correctly--other modern
browsers (desktop Chrome, FF, Safari is as far as we test) were fine.

After I discovered that I simply (and somewhat disappointingly) changed
it to use lower-level direct DOM JS API calls to clear text content, set
contenteditable to true, and set focus.

In order to make the widget modular, we use a channel hooked up to
onChange (we actually have our own version of Google Closure's
delayedchange) to pass the text content out of the field to whatever
wants to list on the channel the widget provides. An alternative, I
suppose, would be to pass in a function to be used as an event handler,
and let the user figure that out.

We also provide channels to trigger resets and blurring of the field.

So far, it works pretty well and we haven't had too many problems--we
are looking to replace all of our usage of Google Closure's
ContentEditableField
(http://docs.closure-library.googlecode.com/git/class_goog_editor_ContentEditableField.html)
in the near term, but have to give it a bit more thorough testing first.

I'll see about getting this code out there and available ASAP. But
hopefully this gives you some help in terms of possibilities to consider
as you hack on your own version...

DD

(2014/04/22 19:58), Paul Butcher wrote:
> After working my way through the various samples and tutorials out
> there, I’m about to start on my first Om app (yay!).
>
> Possibly foolishly, I’m planning to make heavy use of contentEditable.
> In essence, what I need to do is replicate something similar to Word’s
> “track changes” functionality. Ideally, I’d like to get this to play
> nicely with Om’s undo - the complication being that as well as changes
> made by the app, I’d also need to undo changes made by the user (ideally
> wrapping changes made by both into a single logical undo).
>
> I’ve done quite a bit of searching, and getting React to play nicely
> with contentEditable seems to be a largely unexplored area? Chas
> Emerick’s message on the React mailing list seems to capture the current
> state of the art:
>
> https://groups.google.com/d/msg/reactjs/ff5YlPKiqmc/ngDTsk_i2mYJ
>
> Although this looks promising:
>
> http://stackoverflow.com/a/22678516/268371
>
> Is there anything else that I should be aware of? Any words of wisdom or
> advice before I dive into this (including “don’t use Om for this - it’s
> the wrong tool for the job” :-)?
>
> --
> paul.butcher->msgCount++
>
> Silverstone, Brands Hatch, Donington Park...
> Who says I have a one track mind?
>
> http://www.paulbutcher.com <http://www.paulbutcher.com/>/
> LinkedIn: http://www.linkedin.com/in/paulbutcher
> Skype: paulrabutcher
>
> Author of Seven Concurrency Models in Seven Weeks: When Threads Unravel
> http://pragprog.com/book/pb7con
>
> --
> Note that posts from new members are moderated - please be patient with
> your first post.
> ---
> You received this message because you are subscribed to the Google
> Groups "ClojureScript" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to clojurescrip...@googlegroups.com
> <mailto:clojurescrip...@googlegroups.com>.
> To post to this group, send email to clojur...@googlegroups.com
> <mailto:clojur...@googlegroups.com>.

Joel Holdbrooks

unread,
Apr 22, 2014, 12:28:25 PM4/22/14
to clojur...@googlegroups.com
> I would probably spend quite a bit of time prototyping / testing before making any assumptions that it can be accomplished in a reasonable amount of time.

Keeping this in mind is paramount. I've been working on a personal project which entirely built around contentEditable and this is no joke. So far, a combination of local state (owner), tx-listen, and communication channels have proved to be mostly effective.

Chas Emerick

unread,
May 23, 2014, 7:17:45 AM5/23/14
to clojur...@googlegroups.com
Bit of a stale thread here, but I thought I'd say a couple of things since I was mentioned. :-)

contentEditable is absolutely a cluster, through and through. (All the best that the "web standards" processes has to offer, but that's an OT rant for another day.)

As you gleaned from my React ML posts (as as David speculated nearby), working with contentEditable via React *adds* to the challenges. While React's virtual DOM is a simplifying abstraction elsewhere, it simply cannot represent all of the state associated with an editable region, because that state isn't represented in the DOM in the first place. So, caret position, selection ranges, scroll position, etc. are all inevitable casualties of React's particular immediate-mode rendering strategy. You can manage these things "out of band", but at a certain point (very much dependent upon your objectives and requirements) React becomes an obstacle rather than an aid.

That said, if you are looking to use contentEditable for fairly lightweight stuff — e.g. you just want the user to be able to provide some styled content — you can hook into an onChange or onBlur event to update your model and using React/Om should pan out just fine after the requisite contentEditable difficulty.

Good luck,

- Chas
--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.

Joel Holdbrooks

unread,
May 24, 2014, 2:36:39 PM5/24/14
to clojur...@googlegroups.com
I'd like to echo this and say that my experiments with contentEditable spans proven fruitful because I am managing the more difficult tasks (e.g. tracking cursor position) "out of band" as Chas recommends. My opinion is that it isn't necessarily a cluster; it just requires a bit of effort. Again, this all depends on what you are trying to achieve.

In my case I *do not* hook into onChange but I *do* hook into onBlur, onFocus, onClick, and onKey* events. onFocus/onClick is primarily for setting up caret tracking. onKey* events handle caret tracking and logic around specific keys. onBlur does the actual updating of the application state.

Reply all
Reply to author
Forward
0 new messages