aboutsummaryrefslogtreecommitdiff
path: root/js/EditableNumber.purs
blob: eb5ddb0092e8bf4c8602234ed17b45e49cb5c09f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
module EditableNumber
  ( NumberElem
  , set
  , formatNumber
  ) where

import Control.Monad.Eff (Eff)
import Data.Int (round, toNumber, pow) as Int
import Data.Maybe (Maybe(..))
import Data.String (Pattern(..), Replacement(..))
import Data.String (replace) as String
import DOM (DOM)
import DOM.HTML (window) as DOM
import DOM.HTML.Types (htmlDocumentToDocument) as DOM
import DOM.HTML.Window (document) as DOM
import DOM.Node.Document (createElement, createTextNode) as DOM
import DOM.Node.Element (setClassName, setAttribute) as DOM
import DOM.Node.Node (textContent) as DOM
import DOM.Node.Types (Element, Node)
import DOM.Node.Types (elementToNode, textToNode) as DOM
import Math (round) as Math
import Prelude

import Dom (replaceElement, appendNodes) as Dom
import Parser (TextWithNumber)
import Parser (textWithNumber) as Parser

type NumberElem =
  { elem :: Element
  , number :: Number
  }

set :: forall e. { tag :: String, node :: Node } -> Eff (dom :: DOM | e) (Maybe NumberElem)
set { tag, node } = do
  content <- DOM.textContent node
  case Parser.textWithNumber content of
    Just twn -> do
      textWithNumber <- textWithNumberElem tag twn
      Dom.replaceElement node (DOM.elementToNode textWithNumber)
      pure (Just { elem: textWithNumber, number: twn.number })
    Nothing ->
      pure Nothing

textWithNumberElem :: forall e. String -> TextWithNumber -> Eff (dom :: DOM | e) Element
textWithNumberElem tag { begin, number, end } = do
  document <- DOM.htmlDocumentToDocument <$> (DOM.window >>= DOM.document)
  elem <- DOM.createElement tag document
  beginNode <- DOM.textToNode <$> DOM.createTextNode begin document
  numberNode <- numberElem number
  endNode <- DOM.textToNode <$> DOM.createTextNode end document
  Dom.appendNodes (DOM.elementToNode elem) [ beginNode, DOM.elementToNode numberNode, endNode ]
  pure elem

numberElem :: forall e. Number -> Eff (dom :: DOM | e) Element
numberElem number = do
  document <- DOM.htmlDocumentToDocument <$> (DOM.window >>= DOM.document)
  container <- DOM.createElement "input" document
  DOM.setClassName "number" container
  DOM.setAttribute "value" (formatNumber number) container
  pure container

formatNumber :: Number -> String
formatNumber number =
  if Math.round number == number then
    show (Int.round number)
  else
    String.replace (Pattern ".") (Replacement ",") (show (roundAt 1 number))

roundAt :: Int -> Number -> Number
roundAt at n =
  let exp = Int.toNumber (Int.pow 10 at)
  in  Math.round (n * exp) / exp