Skip to content

Commit

Permalink
Initial implementation of generic attribute support
Browse files Browse the repository at this point in the history
This is a initial implementation of generic attribute support
to enable arbitrary `Html.Attributes`. This implementation
tries to minimize the likelyhood of overriding internally used
attributes while still maintaining `MINOR` change.

This implementation may be revisited in the next MAJOR version
to update the implementation.

Add namespaced qualifiers to `Internal.attribute`,
this way internal attributes are easy to search for as well separate
them from `Options.attribute`
  • Loading branch information
vipentti committed Aug 27, 2016
1 parent 2493bf9 commit 16ee5fc
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/Material/Card.elm
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import Html exposing (..)
import Html.Attributes

import Material.Options as Options exposing (Style, cs, css)
import Material.Options.Internal exposing (attribute)
import Material.Options.Internal as Internal


{-| Separate given content block from others by adding a thin border.
Expand Down Expand Up @@ -157,7 +157,7 @@ can't use `Html.Events.onWithOptions` because we can't construct a
-}
stopClick : Style a
stopClick =
attribute <|
Internal.attribute <|
Html.Attributes.attribute
"onclick"
"var event = arguments[0] || window.event; event.stopPropagation();"
Expand Down
6 changes: 3 additions & 3 deletions src/Material/Footer.elm
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ import Html.Events as Events
import Material.Options as Options exposing (Style, cs)
import String
import Regex
import Material.Options.Internal as Internal exposing (attribute)
import Material.Options.Internal as Internal


{-| The type of the footer
Expand Down Expand Up @@ -362,14 +362,14 @@ mini props { left, right } =
-}
onClick : m -> Property m
onClick =
Events.onClick >> attribute
Events.onClick >> Internal.attribute


{-| href for Links.
-}
href : String -> Property m
href =
Html.href >> attribute
Html.href >> Internal.attribute


