web-rep-0.11.0.0: src/Web/Rep/Html/Input.hs
{-# LANGUAGE OverloadedStrings #-}
-- | Common web page input elements, often with bootstrap scaffolding.
module Web.Rep.Html.Input
( Input (..),
InputType (..),
inputToHtml,
)
where
import Data.Bool
import Data.ByteString (ByteString)
import Data.ByteString.Char8 qualified as C
import Data.Maybe
import GHC.Generics
import MarkupParse
-- | something that might exist on a web page and be a front-end input to computations.
data Input a = Input
{ -- | underlying value
inputVal :: a,
-- | label suggestion
inputLabel :: Maybe ByteString,
-- | name//key//id of the Input
inputId :: ByteString,
-- | type of html input
inputType :: InputType
}
deriving (Eq, Show, Generic)
-- | Various types of web page inputs, encapsulating practical bootstrap class functionality
data InputType
= Slider [Attr]
| SliderV [Attr]
| TextBox
| TextBox'
| TextArea Int
| ColorPicker
| ChooseFile
| Dropdown [ByteString]
| DropdownMultiple [ByteString] Char
| DropdownSum [ByteString]
| Datalist [ByteString] ByteString
| Checkbox Bool
| Toggle Bool (Maybe ByteString)
| Button
deriving (Eq, Show, Generic)
inputToHtml :: (Show a) => Input a -> Markup
inputToHtml (Input v l i (Slider satts)) =
element
"div"
[Attr "class" "form-group-sm"]
(maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l)
<> element_
"input"
( [ Attr "type" "range",
Attr "class" " form-control-range form-control-sm custom-range jsbClassEventChange",
Attr "id" i,
Attr "value" (strToUtf8 $ show v)
]
<> satts
)
inputToHtml (Input v l i (SliderV satts)) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element_
"input"
( [ Attr "type" "range",
Attr "class" " form-control-range form-control-sm custom-range jsbClassEventChange",
Attr "id" i,
Attr "value" (strToUtf8 $ show v),
Attr "oninput" ("$('#sliderv" <> i <> "').html($(this).val())")
]
<> satts
)
)
<> elementc "span" [Attr "id" ("sliderv" <> i)] (strToUtf8 $ show v)
inputToHtml (Input v l i TextBox) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element_
"input"
[ Attr "type" "text",
Attr "class" "form-control form-control-sm jsbClassEventInput",
Attr "id" i,
Attr "value" (strToUtf8 $ show v)
]
)
inputToHtml (Input v l i TextBox') =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element_
"input"
[ Attr "type" "text",
Attr "class" "form-control form-control-sm jsbClassEventFocusout",
Attr "id" i,
Attr "value" (strToUtf8 $ show v)
]
)
inputToHtml (Input v l i (TextArea rows)) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> elementc
"textarea"
[ Attr "rows" (strToUtf8 $ show rows),
Attr "class" "form-control form-control-sm jsbClassEventInput",
Attr "id" i
]
(strToUtf8 $ show v)
)
inputToHtml (Input v l i ColorPicker) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element_
"input"
[ Attr "type" "color",
Attr "class" "form-control form-control-sm jsbClassEventInput",
Attr "id" i,
Attr "value" (strToUtf8 $ show v)
]
)
inputToHtml (Input _ l i ChooseFile) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element_
"input"
[ Attr "type" "file",
Attr "class" "form-control-file form-control-sm jsbClassEventChooseFile",
Attr "id" i
]
)
inputToHtml (Input v l i (Dropdown opts)) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element
"select"
[ Attr "class" "form-control form-control-sm jsbClassEventInput",
Attr "id" i
]
(mconcat opts')
)
where
opts' =
( \o ->
elementc
"option"
( bool
[]
[Attr "selected" "selected"]
(o == strToUtf8 (show v))
)
o
)
<$> opts
inputToHtml (Input vs l i (DropdownMultiple opts sep)) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element
"select"
[ Attr "class" "form-control form-control-sm jsbClassEventChangeMultiple",
Attr "multiple" "multiple",
Attr "id" i
]
(mconcat opts')
)
where
opts' =
( \o ->
elementc
"option"
( bool
[]
[Attr "selected" "selected"]
(any (\v -> o == strToUtf8 (show v)) (C.split sep (strToUtf8 $ show vs)))
)
o
)
<$> opts
inputToHtml (Input v l i (DropdownSum opts)) =
element
"div"
[Attr "class" "form-group-sm sumtype-group"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element
"select"
[ Attr "class" "form-control form-control-sm jsbClassEventInput jsbClassEventShowSum",
Attr "id" i
]
(mconcat opts')
)
where
opts' =
( \o ->
elementc
"option"
(bool [] [Attr "selected" "selected"] (o == strToUtf8 (show v)))
o
)
<$> opts
inputToHtml (Input v l i (Datalist opts listId)) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element_
"input"
[ Attr "type" "text",
Attr "class" "form-control form-control-sm jsbClassEventInput",
Attr "id" i,
Attr "list" listId
-- the datalist concept in html assumes initial state is a null
-- and doesn't present the list if it has a value alreadyx
-- , value_ (show $ toHtml v)
]
<> element
"datalist"
[Attr "id" listId]
( mconcat
( ( \o ->
elementc
"option"
( bool
[]
[Attr "selected" "selected"]
(o == strToUtf8 (show v))
)
o
)
<$> opts
)
)
)
inputToHtml (Input _ l i (Checkbox checked)) =
element
"div"
[Attr "class" "form-check form-check-sm"]
( element
"input"
( [ Attr "type" "checkbox",
Attr "class" "form-check-input jsbClassEventCheckbox",
Attr "id" i
]
<> bool [] [Attr "checked" ""] checked
)
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "form-label-check mb-0"]) l
)
)
inputToHtml (Input _ l i (Toggle pushed lab)) =
element
"div"
[Attr "class" "form-group-sm"]
( maybe mempty (elementc "label" [Attr "for" i, Attr "class" "mb-0"]) l
<> element_
"input"
( [ Attr "type" "button",
Attr "class" "btn btn-primary btn-sm jsbClassEventToggle",
Attr "data-bs-toggle" "button",
Attr "id" i,
Attr "aria-pressed" (bool "false" "true" pushed)
]
<> maybe [] (\l' -> [Attr "value" l']) lab
<> bool [] [Attr "checked" ""] pushed
)
)
inputToHtml (Input _ l i Button) =
element
"div"
[Attr "class" "form-group-sm"]
( element_
"input"
[ Attr "type" "button",
Attr "id" i,
Attr "class" "btn btn-primary btn-sm jsbClassEventButton",
Attr "value" (fromMaybe "button" l)
]
)