HtmlTree
matching a criterionThis package module provides functions for modifying the internal nodes of an
HtmlTree
. Nodes may be selected for modification by id, tag, class, or
attribute value, or you can modify all nodes in the tree.
Given an id
string and a modify function, apply the modify function to
every node in the tree whose element has a matching id
. Note that HTML
elements should be assigned unique id
strings, so in theory the modify
function should only be applied to one node.
welcomeMessage =
"Hello, World!"
|> textWrapper "p"
|> withId "messageText"
|> List.singleton
|> container "div"
welcomeMessage
|> Modify.matchingId "messageText"
( withText "Hello, Universe!" )
Given a string representing an HTML tag and a modify function, apply the modify function to every node in the tree whose element has a matching HTML tag.
page
|> Modify.matchingTag "button"
( addAttribute ("disabled", "True") )
Given a string representing a class name and a modify function, apply the modify function to every node in the tree whose element has a matching class assignment.
page
|> Modify.matchingClass "button"
( addClass "large-button" )
Given a tuple containing an attribute name and value and a modify function, apply the modify function to every node in the tree whose element has a matching value for the named attribute.
page
|> Modify.matchingAttrValue ("disabled", "True")
( addAttribute ("disabled", "False") )
Apply the modify function to every node in the tree
page
|> Modify.allNodes
( addAttribute ("hidden", "True") )
module HtmlTree.Modify exposing
( matchingId, matchingTag, matchingClass, matchingAttrValue, allNodes )
{-| ## Apply a modify function to every node of an `HtmlTree` matching a criterion
This package module provides functions for modifying the internal nodes of an
`HtmlTree`. Nodes may be selected for modification by id, tag, class, or
attribute value, or you can modify all nodes in the tree.
@docs matchingId, matchingTag, matchingClass, matchingAttrValue, allNodes
-}
import HtmlTree exposing (..)
import Internal.HtmlElement as Element exposing (HtmlElement)
{-| Given an `id` string and a modify function, apply the modify function to
every node in the tree whose element has a matching `id`. Note that HTML
elements should be assigned unique `id` strings, so in theory the modify
function should only be applied to one node.
welcomeMessage =
"Hello, World!"
|> textWrapper "p"
|> withId "messageText"
|> List.singleton
|> container "div"
welcomeMessage
|> Modify.matchingId "messageText"
( withText "Hello, Universe!" )
-}
matchingId : String -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg
matchingId idString modifyFunction htmlTree =
let
matchId string htmlElement =
htmlElement
|> Element.getId
|> Maybe.map ((==) string)
|> Maybe.withDefault False
in
htmlTree
|> modifyMatching (matchId idString, modifyFunction)
{-| Given a string representing an HTML tag and a modify function, apply the
modify function to every node in the tree whose element has a matching HTML tag.
page
|> Modify.matchingTag "button"
( addAttribute ("disabled", "True") )
-}
matchingTag : String -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg
matchingTag tag modifyFunction htmlTree =
let
matchTag string htmlElement =
htmlElement
|> Element.getTag
|> (==) string
in
htmlTree
|> modifyMatching (matchTag tag, modifyFunction)
{-| Given a string representing a class name and a modify function, apply the
modify function to every node in the tree whose element has a matching class
assignment.
page
|> Modify.matchingClass "button"
( addClass "large-button" )
-}
matchingClass : String -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg
matchingClass class modifyFunction htmlTree =
let
matchClass string htmlElement =
htmlElement
|> Element.getClasses
|> List.member string
in
htmlTree
|> modifyMatching (matchClass class, modifyFunction)
{-| Given a tuple containing an attribute name and value and a modify function,
apply the modify function to every node in the tree whose element has a matching
value for the named attribute.
page
|> Modify.matchingAttrValue ("disabled", "True")
( addAttribute ("disabled", "False") )
-}
matchingAttrValue : (String, String) -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg
matchingAttrValue (attrName, attrValue) modifyFunction htmlTree =
let
matchAttrValue (name, value) htmlElement =
htmlElement
|> Element.getAttrValue name
|> Maybe.map ((==) value)
|> Maybe.withDefault False
in
htmlTree
|> modifyMatching
( matchAttrValue (attrName, attrValue)
, modifyFunction
)
{-| Apply the modify function to every node in the tree
page
|> Modify.allNodes
( addAttribute ("hidden", "True") )
-}
allNodes : (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg
allNodes modifyFunction htmlTree =
htmlTree
|> modifyMatching (always True, modifyFunction)
-- INTERNAL MODIFY FUNCTION
{-| Given an expression generator that accepts an `HtmlElement` and returns a
`Bool` and a modify function that accepts an `HtmlTree` and returns a modified
`HtmlTree`, apply the modify function to every node in the tree for which the
resulting expression evaluates to `True`.
-}
modifyMatching : (HtmlElement msg -> Bool, HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg
modifyMatching (expressionGenerator, modifyFunction) htmlTree =
case htmlTree of
Leaf htmlElement ->
htmlTree
|> if htmlElement |> expressionGenerator then modifyFunction
else identity
Stem htmlElement childList ->
childList
|> List.map (modifyMatching (expressionGenerator, modifyFunction))
|> Stem htmlElement
|> if htmlElement |> expressionGenerator then modifyFunction
else identity
_ ->
htmlTree