svg.escobar.life

A simple SVG markup editor for the web

Editor.elm (2086B)

      1 module Editor exposing (editor)
      2 
      3 import Types exposing (..)
      4 import Html exposing (Html, Attribute, div, pre, code, text, textarea)
      5 import Html.Attributes exposing (id, value, style, spellcheck, alt, attribute)
      6 import Html.Events exposing (onInput, on)
      7 import Accessibility.Landmark exposing (region)
      8 import Accessibility.Widget exposing (label, hidden)
      9 import Json.Decode
     10 import SyntaxHighlight exposing (xml, toBlockHtml)
     11 
     12 editor : Model -> Html Msg
     13 editor model =
     14   let
     15     -- Indent the editor according to the order of magnitude of the number of
     16     -- lines in the input file
     17     indent 
     18       = model.image
     19         |> String.lines
     20         |> List.length
     21         |> toFloat
     22         |> logBase 10
     23         |> floor
     24         |> (+) 1
     25         |> max 1
     26         |> String.fromInt
     27         |> \s -> "--indent: " ++ s ++"em;"
     28   in
     29     div 
     30       [ id "editor"
     31       , region
     32       , label "Text editor" 
     33       , attribute "style" indent
     34       ]
     35       [ div 
     36         [ hidden True, translate model.editorScroll ]
     37         [ codeDisplay model ]
     38       , textarea model
     39       ]
     40 
     41 textarea : Model -> Html Msg
     42 textarea model =
     43   Html.textarea
     44     [ value model.image
     45     , onInput Update
     46     , onScroll Scroll
     47     , spellcheck False
     48     , alt "Text Editor"
     49     ] []
     50 
     51 codeDisplay : Model -> Html Msg
     52 codeDisplay model =
     53   xml (if model.image == "" then placeholder else model.image)
     54     |> Result.map (toBlockHtml (Just 1))
     55     |> Result.withDefault (pre [] [ code [] [ text model.image ] ])
     56 
     57 onScroll : ((Int, Int) -> msg) -> Attribute msg
     58 onScroll f = 
     59   Json.Decode.map2 
     60     (\x -> \y -> (x, y))
     61     (Json.Decode.at [ "target", "scrollLeft" ] Json.Decode.int)
     62     (Json.Decode.at [ "target", "scrollTop"  ] Json.Decode.int)
     63     |> Json.Decode.map f
     64     |> on "scroll"
     65 
     66 translate : (Int, Int) -> Attribute Msg
     67 translate (x, y) =
     68   let 
     69     show = String.fromInt
     70   in
     71     style 
     72       "transform" 
     73       ("translate(" ++ (show -x) ++ "px, " ++ (show -y) ++ "px)")
     74 
     75 placeholder : String
     76 placeholder = "<svg> ... </svg>"
     77