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 <[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.

Reply via email to