# Pure Elm Text Editor

**URL:** <https://discourse.elm-lang.org/t/pure-elm-text-editor/1709>\
**Category:** Show and Tell\
**Created:** [August 22, 2018, 10:19pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709 "2018-08-22T22:19:05Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sidney](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sidney/32/3290_2.png) [@Sidney](https://discourse.elm-lang.org/u/Sidney)\
**Post date:** [August 22, 2018, 10:19pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/1 "2018-08-22T22:19:05Z")

</div>

Thought you all would be interested in the pure elm text editor I’ve been working on. I’ve got text selection and quite a few keyboard shortcuts implemented.

Demo: [SidneyNemzer/elm-text-editor](https://sidneynemzer.github.io/elm-text-editor/)  
Github: [GitHub - SidneyNemzer/elm-text-editor: A text editor written completely in Elm](https://github.com/SidneyNemzer/elm-text-editor)

Next big features I want to implement are scrolling/viewport support, undo/redo, and line-wrap. (Check out the Github project for more plans).

> I hope this inspires somebody to try some stuff in Elm they’ve been needing but seemed too big / hard for them! You might, like me with this project, find out it’s in your reach - no doubt thanks to Elm  
> _- Janiczek_ [(source)](https://discourse.elm-lang.org/t/text-editor-done-in-pure-elm/1365)

---

<div class="post-metadata">

**Author:** ![stevensonmt](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/stevensonmt/32/889_2.png) [@stevensonmt](https://discourse.elm-lang.org/u/stevensonmt)\
**Post date:** [August 23, 2018, 2:21pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/2 "2018-08-23T14:21:12Z")

</div>

Very cool. There is a bit of artifact when dragging the mouse to select text which makes the text box jump around for me.

---

<div class="post-metadata">

**Author:** ![evancz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/evancz/32/16_2.png) [@evancz](https://discourse.elm-lang.org/u/evancz)\
**Post date:** [August 23, 2018, 2:51pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/3 "2018-08-23T14:51:22Z")

</div>

This is extremely exciting! 😃 Great work!

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [August 23, 2018, 3:52pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/4 "2018-08-23T15:52:44Z")

</div>

This really has a lot of potential.

I am curious what is the relationship with Janiczek’s pure Elm text editor? Does it work in a very similar way?

---

<div class="post-metadata">

**Author:** ![Viir](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/viir/32/4103_2.png) [@Viir](https://discourse.elm-lang.org/u/Viir)\
**Post date:** [August 23, 2018, 3:58pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/5 "2018-08-23T15:58:05Z")

</div>

Awesome!

What is the overall goal with this project? I mean is developing an editor a means to support something else in this case? Do you have an application where you integrate this?

I see the readme mentions `syntax highlighting` as a planned feature. Does this mean it is primarily meant for editing programs?

---

<div class="post-metadata">

**Author:** ![Sidney](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sidney/32/3290_2.png) [@Sidney](https://discourse.elm-lang.org/u/Sidney)\
**Post date:** [August 23, 2018, 4:32pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/6 "2018-08-23T16:32:55Z")

</div>

Thanks everyone!

> [@stevensonmt](#):
>
> There is a bit of artifact when dragging the mouse to select text which makes the text box jump around for me.

If you’ve got the debug info shown, the debug text affects the editor’s centering on the page as state changes. If you don’t have the debug info open, then it’s definitely a bug, maybe you could open an issue with more info?

> [@rupert](#):
>
> I am curious what is the relationship with Janiczek’s pure Elm text editor? Does it work in a very similar way?

They started basically the same (I think I still have the branch that is heavily based of Janiczek’s editor?). Over time, they diverged as I split up modules and added new functionality. Some core pieces are still similar, like the event listeners and rendered DOM structure.

> [@Viir](#):
>
> What is the overall goal with this project? I mean is developing an editor a means to support something else in this case? Do you have an application where you integrate this?

I would love if this editor could get to the level of Ace or CodeMirror! The company I work for has a web-IDE (similar to Mozilla’s Thimble) for our students. We’re using Ace at the moment via elm-ace. It works but it’s far from ideal and it inspired me to create a pure Elm solution.

I’ve been working on this editor in my spare time, so I can’t guarantee any particular timelines, but I’ll continue to work on it when I can. I’m pretty happy with it so far 😃

---

<div class="post-metadata">

**Author:** ![stevensonmt](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/stevensonmt/32/889_2.png) [@stevensonmt](https://discourse.elm-lang.org/u/stevensonmt)\
**Post date:** [August 24, 2018, 8:35pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/7 "2018-08-24T20:35:23Z")

</div>

Confirm it is only jumpy when debug info displayed.

---

<div class="post-metadata">

**Author:** ![Sidney](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sidney/32/3290_2.png) [@Sidney](https://discourse.elm-lang.org/u/Sidney)\
**Post date:** [August 24, 2018, 8:58pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/8 "2018-08-24T20:58:02Z")

</div>

Cool, thanks for clarifying. It definitely annoys me that the debug info messes with the position of the editor, but I didn’t care enough to fix it. That’s just the demo app, not part of the editor of course. (contributions are welcome though 😉 )

---

<div class="post-metadata">

**Author:** ![Janiczek](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/janiczek/32/4516_2.png) [@Janiczek](https://discourse.elm-lang.org/u/Janiczek)\
**Post date:** [August 25, 2018, 5:26pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/9 "2018-08-25T17:26:46Z")

</div>

Very very **very** cool! 🙂 🎉

---

<div class="post-metadata">

**Author:** ![myrho](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/myrho/32/1093_2.png) [@myrho](https://discourse.elm-lang.org/u/myrho)\
**Post date:** [August 28, 2018, 9:18am UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/10 "2018-08-28T09:18:46Z")

</div>

Great work! Have you considered using a hidden input field for capturing user input? CodeMirror does it this way. So the editor would also work on mobile devices (soft keyboards).

With Elm 0.19 race conditions between the virtualdom and users typing fast (ie. in rendering the input field) should have gone away!

---

<div class="post-metadata">

**Author:** ![Sidney](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sidney/32/3290_2.png) [@Sidney](https://discourse.elm-lang.org/u/Sidney)\
**Post date:** [August 28, 2018, 5:10pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/11 "2018-08-28T17:10:02Z")

</div>

Thanks! Yeah, at some point I think it will need to integrate a textarea, that seems to be the best way to support mobile. Ace uses a hidden textarea too.

For now, I’m focusing on desktop but in the future I also want to support mobile.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [August 28, 2018, 5:27pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/12 "2018-08-28T17:27:48Z")

</div>

Really promising!

For those interested, here is a related article about `contentEditable` from a CKEditor developer that gives a preview of the headache to support all use cases:

[ContentEditable — The Good, the Bad and the Ugly](https://medium.com/content-uneditable/contenteditable-the-good-the-bad-and-the-ugly-261a38555e9c).

And the recent design document of the [rewrite](https://codemirror.net/6/) of CodeMirror:

[CodeMirror 6 design doc](https://codemirror.net/6/design.html)

Keep up the good work!

---

<div class="post-metadata">

**Author:** ![giulioungaretti](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/giulioungaretti/32/682_2.png) [@giulioungaretti](https://discourse.elm-lang.org/u/giulioungaretti)\
**Post date:** [August 30, 2018, 10:32am UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/13 "2018-08-30T10:32:38Z")

</div>

This looks really awesome! I have a question I have been asking my self while building something similar ( a full wysiwyg editor but not focused on code), which is: is such a package even possible in pure elm ?

My conclusion was, no. Because:

1. copy and paste works smoothly and is safe and accessible only if one uses the selection API
2. undo/redo has to be implemented ad hoc, breaking the native browser implementation
3. in general accessibility becomes a bit a nightmare.

I wonder if you or any folk here has come to a different conclusion ?

---

<div class="post-metadata">

**Author:** ![Sidney](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sidney/32/3290_2.png) [@Sidney](https://discourse.elm-lang.org/u/Sidney)\
**Post date:** [August 30, 2018, 4:42pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/14 "2018-08-30T16:42:24Z")

</div>

> [@giulioungaretti](#):
>
> is such a package even possible in pure elm ?

Well, depends on what features you want! Looks like you’ve identified the problem areas…

> [@giulioungaretti](#):
>
> copy and paste works smoothly and is safe and accessible only if one uses the selection API

I was planning to use a ‘local’ clipboard by default, which can be done with pure Elm. I’ll also provide functions to hook up ports that use JavaScript to capture paste and trigger copy events for the system clipboard.

Chrome has introduced an [async clipboard API](https://developers.google.com/web/updates/2018/03/clipboardapi) which means in the future we won’t need to use hacks like an offscreen textarea for coping arbitrary text! (It’s not even on [caniuse.com](http://caniuse.com) though, so I don’t have much confidence it it’s adoption yet). It’s up to the consumer of the text editor to decide which clipboard API they want to use.

> [@giulioungaretti](#):
>
> undo/redo has to be implemented ad hoc, breaking the native browser implementation

Yes, the editor has to handle undo/redo (I’m working on that now!). Not sure how that breaks the browser implementation? I believe Ace and CodeMirror also handle undo/redo in JavaScript.

> [@giulioungaretti](#):
>
> in general accessibility becomes a bit a nightmare.

Yep, I don’t expect good support for mobile devices at first, particularly since they have a software keyboard. In the future, a hidden textarea can potentially fix that. (Ace and CodeMirror also do this).

> [@giulioungaretti](#):
>
> I wonder if you or any folk here has come to a different conclusion ?

The conclusion I came to is that it will take a lot of work to implement features that a basic textarea supports. But I hope that we can support additional features without much effort like syntax highlighting, code annotations, and even multiple ‘editor’ views for a single buffer/file. I think a pure Elm text editor that mostly works is better than no pure Elm text editor!

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [August 30, 2018, 4:51pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/15 "2018-08-30T16:51:24Z")

</div>

> [@Sidney](#):
>
> In the future, a hidden textarea can potentially fix that. (Ace and CodeMirror also do this).

As [linked previously](https://codemirror.net/6/design.htm), CodeMirror developers think that `contentEditable` is now the best way:

> This was a good approach, in 2011, because `contentEditable` was terribly buggy, and browsers awfully incompatible. But it’s 2018, Internet Explorer is almost extinct (we do want to support version 11, possibly with some features degraded), and other browsers have come a long way. Our experience with [ProseMirror](https://prosemirror.net/) shows that you _can_ build something solid on `contentEditable` now.

---

<div class="post-metadata">

**Author:** ![Sidney](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sidney/32/3290_2.png) [@Sidney](https://discourse.elm-lang.org/u/Sidney)\
**Post date:** [August 30, 2018, 4:57pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/16 "2018-08-30T16:57:19Z")

</div>

> [@dmy](#):
>
> CodeMirror developers think that `contentEditable` is now the best way

I’m curious to see how CodeMirror 6 progresses! For now I’m staying away from `contentEditable` in Elm because it means a lot of ports, but maybe I’ll end up using it in the future.

---

<div class="post-metadata">

**Author:** ![Atlewee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/atlewee/32/4603_2.png) [@Atlewee](https://discourse.elm-lang.org/u/Atlewee)\
**Post date:** [August 30, 2018, 5:45pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/17 "2018-08-30T17:45:31Z")

</div>

Pure Elm Copy/Paste solution/suggestion:  
I have an idea for how this maybe can be done in pure elm, hacky but pure Elm 🙂

**Copy:**  
Have a hidden textfield (offscreen) that always holds whatever is selected in your editor.  
And also, whenever the selection is changed, put focus to this hidden textField, this should make this text in that field highlighted automatically (At least this is what happens when you tab into a textfield that already contains text on any webpage I ever seen)  
So now the text you want is already hightlighted by the system/browser and any native Copy or Cut action will copy your text to clipboard. Ctrl+C…

**Paste:**  
By implementing the logic above, the textfield should already be highlighted, either with text ready to be replaced, or empty, ready for new input.  
When the user types or pasted, you pick up whatever is beeing typed or pasted in that textField, be it one character or a multiline thing… You already know the position where this input should start from and than you pass the new input to a function that includes this input to your model of the text.

Not tested this, but might be doable 🙂  
It also means that any copy/cut/paste happens in one browser native way, no need for a separate internal copy paste, should also not require any user ports… ?

---

<div class="post-metadata">

**Author:** ![giulioungaretti](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/giulioungaretti/32/682_2.png) [@giulioungaretti](https://discourse.elm-lang.org/u/giulioungaretti)\
**Post date:** [August 30, 2018, 7:24pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/18 "2018-08-30T19:24:12Z")

</div>

Awesome! I will keep an eye on your project! The route I have chosen it’s the opposite that is using content-editable and one port for the selection. I hope to open source soon!

---

<div class="post-metadata">

**Author:** ![Sidney](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sidney/32/3290_2.png) [@Sidney](https://discourse.elm-lang.org/u/Sidney)\
**Post date:** [August 30, 2018, 9:53pm UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/19 "2018-08-30T21:53:01Z")

</div>

Interesting ideas!

> [@Atlewee](#):
>
> whenever the selection is changed, put focus to this hidden textField, this should make this text in that field highlighted automatically (At least this is what happens when you tab into a textfield that already contains text on any webpage I ever seen)

That’s not the behavior I’m seeing in Chrome 68, it just places the cursor at 0,0. Also the editor needs focus when you’re typing. Or more specifically the `div` that wraps all the other elements needs focus, because it needs to receive key events (which the browser only sends when an element has focus).

This is similar to how Ace and CodeMirror behave though. They stick a hidden textarea at the “cursor” which, among other things, tells mobile devices to show the keyboard.

---

<div class="post-metadata">

**Author:** ![Atlewee](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/atlewee/32/4603_2.png) [@Atlewee](https://discourse.elm-lang.org/u/Atlewee)\
**Post date:** [August 31, 2018, 9:36am UTC](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709/20 "2018-08-31T09:36:29Z")

</div>

Hi again,

Think of this hidden field as the input for all text into your editor. (After all its the Html.input function) 🙂 haha…  
If you type a character, this comes into your editor content via this input field. If you paste something bigger, thats a single event with text to be placed inside your content as well.  
Also, if you have something selected in your editor, this is already highlighted/selected inside this Html.input element, ready to be overwritten.  
The more I think of it, the less hacky it feels 🙂  
So this input field does never hold your content, just what is to be put into your content.

The way I see it, the editor itself could even be rendered with Elm-UI or Svg+++ as long as you have a way of knowing the selected positions.

I gave it a try and updated your editor to Elm 0.19 (quick and dirty) to get the new Browser.Dom in Elm 0.19. (For setting focus to an element)  
But it just gives focus to the inputBox, it does not seem highlight/select the content like a normal tab would do.

**Paste** from system clipboard actually works 🙂 I can paste whatever is on my system clipboard to any position selected by mouse or keyboard in your editor.

You can have a look and test it here:  
(That index.html is already compiled, but I don’t know how to host it on github)

> **[atlewee/elm-text-editor](https://github.com/atlewee/elm-text-editor)**
>
> A text editor written completely in Elm. Contribute to atlewee/elm-text-editor development by creating an account on GitHub.

The change is simply that everytime you change your selection, the selected text would be put in the “copyPasteArea”  
(Currently its just Debug.toString on your Selection, but would offcourse be the actual text in a real app)  
Whenever there is something selected, I also set focus to that “copyPasteArea”

If Browser.Dom.focus had an option to also hightlight the content ( select() in JS )  
Then any overwrite/copy/cut action would just work on any system and any Browser without relying on any API.  
An alternative is to add something like Browser.Dom.focusAndSelect.  
If that does not make it into the Browser package, a port for setting Focus().Select() on that input should also work.  
Do you think the idea makes any more sense now ?

[Next page](https://discourse.elm-lang.org/t/pure-elm-text-editor/1709.md?page=2)
