packages feed

ditto-lucid 0.1.0.2 → 0.1.0.3

raw patch · 4 files changed

+360/−452 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Ditto.Lucid: arbitraryHtml :: Monad m => view -> Form m input error view ()
- Ditto.Lucid: button :: (Monad m, FormError error, ToHtml children, Monad f) => children -> Form m input error (HtmlT f ()) ()
- Ditto.Lucid: buttonReset :: (Monad m, FormError error, ToHtml children, Monad f) => children -> Form m input error (HtmlT f ()) ()
- Ditto.Lucid: buttonSubmit :: (Monad m, FormError error, PathPiece text, ToHtml children, Monad f) => (input -> Either error text) -> text -> children -> Form m input error (HtmlT f ()) (Maybe text)
- Ditto.Lucid: inputButton :: (Monad m, FormError error, PathPiece text, Applicative f) => text -> Form m input error (HtmlT f ()) ()
- Ditto.Lucid: inputCheckbox :: forall x error input m f. (Monad m, FormInput input, FormError error, ErrorInputType error ~ input, Applicative f) => Bool -> Form m input error (HtmlT f ()) Bool
- Ditto.Lucid: inputCheckboxes :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) [a]
- Ditto.Lucid: inputDouble :: (Monad m, FormError err, Applicative f) => (input -> Either err Double) -> Double -> Form m input err (HtmlT f ()) Double
- Ditto.Lucid: inputFile :: (Monad m, FormError error, FormInput input, ErrorInputType error ~ input, Applicative f) => Form m input error (HtmlT f ()) (FileType input)
- Ditto.Lucid: inputHidden :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) text
- Ditto.Lucid: inputInt :: (Monad m, FormError err, Applicative f) => (input -> Either err Int) -> Int -> Form m input err (HtmlT f ()) Int
- Ditto.Lucid: inputPassword :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) text
- Ditto.Lucid: inputRadio :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) a
- Ditto.Lucid: inputReset :: (Monad m, FormError error, PathPiece text, Applicative f) => text -> Form m input error (HtmlT f ()) ()
- Ditto.Lucid: inputSubmit :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) (Maybe text)
- Ditto.Lucid: inputText :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) text
- Ditto.Lucid: label :: (Monad m, Monad f) => HtmlT f () -> Form m input error (HtmlT f ()) ()
- Ditto.Lucid: select :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) a
- Ditto.Lucid: selectMultiple :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) [a]
- Ditto.Lucid: textarea :: (Monad m, FormError error, ToHtml text, Monad f) => (input -> Either error text) -> Int -> Int -> text -> Form m input error (HtmlT f ()) text
- Ditto.Lucid.Named: br :: (Monad m, Applicative f) => Form m input error (HtmlT f ()) ()
- Ditto.Lucid.Named: childErrorList :: (Monad m, ToHtml error, Monad f) => Form m input error (HtmlT f ()) ()
- Ditto.Lucid.Named: errorList :: (Monad m, ToHtml error, Monad f) => Form m input error (HtmlT f ()) ()
- Ditto.Lucid.Named: fieldset :: (Monad m, Functor m, Applicative f) => Form m input error (HtmlT f ()) a -> Form m input error (HtmlT f ()) a
- Ditto.Lucid.Named: formGenGET :: Applicative m => Text -> [(Text, Text)] -> HtmlT m b -> HtmlT m b
- Ditto.Lucid.Named: formGenPOST :: Applicative m => Text -> [(Text, Text)] -> HtmlT m b -> HtmlT m b
- Ditto.Lucid.Named: instance Web.PathPieces.PathPiece Ditto.Result.FormId
- Ditto.Lucid.Named: li :: (Monad m, Functor m, Applicative f) => Form m input error (HtmlT f ()) a -> Form m input error (HtmlT f ()) a
- Ditto.Lucid.Named: ol :: (Monad m, Functor m, Applicative f) => Form m input error (HtmlT f ()) a -> Form m input error (HtmlT f ()) a
- Ditto.Lucid.Named: setAttr :: (Monad m, Functor m, Applicative f) => Form m input error (HtmlT f ()) a -> [Attribute] -> Form m input error (HtmlT f ()) a
- Ditto.Lucid.Named: ul :: (Monad m, Functor m, Applicative f) => Form m input error (HtmlT f ()) a -> Form m input error (HtmlT f ()) a
+ Ditto.Lucid.Unnamed: arbitraryHtml :: Monad m => view -> Form m input error view ()
+ Ditto.Lucid.Unnamed: button :: (Monad m, FormError error, ToHtml children, Monad f) => children -> Form m input error (HtmlT f ()) ()
+ Ditto.Lucid.Unnamed: buttonReset :: (Monad m, FormError error, ToHtml children, Monad f) => children -> Form m input error (HtmlT f ()) ()
+ Ditto.Lucid.Unnamed: buttonSubmit :: (Monad m, FormError error, PathPiece text, ToHtml children, Monad f) => (input -> Either error text) -> text -> children -> Form m input error (HtmlT f ()) (Maybe text)
+ Ditto.Lucid.Unnamed: inputButton :: (Monad m, FormError error, PathPiece text, Applicative f) => text -> Form m input error (HtmlT f ()) ()
+ Ditto.Lucid.Unnamed: inputCheckbox :: forall x error input m f. (Monad m, FormInput input, FormError error, ErrorInputType error ~ input, Applicative f) => Bool -> Form m input error (HtmlT f ()) Bool
+ Ditto.Lucid.Unnamed: inputCheckboxes :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) [a]
+ Ditto.Lucid.Unnamed: inputDouble :: (Monad m, FormError err, Applicative f) => (input -> Either err Double) -> Double -> Form m input err (HtmlT f ()) Double
+ Ditto.Lucid.Unnamed: inputFile :: (Monad m, FormError error, FormInput input, ErrorInputType error ~ input, Applicative f) => Form m input error (HtmlT f ()) (FileType input)
+ Ditto.Lucid.Unnamed: inputHidden :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) text
+ Ditto.Lucid.Unnamed: inputInt :: (Monad m, FormError err, Applicative f) => (input -> Either err Int) -> Int -> Form m input err (HtmlT f ()) Int
+ Ditto.Lucid.Unnamed: inputPassword :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) text
+ Ditto.Lucid.Unnamed: inputRadio :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) a
+ Ditto.Lucid.Unnamed: inputReset :: (Monad m, FormError error, PathPiece text, Applicative f) => text -> Form m input error (HtmlT f ()) ()
+ Ditto.Lucid.Unnamed: inputSubmit :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) (Maybe text)
+ Ditto.Lucid.Unnamed: inputText :: (Monad m, FormError error, PathPiece text, Applicative f) => (input -> Either error text) -> text -> Form m input error (HtmlT f ()) text
+ Ditto.Lucid.Unnamed: label :: (Monad m, Monad f) => HtmlT f () -> Form m input error (HtmlT f ()) ()
+ Ditto.Lucid.Unnamed: select :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) a
+ Ditto.Lucid.Unnamed: selectMultiple :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f) => [(a, lbl)] -> (a -> Bool) -> Form m input error (HtmlT f ()) [a]
+ Ditto.Lucid.Unnamed: textarea :: (Monad m, FormError error, ToHtml text, Monad f) => (input -> Either error text) -> Int -> Int -> text -> Form m input error (HtmlT f ()) text
- Ditto.Lucid: setAttr :: (Monad m, Functor m, Applicative f) => Form m input error (HtmlT f ()) a -> [Attribute] -> Form m input error (HtmlT f ()) a
+ Ditto.Lucid: setAttr :: (Monad m, Functor m, Applicative f) => [Attribute] -> Form m input error (HtmlT f ()) a -> Form m input error (HtmlT f ()) a

