digestive-functors-blaze 0.0.2.2 → 0.1.0.0
raw patch · 2 files changed
+141/−38 lines, 2 filesdep ~blaze-htmldep ~digestive-functorsPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: blaze-html, digestive-functors
API changes (from Hackage documentation)
+ Text.Digestive.Blaze.Html5: inputList :: (Monad m, Functor m, FormInput i f) => Formlet m i e BlazeFormHtml Int -> Formlet m i e BlazeFormHtml a -> Formlet m i e BlazeFormHtml [a]
+ Text.Digestive.Blaze.Html5: inputListJs :: String
- Text.Digestive.Blaze.Html5: inputHidden :: (Monad m, Functor m, FormInput i f) => Maybe String -> Form m i e BlazeFormHtml String
+ Text.Digestive.Blaze.Html5: inputHidden :: (Monad m, Functor m, FormInput i f) => Formlet m i e BlazeFormHtml String
- Text.Digestive.Blaze.Html5: inputText :: (Monad m, Functor m, FormInput i f) => Maybe String -> Form m i e BlazeFormHtml String
+ Text.Digestive.Blaze.Html5: inputText :: (Monad m, Functor m, FormInput i f) => Formlet m i e BlazeFormHtml String
Files
digestive-functors-blaze.cabal view
@@ -1,6 +1,6 @@ Name: digestive-functors-blaze-Version: 0.0.2.2-Synopsis: Snap backend for the digestive-functors library+Version: 0.1.0.0+Synopsis: Blaze frontend for the digestive-functors library Description: This is a blaze frontend for the digestive-functors library. Homepage: http://github.com/jaspervdj/digestive-functors@@ -17,5 +17,5 @@ Hs-source-dirs: src Exposed-modules: Text.Digestive.Blaze.Html5 Build-depends: base >= 4 && < 5,- digestive-functors == 0.0.2.*,- blaze-html >= 0.3 && < 0.4+ digestive-functors == 0.1.0.*,+ blaze-html >= 0.3 && < 0.6
src/Text/Digestive/Blaze/Html5.hs view
@@ -13,6 +13,8 @@ , label , errors , childErrors+ , inputList+ , inputListJs , module Text.Digestive.Forms.Html ) where @@ -20,7 +22,7 @@ import Data.Maybe (fromMaybe) import Data.Monoid (mempty) -import Text.Blaze.Html5 (Html, (!))+import Text.Blaze.Html5 (Html, (!), toValue, toHtml) import qualified Text.Blaze.Html5 as H import qualified Text.Blaze.Html5.Attributes as A @@ -41,7 +43,7 @@ -> Html -- ^ HTML element -> Html -- ^ Resulting element applyClasses' = applyClasses $ \element value ->- element ! A.class_ (H.stringValue value)+ element ! A.class_ (toValue value) -- | Checks the input element when the argument is true --@@ -50,24 +52,22 @@ checked True x = x ! A.checked "checked" inputText :: (Monad m, Functor m, FormInput i f)- => Maybe String- -> Form m i e BlazeFormHtml String+ => Formlet m i e BlazeFormHtml String inputText = Forms.inputString $ \id' inp -> createFormHtml $ \cfg -> applyClasses' [htmlInputClasses] cfg $ H.input ! A.type_ "text"- ! A.name (H.stringValue $ show id')- ! A.id (H.stringValue $ show id')- ! A.value (H.stringValue $ fromMaybe "" inp)+ ! A.name (toValue $ show id')+ ! A.id (toValue $ show id')+ ! A.value (toValue $ fromMaybe "" inp) inputHidden :: (Monad m, Functor m, FormInput i f)- => Maybe String- -> Form m i e BlazeFormHtml String+ => Formlet m i e BlazeFormHtml String inputHidden = Forms.inputString $ \id' inp -> createFormHtml $ \cfg -> applyClasses' [htmlInputClasses] cfg $ H.input ! A.type_ "hidden"- ! A.name (H.stringValue $ show id')- ! A.id (H.stringValue $ show id')- ! A.value (H.stringValue $ fromMaybe "" inp)+ ! A.name (toValue $ show id')+ ! A.id (toValue $ show id')+ ! A.value (toValue $ fromMaybe "" inp) inputTextArea :: (Monad m, Functor m, FormInput i f) => Maybe Int -- ^ Rows@@ -76,14 +76,14 @@ -> Form m i e BlazeFormHtml String -- ^ Result inputTextArea r c = Forms.inputString $ \id' inp -> createFormHtml $ \cfg -> applyClasses' [htmlInputClasses] cfg $ rows r $ cols c $- H.textarea ! A.name (H.stringValue $ show id')- ! A.id (H.stringValue $ show id')- $ H.string $ fromMaybe "" inp+ H.textarea ! A.name (toValue $ show id')+ ! A.id (toValue $ show id')+ $ toHtml $ fromMaybe "" inp where rows Nothing = id- rows (Just x) = (! A.rows (H.stringValue $ show x))+ rows (Just x) = (! A.rows (toValue $ show x)) cols Nothing = id- cols (Just x) = (! A.cols (H.stringValue $ show x))+ cols (Just x) = (! A.cols (toValue $ show x)) inputTextRead :: (Monad m, Functor m, FormInput i f, Show a, Read a) => e@@ -92,18 +92,18 @@ inputTextRead error' = flip Forms.inputRead error' $ \id' inp -> createFormHtml $ \cfg -> applyClasses' [htmlInputClasses] cfg $ H.input ! A.type_ "text"- ! A.name (H.stringValue $ show id')- ! A.id (H.stringValue $ show id')- ! A.value (H.stringValue $ fromMaybe "" inp)+ ! A.name (toValue $ show id')+ ! A.id (toValue $ show id')+ ! A.value (toValue $ fromMaybe "" inp) inputPassword :: (Monad m, Functor m, FormInput i f) => Form m i e BlazeFormHtml String inputPassword = flip Forms.inputString Nothing $ \id' inp -> createFormHtml $ \cfg -> applyClasses' [htmlInputClasses] cfg $ H.input ! A.type_ "password"- ! A.name (H.stringValue $ show id')- ! A.id (H.stringValue $ show id')- ! A.value (H.stringValue $ fromMaybe "" inp)+ ! A.name (toValue $ show id')+ ! A.id (toValue $ show id')+ ! A.value (toValue $ fromMaybe "" inp) inputCheckBox :: (Monad m, Functor m, FormInput i f) => Bool@@ -111,8 +111,8 @@ inputCheckBox inp = flip Forms.inputBool inp $ \id' inp' -> createFormHtml $ \cfg -> applyClasses' [htmlInputClasses] cfg $ checked inp' $ H.input ! A.type_ "checkbox"- ! A.name (H.stringValue $ show id')- ! A.id (H.stringValue $ show id')+ ! A.name (toValue $ show id')+ ! A.id (toValue $ show id') inputRadio :: (Monad m, Functor m, FormInput i f, Eq a) => Bool -- ^ Use @<br>@ tags@@ -124,10 +124,10 @@ toView group id' sel val = createFormHtml $ \cfg -> do applyClasses' [htmlInputClasses] cfg $ checked sel $ H.input ! A.type_ "radio"- ! A.name (H.stringValue $ show group)- ! A.value (H.stringValue id')- ! A.id (H.stringValue id')- H.label ! A.for (H.stringValue id')+ ! A.name (toValue $ show group)+ ! A.value (toValue id')+ ! A.id (toValue id')+ H.label ! A.for (toValue id') $ fromMaybe mempty $ lookup val choices when br H.br @@ -138,8 +138,8 @@ toView id' = createFormHtmlWith MultiPart $ \cfg -> do applyClasses' [htmlInputClasses] cfg $ H.input ! A.type_ "file"- ! A.name (H.stringValue $ show id')- ! A.id (H.stringValue $ show id')+ ! A.name (toValue $ show id')+ ! A.id (toValue $ show id') submit :: Monad m => String -- ^ Text on the submit button@@ -147,15 +147,15 @@ submit text = view $ createFormHtml $ \cfg -> applyClasses' [htmlInputClasses, htmlSubmitClasses] cfg $ H.input ! A.type_ "submit"- ! A.value (H.stringValue text)+ ! A.value (toValue text) label :: Monad m => String -> Form m i e BlazeFormHtml () label string = Common.label $ \id' -> createFormHtml $ \cfg -> applyClasses' [htmlLabelClasses] cfg $- H.label ! A.for (H.stringValue $ show id')- $ H.string string+ H.label ! A.for (toValue $ show id')+ $ toHtml string errorList :: [Html] -> BlazeFormHtml errorList errors' = createFormHtml $ \cfg -> unless (null errors') $@@ -169,3 +169,106 @@ childErrors :: Monad m => Form m i Html BlazeFormHtml () childErrors = Common.childErrors errorList++-- | Wraps the more generic 'Text.Digestive.Forms.inputList' function to+-- provide a reasonable default for adding add/remove controls to a form.+-- The whole thing is wrapped in another div with the class inputList. For+-- this function to work, the javascript code in 'inputListJs' or something+-- similar must be in scope.+--+-- The user needs to specify the hidden formlet because transformRead requires+-- an error parameter, and this function can't specify it without loss of+-- generality. The idea is that the extra power of being able to customize+-- the formlet is worth the small amount of extra code compared to having to+-- specify the error.+--+inputList :: (Monad m, Functor m, FormInput i f)+ => Formlet m i e BlazeFormHtml Int+ -- ^ The formlet holding the number of items in the list+ -> Formlet m i e BlazeFormHtml a+ -- ^ The formlet used for each list item. This function surrounds it+ -- with a div tag with the inputListItem class.+ -> Formlet m i e BlazeFormHtml [a]+ -- ^ The dynamic list formlet+inputList hidden single d =+ mapView (fmap addControls) $ Forms.inputList hidden s d+ where+ s def = mapView (fmap (H.div ! A.class_ "inputListItem")) $ single def+ addControls form = do+ H.div ! A.class_ "inputList" $ do+ H.div $ do+ H.input ! A.type_ "button"+ ! A.onclick "addItem(this); return false;"+ ! A.value "Add Item"+ H.input ! A.type_ "button"+ ! A.onclick "removeItem(this); return false;"+ ! A.value "Remove Item"+ form++-- | A string containing the javascript functions needed for inputList. This+-- code requires JQuery.+--+inputListJs :: String+inputListJs = unlines+ ["// Requires that JQuery also be in scope"+ ,"function findInputList(button) {"+ ," var mainDiv = $(button).parent();"+ ," while ( !mainDiv.hasClass('inputList') ) {"+ ," mainDiv = $(mainDiv).parent();"+ ," }"+ ," return mainDiv;"+ ,"}"+ ,""+ ,"function findItems(button) {"+ ," return $('.inputListItem', findInputList(button));"+ ,"}"+ ,""+ ,"function addItem(button) {"+ ," var count = $(':hidden', findInputList(button))[0];"+ ," var items = findItems(button);"+ ," var item = $(items[items.length-1]);"+ ," var newItem = item.clone(true);"+ ," var i;"+ ,""+ ," // Increment counter"+ ," $(count).val(parseInt($(count).val())+1);"+ ,""+ ," // We have to change the raw html because IE doesn't allow the"+ ," // name field to be changed."+ ," newItem.html(newItem.html().replace(/fval\\[(\\d+\\.)*(\\d+)\\.(\\d+)\\]/g,"+ ," function(a, b, c, d) {"+ ," var newC = parseInt(c)+1;"+ ," return a.replace(/\\d+\\.\\d+\\]/, newC+'.'+d+']');"+ ," }"+ ," ));"+ ," newItem.appendTo(item.parent());"+ ,""+ ," // Copy the values of all children that had the name attribute set."+ ," // The direct html insertion does not preserve the most current"+ ," // values. It only preserves default values, so if we want values"+ ," // copied, we have to use an approach like this."+ ," var items2 = findItems(button);"+ ," var newLast = $(items2[items2.length-1]);"+ ," var c1 = $('[name]', item);"+ ," var c2 = $('[name]', newLast);"+ ," if ( c1.length == c2.length ) {"+ ," for ( i = 0; i < c1.length; i++ ) {"+ ," $(c2[i]).val($(c1[i]).val());"+ ," }"+ ," }"+ ,"}"+ ,""+ ,"function removeItem(button) {"+ ," var items = findItems(button);"+ ," if ( items.length > 1 ) {"+ ," var count = $(':hidden', findInputList(button))[0];"+ ," var item = $(items[items.length-1]);"+ ," item.remove();"+ ,""+ ," // Decrement counter"+ ," $(count).val(parseInt($(count).val())-1);"+ ," } else {"+ ," alert('Cannot remove any more rows');"+ ," }"+ ,"}"+ ]