For what I needed to do (convert an enter into a 'finished editing' action 
i found quite a nice solution

https://stackoverflow.com/questions/42390708/elm-conditional-preventdefault-with-contenteditable

In brief, I catch the keydown event but convert anything other than an 
enter in to json decode fail, so that it does not reach the update loop. An 
enter is caught, with preventDefault applied, and is passed to update as a 
finished editing action, which I pass to Dom.blur and then catch the blur 
event and use that to cause the model to updated.

Simon


On Sunday, 26 February 2017 09:11:51 UTC+1, Vincent Jousse wrote:
>
> 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 <witold...@gmail.com 
> <javascript:>>:
>
>> 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 <jos...@gmail.com 
>> <javascript:>> 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-lang.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 <vjo...@gmail.com> 
>>>>>> 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 elm-discuss...@googlegroups.com.
>>>>>>> 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 elm-discuss...@googlegroups.com <javascript:>.
>>> 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 
>> elm-discuss...@googlegroups.com <javascript:>.
>> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to