This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.

HtmlTree.Modify

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.

matchingId : String -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg

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!" )
matchingTag : String -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg

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") )
matchingClass : String -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg

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" )
matchingAttrValue : (String, String) -> (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg

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") )
allNodes : (HtmlTree msg -> HtmlTree msg) -> HtmlTree msg -> HtmlTree msg

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