Files

ditto-lucid.cabal view
@@ -1,5 +1,5 @@ Name:                ditto-lucid-Version:             0.1.0.2+Version:             0.1.0.3 Synopsis:            Add support for using lucid with Ditto Description:         Ditto is a library for building and validating forms using applicative functors. This package add support for using ditto with lucid. License:             BSD3@@ -19,6 +19,7 @@ Library   exposed-modules:      Ditto.Lucid+    Ditto.Lucid.Unnamed     Ditto.Lucid.Named   build-depends:       base >4.5 && <5
src/Ditto/Lucid.hs view
@@ -20,312 +20,41 @@   toPathPiece fid = T.pack (show fid)   fromPathPiece fidT = Nothing -inputText-  :: (Monad m, FormError error, PathPiece text, Applicative f)-  => (input -> Either error text)-  -> text-  -> Form m input error (HtmlT f ()) text-inputText getInput initialValue = G.input getInput inputField initialValue-  where-    inputField i a = input_ [type_ "text", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]--inputPassword-  :: (Monad m, FormError error, PathPiece text, Applicative f)-  => (input -> Either error text)-  -> text-  -> Form m input error (HtmlT f ()) text-inputPassword getInput initialValue = G.input getInput inputField initialValue-  where-    inputField i a = input_ [type_ "password", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]--inputSubmit-  :: (Monad m, FormError error, PathPiece text, Applicative f)-  => (input -> Either error text)-  -> text-  -> Form m input error (HtmlT f ()) (Maybe text)-inputSubmit getInput initialValue = G.inputMaybe getInput inputField initialValue-  where-    inputField i a = input_ [type_ "submit", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]--inputReset-  :: (Monad m, FormError error, PathPiece text, Applicative f)-  => text-  -> Form m input error (HtmlT f ()) ()-inputReset lbl = G.inputNoData inputField lbl-  where-    inputField i a = input_ [type_ "submit", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]--inputHidden-  :: (Monad m, FormError error, PathPiece text, Applicative f)-  => (input -> Either error text)-  -> text-  -> Form m input error (HtmlT f ()) text-inputHidden getInput initialValue = G.input getInput inputField initialValue-  where-    inputField i a = input_ [type_ "hidden", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]--inputButton-  :: (Monad m, FormError error, PathPiece text, Applicative f)-  => text-  -> Form m input error (HtmlT f ()) ()-inputButton label = G.inputNoData inputField label-  where-    inputField i a = input_ [type_ "button", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]--textarea-  :: (Monad m, FormError error, ToHtml text, Monad f)-  => (input -> Either error text)-  -> Int -- ^ cols-  -> Int -- ^ rows-  -> text -- ^ initial text-  -> Form m input error (HtmlT f ()) text-textarea getInput cols rows initialValue = G.input getInput textareaView initialValue-  where-    textareaView i txt =-      textarea_-        [ rows_ (toPathPiece rows)-        , cols_ (toPathPiece cols)-        , id_ (toPathPiece i)-        , name_ (toPathPiece i)-        ] $-        toHtml txt---- | Create an @\<input type=\"file\"\>@ element------ This control may succeed even if the user does not actually select a file to upload. In that case the uploaded name will likely be \"\" and the file contents will be empty as well.-inputFile-  :: (Monad m, FormError error, FormInput input, ErrorInputType error ~ input, Applicative f)-  => Form m input error (HtmlT f ()) (FileType input)-inputFile = G.inputFile fileView-  where-    fileView i = input_ [type_ "file", id_ (toPathPiece i), name_ (toPathPiece i)]---- | Create a @\<button type=\"submit\"\>@ element-buttonSubmit-  :: (Monad m, FormError error, PathPiece text, ToHtml children, Monad f)-  => (input -> Either error text)-  -> text-  -> children-  -> Form m input error (HtmlT f ()) (Maybe text)-buttonSubmit getInput text c = G.inputMaybe getInput inputField text-  where-    inputField i a = button_ [type_ "submit", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)] $ toHtml c---- | create a  @\<button type=\"reset\"\>\<\/button\>@ element------ This element does not add any data to the form data set.-buttonReset-  :: (Monad m, FormError error, ToHtml children, Monad f)-  => children-  -> Form m input error (HtmlT f ()) ()-buttonReset c = G.inputNoData inputField Nothing-  where-    inputField i a = button_ [type_ "reset", id_ (toPathPiece i), name_ (toPathPiece i)] $ toHtml c---- | create a  @\<button type=\"button\"\>\<\/button\>@ element------ This element does not add any data to the form data set.-button-  :: (Monad m, FormError error, ToHtml children, Monad f)-  => children-  -> Form m input error (HtmlT f ()) ()-button c = G.inputNoData inputField Nothing-  where-    inputField i a = button_ [type_ "button", id_ (toPathPiece i), name_ (toPathPiece i)] $ toHtml c---- | create a @\<label\>@ element.------ Use this with <++ or ++> to ensure that the @for@ attribute references the correct @id@.------ > label "some input field: " ++> inputText ""-label-  :: (Monad m, Monad f)-  => HtmlT f ()-  -> Form m input error (HtmlT f ()) ()-label c = G.label mkLabel-  where-    mkLabel i = label_ [for_ (toPathPiece i)] c--arbitraryHtml :: Monad m => view -> Form m input error view ()-arbitraryHtml wrap =-  Form $ do-    id' <- getFormId-    pure-      ( View (const $ wrap)-      , pure-        ( Ok $ Proved-          { pos = unitRange id'-          , unProved = ()-          }-        )-      )--inputInt-  :: (Monad m, FormError err, Applicative f)-  => (input -> Either err Int)-  -> Int-  -> Form m input err (HtmlT f ()) Int-inputInt getInput initialValue = G.input getInput inputField initialValue-  where-    inputField i a =-      input_-        [ type_ "number"-        , id_ (toPathPiece i)-        , name_ (toPathPiece i)-        , value_ (toPathPiece a)-        ]--inputDouble-  :: (Monad m, FormError err, Applicative f)-  => (input -> Either err Double)-  -> Double-  -> Form m input err (HtmlT f ()) Double-inputDouble getInput initialValue = G.input getInput inputField initialValue-  where-    inputField i a = input_ [type_ "number", step_ "any", id_ (toPathPiece i), name_ (toPathPiece i), value_ (T.pack $ show a)]---- | Create a single @\<input type=\"checkbox\"\>@ element------ returns a 'Bool' indicating if it was checked or not.------ see also 'inputCheckboxes'--- FIXME: Should this built on something in Generalized?-inputCheckbox-  :: forall x error input m f. (Monad m, FormInput input, FormError error, ErrorInputType error ~ input, Applicative f)-  => Bool -- ^ initially checked-  -> Form m input error (HtmlT f ()) Bool-inputCheckbox initiallyChecked =-  Form $ do-    i <- getFormId-    v <- getFormInput' i-    case v of-      Default -> mkCheckbox i initiallyChecked-      Missing -> mkCheckbox i False -- checkboxes only appear in the submitted data when checked-      (Found input) ->-        case getInputString input of-          (Right _) -> mkCheckbox i True-          (Left (e :: error)) -> mkCheckbox i False-  where-    mkCheckbox i checked =-      let checkbox =-            input_ $-              (if checked then (:) checked_ else id)-                [type_ "checkbox", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece i)]-       in pure-            ( View $ const $ checkbox-            , pure $-              Ok-                ( Proved-                  { pos = unitRange i-                  , unProved = if checked then True else False-                  }-                )-            )---- | Create a group of @\<input type=\"checkbox\"\>@ elements----inputCheckboxes-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)-  => [(a, lbl)] -- ^ value, label, initially checked-  -> (a -> Bool) -- ^ function which indicates if a value should be checked initially-  -> Form m input error (HtmlT f ()) [a]-inputCheckboxes choices isChecked =-  G.inputMulti choices mkCheckboxes isChecked+-- | create @\<form action=action method=\"GET\" enctype=\"multipart/form-data\"\>@+formGenGET+  :: (Applicative m)+  => Text -- ^ action url+  -> [(Text, Text)] -- ^ hidden fields to add to form+  -> HtmlT m b+  -> HtmlT m b+formGenGET action hidden children = do+  form_ [action_ action, method_ "GET", enctype_ "multipart/form-data"] $+    traverse_ mkHidden hidden *>+    children   where-    mkCheckboxes nm choices' = mconcat $ concatMap (mkCheckbox nm) choices'-    mkCheckbox nm (i, val, lbl, checked) =-      [ input_ $-          ( (if checked then (checked_ :) else id)-            [type_ "checkbox", id_ (toPathPiece i), name_ (toPathPiece nm), value_ (toPathPiece val)]-          )-      , label_ [for_ (toPathPiece i)] $ toHtml lbl-      ]+    mkHidden (name, value) = input_ [type_ "hidden", name_ name, value_ value] --- | Create a group of @\<input type=\"radio\"\>@ elements-inputRadio-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)-  => [(a, lbl)] -- ^ value, label, initially checked-  -> (a -> Bool) -- ^ isDefault-  -> Form m input error (HtmlT f ()) a-inputRadio choices isDefault =-  G.inputChoice isDefault choices mkRadios+-- | create @\<form action=action method=\"POST\" enctype=\"multipart/form-data\"\>@+formGenPOST+  :: (Applicative m)+  => Text -- ^ action url+  -> [(Text, Text)] -- ^ hidden fields to add to form+  -> HtmlT m b+  -> HtmlT m b+formGenPOST action hidden children = do+  form_ [action_ action, method_ "POST", enctype_ "multipart/form-data"] $+    traverse_ mkHidden hidden *>+    children   where-    mkRadios nm choices' = mconcat $ concatMap (mkRadio nm) choices'-    mkRadio nm (i, val, lbl, checked) =-      [ input_ $-          (if checked then (checked_ :) else id)-            [type_ "radio", id_ (toPathPiece i), name_ (toPathPiece nm), value_ (toPathPiece val)]-      , label_ [for_ (toPathPiece i)] $ toHtml lbl-      , br_ []-      ]+    mkHidden (name, value) = input_ [type_ "hidden", name_ name, value_ value] --- | create @\<select\>\<\/select\>@ element plus its @\<option\>\<\/option\>@ children.------ see also: 'selectMultiple'-select-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)-  => [(a, lbl)] -- ^ value, label-  -> (a -> Bool) -- ^ isDefault, must match *exactly one* element in the list of choices+-- | add an attribute to the 'Html' for a form element.+setAttr+  :: (Monad m, Functor m, Applicative f)+  => [Attribute]+  -> Form m input error (HtmlT f ()) a    -> Form m input error (HtmlT f ()) a-select choices isDefault =-  G.inputChoice isDefault choices mkSelect-  where-    mkSelect :: (ToHtml lbl, Monad f) => FormId -> [(a, Int, lbl, Bool)] -> HtmlT f ()-    mkSelect nm choices' =-      select_ [name_ (toPathPiece nm)] $-        traverse_ mkOption choices'-    mkOption :: (ToHtml lbl, Monad f) => (a, Int, lbl, Bool) -> HtmlT f ()-    mkOption (_, val, lbl, selected) =-      option_-        ( (if selected then ((:) (selected_ "selected")) else id)-          [value_ (toPathPiece val)]-        )-        (toHtml lbl)---- | create @\<select multiple=\"multiple\"\>\<\/select\>@ element plus its @\<option\>\<\/option\>@ children.------ This creates a @\<select\>@ element which allows more than one item to be selected.-selectMultiple-  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)-  => [(a, lbl)] -- ^ value, label, initially checked-  -> (a -> Bool) -- ^ isSelected initially-  -> Form m input error (HtmlT f ()) [a]-selectMultiple choices isSelected =-  G.inputMulti choices mkSelect isSelected-  where-    mkSelect :: (ToHtml lbl, Monad f) => FormId -> [(a, Int, lbl, Bool)] -> HtmlT f ()-    mkSelect nm choices' =-      select_ [name_ (toPathPiece nm), multiple_ "multiple"] $-        traverse_ mkOption choices'-    mkOption :: (ToHtml lbl, Monad f) => (a, Int, lbl, Bool) -> HtmlT f ()-    mkOption (_, val, lbl, selected) =-      option_-        ( (if selected then ((:) (selected_ "selected")) else id)-          [value_ (toPathPiece val)]-        )-        (toHtml lbl)--{--inputMultiSelectOptGroup :: (Functor m, XMLGenerator x, EmbedAsChild x groupLbl, EmbedAsChild x lbl, EmbedAsAttr x (Attr String FormId), FormError error, ErrorInputType error ~ input, FormInput input, Monad m, Applicative f) =>-                   [(groupLbl, [(a, lbl, Bool)])]  -- ^ value, label, initially checked-                -> Form m input error (HtmlT f ()) [a]-inputMultiSelectOptGroup choices =-    G.inputMulti choices mkSelect-    where-      mkSelect nm choices' =-          [<select name=nm multiple="multiple">-            <% mapM mkOptGroup choices' %>-           </select>-          ]-      mkOptGroup (grpLabel, options) =-          <optgroup label=grpLabel>-           <% mapM mkOption options %>-          </optgroup>-      mkOption (_, val, lbl, selected) =-          <option value=val (if selected then ["selected" := "selected"] else [])>-           <% lbl %>-          </option>--}+setAttr attr form = mapView (\x -> x `with` attr) form  -- | create a @\<ul\>@ which contains all the errors related to the 'Form'. --@@ -390,38 +119,3 @@   -> Form m input error (HtmlT f ()) a li frm = mapView (li_ [class_ "ditto"]) frm --- | create @\<form action=action method=\"GET\" enctype=\"multipart/form-data\"\>@-formGenGET-  :: (Applicative m)-  => Text -- ^ action url-  -> [(Text, Text)] -- ^ hidden fields to add to form-  -> HtmlT m b-  -> HtmlT m b-formGenGET action hidden children = do-  form_ [action_ action, method_ "GET", enctype_ "multipart/form-data"] $-    traverse_ mkHidden hidden *>-    children-  where-    mkHidden (name, value) = input_ [type_ "hidden", name_ name, value_ value]---- | create @\<form action=action method=\"POST\" enctype=\"multipart/form-data\"\>@-formGenPOST-  :: (Applicative m)-  => Text -- ^ action url-  -> [(Text, Text)] -- ^ hidden fields to add to form-  -> HtmlT m b-  -> HtmlT m b-formGenPOST action hidden children = do-  form_ [action_ action, method_ "POST", enctype_ "multipart/form-data"] $-    traverse_ mkHidden hidden *>-    children-  where-    mkHidden (name, value) = input_ [type_ "hidden", name_ name, value_ value]---- | add an attribute to the 'Html' for a form element.-setAttr-  :: (Monad m, Functor m, Applicative f)-  => Form m input error (HtmlT f ()) a-  -> [Attribute]-  -> Form m input error (HtmlT f ()) a-setAttr form attr = mapView (\x -> x `with` attr) form
src/Ditto/Lucid/Named.hs view
@@ -7,19 +7,16 @@ import Data.Foldable (traverse_) import Data.Monoid ((<>), mconcat, mempty) import Data.Text (Text)-import Lucid import Ditto.Backend import Ditto.Core import Ditto.Generalized.Named as G+import Ditto.Lucid import Ditto.Result (FormId, Result (Ok), unitRange)+import Lucid import Web.PathPieces import qualified Data.Text as T import qualified Text.Read -instance PathPiece FormId where-  toPathPiece fid = T.pack (show fid)-  fromPathPiece fidT = Nothing- inputText   :: (Monad m, FormError error, PathPiece text, Applicative f)   => (input -> Either error text)@@ -158,18 +155,7 @@     mkLabel i = label_ [for_ (toPathPiece i)] c  arbitraryHtml :: Monad m => view -> Form m input error view ()-arbitraryHtml wrap =-  Form $ do-    id' <- getFormId-    pure-      ( View (const $ wrap)-      , pure-        ( Ok $ Proved-          { pos = unitRange id'-          , unProved = ()-          }-        )-      )+arbitraryHtml = view  inputInt   :: (Monad m, FormError err, Applicative f)@@ -341,101 +327,3 @@           </option> -} --- | create a @\<ul\>@ which contains all the errors related to the 'Form'.------ The @<\ul\>@ will have the attribute @class=\"ditto-error-list\"@.-errorList-  :: (Monad m, ToHtml error, Monad f)-  => Form m input error (HtmlT f ()) ()-errorList = G.errors mkErrors-  where-    mkErrors :: Monad f => ToHtml a => [a] -> HtmlT f ()-    mkErrors [] = mempty-    mkErrors errs = ul_ [class_ "ditto-error-list"] $ traverse_ mkError errs-    mkError :: Monad f => ToHtml a => a -> HtmlT f ()-    mkError e = li_ [] $ toHtml e---- | create a @\<ul\>@ which contains all the errors related to the 'Form'.------ Includes errors from child forms.------ The @<\ul\>@ will have the attribute @class=\"ditto-error-list\"@.-childErrorList-  :: (Monad m, ToHtml error, Monad f)-  => Form m input error (HtmlT f ()) ()-childErrorList = G.childErrors mkErrors-  where-    mkErrors :: Monad f => ToHtml a => [a] -> HtmlT f ()-    mkErrors [] = mempty-    mkErrors errs = ul_ [class_ "ditto-error-list"] $ traverse_ mkError errs-    mkError :: Monad f => ToHtml a => a -> HtmlT f ()-    mkError e = li_ [] $ toHtml e---- | create a @\<br\>@ tag.-br :: (Monad m, Applicative f) => Form m input error (HtmlT f ()) ()-br = view (br_ [])---- | wrap a @\<fieldset class=\"ditto\"\>@ around a 'Form'----fieldset-  :: (Monad m, Functor m, Applicative f)-  => Form m input error (HtmlT f ()) a-  -> Form m input error (HtmlT f ()) a-fieldset frm = mapView (fieldset_ [class_ "ditto"]) frm---- | wrap an @\<ol class=\"ditto\"\>@ around a 'Form'-ol-  :: (Monad m, Functor m, Applicative f)-  => Form m input error (HtmlT f ()) a-  -> Form m input error (HtmlT f ()) a-ol frm = mapView (ol_ [class_ "ditto"]) frm---- | wrap a @\<ul class=\"ditto\"\>@ around a 'Form'-ul-  :: (Monad m, Functor m, Applicative f)-  => Form m input error (HtmlT f ()) a-  -> Form m input error (HtmlT f ()) a-ul frm = mapView (ul_ [class_ "ditto"]) frm---- | wrap a @\<li class=\"ditto\"\>@ around a 'Form'-li-  :: (Monad m, Functor m, Applicative f)-  => Form m input error (HtmlT f ()) a-  -> Form m input error (HtmlT f ()) a-li frm = mapView (li_ [class_ "ditto"]) frm---- | create @\<form action=action method=\"GET\" enctype=\"multipart/form-data\"\>@-formGenGET-  :: (Applicative m)-  => Text -- ^ action url-  -> [(Text, Text)] -- ^ hidden fields to add to form-  -> HtmlT m b-  -> HtmlT m b-formGenGET action hidden children = do-  form_ [action_ action, method_ "GET", enctype_ "multipart/form-data"] $-    traverse_ mkHidden hidden *>-    children-  where-    mkHidden (name, value) = input_ [type_ "hidden", name_ name, value_ value]---- | create @\<form action=action method=\"POST\" enctype=\"multipart/form-data\"\>@-formGenPOST-  :: (Applicative m)-  => Text -- ^ action url-  -> [(Text, Text)] -- ^ hidden fields to add to form-  -> HtmlT m b-  -> HtmlT m b-formGenPOST action hidden children = do-  form_ [action_ action, method_ "POST", enctype_ "multipart/form-data"] $-    traverse_ mkHidden hidden *>-    children-  where-    mkHidden (name, value) = input_ [type_ "hidden", name_ name, value_ value]---- | add an attribute to the 'Html' for a form element.-setAttr-  :: (Monad m, Functor m, Applicative f)-  => Form m input error (HtmlT f ()) a-  -> [Attribute]-  -> Form m input error (HtmlT f ()) a-setAttr form attr = mapView (\x -> x `with` attr) form
+ src/Ditto/Lucid/Unnamed.hs view
@@ -0,0 +1,325 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}++module Ditto.Lucid.Unnamed where++import Data.Foldable (traverse_)+import Data.Monoid ((<>), mconcat, mempty)+import Data.Text (Text)+import Ditto.Backend+import Ditto.Core+import Ditto.Generalized as G+import Ditto.Lucid+import Ditto.Result (FormId, Result (Ok), unitRange)+import Lucid+import Web.PathPieces+import qualified Data.Text as T+import qualified Text.Read++inputText+  :: (Monad m, FormError error, PathPiece text, Applicative f)+  => (input -> Either error text)+  -> text+  -> Form m input error (HtmlT f ()) text+inputText getInput initialValue = G.input getInput inputField initialValue+  where+    inputField i a = input_ [type_ "text", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]++inputPassword+  :: (Monad m, FormError error, PathPiece text, Applicative f)+  => (input -> Either error text)+  -> text+  -> Form m input error (HtmlT f ()) text+inputPassword getInput initialValue = G.input getInput inputField initialValue+  where+    inputField i a = input_ [type_ "password", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]++inputSubmit+  :: (Monad m, FormError error, PathPiece text, Applicative f)+  => (input -> Either error text)+  -> text+  -> Form m input error (HtmlT f ()) (Maybe text)+inputSubmit getInput initialValue = G.inputMaybe getInput inputField initialValue+  where+    inputField i a = input_ [type_ "submit", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]++inputReset+  :: (Monad m, FormError error, PathPiece text, Applicative f)+  => text+  -> Form m input error (HtmlT f ()) ()+inputReset lbl = G.inputNoData inputField lbl+  where+    inputField i a = input_ [type_ "submit", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]++inputHidden+  :: (Monad m, FormError error, PathPiece text, Applicative f)+  => (input -> Either error text)+  -> text+  -> Form m input error (HtmlT f ()) text+inputHidden getInput initialValue = G.input getInput inputField initialValue+  where+    inputField i a = input_ [type_ "hidden", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]++inputButton+  :: (Monad m, FormError error, PathPiece text, Applicative f)+  => text+  -> Form m input error (HtmlT f ()) ()+inputButton label = G.inputNoData inputField label+  where+    inputField i a = input_ [type_ "button", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)]++textarea+  :: (Monad m, FormError error, ToHtml text, Monad f)+  => (input -> Either error text)+  -> Int -- ^ cols+  -> Int -- ^ rows+  -> text -- ^ initial text+  -> Form m input error (HtmlT f ()) text+textarea getInput cols rows initialValue = G.input getInput textareaView initialValue+  where+    textareaView i txt =+      textarea_+        [ rows_ (toPathPiece rows)+        , cols_ (toPathPiece cols)+        , id_ (toPathPiece i)+        , name_ (toPathPiece i)+        ] $+        toHtml txt++-- | Create an @\<input type=\"file\"\>@ element+--+-- This control may succeed even if the user does not actually select a file to upload. In that case the uploaded name will likely be \"\" and the file contents will be empty as well.+inputFile+  :: (Monad m, FormError error, FormInput input, ErrorInputType error ~ input, Applicative f)+  => Form m input error (HtmlT f ()) (FileType input)+inputFile = G.inputFile fileView+  where+    fileView i = input_ [type_ "file", id_ (toPathPiece i), name_ (toPathPiece i)]++-- | Create a @\<button type=\"submit\"\>@ element+buttonSubmit+  :: (Monad m, FormError error, PathPiece text, ToHtml children, Monad f)+  => (input -> Either error text)+  -> text+  -> children+  -> Form m input error (HtmlT f ()) (Maybe text)+buttonSubmit getInput text c = G.inputMaybe getInput inputField text+  where+    inputField i a = button_ [type_ "submit", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece a)] $ toHtml c++-- | create a  @\<button type=\"reset\"\>\<\/button\>@ element+--+-- This element does not add any data to the form data set.+buttonReset+  :: (Monad m, FormError error, ToHtml children, Monad f)+  => children+  -> Form m input error (HtmlT f ()) ()+buttonReset c = G.inputNoData inputField Nothing+  where+    inputField i a = button_ [type_ "reset", id_ (toPathPiece i), name_ (toPathPiece i)] $ toHtml c++-- | create a  @\<button type=\"button\"\>\<\/button\>@ element+--+-- This element does not add any data to the form data set.+button+  :: (Monad m, FormError error, ToHtml children, Monad f)+  => children+  -> Form m input error (HtmlT f ()) ()+button c = G.inputNoData inputField Nothing+  where+    inputField i a = button_ [type_ "button", id_ (toPathPiece i), name_ (toPathPiece i)] $ toHtml c++-- | create a @\<label\>@ element.+--+-- Use this with <++ or ++> to ensure that the @for@ attribute references the correct @id@.+--+-- > label "some input field: " ++> inputText ""+label+  :: (Monad m, Monad f)+  => HtmlT f ()+  -> Form m input error (HtmlT f ()) ()+label c = G.label mkLabel+  where+    mkLabel i = label_ [for_ (toPathPiece i)] c++arbitraryHtml :: Monad m => view -> Form m input error view ()+arbitraryHtml wrap =+  Form $ do+    id' <- getFormId+    pure+      ( View (const $ wrap)+      , pure+        ( Ok $ Proved+          { pos = unitRange id'+          , unProved = ()+          }+        )+      )++inputInt+  :: (Monad m, FormError err, Applicative f)+  => (input -> Either err Int)+  -> Int+  -> Form m input err (HtmlT f ()) Int+inputInt getInput initialValue = G.input getInput inputField initialValue+  where+    inputField i a =+      input_+        [ type_ "number"+        , id_ (toPathPiece i)+        , name_ (toPathPiece i)+        , value_ (toPathPiece a)+        ]++inputDouble+  :: (Monad m, FormError err, Applicative f)+  => (input -> Either err Double)+  -> Double+  -> Form m input err (HtmlT f ()) Double+inputDouble getInput initialValue = G.input getInput inputField initialValue+  where+    inputField i a = input_ [type_ "number", step_ "any", id_ (toPathPiece i), name_ (toPathPiece i), value_ (T.pack $ show a)]++-- | Create a single @\<input type=\"checkbox\"\>@ element+--+-- returns a 'Bool' indicating if it was checked or not.+--+-- see also 'inputCheckboxes'+-- FIXME: Should this built on something in Generalized?+inputCheckbox+  :: forall x error input m f. (Monad m, FormInput input, FormError error, ErrorInputType error ~ input, Applicative f)+  => Bool -- ^ initially checked+  -> Form m input error (HtmlT f ()) Bool+inputCheckbox initiallyChecked =+  Form $ do+    i <- getFormId+    v <- getFormInput' i+    case v of+      Default -> mkCheckbox i initiallyChecked+      Missing -> mkCheckbox i False -- checkboxes only appear in the submitted data when checked+      (Found input) ->+        case getInputString input of+          (Right _) -> mkCheckbox i True+          (Left (e :: error)) -> mkCheckbox i False+  where+    mkCheckbox i checked =+      let checkbox =+            input_ $+              (if checked then (:) checked_ else id)+                [type_ "checkbox", id_ (toPathPiece i), name_ (toPathPiece i), value_ (toPathPiece i)]+       in pure+            ( View $ const $ checkbox+            , pure $+              Ok+                ( Proved+                  { pos = unitRange i+                  , unProved = if checked then True else False+                  }+                )+            )++-- | Create a group of @\<input type=\"checkbox\"\>@ elements+--+inputCheckboxes+  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)+  => [(a, lbl)] -- ^ value, label, initially checked+  -> (a -> Bool) -- ^ function which indicates if a value should be checked initially+  -> Form m input error (HtmlT f ()) [a]+inputCheckboxes choices isChecked =+  G.inputMulti choices mkCheckboxes isChecked+  where+    mkCheckboxes nm choices' = mconcat $ concatMap (mkCheckbox nm) choices'+    mkCheckbox nm (i, val, lbl, checked) =+      [ input_ $+          ( (if checked then (checked_ :) else id)+            [type_ "checkbox", id_ (toPathPiece i), name_ (toPathPiece nm), value_ (toPathPiece val)]+          )+      , label_ [for_ (toPathPiece i)] $ toHtml lbl+      ]++-- | Create a group of @\<input type=\"radio\"\>@ elements+inputRadio+  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)+  => [(a, lbl)] -- ^ value, label, initially checked+  -> (a -> Bool) -- ^ isDefault+  -> Form m input error (HtmlT f ()) a+inputRadio choices isDefault =+  G.inputChoice isDefault choices mkRadios+  where+    mkRadios nm choices' = mconcat $ concatMap (mkRadio nm) choices'+    mkRadio nm (i, val, lbl, checked) =+      [ input_ $+          (if checked then (checked_ :) else id)+            [type_ "radio", id_ (toPathPiece i), name_ (toPathPiece nm), value_ (toPathPiece val)]+      , label_ [for_ (toPathPiece i)] $ toHtml lbl+      , br_ []+      ]++-- | create @\<select\>\<\/select\>@ element plus its @\<option\>\<\/option\>@ children.+--+-- see also: 'selectMultiple'+select+  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)+  => [(a, lbl)] -- ^ value, label+  -> (a -> Bool) -- ^ isDefault, must match *exactly one* element in the list of choices+  -> Form m input error (HtmlT f ()) a+select choices isDefault =+  G.inputChoice isDefault choices mkSelect+  where+    mkSelect :: (ToHtml lbl, Monad f) => FormId -> [(a, Int, lbl, Bool)] -> HtmlT f ()+    mkSelect nm choices' =+      select_ [name_ (toPathPiece nm)] $+        traverse_ mkOption choices'+    mkOption :: (ToHtml lbl, Monad f) => (a, Int, lbl, Bool) -> HtmlT f ()+    mkOption (_, val, lbl, selected) =+      option_+        ( (if selected then ((:) (selected_ "selected")) else id)+          [value_ (toPathPiece val)]+        )+        (toHtml lbl)++-- | create @\<select multiple=\"multiple\"\>\<\/select\>@ element plus its @\<option\>\<\/option\>@ children.+--+-- This creates a @\<select\>@ element which allows more than one item to be selected.+selectMultiple+  :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, ToHtml lbl, Monad f)+  => [(a, lbl)] -- ^ value, label, initially checked+  -> (a -> Bool) -- ^ isSelected initially+  -> Form m input error (HtmlT f ()) [a]+selectMultiple choices isSelected =+  G.inputMulti choices mkSelect isSelected+  where+    mkSelect :: (ToHtml lbl, Monad f) => FormId -> [(a, Int, lbl, Bool)] -> HtmlT f ()+    mkSelect nm choices' =+      select_ [name_ (toPathPiece nm), multiple_ "multiple"] $+        traverse_ mkOption choices'+    mkOption :: (ToHtml lbl, Monad f) => (a, Int, lbl, Bool) -> HtmlT f ()+    mkOption (_, val, lbl, selected) =+      option_+        ( (if selected then ((:) (selected_ "selected")) else id)+          [value_ (toPathPiece val)]+        )+        (toHtml lbl)++{-+inputMultiSelectOptGroup :: (Functor m, XMLGenerator x, EmbedAsChild x groupLbl, EmbedAsChild x lbl, EmbedAsAttr x (Attr String FormId), FormError error, ErrorInputType error ~ input, FormInput input, Monad m, Applicative f) =>+                   [(groupLbl, [(a, lbl, Bool)])]  -- ^ value, label, initially checked+                -> Form m input error (HtmlT f ()) [a]+inputMultiSelectOptGroup choices =+    G.inputMulti choices mkSelect+    where+      mkSelect nm choices' =+          [<select name=nm multiple="multiple">+            <% mapM mkOptGroup choices' %>+           </select>+          ]+      mkOptGroup (grpLabel, options) =+          <optgroup label=grpLabel>+           <% mapM mkOption options %>+          </optgroup>+      mkOption (_, val, lbl, selected) =+          <option value=val (if selected then ["selected" := "selected"] else [])>+           <% lbl %>+          </option>+-}