The best workaround I've found is to use a webcomponent wrapper (only compatible with chrome): https://github.com/vjousse/the-transcriber/blob/webcomponents/src/static/js/custom-text-editor-element.js
I'm using a custom attribute called "content" that is mapped to my Elm Model. With this solution I've got the best of both worlds: Elm is managing the DOM of my contenteditable element while being able to write custom behavior in javascript for it. It is based on this talk by Richard Feldman: https://www.youtube.com/watch?v=ar3TakwE8o0 2017-02-25 11:41 GMT+01:00 Witold Szczerba <[email protected]>: > One trick I have learned when integrating date range picker is that you > can push data from component to Elm using custom HTML events instead of > sending data through a port(s). > I have described it shortly here: > https://www.reddit.com/r/elm/comments/5uqa13/those_fancy_ > date_pickers_in_elm_watch_this_no/ > > input [ class "form-control date-range" , value <| formatMaybeDuration > item.duration , onDateRangePicker DurationChanged *-- see demo for > details* ] [] > > Regards, > Witold Szczerba > > On Fri, Feb 24, 2017 at 4:30 PM, Josh Szmajda <[email protected]> wrote: > >> I'm working with http://github.com/Voog/wysihtml, integration has been >> pretty alright.. Still very much in the figuring things out stage for my >> app but here are some key snippets: >> >> Ports: >> ``` >> port startEditor : (String, String, String) -> Cmd msg >> port stopEditor : String -> Cmd msg >> port editorChanges : (String -> msg) -> Sub msg >> port selectionChange : (Selection -> msg) -> Sub msg >> ``` >> >> Selection: >> ``` >> type alias Selection = >> { text : String >> , t : Float >> , r : Float >> , b : Float >> , l : Float >> } >> ``` >> >> WYSIHtml View: >> ``` >> module Wysihtml.View exposing (wysiToolbar, wysiEditor) >> >> import Html exposing (..) >> import Html.Attributes exposing (id, attribute, class) >> >> wysiToolbar : a -> Html a >> wysiToolbar msg = >> div [ id "wysi-toolbar" ] >> [ a [ class "bold", command msg "bold" ] [ text "B" ] >> , a [ class "italic", command msg "italic" ] [ text "I" ] >> , a [ class "h1", command msg "formatBlock", commandValue msg "h1" ] >> [ text "H1" ] >> , a [ class "p", command msg "formatBlock", commandValue msg "p" ] [ >> text "P" ] >> , a [ class "ul", command msg "inserUnorderedList" ] [ text "list" ] >> ] >> >> wysiEditor : a -> Html a >> wysiEditor msg = >> div [ id "wysi-editor", dataPlaceholder msg "Start editing" ] [] >> >> >> dataPlaceholder : a -> String -> Attribute a >> dataPlaceholder msg data = >> attribute "data-placeholder" data >> >> command : a -> String -> Attribute a >> command msg command = >> attribute "data-wysihtml5-command" command >> >> commandValue : a -> String -> Attribute a >> commandValue msg value = >> attribute "data-wysihtml5-command-value" value >> ``` >> >> index.html wiring: >> ``` >> app.ports.startEditor.subscribe(function(){ >> var editor = arguments[0][0]; >> var toolbar = arguments[0][1]; >> var initialText = arguments[0][2]; >> // todo change setTimeout to MutationObserver >> setTimeout(function(){ >> console.log('start editor'); >> window.x_editor = new wysihtml5.Editor(editor, { >> toolbar: toolbar, >> parserRules: wysihtml5ParserRules >> }); >> window.x_editor.setValue(initialText, true); >> window.x_editor.on('interaction', function(){ >> app.ports.editorChanges.send(x_editor.getValue()); >> }); >> }, 60); >> }); >> document.addEventListener("selectionchange", function(){ >> console.log("selection changed, sending to elm"); >> selection = window.getSelection(); >> if(!selection.isCollapsed){ >> for(var i = 0; i < selection.rangeCount; i++) { >> range = selection.getRangeAt(i); >> rect = range.getBoundingClientRect(); >> app.ports.selectionChange.send({ text: selection.toString(), t: >> rect.top, r: rect.right, b: rect.bottom, l: rect.left }); >> } >> } >> }); >> ``` >> >> I think that's the meat. Happy to chat more. >> >> >> On Friday, February 24, 2017 at 3:38:33 AM UTC-5, Simon wrote: >>> >>> I'm also trying to work with contenteditable. I have a basic system >>> working with pure Elm, in that I can click on a field to edit it and then >>> click elsewhere with blur causing an update of the model. But the challenge >>> I face is detecting an enter key and using that save the updated value and >>> blur the current field. I seem to be getting some virtual DOM issues. >>> >>> Anyway I have an Ellie at https://ellie-app.com/tnXL92zwvka1/3 and if >>> anyone can help, I'd love to know >>> >>> Simon >>> >>> On Tuesday, 27 September 2016 16:35:04 UTC+2, Girish Sonawane wrote: >>>> >>>> Instead of onChange, you can try using Events.on http://package.elm-l >>>> ang.org/packages/elm-lang/html/1.1.0/Html-Events#on >>>> >>>> >>>> On Tuesday, August 30, 2016 at 3:16:12 PM UTC+5:30, Peter Damoc wrote: >>>>> >>>>> I've tried a naive implementation in Elm but, for some reason, it >>>>> doesn't work (events are not fired for divs that have content editable) >>>>> >>>>> import Html exposing (..) >>>>> import Html.Attributes exposing (..) >>>>> import Html.App exposing (beginnerProgram) >>>>> import Html.Events exposing (on) >>>>> import Json.Encode as JE >>>>> import Json.Decode as JD exposing ((:=)) >>>>> >>>>> >>>>> main = >>>>> beginnerProgram { model = "", view = view, update = update } >>>>> >>>>> >>>>> onContent tagger = >>>>> on "input" (JD.map tagger ("innerHTML" := JD.string)) >>>>> >>>>> view model = >>>>> div [] >>>>> [ div [property "innerHTML" (JE.string model), onContent OnChange, >>>>> contenteditable True][] >>>>> ] >>>>> >>>>> >>>>> type Msg = OnChange String >>>>> >>>>> >>>>> update msg model = >>>>> case (Debug.log "msg:" msg) of >>>>> OnChange str -> str >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On Tue, Aug 30, 2016 at 12:03 PM, Vincent Jousse <[email protected]> >>>>> wrote: >>>>> >>>>>> Hello, >>>>>> >>>>>> I'm writing an application where the user needs to edit some HTML >>>>>> content. When I first wrote this application in JS, I was using some >>>>>> contenteditable fields to do so. >>>>>> >>>>>> How should I handle this with Elm? My problem is that if I set a div >>>>>> with contenteditable=true in elm, and that the content of this div >>>>>> depends >>>>>> on my model state, when an user edits the HTML, my model is now out of >>>>>> sync. >>>>>> Maybe getting the innerHTML field when the user is changing the >>>>>> content of the div and set this to a field in my model? But how would I >>>>>> do >>>>>> to convert this string back to some Html.div/Html.span/whatever code in >>>>>> Elm? >>>>>> The tricky part is that I need to handle events on spans that are in >>>>>> the div with contenteditable=true. >>>>>> >>>>>> I tried to do it using Ports and Draft-js but the problem is that I >>>>>> now have 2 states in my application: one in Elm and one in JS/React. >>>>>> Then, >>>>>> all the beauty of "my application just depends on my Elm model state" is >>>>>> not true anymore, as I know need to sync the 2 states… >>>>>> >>>>>> Not sure if I'm really clear, but thanks for reading this anyway ;-) >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "Elm Discuss" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to [email protected]. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> There is NO FATE, we are the creators. >>>>> blog: http://damoc.ro/ >>>>> >>>> -- >> You received this message because you are subscribed to the Google Groups >> "Elm Discuss" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> For more options, visit https://groups.google.com/d/optout. >> > > -- > You received this message because you are subscribed to a topic in the > Google Groups "Elm Discuss" group. > To unsubscribe from this topic, visit https://groups.google.com/d/ > topic/elm-discuss/YKz8rgffoWc/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- Vincent Jousse http://vincent.jousse.org -- You received this message because you are subscribed to the Google Groups "Elm Discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
