1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
module Tooltip exposing
( Msg(..)
, Model
, init
, subscription
, update
, view
, show
)
import Platform.Cmd
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Mouse exposing (Position)
import Window exposing (Size)
type Msg =
UpdateMousePosition Position
| UpdateWindowSize Size
| ShowMessage String
| HideMessage
type alias Model =
{ mousePosition : Maybe Position
, windowSize : Size
, message : Maybe String
}
init : Int -> Int -> Model
init width height =
{ mousePosition = Nothing
, windowSize =
{ width = width
, height = height
}
, message = Nothing
}
subscription : Sub Msg
subscription =
Sub.batch
[ Mouse.moves UpdateMousePosition
, Window.resizes UpdateWindowSize
]
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
UpdateMousePosition position ->
( { model | mousePosition = Just position }
, Cmd.none
)
UpdateWindowSize size ->
( { model | windowSize = size }
, Cmd.none
)
ShowMessage message ->
( { model | message = Just message }
, Cmd.none
)
HideMessage ->
( { model | message = Nothing }
, Cmd.none
)
view : Model -> Html Msg
view { mousePosition, windowSize, message } =
case (mousePosition, message) of
(Just pos, Just msg) ->
div
[ class "tooltip"
, style
[ ("position", "absolute")
, horizontalPosition windowSize pos
, ("top", px <| pos.y + 15)
]
]
[ text msg ]
_ ->
text ""
horizontalPosition : Size -> Position -> (String, String)
horizontalPosition size position =
if isLeft size position
then ("left", px <| position.x + 5)
else ("right", px <| size.width - position.x)
verticalPosition : Size -> Position -> (String, String)
verticalPosition size position =
if isTop size position
then ("top", px <| position.y + 20)
else ("bottom", px <| size.height - position.y + 15)
px : Int -> String
px n = (toString n) ++ "px"
isLeft : Size -> Position -> Bool
isLeft { width } { x } = x < width // 2
isTop : Size -> Position -> Bool
isTop { height } { y } = y < height // 2
show : (Msg -> msg) -> String -> List (Attribute msg)
show mapMsg message =
[ onMouseEnter <| mapMsg <| ShowMessage message
, onMouseLeave <| mapMsg <| HideMessage
]
|