{-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} -- | Odd tag helpers, these have uncommen html attributes -- They don't fit in the 'normal' pattern of Abstract module Reflex.Bulmex.Tag.Odd ( image , imageClass -- * Link , ahref , ahref' , ahrefDyn -- * Space , textSpace -- * Prevent browser default , elDynAttrPrevDef , elDynAttrModConf ) where import Control.Lens ((%~), (.~)) import Data.Map (Map) import qualified Data.Map.Strict as Map import Data.Proxy (Proxy (..)) import Data.Text (Text) import qualified Data.Text as Text import Reflex import Reflex.Bulmex.Attr import Reflex.Bulmex.Space import qualified Reflex.Dom.Builder.Class as Dom import Reflex.Dom.Core import qualified Reflex.Dom.Widget as Dom import qualified Reflex.Tags as T -- | kindoff hard to set an image tag in reflex image :: Dom.DomBuilder t m => Text.Text -> m () image url = T.imgAttr (Map.singleton "src" url) Dom.blank -- | first class second src imageClass :: Dom.DomBuilder t m => Text.Text -> Text.Text -> m () imageClass clazz url = T.imgAttr (Map.fromList [("src", url), ("class", clazz)]) Dom.blank -- | sometimes you just need 2 pieces of text to seperate with a space textSpace :: Dom.DomBuilder t m => m () textSpace = Dom.text space -- | a html tag that accepts any text into it's href value ahref :: (Dom.DomBuilder t m, PostBuild t m) => Text.Text -> m a -> m a ahref = ahref' mempty ahref' :: (Dom.DomBuilder t m, PostBuild t m) => AttrMap -> Text.Text -> m a -> m a ahref' uno = ahrefDyn (constDyn uno) . constDyn ahrefDyn :: (Dom.DomBuilder t m, PostBuild t m) => Dynamic t AttrMap -> Dynamic t Text.Text -> m a -> m a ahrefDyn uno txt = T.aDynAttr $ (attrUnion <$> uno) <*> (Map.singleton "href" <$> txt) -- | From https://gist.github.com/3noch/134b1ee7fa48c347be9d164c3fac4ef7 -- Like 'elDynAttr'' but configures "prevent default" on the given event. -- Blocks for example a context menu from poping up on right mouse click. -- This should be used with caution, as it may be unexpected for end user. elDynAttrPrevDef :: forall a en m t. (DomBuilder t m, PostBuild t m) => EventName en -- ^ Event on the element to configure with 'preventDefault' -> Text -- ^ Element tag -> Dynamic t (Map Text Text) -- ^ Element attributes -> m a -- ^ Child of element -> m (Element EventResult (DomBuilderSpace m) t, a) -- An element and the result of the child elDynAttrPrevDef ev = elDynAttrModConf (\elCfg -> elCfg & elementConfig_eventSpec %~ addEventSpecFlags (Proxy :: Proxy (DomBuilderSpace m)) ev (const preventDefault)) -- | Like 'elDynAttr'' but allows you to modify the element configuration. -- -- Special thanks to @luigy: https://gist.github.com/luigy/b49ce04de8462e594c9c2b5b455ae5a5#file-foo-hs elDynAttrModConf :: (DomBuilder t m, PostBuild t m) => (ElementConfig EventResult t (DomBuilderSpace m) -> ElementConfig EventResult t (DomBuilderSpace m)) -> Text -> Dynamic t (Map Text Text) -> m a -> m (Element EventResult (DomBuilderSpace m) t, a) elDynAttrModConf f elementTag attrs child = do modifyAttrs <- dynamicAttributesToModifyAttributes attrs let cfg = def & modifyAttributes .~ fmapCheap mapKeysToAttributeName modifyAttrs result <- element elementTag (f cfg) child postBuild <- getPostBuild notReadyUntil postBuild pure result