{-| Wraps a normal HTML value into `Content`
Expand Down
18 changes: 9 additions & 9 deletions src/Material/Layout.elm
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ import Material.Helpers as Helpers exposing (filter, delay, pure, map1st, map2nd
import Material.Ripple as Ripple
import Material.Icon as Icon
import Material.Options as Options exposing (Style, cs, nop, css, when, styled)
import Material.Options.Internal exposing (attribute)
import Material.Options.Internal as Internal

import DOM

Expand Down Expand Up @@ -489,14 +489,14 @@ type alias LinkProperty m =
-}
onClick : m -> LinkProperty m
onClick =
Events.onClick >> attribute
Events.onClick >> Internal.attribute


{-| href for Links.
-}
href : String -> LinkProperty m
href =
Html.Attributes.href >> attribute
Html.Attributes.href >> Internal.attribute


{-| Link.
Expand All @@ -505,7 +505,7 @@ link : List (LinkProperty m) -> List (Html m) -> Html m
link styles contents =
Options.styled a
(cs "mdl-navigation__link"
:: attribute (Html.Attributes.attribute "tabindex" "1")
:: Internal.attribute (Html.Attributes.attribute "tabindex" "1")
:: styles)
contents

Expand Down Expand Up @@ -581,7 +581,7 @@ tabsView lift config model (tabs, tabStyles) =
, Html.Attributes.attribute
"onclick"
("document.getElementsByClassName('mdl-layout__tab-bar')[0].scrollLeft += " ++ toString offset)
|> attribute
|> Internal.attribute
]
]
in
Expand All @@ -601,7 +601,7 @@ tabsView lift config model (tabs, tabStyles) =
nop
, if config.mode == Standard then cs "is-casting-shadow" else nop
, Options.many tabStyles
, attribute <|
, Internal.attribute <|
on "scroll"
(DOM.target
(Decoder.object3
Expand Down Expand Up @@ -662,11 +662,11 @@ headerView lift config model (drawerButton, rows, tabs) =
, cs "is-compact" `when` model.isCompact
, mode
, cs "mdl-layout__header--transparent" `when` config.transparentHeader
, Options.attribute <|
, Internal.attribute <|
Events.onClick
(TransitionHeader { toCompact=False, fixedHeader=config.fixedHeader }
|> lift)
, Options.attribute <|
, Internal.attribute <|
Events.on "transitionend" (Decoder.succeed <| lift TransitionEnd)
]
(List.concatMap (\x -> x)
Expand Down Expand Up @@ -858,7 +858,7 @@ view lift model options { drawer, header, tabs, main } =
, css "overflow-x" "visible" `when` (config.mode == Scrolling && config.fixedHeader)
, css "overflow" "visible" `when` (config.mode == Scrolling && config.fixedHeader)
{- Above three lines fixes upstream bug #4180. -}
, (on "scroll" >> attribute)
, (on "scroll" >> Internal.attribute)
(Decoder.map
(ScrollPane config.fixedHeader >> lift)
(DOM.target DOM.scrollTop))
Expand Down
8 changes: 4 additions & 4 deletions src/Material/Menu.elm
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ import Material.Helpers as Helpers exposing (pure)
import Material.Icon as Icon
import Material.Menu.Geometry as Geometry exposing (Geometry)
import Material.Options as Options exposing (Style, cs, css, styled, styled', when)
import Material.Options.Internal exposing (attribute)
import Material.Options.Internal as Internal
import Material.Ripple as Ripple
import Parts exposing (Indexed, Index)

Expand Down Expand Up @@ -547,9 +547,9 @@ view lift model properties items =
[ cs "mdl-button"
, cs "mdl-js-button"
, cs "mdl-button--icon"
, attribute (onKeyDown (Key itemSummaries)) `when` isActive model
, attribute (onClick Geometry.decode (Open)) `when` (model.animationState /= Opened)
, attribute (Html.Events.onClick Close) `when` isActive model
, Internal.attribute (onKeyDown (Key itemSummaries)) `when` isActive model
, Internal.attribute (onClick Geometry.decode (Open)) `when` (model.animationState /= Opened)
, Internal.attribute (Html.Events.onClick Close) `when` isActive model
]
[ Icon.view config.icon
[ cs "material-icons"
Expand Down
46 changes: 39 additions & 7 deletions src/Material/Options.elm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Material.Options exposing
, Style, div, span, img, attribute, center, scrim
, id
, inner
, attr
)


Expand Down Expand Up @@ -49,7 +50,7 @@ applying MDL typography or color to standard elements.
@docs stylesheet
## Attributes
@docs attribute, id, inner
@docs attribute, attr, id, inner
@docs center, scrim, disabled
# Internal
Expand Down Expand Up @@ -98,6 +99,12 @@ collect1 f option acc =
case option of
Class x -> { acc | classes = x :: acc.classes }
CSS x -> { acc | css = x :: acc.css }
{- NOTE: Internal attributes get appended as latter
attributes override former.
Attributes get added to the front so they can be
overridden by internal ones if needed.
-}
Internal x -> { acc | attrs = acc.attrs ++ [x] }
Attribute x -> { acc | attrs = x :: acc.attrs }
Many options -> List.foldl (collect1 f) acc options
Set g -> { acc | config = f g acc.config }
Expand Down Expand Up @@ -126,12 +133,17 @@ collect' options =


addAttributes : Summary c m -> List (Attribute m) -> List (Attribute m)
addAttributes summary attrs =
addAttributes summary attrs =
{- NOTE: Ordering here is important.
Allow users to specify arbitrary attributes in summary.attrs.
However, internal attributes should overwrite the ones that we need
to maintain functionality
-}
List.concat
[ attrs
[ summary.attrs
, attrs
, [ Html.Attributes.style summary.css ]
, [ Html.Attributes.class (String.join " " summary.classes) ]
, summary.attrs
]


Expand Down Expand Up @@ -302,9 +314,29 @@ general Properties. Use like this:
[ Options.attribute <| Html.onClick MyClickEvent ]
[ ... ]
-}
attribute : Html.Attribute m -> Style m
attribute : Html.Attribute m -> Style m
attribute =
Attribute
Attribute


{-| Install arbitrary `Html.Attribute`. Use like this:
Options.div
[ Options.attr <| Html.onClick MyClickEvent ]
[ ... ]
**NOTE** Some attributes might be overridden by attributes
used internally by *elm-mdl*. Such attributes often include
`focus` and `blur` on certain elements, such as `Textfield`.
In the case of `focus` and `blur` you may use `focusin` and `focusout`
respectively instead (these attributes require polyfill on Firefox).
See [Textfield.onBlur](http://package.elm-lang.org/packages/debois/elm-mdl/latest/Material-Textfield#onBlur) for more information regarding the polyfill.
-}
attr : Html.Attribute m -> Property c m
attr =
Attribute


{-| Options installing css for element to be a flex-box container centering its
elements.
Expand All @@ -323,7 +355,7 @@ depend on the underlying image. `0.6` works well often.
-}
scrim : Float -> Property c m
scrim opacity =
css "background" <| "linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, " ++ toString opacity ++ "))"
css "background" <| "linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, " ++ toString opacity ++ "))"


{-| Sets the id attribute
Expand Down
7 changes: 2 additions & 5 deletions src/Material/Options/Internal.elm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type Property c m
= Class String
| CSS (String, String)
| Attribute (Html.Attribute m)
| Internal (Html.Attribute m)
| Many (List (Property c m))
| Set (c -> c)
| None
Expand All @@ -21,8 +22,4 @@ So we hide it away here.
-}
attribute : Html.Attribute m -> Property c m
attribute =
Attribute




Internal

0 comments on commit 16ee5fc

Please sign in to comment.