Help working with 'contenteditable'?

I have very little experience with using ‘contenteditable’ in any way (Elm or otherwise) but at work we’re starting to consider using it more to provide ‘slicker’ interfaces. Mostly to allow users to enter text into boxes that will naturally expand with the content being written whether single line or multi-line.

When I google around I find bits of information from down the years but I’m finding it hard to get a clear idea of how best to use contenteditable.

My main question is quite basic: Can you use a ‘contenteditable’ div much like you use a standard input box or textarea? Are there particular things you need to work around? And if so, is it just a couple of things to bear in mind or do you end up having to write most of a text editor in order to cover the various edge cases or typical behaviours?

The last part is where i think I get confused as ‘contenteditable’ conversations often overlap with “I’m writing my own client side text editor” conversations. I’m not looking for an editor component or a ‘wysiwyg’ experience. I’m mostly just after slightly nicer and more flexible textarea/input box. Should I be considering ‘contenteditable’ or perhaps there are other approaches?

Sure, you can use contenteditable as an upgraded textarea, but there are a number of gotcha’s that aren’t always so transparent.

Actually there is a Medium post by Nick Santos way back in the olden days of 2014 which goes into detail. Perhaps your use case can get around some of these caveats, but in general I’d advise you to take a good look into this before settling on it as a solution.

Can you give me some more details regarding what you’re after specifically? If it’s just autoexpansion ohanhi/autoexpand does this already.
If you’re looking for a richer markup, you could consider a textarea and live preview like discourse does, but drop most of the WYSIWYG interface.

2 Likes

Thank you for the reply.

I didn’t know about ohanhi/autoexpand! Excited to try that out.

It is mostly just auto-expansion in the case that I’m currently dealing with. Otherwise, if for any reason it is easier to style a contenteditable div than a textarea then that might be of interest. Beyond that, I don’t need richer markup or anything.

We have one case where we’ve successfully used it for a ‘click to edit in place’ title on a screen. And the ‘contenteditable’ approach produces much smoother results than an inline input box. We have to capture and ignore any ‘Enter’ key presses so that they don’t disrupt the ‘single line’ nature of the input.

I confess a colleague did that and I need to quiz him on the details and extend of his knowledge. My own ventures into using it are with naively hooking up block where the text appeared to come in backwards from what I was typing. The cursor remained at the start of the div. And then when I changed strategy, I came across an issue where new lines weren’t being reported I guess because I was using a Decode.at [ "target", "textContent" ] decoder and I guess that extracts all text content and new lines (in Chrome) or modelled by inserting divs into the DOM under the contenteditable element. My attempts to research how best to tackle that lead down the uncertain path of ‘is this a quick fix or do I need to implement a whole text editor?’

I hope that helps to clarify my current position and experience. Thanks again for the response.

That makes sense. Yeah, your title example is probably a good place for contenteditable since it’s quite a restricted location. In a textbox however your not expected to be as constrained.

A question that perhaps can’t be answered easily. I think getting something mocked up and functioning would actually be quite quick and straightforward. Maintenance is going to be the problem. Users will probably find edge cases you didn’t expect and you’ll have to patch it up. So I guess if you’re fine with that price, then contentedible is a good solution. If you like ohanhi/autoexpand though, I’m certain it’ll save you some headache.

1 Like

So far, I have struggled quite a bit with contenteditable. It messes with the DOM that elm expects to be consistent. This includes, but is not limited to, text and text formatting nodes.

This is the snippet I created to tame contenteditable a bit but it just always ended up screwing with the vdom: https://gist.github.com/FranzSkuffka/a3140100b7115d6270da1d5222fbb040

I think there are two options to this:

  1. A contenteditable web component of which children elm knows nothing and thus can not mess up or
  2. a pure elm implemtation

I would be happy to join forces to build either of theese.
I think it is somewhat feasible to manually implement a more reasonable content editable. I have some ideas for implementation in mind and would love to discuss further.

1 Like

“contenteditable” should not be touched with a ten-foot-pole unless you absolutely have to (ie. you’re making a wysiwyg editor).

It’s actually pretty easy to make a reliable autoexpanding textarea with some CSS and a hidden div which has the same content as the textarea: https://ellie-app.com/4JWL4rSW5Gra1
You just have to make sure that the textarea and the hidden div have the same font, line-height, padding and border.

It may look a bit like a hack but it’s the most reliable method from my experience.

It does not seem to be enough, as it does not work here with Firefox 65:textareadiv

Yay for browser inconsistencies :expressionless:
Updated with more CSS rules: https://ellie-app.com/4JXpzRVXjYWa1
Tested in Chrome, Firefox and Safari now.

Edit: also added a fix for the case where the user writes a superlong word without spaces that’s longer than the textarea :stuck_out_tongue:

2 Likes

Good point, still no love from firefox though:
autoheight_textarea

Sorry to bother, but I’m interested to see how reliable it is.

D’oh, apparantly Firefox and IE don’t support word-break: break-word, however word-break: break-all works: https://ellie-app.com/4JY5PFRWYW3a1

4 Likes

That’s not too bad at all! I like that you still input everything in the textarea so accessibility is not an issue.

I really like my textareas to grow, and I use this basic technique, just set the rows attribute depending on the contents.

myTextarea : String -> String -> String -> (Session.Data -> String -> Session.Data) -> Html Msg
myTextarea val id title setter =
 let
    rows =
        Basics.min 20 (Basics.max 3 (1 + String.Extra.countOccurrences "\n" val))
 in
 Form.group []
    [ Form.label [ for id ] [ text title ]
    , Textarea.textarea
        [ Textarea.id id
        , Textarea.value val
        , Textarea.rows rows
        , Textarea.onInput (\txt -> UpdateSessionMsg ( setter, txt ))
        , Textarea.attrs [ onBlur OnBlurMsg ]
        ]
    ]
1 Like

Hi !

If you are interested :

It’s an attempt to create a styleable (that could also auto expand) textarea widget, in pure Elm, with a hidden native textarea instead of contenteditable.

It’s work in progress and also a way to validate the approach, but it should work on relatively small chunks of text.

Hth

Rémi

3 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.