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.

Reply via email to