├── examples ├── .gitignore ├── build.sh ├── elm.json ├── Configs.elm └── Main.elm ├── .gitignore ├── elm.json ├── docs ├── index.html └── index.js ├── LICENSE ├── README.md └── src ├── Styles.elm └── ContextMenu.elm /examples/.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff 2 | docs.json 3 | -------------------------------------------------------------------------------- /examples/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | elm make Main.elm --output=../docs/index.js -------------------------------------------------------------------------------- /elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "package", 3 | "name": "jinjor/elm-contextmenu", 4 | "summary": "Flexible context menu for Elm", 5 | "license": "BSD-3-Clause", 6 | "version": "2.0.0", 7 | "exposed-modules": [ 8 | "ContextMenu" 9 | ], 10 | "elm-version": "0.19.0 <= v < 0.20.0", 11 | "dependencies": { 12 | "elm/browser": "1.0.0 <= v < 2.0.0", 13 | "elm/core": "1.0.0 <= v < 2.0.0", 14 | "elm/html": "1.0.0 <= v < 2.0.0", 15 | "elm/json": "1.0.0 <= v < 2.0.0" 16 | }, 17 | "test-dependencies": {} 18 | } -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Main 7 | 20 | 21 | 22 | 23 | 24 |
25 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | ".", 5 | "../src" 6 | ], 7 | "elm-version": "0.19.0", 8 | "dependencies": { 9 | "direct": { 10 | "elm/browser": "1.0.0", 11 | "elm/core": "1.0.0", 12 | "elm/html": "1.0.0", 13 | "elm/json": "1.0.0", 14 | "elm/svg": "1.0.0" 15 | }, 16 | "indirect": { 17 | "elm/time": "1.0.0", 18 | "elm/url": "1.0.0", 19 | "elm/virtual-dom": "1.0.0" 20 | } 21 | }, 22 | "test-dependencies": { 23 | "direct": {}, 24 | "indirect": {} 25 | } 26 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2016, Yosuke Torii 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | elm-contextmenu 2 | === 3 | 4 | Flexible context menu for Elm ([Demo](https://jinjor.github.io/elm-contextmenu/)) 5 | 6 | ## Warning 7 | 8 | On the migration from Elm 0.18 to 0.19, the legacy `Color` type has changed to just a type alias of `String` like `#aaa`, `rgb(100,100,200)`. Also, some icon libraries that uses `Color` type (i.e. `FontAwesome`, `MaterialIcons`) cannot be used anymore. So now you need to make a function typed as `String -> Int -> Html msg`. It *should* work but I haven't tested yet. 9 | 10 | I also think the implementation can be improved using new Browser API, but I cannot spend my time to try it. The styling method can be improved too. I would really appreciate if someone do that. Don't hesitate to fork this package or make your own from scratch! ([This article](http://jinjor-labo.hatenablog.com/entry/2016/11/05/201107) may help.) 11 | 12 | 13 | ## How to use 14 | 15 | This component works with [The Elm Architecture](https://guide.elm-lang.org/architecture/). 16 | 17 | 1. Model 18 | ```elm 19 | type alias Model = 20 | { contextMenu : ContextMenu Context 21 | , config : ContextMenu.Config 22 | , message : String 23 | } 24 | ``` 25 | 26 | 2. Msg 27 | ```elm 28 | type Msg 29 | = ContextMenuMsg (ContextMenu.Msg Context) 30 | | Item Int 31 | ``` 32 | 33 | 3. Initialize 34 | ```elm 35 | init : Flags -> (Model, Cmd Msg) 36 | init flags = 37 | let 38 | (contextMenu, msg) = ContextMenu.init 39 | in 40 | ( { contextMenu = contextMenu 41 | } 42 | , Cmd.map ContextMenuMsg msg 43 | ) 44 | ``` 45 | 46 | 4. Update 47 | ```elm 48 | update : Msg -> Model -> (Model, Cmd Msg) 49 | update msg model = 50 | case msg of 51 | ContextMenuMsg msg -> 52 | let 53 | (contextMenu, cmd) = 54 | ContextMenu.update msg model.contextMenu 55 | in 56 | ( { model | contextMenu = contextMenu } 57 | , Cmd.map ContextMenuMsg cmd 58 | ) 59 | ``` 60 | 61 | 5. Subscribe 62 | ```elm 63 | subscriptions : Model -> Sub Msg 64 | subscriptions model = 65 | Sub.map ContextMenuMsg (ContextMenu.subscriptions model.contextMenu) 66 | ``` 67 | 68 | 6. View 69 | ```elm 70 | view : Model -> Html Msg 71 | view model = 72 | div 73 | [ ContextMenu.open ContextMenuMsg "context1" ] 74 | [ ContextMenu.view 75 | ContextMenu.defaultConfig 76 | ContextMenuMsg 77 | toItemGroups 78 | toItemGroups model.contextMenu 79 | ] 80 | 81 | toItemGroups : String -> List (List Item) 82 | toItemGroups context = 83 | if context == "context1" then 84 | [ [ (ContextMenu.item "Hey", Item 1) 85 | , (ContextMenu.item "Yo!", Item 2) 86 | ] 87 | ] 88 | else 89 | [] 90 | ``` 91 | 92 | 93 | ## License 94 | 95 | BSD-3-Clause 96 | -------------------------------------------------------------------------------- /examples/Configs.elm: -------------------------------------------------------------------------------- 1 | module Configs exposing (deepBlue, googleSpreadsheet, gray, lightBlue, lightGray, mac, white, winChrome, winDesktop, winEdge, winFirefox) 2 | 3 | import ContextMenu exposing (..) 4 | 5 | 6 | type alias Color = 7 | String 8 | 9 | 10 | winDesktop : ContextMenu.Config 11 | winDesktop = 12 | { defaultConfig 13 | | direction = LeftBottom 14 | , overflowX = Shift 15 | , overflowY = Mirror 16 | , containerColor = lightGray 17 | , hoverColor = gray 18 | , invertText = False 19 | , cursor = Arrow 20 | , rounded = False 21 | } 22 | 23 | 24 | winChrome : ContextMenu.Config 25 | winChrome = 26 | { defaultConfig 27 | | direction = RightBottom 28 | , overflowX = Shift 29 | , overflowY = Mirror 30 | , containerColor = white 31 | , hoverColor = lightGray 32 | , invertText = False 33 | , cursor = Arrow 34 | , rounded = False 35 | } 36 | 37 | 38 | winFirefox : ContextMenu.Config 39 | winFirefox = 40 | { defaultConfig 41 | | direction = RightBottom 42 | , overflowX = Shift 43 | , overflowY = Mirror 44 | , containerColor = lightGray 45 | , hoverColor = lightBlue 46 | , invertText = False 47 | , cursor = Arrow 48 | , rounded = False 49 | } 50 | 51 | 52 | winEdge : ContextMenu.Config 53 | winEdge = 54 | { defaultConfig 55 | | direction = RightBottom 56 | , overflowX = Mirror 57 | , overflowY = Mirror 58 | , containerColor = lightGray 59 | , hoverColor = gray 60 | , invertText = False 61 | , cursor = Arrow 62 | , rounded = False 63 | } 64 | 65 | 66 | mac : ContextMenu.Config 67 | mac = 68 | { defaultConfig 69 | | direction = RightBottom 70 | , overflowX = Mirror 71 | , overflowY = Shift 72 | , containerColor = lightGray 73 | , hoverColor = deepBlue 74 | , invertText = True 75 | , cursor = Arrow 76 | , rounded = True 77 | } 78 | 79 | 80 | googleSpreadsheet : ContextMenu.Config 81 | googleSpreadsheet = 82 | { defaultConfig 83 | | direction = RightBottom 84 | , overflowX = Shift 85 | , overflowY = Shift 86 | , containerColor = white 87 | , hoverColor = lightGray 88 | , invertText = False 89 | , cursor = Pointer 90 | , rounded = False 91 | } 92 | 93 | 94 | 95 | ---- COLORS 96 | 97 | 98 | white : Color 99 | white = 100 | "rgb(255, 255, 255)" 101 | 102 | 103 | lightGray : Color 104 | lightGray = 105 | "rgb(238, 238, 238)" 106 | 107 | 108 | gray : Color 109 | gray = 110 | "rgb(217, 217, 217)" 111 | 112 | 113 | lightBlue : Color 114 | lightBlue = 115 | "rgb(117, 199, 253)" 116 | 117 | 118 | deepBlue : Color 119 | deepBlue = 120 | "rgb(62,126,255)" 121 | -------------------------------------------------------------------------------- /src/Styles.elm: -------------------------------------------------------------------------------- 1 | module Styles exposing (Style, annotation, borderColor, container, icon, partition, px, row, shortcut, text) 2 | 3 | import Html exposing (Attribute) 4 | import Html.Attributes exposing (style) 5 | 6 | 7 | type alias Color = 8 | String 9 | 10 | 11 | type alias Style msg = 12 | List (Attribute msg) 13 | 14 | 15 | borderColor : String 16 | borderColor = 17 | "#ccc" 18 | 19 | 20 | container : Color -> Float -> Float -> Bool -> Float -> Float -> Float -> String -> Float -> Style msg 21 | container containerColor borderWidth padding rounded width left top fontFamily fontSize = 22 | [ style "border-style" "solid" 23 | , style "border-width" (px borderWidth) 24 | , style "border-color" borderColor 25 | , style "position" "fixed" 26 | , style "top" (px top) 27 | , style "left" (px left) 28 | , style "width" (px width) 29 | , style "z-index" (String.fromFloat (2147483647 - 10)) 30 | , style "background-color" containerColor 31 | , style "cursor" "default" 32 | , style "box-shadow" "0px 3px 8px 0px rgba(0,0,0,0.3)" 33 | , style "padding" (px padding ++ " 0") 34 | , style "border-radius" 35 | (if rounded then 36 | px padding 37 | 38 | else 39 | "" 40 | ) 41 | , style "font-family" fontFamily 42 | , style "font-size" (px fontSize) 43 | ] 44 | 45 | 46 | row : Color -> Color -> Bool -> Bool -> Float -> Bool -> Bool -> Bool -> Style msg 47 | row hoverColor disabledTextColor invertText usePointer lineHeight hovered disabled hasShortCut = 48 | [ style "position" "relative" 49 | , style "padding" "0 18px 0 28px" 50 | , style "background-color" 51 | (if hovered then 52 | hoverColor 53 | 54 | else 55 | "" 56 | ) 57 | , style "height" (px lineHeight) 58 | , style "color" 59 | (if disabled then 60 | disabledTextColor 61 | 62 | else if hovered && invertText then 63 | "#fff" 64 | 65 | else 66 | "" 67 | ) 68 | , style "cursor" 69 | (if not disabled && usePointer then 70 | "pointer" 71 | 72 | else 73 | "" 74 | ) 75 | , style "display" "flex" 76 | , style "justify-content" 77 | (if hasShortCut then 78 | "space-between" 79 | 80 | else 81 | "" 82 | ) 83 | ] 84 | 85 | 86 | text : Float -> Style msg 87 | text lineHeight = 88 | [ style "line-height" (px lineHeight) 89 | , style "text-overflow" "ellipsis" 90 | , style "overflow" "hidden" 91 | , style "white-space" "nowrap" 92 | ] 93 | 94 | 95 | annotation : Color -> Float -> Float -> Bool -> Style msg 96 | annotation color annotationHeight fontSize disabled = 97 | [ style "margin-top" "-2px" 98 | , style "line-height" (px annotationHeight) 99 | , style "font-size" (px fontSize) 100 | , style "color" color 101 | ] 102 | 103 | 104 | shortcut : Color -> Float -> Bool -> Style msg 105 | shortcut color lineHeight hovered = 106 | [ style "line-height" (px lineHeight) 107 | , style "color" 108 | (if hovered then 109 | "" 110 | 111 | else 112 | color 113 | ) 114 | ] 115 | 116 | 117 | partition : Float -> Float -> Style msg 118 | partition borderWidth margin = 119 | [ style "border-bottom-style" "solid" 120 | , style "border-bottom-width" (px 1) 121 | , style "border-bottom-color" borderColor 122 | , style "border-top" "none" 123 | , style "margin" (px margin ++ " 0") 124 | ] 125 | 126 | 127 | icon : Float -> Style msg 128 | icon size = 129 | [ style "position" "absolute" 130 | , style "margin-left" (px (-size - 4)) 131 | , style "top" "2px" 132 | ] 133 | 134 | 135 | 136 | ---- 137 | 138 | 139 | px : Float -> String 140 | px n = 141 | String.fromFloat n ++ "px" 142 | -------------------------------------------------------------------------------- /examples/Main.elm: -------------------------------------------------------------------------------- 1 | port module Main exposing (Context(..), Model, Msg(..), backgroundStyles, init, main, objectStyles, subscriptions, toItemGroups, update, view) 2 | 3 | import Browser 4 | import Configs 5 | import ContextMenu exposing (ContextMenu) 6 | import Html exposing (..) 7 | import Html.Attributes exposing (..) 8 | 9 | 10 | main : Program () Model Msg 11 | main = 12 | Browser.element 13 | { init = init 14 | , update = update 15 | , view = view 16 | , subscriptions = subscriptions 17 | } 18 | 19 | 20 | type alias Model = 21 | { contextMenu : ContextMenu Context 22 | , config : ContextMenu.Config 23 | , message : String 24 | } 25 | 26 | 27 | type Context 28 | = Object 29 | | Background 30 | 31 | 32 | type Msg 33 | = ContextMenuMsg (ContextMenu.Msg Context) 34 | | Item Int 35 | 36 | 37 | init : () -> ( Model, Cmd Msg ) 38 | init _ = 39 | let 40 | ( contextMenu, msg ) = 41 | ContextMenu.init 42 | in 43 | ( { contextMenu = contextMenu 44 | , config = Configs.winChrome 45 | , message = "" 46 | } 47 | , Cmd.map ContextMenuMsg msg 48 | ) 49 | 50 | 51 | update : Msg -> Model -> ( Model, Cmd Msg ) 52 | update msg model = 53 | case msg of 54 | ContextMenuMsg msg_ -> 55 | let 56 | ( contextMenu, cmd ) = 57 | ContextMenu.update msg_ model.contextMenu 58 | in 59 | ( { model | contextMenu = contextMenu } 60 | , Cmd.map ContextMenuMsg cmd 61 | ) 62 | 63 | Item num -> 64 | ( { model | message = "Item[" ++ String.fromInt num ++ "] was clicked." } 65 | , Cmd.none 66 | ) 67 | 68 | 69 | subscriptions : Model -> Sub Msg 70 | subscriptions model = 71 | Sub.map ContextMenuMsg (ContextMenu.subscriptions model.contextMenu) 72 | 73 | 74 | view : Model -> Html Msg 75 | view model = 76 | div 77 | [] 78 | [ div 79 | (ContextMenu.open ContextMenuMsg Background :: backgroundStyles) 80 | [ div 81 | (ContextMenu.open ContextMenuMsg Object :: objectStyles) 82 | [] 83 | ] 84 | , div [] [ text model.message ] 85 | , ContextMenu.view 86 | model.config 87 | ContextMenuMsg 88 | toItemGroups 89 | model.contextMenu 90 | ] 91 | 92 | 93 | backgroundStyles : List (Attribute msg) 94 | backgroundStyles = 95 | [ style "left" "10%" 96 | , style "right" "10%" 97 | , style "top" "10%" 98 | , style "bottom" "-10%" 99 | , style "position" "absolute" 100 | , style "background-color" "#cdb" 101 | ] 102 | 103 | 104 | objectStyles : List (Attribute msg) 105 | objectStyles = 106 | [ style "position" "absolute" 107 | , style "top" "100px" 108 | , style "left" "150px" 109 | , style "width" "100px" 110 | , style "height" "100px" 111 | , style "background-color" "#976" 112 | ] 113 | 114 | 115 | toItemGroups : Context -> List (List ( ContextMenu.Item, Msg )) 116 | toItemGroups context = 117 | case context of 118 | Background -> 119 | [ [ ( ContextMenu.item "Hey", Item 1 ) 120 | , ( ContextMenu.item "Yo!", Item 2 ) 121 | ] 122 | , [ ( ContextMenu.item "Take photos" 123 | -- |> ContextMenu.icon FontAwesome.camera Color.green 124 | |> ContextMenu.disabled True 125 | , Item 3 126 | ) 127 | , ( ContextMenu.item "Have a break" 128 | -- |> ContextMenu.icon FontAwesome.coffee Color.brown 129 | |> ContextMenu.disabled False 130 | , Item 4 131 | ) 132 | , ( ContextMenu.item "Pneumonoultramicroscopicsilicovolcanoconiosis", Item 5 ) 133 | , ( ContextMenu.item "Save" 134 | |> ContextMenu.shortcut "Ctrl+S" 135 | , Item 6 136 | ) 137 | , ( ContextMenu.itemWithAnnotation "Item with annotation" "Some annotation here" 138 | -- |> ContextMenu.icon Material.tag_faces Color.red 139 | |> ContextMenu.disabled False 140 | , Item 7 141 | ) 142 | ] 143 | ] 144 | 145 | Object -> 146 | [ [ ( ContextMenu.item "Pen", Item 8 ) 147 | , ( ContextMenu.item "Pineapple", Item 9 ) 148 | , ( ContextMenu.item "Apple", Item 10 ) 149 | ] 150 | ] 151 | -------------------------------------------------------------------------------- /src/ContextMenu.elm: -------------------------------------------------------------------------------- 1 | module ContextMenu exposing 2 | ( ContextMenu, Msg, init, update, subscriptions 3 | , Item, item, itemWithAnnotation, disabled, icon, shortcut 4 | , Config, Direction(..), Overflow(..), Cursor(..), defaultConfig 5 | , view, open, openIf 6 | , setOnDehover 7 | ) 8 | 9 | {-| The ContextMenu component that follows the Elm Architecture. 10 | 11 | See [How to use](http://package.elm-lang.org/packages/jinjor/elm-contextmenu/latest). 12 | 13 | 14 | # TEA Parts 15 | 16 | The boilerplace functions. See [The Elm Architecture](https://guide.elm-lang.org/architecture/) for more information. 17 | 18 | @docs ContextMenu, Msg, init, update, subscriptions 19 | 20 | 21 | # Item 22 | 23 | @docs Item, item, itemWithAnnotation, disabled, icon, shortcut 24 | 25 | 26 | # Config 27 | 28 | @docs Config, Direction, Overflow, Cursor, defaultConfig 29 | 30 | 31 | # View 32 | 33 | @docs view, open, openIf 34 | 35 | 36 | # Advanced 37 | 38 | @docs setOnDehover 39 | 40 | -} 41 | 42 | import Browser 43 | import Browser.Dom 44 | import Browser.Events 45 | import Html exposing (..) 46 | import Html.Attributes exposing (..) 47 | import Html.Events exposing (..) 48 | import Json.Decode as Decode 49 | import Process 50 | import Styles as S 51 | import Task exposing (Task) 52 | 53 | 54 | 55 | -- TYPES 56 | 57 | 58 | type alias Color = 59 | String 60 | 61 | 62 | type alias Size = 63 | { width : Float 64 | , height : Float 65 | } 66 | 67 | 68 | type alias Position = 69 | { x : Float 70 | , y : Float 71 | } 72 | 73 | 74 | 75 | -- MODEL 76 | 77 | 78 | {-| The Model. Put whatever context you like, which is used to create menu items. 79 | -} 80 | type ContextMenu context 81 | = ContextMenu { openState : OpenState context, closeOnDehover : Bool } 82 | 83 | 84 | type HoverState 85 | = Container 86 | | ItemIndex ( Int, Int ) 87 | | None 88 | 89 | 90 | getItemIndex : HoverState -> Maybe ( Int, Int ) 91 | getItemIndex hover = 92 | case hover of 93 | ItemIndex index -> 94 | Just index 95 | 96 | _ -> 97 | Nothing 98 | 99 | 100 | type alias OpenState context = 101 | Maybe 102 | { mouse : Position 103 | , window : Size 104 | , hover : HoverState 105 | , context : context 106 | } 107 | 108 | 109 | shouldCloseOnClick : Bool -> OpenState context -> Bool 110 | shouldCloseOnClick closeOnDehover openState = 111 | case openState of 112 | Just { hover } -> 113 | if closeOnDehover then 114 | False 115 | 116 | else 117 | hover /= Container 118 | 119 | Nothing -> 120 | True 121 | 122 | 123 | setHoverState : HoverState -> OpenState context -> OpenState context 124 | setHoverState hover openState = 125 | openState 126 | |> Maybe.map 127 | (\{ mouse, window, context } -> 128 | { mouse = mouse 129 | , window = window 130 | , hover = hover 131 | , context = context 132 | } 133 | ) 134 | 135 | 136 | {-| This switches when the menu should be closed. 137 | 138 | - True: Closes when mouse leaves the menu (keeps opening on cliking) 139 | - False(default): Closes when somewhere in the window is clicked 140 | 141 | -} 142 | setOnDehover : Bool -> ContextMenu context -> ContextMenu context 143 | setOnDehover closeOnDehover (ContextMenu model) = 144 | ContextMenu { model | closeOnDehover = closeOnDehover } 145 | 146 | 147 | enterItem : ( Int, Int ) -> OpenState context -> OpenState context 148 | enterItem index openState = 149 | setHoverState (ItemIndex index) openState 150 | 151 | 152 | leaveItem : OpenState context -> OpenState context 153 | leaveItem openState = 154 | setHoverState Container openState 155 | 156 | 157 | enterContainer : OpenState context -> OpenState context 158 | enterContainer openState = 159 | setHoverState Container openState 160 | 161 | 162 | leaveContainer : OpenState context -> OpenState context 163 | leaveContainer openState = 164 | setHoverState None openState 165 | 166 | 167 | 168 | -- UPDATE 169 | 170 | 171 | {-| The Message. 172 | -} 173 | type Msg context 174 | = NoOp 175 | | RequestOpen context Position 176 | | Open context Position Size 177 | | Close 178 | | EnterItem ( Int, Int ) 179 | | LeaveItem 180 | | EnterContainer 181 | | LeaveContainer 182 | 183 | 184 | {-| The init function. 185 | -} 186 | init : ( ContextMenu context, Cmd (Msg context) ) 187 | init = 188 | ( ContextMenu { openState = Nothing, closeOnDehover = False }, Cmd.none ) 189 | 190 | 191 | {-| The update function. 192 | -} 193 | update : Msg context -> ContextMenu context -> ( ContextMenu context, Cmd (Msg context) ) 194 | update msg (ContextMenu model) = 195 | case msg of 196 | NoOp -> 197 | ( ContextMenu model, Cmd.none ) 198 | 199 | RequestOpen context mouse -> 200 | ( ContextMenu model 201 | , Task.perform (Open context mouse) windowSize 202 | ) 203 | 204 | Open context mouse window -> 205 | ( ContextMenu 206 | { model 207 | | openState = 208 | Just 209 | { mouse = mouse 210 | , window = window 211 | , hover = None 212 | , context = context 213 | } 214 | } 215 | , Cmd.none 216 | ) 217 | 218 | Close -> 219 | ( ContextMenu { model | openState = Nothing }, Cmd.none ) 220 | 221 | EnterItem index -> 222 | ( ContextMenu { model | openState = enterItem index model.openState } 223 | , Cmd.none 224 | ) 225 | 226 | LeaveItem -> 227 | ( ContextMenu { model | openState = leaveItem model.openState } 228 | , Cmd.none 229 | ) 230 | 231 | EnterContainer -> 232 | ( ContextMenu { model | openState = enterContainer model.openState } 233 | , Cmd.none 234 | ) 235 | 236 | LeaveContainer -> 237 | if model.closeOnDehover then 238 | update Close (ContextMenu { model | openState = leaveContainer model.openState }) 239 | 240 | else 241 | ( ContextMenu { model | openState = leaveContainer model.openState }, Cmd.none ) 242 | 243 | 244 | windowSize : Task x Size 245 | windowSize = 246 | Browser.Dom.getViewport 247 | |> Task.map 248 | (\v -> 249 | Size v.viewport.width v.viewport.height 250 | ) 251 | 252 | 253 | {-| The Subscription. 254 | -} 255 | subscriptions : ContextMenu context -> Sub (Msg context) 256 | subscriptions (ContextMenu model) = 257 | Sub.batch 258 | [ if shouldCloseOnClick model.closeOnDehover model.openState then 259 | Browser.Events.onMouseDown (Decode.succeed Close) 260 | 261 | else 262 | Sub.none 263 | ] 264 | 265 | 266 | 267 | -- NUMBERS AND CALCULATION 268 | 269 | 270 | disabledTextColor : Color 271 | disabledTextColor = 272 | "rgb(200, 200, 200)" 273 | 274 | 275 | annotationTextColor : Color 276 | annotationTextColor = 277 | "rgb(200, 200, 200)" 278 | 279 | 280 | shortcutTextColor : Color 281 | shortcutTextColor = 282 | "rgb(200, 200, 200)" 283 | 284 | 285 | containerBorderWidth : Float 286 | containerBorderWidth = 287 | 1 288 | 289 | 290 | containerPadding : Float 291 | containerPadding = 292 | 4 293 | 294 | 295 | partitionWidth : Float 296 | partitionWidth = 297 | 1 298 | 299 | 300 | partitionMargin : Float 301 | partitionMargin = 302 | 6 303 | 304 | 305 | defaultItemHeight : Float 306 | defaultItemHeight = 307 | 20 308 | 309 | 310 | fontSize : Float 311 | fontSize = 312 | 13 313 | 314 | 315 | annotationHeight : Float 316 | annotationHeight = 317 | 12 318 | 319 | 320 | annotationFontSize : Float 321 | annotationFontSize = 322 | 10 323 | 324 | 325 | menuWidthWithBorders : Float -> Float 326 | menuWidthWithBorders menuWidth = 327 | menuWidth + containerBorderWidth * 2 328 | 329 | 330 | calculateMenuHeight : List (List Item) -> Float 331 | calculateMenuHeight groups = 332 | let 333 | containerBorders = 334 | containerBorderWidth * 2 335 | 336 | containerPaddings = 337 | containerPadding * 2 338 | 339 | partitions = 340 | toFloat (List.length groups - 1) * (partitionMargin * 2 + partitionWidth) 341 | 342 | items = 343 | List.sum 344 | (List.map 345 | (\items_ -> 346 | List.sum (List.map (\(Item item_) -> item_.height) items_) 347 | ) 348 | groups 349 | ) 350 | in 351 | containerBorders + containerPaddings + partitions + toFloat items 352 | 353 | 354 | calculateX : Direction -> Overflow -> Float -> Float -> Float -> Float 355 | calculateX direction overflow windowWidth menuWidth x = 356 | Basics.max 0 <| 357 | case direction of 358 | LeftBottom -> 359 | if x - menuWidth < 0 then 360 | if overflow == Shift then 361 | 0 362 | 363 | else 364 | x 365 | 366 | else 367 | x - menuWidth 368 | 369 | RightBottom -> 370 | if x + menuWidth > windowWidth then 371 | if overflow == Shift then 372 | windowWidth - menuWidth 373 | 374 | else 375 | x - menuWidth 376 | 377 | else 378 | x 379 | 380 | 381 | calculateY : Overflow -> Float -> Float -> Float -> Float 382 | calculateY overflow windowHeight menuHeight y = 383 | Basics.max 0 <| 384 | if y + menuHeight > windowHeight then 385 | if overflow == Shift then 386 | windowHeight - menuHeight 387 | 388 | else 389 | y - menuHeight 390 | 391 | else 392 | y 393 | 394 | 395 | 396 | -- ITEM 397 | 398 | 399 | {-| The menu item. You can construct it with pipe-friendly functions. 400 | 401 | ContextMenu.item "Take photos" 402 | -- This library is outdated. See README. 403 | -- |> ContextMenu.icon FontAwesome.camera Color.green 404 | |> ContextMenu.disabled True 405 | 406 | -} 407 | type Item 408 | = Item 409 | { height : Int 410 | , icon : Maybe ( String -> Int -> Html Never, String ) 411 | , content : Content 412 | , shortcut : String 413 | , disabled : Bool 414 | } 415 | 416 | 417 | type Content 418 | = Text String 419 | | Custom (Bool -> Html Never) 420 | 421 | 422 | {-| Creates a simple text item. 423 | -} 424 | item : String -> Item 425 | item s = 426 | Item 427 | { height = floor defaultItemHeight 428 | , icon = Nothing 429 | , content = Text s 430 | , shortcut = "" 431 | , disabled = False 432 | } 433 | 434 | 435 | custom : Int -> (Bool -> Html Never) -> Item 436 | custom height content = 437 | Item 438 | { height = Basics.max (floor defaultItemHeight) height 439 | , icon = Nothing 440 | , content = Custom content 441 | , shortcut = "" 442 | , disabled = False 443 | } 444 | 445 | 446 | {-| Creates an item with annotation which will displayed just below the item name. 447 | -} 448 | itemWithAnnotation : String -> String -> Item 449 | itemWithAnnotation s ann = 450 | custom (floor <| defaultItemHeight + annotationHeight - 2) (annotationView s ann) 451 | 452 | 453 | {-| Disables the item. True = disabled, False = enabled. 454 | -} 455 | disabled : Bool -> Item -> Item 456 | disabled disabled_ (Item item_) = 457 | Item { item_ | disabled = disabled_ } 458 | 459 | 460 | {-| Displays the shortcut key at the right. 461 | -} 462 | shortcut : String -> Item -> Item 463 | shortcut shortcutName (Item item_) = 464 | Item { item_ | shortcut = shortcutName } 465 | 466 | 467 | {-| Shows the icon. 468 | 469 | The first argument is a function that creates an icon, 470 | given a color string(like `#fff`, `rgb(100,200,200)`, etc.) and icon size (px). 471 | 472 | -} 473 | icon : (String -> Int -> Html Never) -> String -> Item -> Item 474 | icon icon_ color (Item item_) = 475 | Item { item_ | icon = Just ( icon_, color ) } 476 | 477 | 478 | 479 | -- CONFIG 480 | 481 | 482 | {-| Defines the styles of the menu. See [examples](https://github.com/jinjor/elm-contextmenu/blob/master/examples/Configs.elm). 483 | -} 484 | type alias Config = 485 | { width : Int 486 | , direction : Direction 487 | , overflowX : Overflow 488 | , overflowY : Overflow 489 | , containerColor : Color 490 | , hoverColor : Color 491 | , invertText : Bool 492 | , cursor : Cursor 493 | , rounded : Bool 494 | , fontFamily : String 495 | } 496 | 497 | 498 | {-| The default direction the menu will be shown at. 499 | -} 500 | type Direction 501 | = LeftBottom 502 | | RightBottom 503 | 504 | 505 | {-| The strategies how to show the menu when it goes out of window. 506 | -} 507 | type Overflow 508 | = Shift 509 | | Mirror 510 | 511 | 512 | {-| The shape of cursor during hovering on the menu. 513 | -} 514 | type Cursor 515 | = Arrow 516 | | Pointer 517 | 518 | 519 | {-| The default config. 520 | 521 | defaultConfig = 522 | { width = 300 523 | , direction = RightBottom 524 | , overflowX = Mirror 525 | , overflowY = Mirror 526 | , containerColor = "white" 527 | , hoverColor = "rgb(240 240 240)" 528 | , invertText = False 529 | , cursor = Pointer 530 | , rounded = False 531 | , fontFamily = "initial" 532 | } 533 | 534 | -} 535 | defaultConfig : Config 536 | defaultConfig = 537 | { width = 300 538 | , direction = RightBottom 539 | , overflowX = Mirror 540 | , overflowY = Mirror 541 | , containerColor = "white" 542 | , hoverColor = "rgb(240 240 240)" 543 | , invertText = False 544 | , cursor = Pointer 545 | , rounded = False 546 | , fontFamily = "initial" 547 | } 548 | 549 | 550 | 551 | -- VIEW 552 | 553 | 554 | {-| Makes the attribute that triggers to open the menu. 555 | This attribute is passed for each element that needs a menu. 556 | 557 | Arguments: 558 | 559 | 1. function to transform component's message into user's message 560 | 2. the context which is used to create items 561 | 562 | -} 563 | open : (Msg context -> msg) -> context -> Attribute msg 564 | open transform context = 565 | openIf True transform context 566 | 567 | 568 | {-| Similar to `open` but only works under particular condition. 569 | 570 | This is useful for debugging on browser. 571 | 572 | -} 573 | openIf : Bool -> (Msg context -> msg) -> context -> Attribute msg 574 | openIf condition transform context = 575 | if condition then 576 | Html.Events.custom 577 | "contextmenu" 578 | (position 579 | |> Decode.map (RequestOpen context) 580 | |> Decode.map transform 581 | |> Decode.map 582 | (\msg -> 583 | { message = msg 584 | , stopPropagation = True 585 | , preventDefault = True 586 | } 587 | ) 588 | ) 589 | 590 | else 591 | on "contextmenu" (Decode.succeed (transform NoOp)) 592 | 593 | 594 | position : Decode.Decoder Position 595 | position = 596 | Decode.map2 Position 597 | (Decode.field "clientX" Decode.float) 598 | (Decode.field "clientY" Decode.float) 599 | 600 | 601 | {-| Shows the menu. This should be called at only one place. 602 | 603 | Arguments: 604 | 605 | 1. the Config 606 | 2. function to transform component's message into user's message 607 | 3. function to create item groups 608 | 4. the Model 609 | 610 | -} 611 | view : Config -> (Msg context -> msg) -> (context -> List (List ( Item, msg ))) -> ContextMenu context -> Html msg 612 | view config transform toItemGroups (ContextMenu model) = 613 | case model.openState of 614 | Just { mouse, window, hover, context } -> 615 | let 616 | groups = 617 | toItemGroups context 618 | 619 | itemGroups = 620 | List.map (List.map Tuple.first) groups 621 | 622 | groupsView = 623 | List.indexedMap 624 | (itemGroupView config transform (getItemIndex hover)) 625 | groups 626 | in 627 | case joinGroupsWithPartition groupsView of 628 | Just items -> 629 | let 630 | x_ = 631 | calculateX 632 | config.direction 633 | config.overflowX 634 | window.width 635 | (menuWidthWithBorders (toFloat config.width)) 636 | mouse.x 637 | 638 | y_ = 639 | calculateY 640 | config.overflowY 641 | window.height 642 | (calculateMenuHeight itemGroups) 643 | mouse.y 644 | in 645 | div 646 | (S.container 647 | config.containerColor 648 | containerBorderWidth 649 | containerPadding 650 | config.rounded 651 | (toFloat config.width) 652 | x_ 653 | y_ 654 | config.fontFamily 655 | fontSize 656 | ++ [ onMouseEnter (transform EnterContainer) 657 | , onMouseLeave (transform LeaveContainer) 658 | ] 659 | ) 660 | items 661 | 662 | Nothing -> 663 | Html.text "" 664 | 665 | Nothing -> 666 | Html.text "" 667 | 668 | 669 | joinGroupsWithPartition : List (List (Html msg)) -> Maybe (List (Html msg)) 670 | joinGroupsWithPartition groups = 671 | List.foldr 672 | (\group prev -> 673 | case prev of 674 | Just items -> 675 | Just (group ++ (partition :: items)) 676 | 677 | Nothing -> 678 | Just group 679 | ) 680 | Nothing 681 | groups 682 | 683 | 684 | partition : Html msg 685 | partition = 686 | hr (S.partition partitionWidth partitionMargin) [] 687 | 688 | 689 | itemGroupView : Config -> (Msg context -> msg) -> Maybe ( Int, Int ) -> Int -> List ( Item, msg ) -> List (Html msg) 690 | itemGroupView config transform hoverIndex groupIndex items = 691 | List.indexedMap (itemView config transform hoverIndex groupIndex) items 692 | 693 | 694 | itemView : Config -> (Msg context -> msg) -> Maybe ( Int, Int ) -> Int -> Int -> ( Item, msg ) -> Html msg 695 | itemView config transform hoverIndex groupIndex index ( Item item_, msg ) = 696 | let 697 | hovered = 698 | hoverIndex == Just ( groupIndex, index ) 699 | 700 | styles = 701 | S.row 702 | config.hoverColor 703 | disabledTextColor 704 | config.invertText 705 | (config.cursor == Pointer) 706 | (toFloat item_.height) 707 | hovered 708 | item_.disabled 709 | (String.trim item_.shortcut /= "") 710 | 711 | events = 712 | if item_.disabled then 713 | [] 714 | 715 | else 716 | [ onMouseEnter (transform <| EnterItem ( groupIndex, index )) 717 | , onMouseLeave (transform <| LeaveItem) 718 | , onMouseDown msg 719 | ] 720 | 721 | icon_ = 722 | case item_.icon of 723 | Just ( icon__, color ) -> 724 | Html.map never <| 725 | div 726 | (S.icon fontSize) 727 | [ icon__ 728 | (if item_.disabled then 729 | disabledTextColor 730 | 731 | else 732 | color 733 | ) 734 | (floor fontSize) 735 | ] 736 | 737 | Nothing -> 738 | Html.text "" 739 | 740 | content = 741 | case item_.content of 742 | Text s -> 743 | div (S.text (toFloat item_.height)) [ text s ] 744 | 745 | Custom toHtml -> 746 | toHtml item_.disabled 747 | 748 | shortCut = 749 | div 750 | (S.shortcut shortcutTextColor (toFloat item_.height) hovered) 751 | [ text item_.shortcut ] 752 | in 753 | div 754 | (styles ++ events) 755 | [ icon_ 756 | , Html.map never content 757 | , shortCut 758 | ] 759 | 760 | 761 | annotationView : String -> String -> Bool -> Html Never 762 | annotationView s ann disabled_ = 763 | div [] 764 | [ div 765 | (S.text defaultItemHeight) 766 | [ text s ] 767 | , div 768 | (S.annotation 769 | annotationTextColor 770 | annotationHeight 771 | annotationFontSize 772 | disabled_ 773 | ) 774 | [ text ann ] 775 | ] 776 | -------------------------------------------------------------------------------- /docs/index.js: -------------------------------------------------------------------------------- 1 | (function(scope){ 2 | 'use strict'; 3 | 4 | function F(arity, fun, wrapper) { 5 | wrapper.a = arity; 6 | wrapper.f = fun; 7 | return wrapper; 8 | } 9 | 10 | function F2(fun) { 11 | return F(2, fun, function(a) { return function(b) { return fun(a,b); }; }) 12 | } 13 | function F3(fun) { 14 | return F(3, fun, function(a) { 15 | return function(b) { return function(c) { return fun(a, b, c); }; }; 16 | }); 17 | } 18 | function F4(fun) { 19 | return F(4, fun, function(a) { return function(b) { return function(c) { 20 | return function(d) { return fun(a, b, c, d); }; }; }; 21 | }); 22 | } 23 | function F5(fun) { 24 | return F(5, fun, function(a) { return function(b) { return function(c) { 25 | return function(d) { return function(e) { return fun(a, b, c, d, e); }; }; }; }; 26 | }); 27 | } 28 | function F6(fun) { 29 | return F(6, fun, function(a) { return function(b) { return function(c) { 30 | return function(d) { return function(e) { return function(f) { 31 | return fun(a, b, c, d, e, f); }; }; }; }; }; 32 | }); 33 | } 34 | function F7(fun) { 35 | return F(7, fun, function(a) { return function(b) { return function(c) { 36 | return function(d) { return function(e) { return function(f) { 37 | return function(g) { return fun(a, b, c, d, e, f, g); }; }; }; }; }; }; 38 | }); 39 | } 40 | function F8(fun) { 41 | return F(8, fun, function(a) { return function(b) { return function(c) { 42 | return function(d) { return function(e) { return function(f) { 43 | return function(g) { return function(h) { 44 | return fun(a, b, c, d, e, f, g, h); }; }; }; }; }; }; }; 45 | }); 46 | } 47 | function F9(fun) { 48 | return F(9, fun, function(a) { return function(b) { return function(c) { 49 | return function(d) { return function(e) { return function(f) { 50 | return function(g) { return function(h) { return function(i) { 51 | return fun(a, b, c, d, e, f, g, h, i); }; }; }; }; }; }; }; }; 52 | }); 53 | } 54 | 55 | function A2(fun, a, b) { 56 | return fun.a === 2 ? fun.f(a, b) : fun(a)(b); 57 | } 58 | function A3(fun, a, b, c) { 59 | return fun.a === 3 ? fun.f(a, b, c) : fun(a)(b)(c); 60 | } 61 | function A4(fun, a, b, c, d) { 62 | return fun.a === 4 ? fun.f(a, b, c, d) : fun(a)(b)(c)(d); 63 | } 64 | function A5(fun, a, b, c, d, e) { 65 | return fun.a === 5 ? fun.f(a, b, c, d, e) : fun(a)(b)(c)(d)(e); 66 | } 67 | function A6(fun, a, b, c, d, e, f) { 68 | return fun.a === 6 ? fun.f(a, b, c, d, e, f) : fun(a)(b)(c)(d)(e)(f); 69 | } 70 | function A7(fun, a, b, c, d, e, f, g) { 71 | return fun.a === 7 ? fun.f(a, b, c, d, e, f, g) : fun(a)(b)(c)(d)(e)(f)(g); 72 | } 73 | function A8(fun, a, b, c, d, e, f, g, h) { 74 | return fun.a === 8 ? fun.f(a, b, c, d, e, f, g, h) : fun(a)(b)(c)(d)(e)(f)(g)(h); 75 | } 76 | function A9(fun, a, b, c, d, e, f, g, h, i) { 77 | return fun.a === 9 ? fun.f(a, b, c, d, e, f, g, h, i) : fun(a)(b)(c)(d)(e)(f)(g)(h)(i); 78 | } 79 | 80 | console.warn('Compiled in DEV mode. Follow the advice at https://elm-lang.org/0.19.0/optimize for better performance and smaller assets.'); 81 | 82 | 83 | var _List_Nil_UNUSED = { $: 0 }; 84 | var _List_Nil = { $: '[]' }; 85 | 86 | function _List_Cons_UNUSED(hd, tl) { return { $: 1, a: hd, b: tl }; } 87 | function _List_Cons(hd, tl) { return { $: '::', a: hd, b: tl }; } 88 | 89 | 90 | var _List_cons = F2(_List_Cons); 91 | 92 | function _List_fromArray(arr) 93 | { 94 | var out = _List_Nil; 95 | for (var i = arr.length; i--; ) 96 | { 97 | out = _List_Cons(arr[i], out); 98 | } 99 | return out; 100 | } 101 | 102 | function _List_toArray(xs) 103 | { 104 | for (var out = []; xs.b; xs = xs.b) // WHILE_CONS 105 | { 106 | out.push(xs.a); 107 | } 108 | return out; 109 | } 110 | 111 | var _List_map2 = F3(function(f, xs, ys) 112 | { 113 | for (var arr = []; xs.b && ys.b; xs = xs.b, ys = ys.b) // WHILE_CONSES 114 | { 115 | arr.push(A2(f, xs.a, ys.a)); 116 | } 117 | return _List_fromArray(arr); 118 | }); 119 | 120 | var _List_map3 = F4(function(f, xs, ys, zs) 121 | { 122 | for (var arr = []; xs.b && ys.b && zs.b; xs = xs.b, ys = ys.b, zs = zs.b) // WHILE_CONSES 123 | { 124 | arr.push(A3(f, xs.a, ys.a, zs.a)); 125 | } 126 | return _List_fromArray(arr); 127 | }); 128 | 129 | var _List_map4 = F5(function(f, ws, xs, ys, zs) 130 | { 131 | for (var arr = []; ws.b && xs.b && ys.b && zs.b; ws = ws.b, xs = xs.b, ys = ys.b, zs = zs.b) // WHILE_CONSES 132 | { 133 | arr.push(A4(f, ws.a, xs.a, ys.a, zs.a)); 134 | } 135 | return _List_fromArray(arr); 136 | }); 137 | 138 | var _List_map5 = F6(function(f, vs, ws, xs, ys, zs) 139 | { 140 | for (var arr = []; vs.b && ws.b && xs.b && ys.b && zs.b; vs = vs.b, ws = ws.b, xs = xs.b, ys = ys.b, zs = zs.b) // WHILE_CONSES 141 | { 142 | arr.push(A5(f, vs.a, ws.a, xs.a, ys.a, zs.a)); 143 | } 144 | return _List_fromArray(arr); 145 | }); 146 | 147 | var _List_sortBy = F2(function(f, xs) 148 | { 149 | return _List_fromArray(_List_toArray(xs).sort(function(a, b) { 150 | return _Utils_cmp(f(a), f(b)); 151 | })); 152 | }); 153 | 154 | var _List_sortWith = F2(function(f, xs) 155 | { 156 | return _List_fromArray(_List_toArray(xs).sort(function(a, b) { 157 | var ord = A2(f, a, b); 158 | return ord === elm$core$Basics$EQ ? 0 : ord === elm$core$Basics$LT ? -1 : 1; 159 | })); 160 | }); 161 | 162 | 163 | 164 | // EQUALITY 165 | 166 | function _Utils_eq(x, y) 167 | { 168 | for ( 169 | var pair, stack = [], isEqual = _Utils_eqHelp(x, y, 0, stack); 170 | isEqual && (pair = stack.pop()); 171 | isEqual = _Utils_eqHelp(pair.a, pair.b, 0, stack) 172 | ) 173 | {} 174 | 175 | return isEqual; 176 | } 177 | 178 | function _Utils_eqHelp(x, y, depth, stack) 179 | { 180 | if (depth > 100) 181 | { 182 | stack.push(_Utils_Tuple2(x,y)); 183 | return true; 184 | } 185 | 186 | if (x === y) 187 | { 188 | return true; 189 | } 190 | 191 | if (typeof x !== 'object' || x === null || y === null) 192 | { 193 | typeof x === 'function' && _Debug_crash(5); 194 | return false; 195 | } 196 | 197 | /**/ 198 | if (x.$ === 'Set_elm_builtin') 199 | { 200 | x = elm$core$Set$toList(x); 201 | y = elm$core$Set$toList(y); 202 | } 203 | if (x.$ === 'RBNode_elm_builtin' || x.$ === 'RBEmpty_elm_builtin') 204 | { 205 | x = elm$core$Dict$toList(x); 206 | y = elm$core$Dict$toList(y); 207 | } 208 | //*/ 209 | 210 | /**_UNUSED/ 211 | if (x.$ < 0) 212 | { 213 | x = elm$core$Dict$toList(x); 214 | y = elm$core$Dict$toList(y); 215 | } 216 | //*/ 217 | 218 | for (var key in x) 219 | { 220 | if (!_Utils_eqHelp(x[key], y[key], depth + 1, stack)) 221 | { 222 | return false; 223 | } 224 | } 225 | return true; 226 | } 227 | 228 | var _Utils_equal = F2(_Utils_eq); 229 | var _Utils_notEqual = F2(function(a, b) { return !_Utils_eq(a,b); }); 230 | 231 | 232 | 233 | // COMPARISONS 234 | 235 | // Code in Generate/JavaScript.hs, Basics.js, and List.js depends on 236 | // the particular integer values assigned to LT, EQ, and GT. 237 | 238 | function _Utils_cmp(x, y, ord) 239 | { 240 | if (typeof x !== 'object') 241 | { 242 | return x === y ? /*EQ*/ 0 : x < y ? /*LT*/ -1 : /*GT*/ 1; 243 | } 244 | 245 | /**/ 246 | if (x instanceof String) 247 | { 248 | var a = x.valueOf(); 249 | var b = y.valueOf(); 250 | return a === b ? 0 : a < b ? -1 : 1; 251 | } 252 | //*/ 253 | 254 | /**_UNUSED/ 255 | if (!x.$) 256 | //*/ 257 | /**/ 258 | if (x.$[0] === '#') 259 | //*/ 260 | { 261 | return (ord = _Utils_cmp(x.a, y.a)) 262 | ? ord 263 | : (ord = _Utils_cmp(x.b, y.b)) 264 | ? ord 265 | : _Utils_cmp(x.c, y.c); 266 | } 267 | 268 | // traverse conses until end of a list or a mismatch 269 | for (; x.b && y.b && !(ord = _Utils_cmp(x.a, y.a)); x = x.b, y = y.b) {} // WHILE_CONSES 270 | return ord || (x.b ? /*GT*/ 1 : y.b ? /*LT*/ -1 : /*EQ*/ 0); 271 | } 272 | 273 | var _Utils_lt = F2(function(a, b) { return _Utils_cmp(a, b) < 0; }); 274 | var _Utils_le = F2(function(a, b) { return _Utils_cmp(a, b) < 1; }); 275 | var _Utils_gt = F2(function(a, b) { return _Utils_cmp(a, b) > 0; }); 276 | var _Utils_ge = F2(function(a, b) { return _Utils_cmp(a, b) >= 0; }); 277 | 278 | var _Utils_compare = F2(function(x, y) 279 | { 280 | var n = _Utils_cmp(x, y); 281 | return n < 0 ? elm$core$Basics$LT : n ? elm$core$Basics$GT : elm$core$Basics$EQ; 282 | }); 283 | 284 | 285 | // COMMON VALUES 286 | 287 | var _Utils_Tuple0_UNUSED = 0; 288 | var _Utils_Tuple0 = { $: '#0' }; 289 | 290 | function _Utils_Tuple2_UNUSED(a, b) { return { a: a, b: b }; } 291 | function _Utils_Tuple2(a, b) { return { $: '#2', a: a, b: b }; } 292 | 293 | function _Utils_Tuple3_UNUSED(a, b, c) { return { a: a, b: b, c: c }; } 294 | function _Utils_Tuple3(a, b, c) { return { $: '#3', a: a, b: b, c: c }; } 295 | 296 | function _Utils_chr_UNUSED(c) { return c; } 297 | function _Utils_chr(c) { return new String(c); } 298 | 299 | 300 | // RECORDS 301 | 302 | function _Utils_update(oldRecord, updatedFields) 303 | { 304 | var newRecord = {}; 305 | 306 | for (var key in oldRecord) 307 | { 308 | newRecord[key] = oldRecord[key]; 309 | } 310 | 311 | for (var key in updatedFields) 312 | { 313 | newRecord[key] = updatedFields[key]; 314 | } 315 | 316 | return newRecord; 317 | } 318 | 319 | 320 | // APPEND 321 | 322 | var _Utils_append = F2(_Utils_ap); 323 | 324 | function _Utils_ap(xs, ys) 325 | { 326 | // append Strings 327 | if (typeof xs === 'string') 328 | { 329 | return xs + ys; 330 | } 331 | 332 | // append Lists 333 | if (!xs.b) 334 | { 335 | return ys; 336 | } 337 | var root = _List_Cons(xs.a, ys); 338 | xs = xs.b 339 | for (var curr = root; xs.b; xs = xs.b) // WHILE_CONS 340 | { 341 | curr = curr.b = _List_Cons(xs.a, ys); 342 | } 343 | return root; 344 | } 345 | 346 | 347 | 348 | var _JsArray_empty = []; 349 | 350 | function _JsArray_singleton(value) 351 | { 352 | return [value]; 353 | } 354 | 355 | function _JsArray_length(array) 356 | { 357 | return array.length; 358 | } 359 | 360 | var _JsArray_initialize = F3(function(size, offset, func) 361 | { 362 | var result = new Array(size); 363 | 364 | for (var i = 0; i < size; i++) 365 | { 366 | result[i] = func(offset + i); 367 | } 368 | 369 | return result; 370 | }); 371 | 372 | var _JsArray_initializeFromList = F2(function (max, ls) 373 | { 374 | var result = new Array(max); 375 | 376 | for (var i = 0; i < max && ls.b; i++) 377 | { 378 | result[i] = ls.a; 379 | ls = ls.b; 380 | } 381 | 382 | result.length = i; 383 | return _Utils_Tuple2(result, ls); 384 | }); 385 | 386 | var _JsArray_unsafeGet = F2(function(index, array) 387 | { 388 | return array[index]; 389 | }); 390 | 391 | var _JsArray_unsafeSet = F3(function(index, value, array) 392 | { 393 | var length = array.length; 394 | var result = new Array(length); 395 | 396 | for (var i = 0; i < length; i++) 397 | { 398 | result[i] = array[i]; 399 | } 400 | 401 | result[index] = value; 402 | return result; 403 | }); 404 | 405 | var _JsArray_push = F2(function(value, array) 406 | { 407 | var length = array.length; 408 | var result = new Array(length + 1); 409 | 410 | for (var i = 0; i < length; i++) 411 | { 412 | result[i] = array[i]; 413 | } 414 | 415 | result[length] = value; 416 | return result; 417 | }); 418 | 419 | var _JsArray_foldl = F3(function(func, acc, array) 420 | { 421 | var length = array.length; 422 | 423 | for (var i = 0; i < length; i++) 424 | { 425 | acc = A2(func, array[i], acc); 426 | } 427 | 428 | return acc; 429 | }); 430 | 431 | var _JsArray_foldr = F3(function(func, acc, array) 432 | { 433 | for (var i = array.length - 1; i >= 0; i--) 434 | { 435 | acc = A2(func, array[i], acc); 436 | } 437 | 438 | return acc; 439 | }); 440 | 441 | var _JsArray_map = F2(function(func, array) 442 | { 443 | var length = array.length; 444 | var result = new Array(length); 445 | 446 | for (var i = 0; i < length; i++) 447 | { 448 | result[i] = func(array[i]); 449 | } 450 | 451 | return result; 452 | }); 453 | 454 | var _JsArray_indexedMap = F3(function(func, offset, array) 455 | { 456 | var length = array.length; 457 | var result = new Array(length); 458 | 459 | for (var i = 0; i < length; i++) 460 | { 461 | result[i] = A2(func, offset + i, array[i]); 462 | } 463 | 464 | return result; 465 | }); 466 | 467 | var _JsArray_slice = F3(function(from, to, array) 468 | { 469 | return array.slice(from, to); 470 | }); 471 | 472 | var _JsArray_appendN = F3(function(n, dest, source) 473 | { 474 | var destLen = dest.length; 475 | var itemsToCopy = n - destLen; 476 | 477 | if (itemsToCopy > source.length) 478 | { 479 | itemsToCopy = source.length; 480 | } 481 | 482 | var size = destLen + itemsToCopy; 483 | var result = new Array(size); 484 | 485 | for (var i = 0; i < destLen; i++) 486 | { 487 | result[i] = dest[i]; 488 | } 489 | 490 | for (var i = 0; i < itemsToCopy; i++) 491 | { 492 | result[i + destLen] = source[i]; 493 | } 494 | 495 | return result; 496 | }); 497 | 498 | 499 | 500 | // LOG 501 | 502 | var _Debug_log_UNUSED = F2(function(tag, value) 503 | { 504 | return value; 505 | }); 506 | 507 | var _Debug_log = F2(function(tag, value) 508 | { 509 | console.log(tag + ': ' + _Debug_toString(value)); 510 | return value; 511 | }); 512 | 513 | 514 | // TODOS 515 | 516 | function _Debug_todo(moduleName, region) 517 | { 518 | return function(message) { 519 | _Debug_crash(8, moduleName, region, message); 520 | }; 521 | } 522 | 523 | function _Debug_todoCase(moduleName, region, value) 524 | { 525 | return function(message) { 526 | _Debug_crash(9, moduleName, region, value, message); 527 | }; 528 | } 529 | 530 | 531 | // TO STRING 532 | 533 | function _Debug_toString_UNUSED(value) 534 | { 535 | return ''; 536 | } 537 | 538 | function _Debug_toString(value) 539 | { 540 | return _Debug_toAnsiString(false, value); 541 | } 542 | 543 | function _Debug_toAnsiString(ansi, value) 544 | { 545 | if (typeof value === 'function') 546 | { 547 | return _Debug_internalColor(ansi, ''); 548 | } 549 | 550 | if (typeof value === 'boolean') 551 | { 552 | return _Debug_ctorColor(ansi, value ? 'True' : 'False'); 553 | } 554 | 555 | if (typeof value === 'number') 556 | { 557 | return _Debug_numberColor(ansi, value + ''); 558 | } 559 | 560 | if (value instanceof String) 561 | { 562 | return _Debug_charColor(ansi, "'" + _Debug_addSlashes(value, true) + "'"); 563 | } 564 | 565 | if (typeof value === 'string') 566 | { 567 | return _Debug_stringColor(ansi, '"' + _Debug_addSlashes(value, false) + '"'); 568 | } 569 | 570 | if (typeof value === 'object' && '$' in value) 571 | { 572 | var tag = value.$; 573 | 574 | if (typeof tag === 'number') 575 | { 576 | return _Debug_internalColor(ansi, ''); 577 | } 578 | 579 | if (tag[0] === '#') 580 | { 581 | var output = []; 582 | for (var k in value) 583 | { 584 | if (k === '$') continue; 585 | output.push(_Debug_toAnsiString(ansi, value[k])); 586 | } 587 | return '(' + output.join(',') + ')'; 588 | } 589 | 590 | if (tag === 'Set_elm_builtin') 591 | { 592 | return _Debug_ctorColor(ansi, 'Set') 593 | + _Debug_fadeColor(ansi, '.fromList') + ' ' 594 | + _Debug_toAnsiString(ansi, elm$core$Set$toList(value)); 595 | } 596 | 597 | if (tag === 'RBNode_elm_builtin' || tag === 'RBEmpty_elm_builtin') 598 | { 599 | return _Debug_ctorColor(ansi, 'Dict') 600 | + _Debug_fadeColor(ansi, '.fromList') + ' ' 601 | + _Debug_toAnsiString(ansi, elm$core$Dict$toList(value)); 602 | } 603 | 604 | if (tag === 'Array_elm_builtin') 605 | { 606 | return _Debug_ctorColor(ansi, 'Array') 607 | + _Debug_fadeColor(ansi, '.fromList') + ' ' 608 | + _Debug_toAnsiString(ansi, elm$core$Array$toList(value)); 609 | } 610 | 611 | if (tag === '::' || tag === '[]') 612 | { 613 | var output = '['; 614 | 615 | value.b && (output += _Debug_toAnsiString(ansi, value.a), value = value.b) 616 | 617 | for (; value.b; value = value.b) // WHILE_CONS 618 | { 619 | output += ',' + _Debug_toAnsiString(ansi, value.a); 620 | } 621 | return output + ']'; 622 | } 623 | 624 | var output = ''; 625 | for (var i in value) 626 | { 627 | if (i === '$') continue; 628 | var str = _Debug_toAnsiString(ansi, value[i]); 629 | var c0 = str[0]; 630 | var parenless = c0 === '{' || c0 === '(' || c0 === '[' || c0 === '<' || c0 === '"' || str.indexOf(' ') < 0; 631 | output += ' ' + (parenless ? str : '(' + str + ')'); 632 | } 633 | return _Debug_ctorColor(ansi, tag) + output; 634 | } 635 | 636 | if (typeof value === 'object') 637 | { 638 | var output = []; 639 | for (var key in value) 640 | { 641 | var field = key[0] === '_' ? key.slice(1) : key; 642 | output.push(_Debug_fadeColor(ansi, field) + ' = ' + _Debug_toAnsiString(ansi, value[key])); 643 | } 644 | if (output.length === 0) 645 | { 646 | return '{}'; 647 | } 648 | return '{ ' + output.join(', ') + ' }'; 649 | } 650 | 651 | return _Debug_internalColor(ansi, ''); 652 | } 653 | 654 | function _Debug_addSlashes(str, isChar) 655 | { 656 | var s = str 657 | .replace(/\\/g, '\\\\') 658 | .replace(/\n/g, '\\n') 659 | .replace(/\t/g, '\\t') 660 | .replace(/\r/g, '\\r') 661 | .replace(/\v/g, '\\v') 662 | .replace(/\0/g, '\\0'); 663 | 664 | if (isChar) 665 | { 666 | return s.replace(/\'/g, '\\\''); 667 | } 668 | else 669 | { 670 | return s.replace(/\"/g, '\\"'); 671 | } 672 | } 673 | 674 | function _Debug_ctorColor(ansi, string) 675 | { 676 | return ansi ? '\x1b[96m' + string + '\x1b[0m' : string; 677 | } 678 | 679 | function _Debug_numberColor(ansi, string) 680 | { 681 | return ansi ? '\x1b[95m' + string + '\x1b[0m' : string; 682 | } 683 | 684 | function _Debug_stringColor(ansi, string) 685 | { 686 | return ansi ? '\x1b[93m' + string + '\x1b[0m' : string; 687 | } 688 | 689 | function _Debug_charColor(ansi, string) 690 | { 691 | return ansi ? '\x1b[92m' + string + '\x1b[0m' : string; 692 | } 693 | 694 | function _Debug_fadeColor(ansi, string) 695 | { 696 | return ansi ? '\x1b[37m' + string + '\x1b[0m' : string; 697 | } 698 | 699 | function _Debug_internalColor(ansi, string) 700 | { 701 | return ansi ? '\x1b[94m' + string + '\x1b[0m' : string; 702 | } 703 | 704 | 705 | 706 | // CRASH 707 | 708 | 709 | function _Debug_crash_UNUSED(identifier) 710 | { 711 | throw new Error('https://github.com/elm/core/blob/1.0.0/hints/' + identifier + '.md'); 712 | } 713 | 714 | 715 | function _Debug_crash(identifier, fact1, fact2, fact3, fact4) 716 | { 717 | switch(identifier) 718 | { 719 | case 0: 720 | throw new Error('What node should I take over? In JavaScript I need something like:\n\n Elm.Main.init({\n node: document.getElementById("elm-node")\n })\n\nYou need to do this with any Browser.sandbox or Browser.element program.'); 721 | 722 | case 1: 723 | throw new Error('Browser.application programs cannot handle URLs like this:\n\n ' + document.location.href + '\n\nWhat is the root? The root of your file system? Try looking at this program with `elm reactor` or some other server.'); 724 | 725 | case 2: 726 | var jsonErrorString = fact1; 727 | throw new Error('Problem with the flags given to your Elm program on initialization.\n\n' + jsonErrorString); 728 | 729 | case 3: 730 | var portName = fact1; 731 | throw new Error('There can only be one port named `' + portName + '`, but your program has multiple.'); 732 | 733 | case 4: 734 | var portName = fact1; 735 | var problem = fact2; 736 | throw new Error('Trying to send an unexpected type of value through port `' + portName + '`:\n' + problem); 737 | 738 | case 5: 739 | throw new Error('Trying to use `(==)` on functions.\nThere is no way to know if functions are "the same" in the Elm sense.\nRead more about this at https://package.elm-lang.org/packages/elm/core/latest/Basics#== which describes why it is this way and what the better version will look like.'); 740 | 741 | case 6: 742 | var moduleName = fact1; 743 | throw new Error('Your page is loading multiple Elm scripts with a module named ' + moduleName + '. Maybe a duplicate script is getting loaded accidentally? If not, rename one of them so I know which is which!'); 744 | 745 | case 8: 746 | var moduleName = fact1; 747 | var region = fact2; 748 | var message = fact3; 749 | throw new Error('TODO in module `' + moduleName + '` ' + _Debug_regionToString(region) + '\n\n' + message); 750 | 751 | case 9: 752 | var moduleName = fact1; 753 | var region = fact2; 754 | var value = fact3; 755 | var message = fact4; 756 | throw new Error( 757 | 'TODO in module `' + moduleName + '` from the `case` expression ' 758 | + _Debug_regionToString(region) + '\n\nIt received the following value:\n\n ' 759 | + _Debug_toString(value).replace('\n', '\n ') 760 | + '\n\nBut the branch that handles it says:\n\n ' + message.replace('\n', '\n ') 761 | ); 762 | 763 | case 10: 764 | throw new Error('Bug in https://github.com/elm/virtual-dom/issues'); 765 | 766 | case 11: 767 | throw new Error('Cannot perform mod 0. Division by zero error.'); 768 | } 769 | } 770 | 771 | function _Debug_regionToString(region) 772 | { 773 | if (region.start.line === region.end.line) 774 | { 775 | return 'on line ' + region.start.line; 776 | } 777 | return 'on lines ' + region.start.line + ' through ' + region.end.line; 778 | } 779 | 780 | 781 | 782 | // MATH 783 | 784 | var _Basics_add = F2(function(a, b) { return a + b; }); 785 | var _Basics_sub = F2(function(a, b) { return a - b; }); 786 | var _Basics_mul = F2(function(a, b) { return a * b; }); 787 | var _Basics_fdiv = F2(function(a, b) { return a / b; }); 788 | var _Basics_idiv = F2(function(a, b) { return (a / b) | 0; }); 789 | var _Basics_pow = F2(Math.pow); 790 | 791 | var _Basics_remainderBy = F2(function(b, a) { return a % b; }); 792 | 793 | // https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf 794 | var _Basics_modBy = F2(function(modulus, x) 795 | { 796 | var answer = x % modulus; 797 | return modulus === 0 798 | ? _Debug_crash(11) 799 | : 800 | ((answer > 0 && modulus < 0) || (answer < 0 && modulus > 0)) 801 | ? answer + modulus 802 | : answer; 803 | }); 804 | 805 | 806 | // TRIGONOMETRY 807 | 808 | var _Basics_pi = Math.PI; 809 | var _Basics_e = Math.E; 810 | var _Basics_cos = Math.cos; 811 | var _Basics_sin = Math.sin; 812 | var _Basics_tan = Math.tan; 813 | var _Basics_acos = Math.acos; 814 | var _Basics_asin = Math.asin; 815 | var _Basics_atan = Math.atan; 816 | var _Basics_atan2 = F2(Math.atan2); 817 | 818 | 819 | // MORE MATH 820 | 821 | function _Basics_toFloat(x) { return x; } 822 | function _Basics_truncate(n) { return n | 0; } 823 | function _Basics_isInfinite(n) { return n === Infinity || n === -Infinity; } 824 | 825 | var _Basics_ceiling = Math.ceil; 826 | var _Basics_floor = Math.floor; 827 | var _Basics_round = Math.round; 828 | var _Basics_sqrt = Math.sqrt; 829 | var _Basics_log = Math.log; 830 | var _Basics_isNaN = isNaN; 831 | 832 | 833 | // BOOLEANS 834 | 835 | function _Basics_not(bool) { return !bool; } 836 | var _Basics_and = F2(function(a, b) { return a && b; }); 837 | var _Basics_or = F2(function(a, b) { return a || b; }); 838 | var _Basics_xor = F2(function(a, b) { return a !== b; }); 839 | 840 | 841 | 842 | function _Char_toCode(char) 843 | { 844 | var code = char.charCodeAt(0); 845 | if (0xD800 <= code && code <= 0xDBFF) 846 | { 847 | return (code - 0xD800) * 0x400 + char.charCodeAt(1) - 0xDC00 + 0x10000 848 | } 849 | return code; 850 | } 851 | 852 | function _Char_fromCode(code) 853 | { 854 | return _Utils_chr( 855 | (code < 0 || 0x10FFFF < code) 856 | ? '\uFFFD' 857 | : 858 | (code <= 0xFFFF) 859 | ? String.fromCharCode(code) 860 | : 861 | (code -= 0x10000, 862 | String.fromCharCode(Math.floor(code / 0x400) + 0xD800) 863 | + 864 | String.fromCharCode(code % 0x400 + 0xDC00) 865 | ) 866 | ); 867 | } 868 | 869 | function _Char_toUpper(char) 870 | { 871 | return _Utils_chr(char.toUpperCase()); 872 | } 873 | 874 | function _Char_toLower(char) 875 | { 876 | return _Utils_chr(char.toLowerCase()); 877 | } 878 | 879 | function _Char_toLocaleUpper(char) 880 | { 881 | return _Utils_chr(char.toLocaleUpperCase()); 882 | } 883 | 884 | function _Char_toLocaleLower(char) 885 | { 886 | return _Utils_chr(char.toLocaleLowerCase()); 887 | } 888 | 889 | 890 | 891 | var _String_cons = F2(function(chr, str) 892 | { 893 | return chr + str; 894 | }); 895 | 896 | function _String_uncons(string) 897 | { 898 | var word = string.charCodeAt(0); 899 | return word 900 | ? elm$core$Maybe$Just( 901 | 0xD800 <= word && word <= 0xDBFF 902 | ? _Utils_Tuple2(_Utils_chr(string[0] + string[1]), string.slice(2)) 903 | : _Utils_Tuple2(_Utils_chr(string[0]), string.slice(1)) 904 | ) 905 | : elm$core$Maybe$Nothing; 906 | } 907 | 908 | var _String_append = F2(function(a, b) 909 | { 910 | return a + b; 911 | }); 912 | 913 | function _String_length(str) 914 | { 915 | return str.length; 916 | } 917 | 918 | var _String_map = F2(function(func, string) 919 | { 920 | var len = string.length; 921 | var array = new Array(len); 922 | var i = 0; 923 | while (i < len) 924 | { 925 | var word = string.charCodeAt(i); 926 | if (0xD800 <= word && word <= 0xDBFF) 927 | { 928 | array[i] = func(_Utils_chr(string[i] + string[i+1])); 929 | i += 2; 930 | continue; 931 | } 932 | array[i] = func(_Utils_chr(string[i])); 933 | i++; 934 | } 935 | return array.join(''); 936 | }); 937 | 938 | var _String_filter = F2(function(isGood, str) 939 | { 940 | var arr = []; 941 | var len = str.length; 942 | var i = 0; 943 | while (i < len) 944 | { 945 | var char = str[i]; 946 | var word = str.charCodeAt(i); 947 | i++; 948 | if (0xD800 <= word && word <= 0xDBFF) 949 | { 950 | char += str[i]; 951 | i++; 952 | } 953 | 954 | if (isGood(_Utils_chr(char))) 955 | { 956 | arr.push(char); 957 | } 958 | } 959 | return arr.join(''); 960 | }); 961 | 962 | function _String_reverse(str) 963 | { 964 | var len = str.length; 965 | var arr = new Array(len); 966 | var i = 0; 967 | while (i < len) 968 | { 969 | var word = str.charCodeAt(i); 970 | if (0xD800 <= word && word <= 0xDBFF) 971 | { 972 | arr[len - i] = str[i + 1]; 973 | i++; 974 | arr[len - i] = str[i - 1]; 975 | i++; 976 | } 977 | else 978 | { 979 | arr[len - i] = str[i]; 980 | i++; 981 | } 982 | } 983 | return arr.join(''); 984 | } 985 | 986 | var _String_foldl = F3(function(func, state, string) 987 | { 988 | var len = string.length; 989 | var i = 0; 990 | while (i < len) 991 | { 992 | var char = string[i]; 993 | var word = string.charCodeAt(i); 994 | i++; 995 | if (0xD800 <= word && word <= 0xDBFF) 996 | { 997 | char += string[i]; 998 | i++; 999 | } 1000 | state = A2(func, _Utils_chr(char), state); 1001 | } 1002 | return state; 1003 | }); 1004 | 1005 | var _String_foldr = F3(function(func, state, string) 1006 | { 1007 | var i = string.length; 1008 | while (i--) 1009 | { 1010 | var char = string[i]; 1011 | var word = string.charCodeAt(i); 1012 | if (0xDC00 <= word && word <= 0xDFFF) 1013 | { 1014 | i--; 1015 | char = string[i] + char; 1016 | } 1017 | state = A2(func, _Utils_chr(char), state); 1018 | } 1019 | return state; 1020 | }); 1021 | 1022 | var _String_split = F2(function(sep, str) 1023 | { 1024 | return str.split(sep); 1025 | }); 1026 | 1027 | var _String_join = F2(function(sep, strs) 1028 | { 1029 | return strs.join(sep); 1030 | }); 1031 | 1032 | var _String_slice = F3(function(start, end, str) { 1033 | return str.slice(start, end); 1034 | }); 1035 | 1036 | function _String_trim(str) 1037 | { 1038 | return str.trim(); 1039 | } 1040 | 1041 | function _String_trimLeft(str) 1042 | { 1043 | return str.replace(/^\s+/, ''); 1044 | } 1045 | 1046 | function _String_trimRight(str) 1047 | { 1048 | return str.replace(/\s+$/, ''); 1049 | } 1050 | 1051 | function _String_words(str) 1052 | { 1053 | return _List_fromArray(str.trim().split(/\s+/g)); 1054 | } 1055 | 1056 | function _String_lines(str) 1057 | { 1058 | return _List_fromArray(str.split(/\r\n|\r|\n/g)); 1059 | } 1060 | 1061 | function _String_toUpper(str) 1062 | { 1063 | return str.toUpperCase(); 1064 | } 1065 | 1066 | function _String_toLower(str) 1067 | { 1068 | return str.toLowerCase(); 1069 | } 1070 | 1071 | var _String_any = F2(function(isGood, string) 1072 | { 1073 | var i = string.length; 1074 | while (i--) 1075 | { 1076 | var char = string[i]; 1077 | var word = string.charCodeAt(i); 1078 | if (0xDC00 <= word && word <= 0xDFFF) 1079 | { 1080 | i--; 1081 | char = string[i] + char; 1082 | } 1083 | if (isGood(_Utils_chr(char))) 1084 | { 1085 | return true; 1086 | } 1087 | } 1088 | return false; 1089 | }); 1090 | 1091 | var _String_all = F2(function(isGood, string) 1092 | { 1093 | var i = string.length; 1094 | while (i--) 1095 | { 1096 | var char = string[i]; 1097 | var word = string.charCodeAt(i); 1098 | if (0xDC00 <= word && word <= 0xDFFF) 1099 | { 1100 | i--; 1101 | char = string[i] + char; 1102 | } 1103 | if (!isGood(_Utils_chr(char))) 1104 | { 1105 | return false; 1106 | } 1107 | } 1108 | return true; 1109 | }); 1110 | 1111 | var _String_contains = F2(function(sub, str) 1112 | { 1113 | return str.indexOf(sub) > -1; 1114 | }); 1115 | 1116 | var _String_startsWith = F2(function(sub, str) 1117 | { 1118 | return str.indexOf(sub) === 0; 1119 | }); 1120 | 1121 | var _String_endsWith = F2(function(sub, str) 1122 | { 1123 | return str.length >= sub.length && 1124 | str.lastIndexOf(sub) === str.length - sub.length; 1125 | }); 1126 | 1127 | var _String_indexes = F2(function(sub, str) 1128 | { 1129 | var subLen = sub.length; 1130 | 1131 | if (subLen < 1) 1132 | { 1133 | return _List_Nil; 1134 | } 1135 | 1136 | var i = 0; 1137 | var is = []; 1138 | 1139 | while ((i = str.indexOf(sub, i)) > -1) 1140 | { 1141 | is.push(i); 1142 | i = i + subLen; 1143 | } 1144 | 1145 | return _List_fromArray(is); 1146 | }); 1147 | 1148 | 1149 | // TO STRING 1150 | 1151 | function _String_fromNumber(number) 1152 | { 1153 | return number + ''; 1154 | } 1155 | 1156 | 1157 | // INT CONVERSIONS 1158 | 1159 | function _String_toInt(str) 1160 | { 1161 | var total = 0; 1162 | var code0 = str.charCodeAt(0); 1163 | var start = code0 == 0x2B /* + */ || code0 == 0x2D /* - */ ? 1 : 0; 1164 | 1165 | for (var i = start; i < str.length; ++i) 1166 | { 1167 | var code = str.charCodeAt(i); 1168 | if (code < 0x30 || 0x39 < code) 1169 | { 1170 | return elm$core$Maybe$Nothing; 1171 | } 1172 | total = 10 * total + code - 0x30; 1173 | } 1174 | 1175 | return i == start 1176 | ? elm$core$Maybe$Nothing 1177 | : elm$core$Maybe$Just(code0 == 0x2D ? -total : total); 1178 | } 1179 | 1180 | 1181 | // FLOAT CONVERSIONS 1182 | 1183 | function _String_toFloat(s) 1184 | { 1185 | // check if it is a hex, octal, or binary number 1186 | if (s.length === 0 || /[\sxbo]/.test(s)) 1187 | { 1188 | return elm$core$Maybe$Nothing; 1189 | } 1190 | var n = +s; 1191 | // faster isNaN check 1192 | return n === n ? elm$core$Maybe$Just(n) : elm$core$Maybe$Nothing; 1193 | } 1194 | 1195 | function _String_fromList(chars) 1196 | { 1197 | return _List_toArray(chars).join(''); 1198 | } 1199 | 1200 | 1201 | 1202 | 1203 | /**/ 1204 | function _Json_errorToString(error) 1205 | { 1206 | return elm$json$Json$Decode$errorToString(error); 1207 | } 1208 | //*/ 1209 | 1210 | 1211 | // CORE DECODERS 1212 | 1213 | function _Json_succeed(msg) 1214 | { 1215 | return { 1216 | $: 0, 1217 | a: msg 1218 | }; 1219 | } 1220 | 1221 | function _Json_fail(msg) 1222 | { 1223 | return { 1224 | $: 1, 1225 | a: msg 1226 | }; 1227 | } 1228 | 1229 | var _Json_decodeInt = { $: 2 }; 1230 | var _Json_decodeBool = { $: 3 }; 1231 | var _Json_decodeFloat = { $: 4 }; 1232 | var _Json_decodeValue = { $: 5 }; 1233 | var _Json_decodeString = { $: 6 }; 1234 | 1235 | function _Json_decodeList(decoder) { return { $: 7, b: decoder }; } 1236 | function _Json_decodeArray(decoder) { return { $: 8, b: decoder }; } 1237 | 1238 | function _Json_decodeNull(value) { return { $: 9, c: value }; } 1239 | 1240 | var _Json_decodeField = F2(function(field, decoder) 1241 | { 1242 | return { 1243 | $: 10, 1244 | d: field, 1245 | b: decoder 1246 | }; 1247 | }); 1248 | 1249 | var _Json_decodeIndex = F2(function(index, decoder) 1250 | { 1251 | return { 1252 | $: 11, 1253 | e: index, 1254 | b: decoder 1255 | }; 1256 | }); 1257 | 1258 | function _Json_decodeKeyValuePairs(decoder) 1259 | { 1260 | return { 1261 | $: 12, 1262 | b: decoder 1263 | }; 1264 | } 1265 | 1266 | function _Json_mapMany(f, decoders) 1267 | { 1268 | return { 1269 | $: 13, 1270 | f: f, 1271 | g: decoders 1272 | }; 1273 | } 1274 | 1275 | var _Json_andThen = F2(function(callback, decoder) 1276 | { 1277 | return { 1278 | $: 14, 1279 | b: decoder, 1280 | h: callback 1281 | }; 1282 | }); 1283 | 1284 | function _Json_oneOf(decoders) 1285 | { 1286 | return { 1287 | $: 15, 1288 | g: decoders 1289 | }; 1290 | } 1291 | 1292 | 1293 | // DECODING OBJECTS 1294 | 1295 | var _Json_map1 = F2(function(f, d1) 1296 | { 1297 | return _Json_mapMany(f, [d1]); 1298 | }); 1299 | 1300 | var _Json_map2 = F3(function(f, d1, d2) 1301 | { 1302 | return _Json_mapMany(f, [d1, d2]); 1303 | }); 1304 | 1305 | var _Json_map3 = F4(function(f, d1, d2, d3) 1306 | { 1307 | return _Json_mapMany(f, [d1, d2, d3]); 1308 | }); 1309 | 1310 | var _Json_map4 = F5(function(f, d1, d2, d3, d4) 1311 | { 1312 | return _Json_mapMany(f, [d1, d2, d3, d4]); 1313 | }); 1314 | 1315 | var _Json_map5 = F6(function(f, d1, d2, d3, d4, d5) 1316 | { 1317 | return _Json_mapMany(f, [d1, d2, d3, d4, d5]); 1318 | }); 1319 | 1320 | var _Json_map6 = F7(function(f, d1, d2, d3, d4, d5, d6) 1321 | { 1322 | return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6]); 1323 | }); 1324 | 1325 | var _Json_map7 = F8(function(f, d1, d2, d3, d4, d5, d6, d7) 1326 | { 1327 | return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6, d7]); 1328 | }); 1329 | 1330 | var _Json_map8 = F9(function(f, d1, d2, d3, d4, d5, d6, d7, d8) 1331 | { 1332 | return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6, d7, d8]); 1333 | }); 1334 | 1335 | 1336 | // DECODE 1337 | 1338 | var _Json_runOnString = F2(function(decoder, string) 1339 | { 1340 | try 1341 | { 1342 | var value = JSON.parse(string); 1343 | return _Json_runHelp(decoder, value); 1344 | } 1345 | catch (e) 1346 | { 1347 | return elm$core$Result$Err(A2(elm$json$Json$Decode$Failure, 'This is not valid JSON! ' + e.message, _Json_wrap(string))); 1348 | } 1349 | }); 1350 | 1351 | var _Json_run = F2(function(decoder, value) 1352 | { 1353 | return _Json_runHelp(decoder, _Json_unwrap(value)); 1354 | }); 1355 | 1356 | function _Json_runHelp(decoder, value) 1357 | { 1358 | switch (decoder.$) 1359 | { 1360 | case 3: 1361 | return (typeof value === 'boolean') 1362 | ? elm$core$Result$Ok(value) 1363 | : _Json_expecting('a BOOL', value); 1364 | 1365 | case 2: 1366 | if (typeof value !== 'number') { 1367 | return _Json_expecting('an INT', value); 1368 | } 1369 | 1370 | if (-2147483647 < value && value < 2147483647 && (value | 0) === value) { 1371 | return elm$core$Result$Ok(value); 1372 | } 1373 | 1374 | if (isFinite(value) && !(value % 1)) { 1375 | return elm$core$Result$Ok(value); 1376 | } 1377 | 1378 | return _Json_expecting('an INT', value); 1379 | 1380 | case 4: 1381 | return (typeof value === 'number') 1382 | ? elm$core$Result$Ok(value) 1383 | : _Json_expecting('a FLOAT', value); 1384 | 1385 | case 6: 1386 | return (typeof value === 'string') 1387 | ? elm$core$Result$Ok(value) 1388 | : (value instanceof String) 1389 | ? elm$core$Result$Ok(value + '') 1390 | : _Json_expecting('a STRING', value); 1391 | 1392 | case 9: 1393 | return (value === null) 1394 | ? elm$core$Result$Ok(decoder.c) 1395 | : _Json_expecting('null', value); 1396 | 1397 | case 5: 1398 | return elm$core$Result$Ok(_Json_wrap(value)); 1399 | 1400 | case 7: 1401 | if (!Array.isArray(value)) 1402 | { 1403 | return _Json_expecting('a LIST', value); 1404 | } 1405 | return _Json_runArrayDecoder(decoder.b, value, _List_fromArray); 1406 | 1407 | case 8: 1408 | if (!Array.isArray(value)) 1409 | { 1410 | return _Json_expecting('an ARRAY', value); 1411 | } 1412 | return _Json_runArrayDecoder(decoder.b, value, _Json_toElmArray); 1413 | 1414 | case 10: 1415 | var field = decoder.d; 1416 | if (typeof value !== 'object' || value === null || !(field in value)) 1417 | { 1418 | return _Json_expecting('an OBJECT with a field named `' + field + '`', value); 1419 | } 1420 | var result = _Json_runHelp(decoder.b, value[field]); 1421 | return (elm$core$Result$isOk(result)) ? result : elm$core$Result$Err(A2(elm$json$Json$Decode$Field, field, result.a)); 1422 | 1423 | case 11: 1424 | var index = decoder.e; 1425 | if (!Array.isArray(value)) 1426 | { 1427 | return _Json_expecting('an ARRAY', value); 1428 | } 1429 | if (index >= value.length) 1430 | { 1431 | return _Json_expecting('a LONGER array. Need index ' + index + ' but only see ' + value.length + ' entries', value); 1432 | } 1433 | var result = _Json_runHelp(decoder.b, value[index]); 1434 | return (elm$core$Result$isOk(result)) ? result : elm$core$Result$Err(A2(elm$json$Json$Decode$Index, index, result.a)); 1435 | 1436 | case 12: 1437 | if (typeof value !== 'object' || value === null || Array.isArray(value)) 1438 | { 1439 | return _Json_expecting('an OBJECT', value); 1440 | } 1441 | 1442 | var keyValuePairs = _List_Nil; 1443 | // TODO test perf of Object.keys and switch when support is good enough 1444 | for (var key in value) 1445 | { 1446 | if (value.hasOwnProperty(key)) 1447 | { 1448 | var result = _Json_runHelp(decoder.b, value[key]); 1449 | if (!elm$core$Result$isOk(result)) 1450 | { 1451 | return elm$core$Result$Err(A2(elm$json$Json$Decode$Field, key, result.a)); 1452 | } 1453 | keyValuePairs = _List_Cons(_Utils_Tuple2(key, result.a), keyValuePairs); 1454 | } 1455 | } 1456 | return elm$core$Result$Ok(elm$core$List$reverse(keyValuePairs)); 1457 | 1458 | case 13: 1459 | var answer = decoder.f; 1460 | var decoders = decoder.g; 1461 | for (var i = 0; i < decoders.length; i++) 1462 | { 1463 | var result = _Json_runHelp(decoders[i], value); 1464 | if (!elm$core$Result$isOk(result)) 1465 | { 1466 | return result; 1467 | } 1468 | answer = answer(result.a); 1469 | } 1470 | return elm$core$Result$Ok(answer); 1471 | 1472 | case 14: 1473 | var result = _Json_runHelp(decoder.b, value); 1474 | return (!elm$core$Result$isOk(result)) 1475 | ? result 1476 | : _Json_runHelp(decoder.h(result.a), value); 1477 | 1478 | case 15: 1479 | var errors = _List_Nil; 1480 | for (var temp = decoder.g; temp.b; temp = temp.b) // WHILE_CONS 1481 | { 1482 | var result = _Json_runHelp(temp.a, value); 1483 | if (elm$core$Result$isOk(result)) 1484 | { 1485 | return result; 1486 | } 1487 | errors = _List_Cons(result.a, errors); 1488 | } 1489 | return elm$core$Result$Err(elm$json$Json$Decode$OneOf(elm$core$List$reverse(errors))); 1490 | 1491 | case 1: 1492 | return elm$core$Result$Err(A2(elm$json$Json$Decode$Failure, decoder.a, _Json_wrap(value))); 1493 | 1494 | case 0: 1495 | return elm$core$Result$Ok(decoder.a); 1496 | } 1497 | } 1498 | 1499 | function _Json_runArrayDecoder(decoder, value, toElmValue) 1500 | { 1501 | var len = value.length; 1502 | var array = new Array(len); 1503 | for (var i = 0; i < len; i++) 1504 | { 1505 | var result = _Json_runHelp(decoder, value[i]); 1506 | if (!elm$core$Result$isOk(result)) 1507 | { 1508 | return elm$core$Result$Err(A2(elm$json$Json$Decode$Index, i, result.a)); 1509 | } 1510 | array[i] = result.a; 1511 | } 1512 | return elm$core$Result$Ok(toElmValue(array)); 1513 | } 1514 | 1515 | function _Json_toElmArray(array) 1516 | { 1517 | return A2(elm$core$Array$initialize, array.length, function(i) { return array[i]; }); 1518 | } 1519 | 1520 | function _Json_expecting(type, value) 1521 | { 1522 | return elm$core$Result$Err(A2(elm$json$Json$Decode$Failure, 'Expecting ' + type, _Json_wrap(value))); 1523 | } 1524 | 1525 | 1526 | // EQUALITY 1527 | 1528 | function _Json_equality(x, y) 1529 | { 1530 | if (x === y) 1531 | { 1532 | return true; 1533 | } 1534 | 1535 | if (x.$ !== y.$) 1536 | { 1537 | return false; 1538 | } 1539 | 1540 | switch (x.$) 1541 | { 1542 | case 0: 1543 | case 1: 1544 | return x.a === y.a; 1545 | 1546 | case 3: 1547 | case 2: 1548 | case 4: 1549 | case 6: 1550 | case 5: 1551 | return true; 1552 | 1553 | case 9: 1554 | return x.c === y.c; 1555 | 1556 | case 7: 1557 | case 8: 1558 | case 12: 1559 | return _Json_equality(x.b, y.b); 1560 | 1561 | case 10: 1562 | return x.d === y.d && _Json_equality(x.b, y.b); 1563 | 1564 | case 11: 1565 | return x.e === y.e && _Json_equality(x.b, y.b); 1566 | 1567 | case 13: 1568 | return x.f === y.f && _Json_listEquality(x.g, y.g); 1569 | 1570 | case 14: 1571 | return x.h === y.h && _Json_equality(x.b, y.b); 1572 | 1573 | case 15: 1574 | return _Json_listEquality(x.g, y.g); 1575 | } 1576 | } 1577 | 1578 | function _Json_listEquality(aDecoders, bDecoders) 1579 | { 1580 | var len = aDecoders.length; 1581 | if (len !== bDecoders.length) 1582 | { 1583 | return false; 1584 | } 1585 | for (var i = 0; i < len; i++) 1586 | { 1587 | if (!_Json_equality(aDecoders[i], bDecoders[i])) 1588 | { 1589 | return false; 1590 | } 1591 | } 1592 | return true; 1593 | } 1594 | 1595 | 1596 | // ENCODE 1597 | 1598 | var _Json_encode = F2(function(indentLevel, value) 1599 | { 1600 | return JSON.stringify(_Json_unwrap(value), null, indentLevel) + ''; 1601 | }); 1602 | 1603 | function _Json_wrap(value) { return { $: 0, a: value }; } 1604 | function _Json_unwrap(value) { return value.a; } 1605 | 1606 | function _Json_wrap_UNUSED(value) { return value; } 1607 | function _Json_unwrap_UNUSED(value) { return value; } 1608 | 1609 | function _Json_emptyArray() { return []; } 1610 | function _Json_emptyObject() { return {}; } 1611 | 1612 | var _Json_addField = F3(function(key, value, object) 1613 | { 1614 | object[key] = _Json_unwrap(value); 1615 | return object; 1616 | }); 1617 | 1618 | function _Json_addEntry(func) 1619 | { 1620 | return F2(function(entry, array) 1621 | { 1622 | array.push(_Json_unwrap(func(entry))); 1623 | return array; 1624 | }); 1625 | } 1626 | 1627 | var _Json_encodeNull = _Json_wrap(null); 1628 | 1629 | 1630 | 1631 | // TASKS 1632 | 1633 | function _Scheduler_succeed(value) 1634 | { 1635 | return { 1636 | $: 0, 1637 | a: value 1638 | }; 1639 | } 1640 | 1641 | function _Scheduler_fail(error) 1642 | { 1643 | return { 1644 | $: 1, 1645 | a: error 1646 | }; 1647 | } 1648 | 1649 | function _Scheduler_binding(callback) 1650 | { 1651 | return { 1652 | $: 2, 1653 | b: callback, 1654 | c: null 1655 | }; 1656 | } 1657 | 1658 | var _Scheduler_andThen = F2(function(callback, task) 1659 | { 1660 | return { 1661 | $: 3, 1662 | b: callback, 1663 | d: task 1664 | }; 1665 | }); 1666 | 1667 | var _Scheduler_onError = F2(function(callback, task) 1668 | { 1669 | return { 1670 | $: 4, 1671 | b: callback, 1672 | d: task 1673 | }; 1674 | }); 1675 | 1676 | function _Scheduler_receive(callback) 1677 | { 1678 | return { 1679 | $: 5, 1680 | b: callback 1681 | }; 1682 | } 1683 | 1684 | 1685 | // PROCESSES 1686 | 1687 | var _Scheduler_guid = 0; 1688 | 1689 | function _Scheduler_rawSpawn(task) 1690 | { 1691 | var proc = { 1692 | $: 0, 1693 | e: _Scheduler_guid++, 1694 | f: task, 1695 | g: null, 1696 | h: [] 1697 | }; 1698 | 1699 | _Scheduler_enqueue(proc); 1700 | 1701 | return proc; 1702 | } 1703 | 1704 | function _Scheduler_spawn(task) 1705 | { 1706 | return _Scheduler_binding(function(callback) { 1707 | callback(_Scheduler_succeed(_Scheduler_rawSpawn(task))); 1708 | }); 1709 | } 1710 | 1711 | function _Scheduler_rawSend(proc, msg) 1712 | { 1713 | proc.h.push(msg); 1714 | _Scheduler_enqueue(proc); 1715 | } 1716 | 1717 | var _Scheduler_send = F2(function(proc, msg) 1718 | { 1719 | return _Scheduler_binding(function(callback) { 1720 | _Scheduler_rawSend(proc, msg); 1721 | callback(_Scheduler_succeed(_Utils_Tuple0)); 1722 | }); 1723 | }); 1724 | 1725 | function _Scheduler_kill(proc) 1726 | { 1727 | return _Scheduler_binding(function(callback) { 1728 | var task = proc.f; 1729 | if (task.$ === 2 && task.c) 1730 | { 1731 | task.c(); 1732 | } 1733 | 1734 | proc.f = null; 1735 | 1736 | callback(_Scheduler_succeed(_Utils_Tuple0)); 1737 | }); 1738 | } 1739 | 1740 | 1741 | /* STEP PROCESSES 1742 | 1743 | type alias Process = 1744 | { $ : tag 1745 | , id : unique_id 1746 | , root : Task 1747 | , stack : null | { $: SUCCEED | FAIL, a: callback, b: stack } 1748 | , mailbox : [msg] 1749 | } 1750 | 1751 | */ 1752 | 1753 | 1754 | var _Scheduler_working = false; 1755 | var _Scheduler_queue = []; 1756 | 1757 | 1758 | function _Scheduler_enqueue(proc) 1759 | { 1760 | _Scheduler_queue.push(proc); 1761 | if (_Scheduler_working) 1762 | { 1763 | return; 1764 | } 1765 | _Scheduler_working = true; 1766 | while (proc = _Scheduler_queue.shift()) 1767 | { 1768 | _Scheduler_step(proc); 1769 | } 1770 | _Scheduler_working = false; 1771 | } 1772 | 1773 | 1774 | function _Scheduler_step(proc) 1775 | { 1776 | while (proc.f) 1777 | { 1778 | var rootTag = proc.f.$; 1779 | if (rootTag === 0 || rootTag === 1) 1780 | { 1781 | while (proc.g && proc.g.$ !== rootTag) 1782 | { 1783 | proc.g = proc.g.i; 1784 | } 1785 | if (!proc.g) 1786 | { 1787 | return; 1788 | } 1789 | proc.f = proc.g.b(proc.f.a); 1790 | proc.g = proc.g.i; 1791 | } 1792 | else if (rootTag === 2) 1793 | { 1794 | proc.f.c = proc.f.b(function(newRoot) { 1795 | proc.f = newRoot; 1796 | _Scheduler_enqueue(proc); 1797 | }); 1798 | return; 1799 | } 1800 | else if (rootTag === 5) 1801 | { 1802 | if (proc.h.length === 0) 1803 | { 1804 | return; 1805 | } 1806 | proc.f = proc.f.b(proc.h.shift()); 1807 | } 1808 | else // if (rootTag === 3 || rootTag === 4) 1809 | { 1810 | proc.g = { 1811 | $: rootTag === 3 ? 0 : 1, 1812 | b: proc.f.b, 1813 | i: proc.g 1814 | }; 1815 | proc.f = proc.f.d; 1816 | } 1817 | } 1818 | } 1819 | 1820 | 1821 | 1822 | function _Process_sleep(time) 1823 | { 1824 | return _Scheduler_binding(function(callback) { 1825 | var id = setTimeout(function() { 1826 | callback(_Scheduler_succeed(_Utils_Tuple0)); 1827 | }, time); 1828 | 1829 | return function() { clearTimeout(id); }; 1830 | }); 1831 | } 1832 | 1833 | 1834 | 1835 | 1836 | // PROGRAMS 1837 | 1838 | 1839 | var _Platform_worker = F4(function(impl, flagDecoder, debugMetadata, args) 1840 | { 1841 | return _Platform_initialize( 1842 | flagDecoder, 1843 | args, 1844 | impl.init, 1845 | impl.update, 1846 | impl.subscriptions, 1847 | function() { return function() {} } 1848 | ); 1849 | }); 1850 | 1851 | 1852 | 1853 | // INITIALIZE A PROGRAM 1854 | 1855 | 1856 | function _Platform_initialize(flagDecoder, args, init, update, subscriptions, stepperBuilder) 1857 | { 1858 | var result = A2(_Json_run, flagDecoder, _Json_wrap(args ? args['flags'] : undefined)); 1859 | elm$core$Result$isOk(result) || _Debug_crash(2 /**/, _Json_errorToString(result.a) /**/); 1860 | var managers = {}; 1861 | result = init(result.a); 1862 | var model = result.a; 1863 | var stepper = stepperBuilder(sendToApp, model); 1864 | var ports = _Platform_setupEffects(managers, sendToApp); 1865 | 1866 | function sendToApp(msg, viewMetadata) 1867 | { 1868 | result = A2(update, msg, model); 1869 | stepper(model = result.a, viewMetadata); 1870 | _Platform_dispatchEffects(managers, result.b, subscriptions(model)); 1871 | } 1872 | 1873 | _Platform_dispatchEffects(managers, result.b, subscriptions(model)); 1874 | 1875 | return ports ? { ports: ports } : {}; 1876 | } 1877 | 1878 | 1879 | 1880 | // TRACK PRELOADS 1881 | // 1882 | // This is used by code in elm/browser and elm/http 1883 | // to register any HTTP requests that are triggered by init. 1884 | // 1885 | 1886 | 1887 | var _Platform_preload; 1888 | 1889 | 1890 | function _Platform_registerPreload(url) 1891 | { 1892 | _Platform_preload.add(url); 1893 | } 1894 | 1895 | 1896 | 1897 | // EFFECT MANAGERS 1898 | 1899 | 1900 | var _Platform_effectManagers = {}; 1901 | 1902 | 1903 | function _Platform_setupEffects(managers, sendToApp) 1904 | { 1905 | var ports; 1906 | 1907 | // setup all necessary effect managers 1908 | for (var key in _Platform_effectManagers) 1909 | { 1910 | var manager = _Platform_effectManagers[key]; 1911 | 1912 | if (manager.a) 1913 | { 1914 | ports = ports || {}; 1915 | ports[key] = manager.a(key, sendToApp); 1916 | } 1917 | 1918 | managers[key] = _Platform_instantiateManager(manager, sendToApp); 1919 | } 1920 | 1921 | return ports; 1922 | } 1923 | 1924 | 1925 | function _Platform_createManager(init, onEffects, onSelfMsg, cmdMap, subMap) 1926 | { 1927 | return { 1928 | b: init, 1929 | c: onEffects, 1930 | d: onSelfMsg, 1931 | e: cmdMap, 1932 | f: subMap 1933 | }; 1934 | } 1935 | 1936 | 1937 | function _Platform_instantiateManager(info, sendToApp) 1938 | { 1939 | var router = { 1940 | g: sendToApp, 1941 | h: undefined 1942 | }; 1943 | 1944 | var onEffects = info.c; 1945 | var onSelfMsg = info.d; 1946 | var cmdMap = info.e; 1947 | var subMap = info.f; 1948 | 1949 | function loop(state) 1950 | { 1951 | return A2(_Scheduler_andThen, loop, _Scheduler_receive(function(msg) 1952 | { 1953 | var value = msg.a; 1954 | 1955 | if (msg.$ === 0) 1956 | { 1957 | return A3(onSelfMsg, router, value, state); 1958 | } 1959 | 1960 | return cmdMap && subMap 1961 | ? A4(onEffects, router, value.i, value.j, state) 1962 | : A3(onEffects, router, cmdMap ? value.i : value.j, state); 1963 | })); 1964 | } 1965 | 1966 | return router.h = _Scheduler_rawSpawn(A2(_Scheduler_andThen, loop, info.b)); 1967 | } 1968 | 1969 | 1970 | 1971 | // ROUTING 1972 | 1973 | 1974 | var _Platform_sendToApp = F2(function(router, msg) 1975 | { 1976 | return _Scheduler_binding(function(callback) 1977 | { 1978 | router.g(msg); 1979 | callback(_Scheduler_succeed(_Utils_Tuple0)); 1980 | }); 1981 | }); 1982 | 1983 | 1984 | var _Platform_sendToSelf = F2(function(router, msg) 1985 | { 1986 | return A2(_Scheduler_send, router.h, { 1987 | $: 0, 1988 | a: msg 1989 | }); 1990 | }); 1991 | 1992 | 1993 | 1994 | // BAGS 1995 | 1996 | 1997 | function _Platform_leaf(home) 1998 | { 1999 | return function(value) 2000 | { 2001 | return { 2002 | $: 1, 2003 | k: home, 2004 | l: value 2005 | }; 2006 | }; 2007 | } 2008 | 2009 | 2010 | function _Platform_batch(list) 2011 | { 2012 | return { 2013 | $: 2, 2014 | m: list 2015 | }; 2016 | } 2017 | 2018 | 2019 | var _Platform_map = F2(function(tagger, bag) 2020 | { 2021 | return { 2022 | $: 3, 2023 | n: tagger, 2024 | o: bag 2025 | } 2026 | }); 2027 | 2028 | 2029 | 2030 | // PIPE BAGS INTO EFFECT MANAGERS 2031 | 2032 | 2033 | function _Platform_dispatchEffects(managers, cmdBag, subBag) 2034 | { 2035 | var effectsDict = {}; 2036 | _Platform_gatherEffects(true, cmdBag, effectsDict, null); 2037 | _Platform_gatherEffects(false, subBag, effectsDict, null); 2038 | 2039 | for (var home in managers) 2040 | { 2041 | _Scheduler_rawSend(managers[home], { 2042 | $: 'fx', 2043 | a: effectsDict[home] || { i: _List_Nil, j: _List_Nil } 2044 | }); 2045 | } 2046 | } 2047 | 2048 | 2049 | function _Platform_gatherEffects(isCmd, bag, effectsDict, taggers) 2050 | { 2051 | switch (bag.$) 2052 | { 2053 | case 1: 2054 | var home = bag.k; 2055 | var effect = _Platform_toEffect(isCmd, home, taggers, bag.l); 2056 | effectsDict[home] = _Platform_insert(isCmd, effect, effectsDict[home]); 2057 | return; 2058 | 2059 | case 2: 2060 | for (var list = bag.m; list.b; list = list.b) // WHILE_CONS 2061 | { 2062 | _Platform_gatherEffects(isCmd, list.a, effectsDict, taggers); 2063 | } 2064 | return; 2065 | 2066 | case 3: 2067 | _Platform_gatherEffects(isCmd, bag.o, effectsDict, { 2068 | p: bag.n, 2069 | q: taggers 2070 | }); 2071 | return; 2072 | } 2073 | } 2074 | 2075 | 2076 | function _Platform_toEffect(isCmd, home, taggers, value) 2077 | { 2078 | function applyTaggers(x) 2079 | { 2080 | for (var temp = taggers; temp; temp = temp.q) 2081 | { 2082 | x = temp.p(x); 2083 | } 2084 | return x; 2085 | } 2086 | 2087 | var map = isCmd 2088 | ? _Platform_effectManagers[home].e 2089 | : _Platform_effectManagers[home].f; 2090 | 2091 | return A2(map, applyTaggers, value) 2092 | } 2093 | 2094 | 2095 | function _Platform_insert(isCmd, newEffect, effects) 2096 | { 2097 | effects = effects || { i: _List_Nil, j: _List_Nil }; 2098 | 2099 | isCmd 2100 | ? (effects.i = _List_Cons(newEffect, effects.i)) 2101 | : (effects.j = _List_Cons(newEffect, effects.j)); 2102 | 2103 | return effects; 2104 | } 2105 | 2106 | 2107 | 2108 | // PORTS 2109 | 2110 | 2111 | function _Platform_checkPortName(name) 2112 | { 2113 | if (_Platform_effectManagers[name]) 2114 | { 2115 | _Debug_crash(3, name) 2116 | } 2117 | } 2118 | 2119 | 2120 | 2121 | // OUTGOING PORTS 2122 | 2123 | 2124 | function _Platform_outgoingPort(name, converter) 2125 | { 2126 | _Platform_checkPortName(name); 2127 | _Platform_effectManagers[name] = { 2128 | e: _Platform_outgoingPortMap, 2129 | r: converter, 2130 | a: _Platform_setupOutgoingPort 2131 | }; 2132 | return _Platform_leaf(name); 2133 | } 2134 | 2135 | 2136 | var _Platform_outgoingPortMap = F2(function(tagger, value) { return value; }); 2137 | 2138 | 2139 | function _Platform_setupOutgoingPort(name) 2140 | { 2141 | var subs = []; 2142 | var converter = _Platform_effectManagers[name].r; 2143 | 2144 | // CREATE MANAGER 2145 | 2146 | var init = _Process_sleep(0); 2147 | 2148 | _Platform_effectManagers[name].b = init; 2149 | _Platform_effectManagers[name].c = F3(function(router, cmdList, state) 2150 | { 2151 | for ( ; cmdList.b; cmdList = cmdList.b) // WHILE_CONS 2152 | { 2153 | // grab a separate reference to subs in case unsubscribe is called 2154 | var currentSubs = subs; 2155 | var value = _Json_unwrap(converter(cmdList.a)); 2156 | for (var i = 0; i < currentSubs.length; i++) 2157 | { 2158 | currentSubs[i](value); 2159 | } 2160 | } 2161 | return init; 2162 | }); 2163 | 2164 | // PUBLIC API 2165 | 2166 | function subscribe(callback) 2167 | { 2168 | subs.push(callback); 2169 | } 2170 | 2171 | function unsubscribe(callback) 2172 | { 2173 | // copy subs into a new array in case unsubscribe is called within a 2174 | // subscribed callback 2175 | subs = subs.slice(); 2176 | var index = subs.indexOf(callback); 2177 | if (index >= 0) 2178 | { 2179 | subs.splice(index, 1); 2180 | } 2181 | } 2182 | 2183 | return { 2184 | subscribe: subscribe, 2185 | unsubscribe: unsubscribe 2186 | }; 2187 | } 2188 | 2189 | 2190 | 2191 | // INCOMING PORTS 2192 | 2193 | 2194 | function _Platform_incomingPort(name, converter) 2195 | { 2196 | _Platform_checkPortName(name); 2197 | _Platform_effectManagers[name] = { 2198 | f: _Platform_incomingPortMap, 2199 | r: converter, 2200 | a: _Platform_setupIncomingPort 2201 | }; 2202 | return _Platform_leaf(name); 2203 | } 2204 | 2205 | 2206 | var _Platform_incomingPortMap = F2(function(tagger, finalTagger) 2207 | { 2208 | return function(value) 2209 | { 2210 | return tagger(finalTagger(value)); 2211 | }; 2212 | }); 2213 | 2214 | 2215 | function _Platform_setupIncomingPort(name, sendToApp) 2216 | { 2217 | var subs = _List_Nil; 2218 | var converter = _Platform_effectManagers[name].r; 2219 | 2220 | // CREATE MANAGER 2221 | 2222 | var init = _Scheduler_succeed(null); 2223 | 2224 | _Platform_effectManagers[name].b = init; 2225 | _Platform_effectManagers[name].c = F3(function(router, subList, state) 2226 | { 2227 | subs = subList; 2228 | return init; 2229 | }); 2230 | 2231 | // PUBLIC API 2232 | 2233 | function send(incomingValue) 2234 | { 2235 | var result = A2(_Json_run, converter, _Json_wrap(incomingValue)); 2236 | 2237 | elm$core$Result$isOk(result) || _Debug_crash(4, name, result.a); 2238 | 2239 | var value = result.a; 2240 | for (var temp = subs; temp.b; temp = temp.b) // WHILE_CONS 2241 | { 2242 | sendToApp(temp.a(value)); 2243 | } 2244 | } 2245 | 2246 | return { send: send }; 2247 | } 2248 | 2249 | 2250 | 2251 | // EXPORT ELM MODULES 2252 | // 2253 | // Have DEBUG and PROD versions so that we can (1) give nicer errors in 2254 | // debug mode and (2) not pay for the bits needed for that in prod mode. 2255 | // 2256 | 2257 | 2258 | function _Platform_export_UNUSED(exports) 2259 | { 2260 | scope['Elm'] 2261 | ? _Platform_mergeExportsProd(scope['Elm'], exports) 2262 | : scope['Elm'] = exports; 2263 | } 2264 | 2265 | 2266 | function _Platform_mergeExportsProd(obj, exports) 2267 | { 2268 | for (var name in exports) 2269 | { 2270 | (name in obj) 2271 | ? (name == 'init') 2272 | ? _Debug_crash(6) 2273 | : _Platform_mergeExportsProd(obj[name], exports[name]) 2274 | : (obj[name] = exports[name]); 2275 | } 2276 | } 2277 | 2278 | 2279 | function _Platform_export(exports) 2280 | { 2281 | scope['Elm'] 2282 | ? _Platform_mergeExportsDebug('Elm', scope['Elm'], exports) 2283 | : scope['Elm'] = exports; 2284 | } 2285 | 2286 | 2287 | function _Platform_mergeExportsDebug(moduleName, obj, exports) 2288 | { 2289 | for (var name in exports) 2290 | { 2291 | (name in obj) 2292 | ? (name == 'init') 2293 | ? _Debug_crash(6, moduleName) 2294 | : _Platform_mergeExportsDebug(moduleName + '.' + name, obj[name], exports[name]) 2295 | : (obj[name] = exports[name]); 2296 | } 2297 | } 2298 | 2299 | 2300 | 2301 | 2302 | // HELPERS 2303 | 2304 | 2305 | var _VirtualDom_divertHrefToApp; 2306 | 2307 | var _VirtualDom_doc = typeof document !== 'undefined' ? document : {}; 2308 | 2309 | 2310 | function _VirtualDom_appendChild(parent, child) 2311 | { 2312 | parent.appendChild(child); 2313 | } 2314 | 2315 | var _VirtualDom_init = F4(function(virtualNode, flagDecoder, debugMetadata, args) 2316 | { 2317 | // NOTE: this function needs _Platform_export available to work 2318 | 2319 | /**_UNUSED/ 2320 | var node = args['node']; 2321 | //*/ 2322 | /**/ 2323 | var node = args && args['node'] ? args['node'] : _Debug_crash(0); 2324 | //*/ 2325 | 2326 | node.parentNode.replaceChild( 2327 | _VirtualDom_render(virtualNode, function() {}), 2328 | node 2329 | ); 2330 | 2331 | return {}; 2332 | }); 2333 | 2334 | 2335 | 2336 | // TEXT 2337 | 2338 | 2339 | function _VirtualDom_text(string) 2340 | { 2341 | return { 2342 | $: 0, 2343 | a: string 2344 | }; 2345 | } 2346 | 2347 | 2348 | 2349 | // NODE 2350 | 2351 | 2352 | var _VirtualDom_nodeNS = F2(function(namespace, tag) 2353 | { 2354 | return F2(function(factList, kidList) 2355 | { 2356 | for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS 2357 | { 2358 | var kid = kidList.a; 2359 | descendantsCount += (kid.b || 0); 2360 | kids.push(kid); 2361 | } 2362 | descendantsCount += kids.length; 2363 | 2364 | return { 2365 | $: 1, 2366 | c: tag, 2367 | d: _VirtualDom_organizeFacts(factList), 2368 | e: kids, 2369 | f: namespace, 2370 | b: descendantsCount 2371 | }; 2372 | }); 2373 | }); 2374 | 2375 | 2376 | var _VirtualDom_node = _VirtualDom_nodeNS(undefined); 2377 | 2378 | 2379 | 2380 | // KEYED NODE 2381 | 2382 | 2383 | var _VirtualDom_keyedNodeNS = F2(function(namespace, tag) 2384 | { 2385 | return F2(function(factList, kidList) 2386 | { 2387 | for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS 2388 | { 2389 | var kid = kidList.a; 2390 | descendantsCount += (kid.b.b || 0); 2391 | kids.push(kid); 2392 | } 2393 | descendantsCount += kids.length; 2394 | 2395 | return { 2396 | $: 2, 2397 | c: tag, 2398 | d: _VirtualDom_organizeFacts(factList), 2399 | e: kids, 2400 | f: namespace, 2401 | b: descendantsCount 2402 | }; 2403 | }); 2404 | }); 2405 | 2406 | 2407 | var _VirtualDom_keyedNode = _VirtualDom_keyedNodeNS(undefined); 2408 | 2409 | 2410 | 2411 | // CUSTOM 2412 | 2413 | 2414 | function _VirtualDom_custom(factList, model, render, diff) 2415 | { 2416 | return { 2417 | $: 3, 2418 | d: _VirtualDom_organizeFacts(factList), 2419 | g: model, 2420 | h: render, 2421 | i: diff 2422 | }; 2423 | } 2424 | 2425 | 2426 | 2427 | // MAP 2428 | 2429 | 2430 | var _VirtualDom_map = F2(function(tagger, node) 2431 | { 2432 | return { 2433 | $: 4, 2434 | j: tagger, 2435 | k: node, 2436 | b: 1 + (node.b || 0) 2437 | }; 2438 | }); 2439 | 2440 | 2441 | 2442 | // LAZY 2443 | 2444 | 2445 | function _VirtualDom_thunk(refs, thunk) 2446 | { 2447 | return { 2448 | $: 5, 2449 | l: refs, 2450 | m: thunk, 2451 | k: undefined 2452 | }; 2453 | } 2454 | 2455 | var _VirtualDom_lazy = F2(function(func, a) 2456 | { 2457 | return _VirtualDom_thunk([func, a], function() { 2458 | return func(a); 2459 | }); 2460 | }); 2461 | 2462 | var _VirtualDom_lazy2 = F3(function(func, a, b) 2463 | { 2464 | return _VirtualDom_thunk([func, a, b], function() { 2465 | return A2(func, a, b); 2466 | }); 2467 | }); 2468 | 2469 | var _VirtualDom_lazy3 = F4(function(func, a, b, c) 2470 | { 2471 | return _VirtualDom_thunk([func, a, b, c], function() { 2472 | return A3(func, a, b, c); 2473 | }); 2474 | }); 2475 | 2476 | var _VirtualDom_lazy4 = F5(function(func, a, b, c, d) 2477 | { 2478 | return _VirtualDom_thunk([func, a, b, c, d], function() { 2479 | return A4(func, a, b, c, d); 2480 | }); 2481 | }); 2482 | 2483 | var _VirtualDom_lazy5 = F6(function(func, a, b, c, d, e) 2484 | { 2485 | return _VirtualDom_thunk([func, a, b, c, d, e], function() { 2486 | return A5(func, a, b, c, d, e); 2487 | }); 2488 | }); 2489 | 2490 | var _VirtualDom_lazy6 = F7(function(func, a, b, c, d, e, f) 2491 | { 2492 | return _VirtualDom_thunk([func, a, b, c, d, e, f], function() { 2493 | return A6(func, a, b, c, d, e, f); 2494 | }); 2495 | }); 2496 | 2497 | var _VirtualDom_lazy7 = F8(function(func, a, b, c, d, e, f, g) 2498 | { 2499 | return _VirtualDom_thunk([func, a, b, c, d, e, f, g], function() { 2500 | return A7(func, a, b, c, d, e, f, g); 2501 | }); 2502 | }); 2503 | 2504 | var _VirtualDom_lazy8 = F9(function(func, a, b, c, d, e, f, g, h) 2505 | { 2506 | return _VirtualDom_thunk([func, a, b, c, d, e, f, g, h], function() { 2507 | return A8(func, a, b, c, d, e, f, g, h); 2508 | }); 2509 | }); 2510 | 2511 | 2512 | 2513 | // FACTS 2514 | 2515 | 2516 | var _VirtualDom_on = F2(function(key, handler) 2517 | { 2518 | return { 2519 | $: 'a0', 2520 | n: key, 2521 | o: handler 2522 | }; 2523 | }); 2524 | var _VirtualDom_style = F2(function(key, value) 2525 | { 2526 | return { 2527 | $: 'a1', 2528 | n: key, 2529 | o: value 2530 | }; 2531 | }); 2532 | var _VirtualDom_property = F2(function(key, value) 2533 | { 2534 | return { 2535 | $: 'a2', 2536 | n: key, 2537 | o: value 2538 | }; 2539 | }); 2540 | var _VirtualDom_attribute = F2(function(key, value) 2541 | { 2542 | return { 2543 | $: 'a3', 2544 | n: key, 2545 | o: value 2546 | }; 2547 | }); 2548 | var _VirtualDom_attributeNS = F3(function(namespace, key, value) 2549 | { 2550 | return { 2551 | $: 'a4', 2552 | n: key, 2553 | o: { f: namespace, o: value } 2554 | }; 2555 | }); 2556 | 2557 | 2558 | 2559 | // XSS ATTACK VECTOR CHECKS 2560 | 2561 | 2562 | function _VirtualDom_noScript(tag) 2563 | { 2564 | return tag == 'script' ? 'p' : tag; 2565 | } 2566 | 2567 | function _VirtualDom_noOnOrFormAction(key) 2568 | { 2569 | return /^(on|formAction$)/i.test(key) ? 'data-' + key : key; 2570 | } 2571 | 2572 | function _VirtualDom_noInnerHtmlOrFormAction(key) 2573 | { 2574 | return key == 'innerHTML' || key == 'formAction' ? 'data-' + key : key; 2575 | } 2576 | 2577 | function _VirtualDom_noJavaScriptUri_UNUSED(value) 2578 | { 2579 | return /^javascript:/i.test(value.replace(/\s/g,'')) ? '' : value; 2580 | } 2581 | 2582 | function _VirtualDom_noJavaScriptUri(value) 2583 | { 2584 | return /^javascript:/i.test(value.replace(/\s/g,'')) 2585 | ? 'javascript:alert("This is an XSS vector. Please use ports or web components instead.")' 2586 | : value; 2587 | } 2588 | 2589 | function _VirtualDom_noJavaScriptOrHtmlUri_UNUSED(value) 2590 | { 2591 | return /^\s*(javascript:|data:text\/html)/i.test(value) ? '' : value; 2592 | } 2593 | 2594 | function _VirtualDom_noJavaScriptOrHtmlUri(value) 2595 | { 2596 | return /^\s*(javascript:|data:text\/html)/i.test(value) 2597 | ? 'javascript:alert("This is an XSS vector. Please use ports or web components instead.")' 2598 | : value; 2599 | } 2600 | 2601 | 2602 | 2603 | // MAP FACTS 2604 | 2605 | 2606 | var _VirtualDom_mapAttribute = F2(function(func, attr) 2607 | { 2608 | return (attr.$ === 'a0') 2609 | ? A2(_VirtualDom_on, attr.n, _VirtualDom_mapHandler(func, attr.o)) 2610 | : attr; 2611 | }); 2612 | 2613 | function _VirtualDom_mapHandler(func, handler) 2614 | { 2615 | var tag = elm$virtual_dom$VirtualDom$toHandlerInt(handler); 2616 | 2617 | // 0 = Normal 2618 | // 1 = MayStopPropagation 2619 | // 2 = MayPreventDefault 2620 | // 3 = Custom 2621 | 2622 | return { 2623 | $: handler.$, 2624 | a: 2625 | !tag 2626 | ? A2(elm$json$Json$Decode$map, func, handler.a) 2627 | : 2628 | A3(elm$json$Json$Decode$map2, 2629 | tag < 3 2630 | ? _VirtualDom_mapEventTuple 2631 | : _VirtualDom_mapEventRecord, 2632 | elm$json$Json$Decode$succeed(func), 2633 | handler.a 2634 | ) 2635 | }; 2636 | } 2637 | 2638 | var _VirtualDom_mapEventTuple = F2(function(func, tuple) 2639 | { 2640 | return _Utils_Tuple2(func(tuple.a), tuple.b); 2641 | }); 2642 | 2643 | var _VirtualDom_mapEventRecord = F2(function(func, record) 2644 | { 2645 | return { 2646 | message: func(record.message), 2647 | stopPropagation: record.stopPropagation, 2648 | preventDefault: record.preventDefault 2649 | } 2650 | }); 2651 | 2652 | 2653 | 2654 | // ORGANIZE FACTS 2655 | 2656 | 2657 | function _VirtualDom_organizeFacts(factList) 2658 | { 2659 | for (var facts = {}; factList.b; factList = factList.b) // WHILE_CONS 2660 | { 2661 | var entry = factList.a; 2662 | 2663 | var tag = entry.$; 2664 | var key = entry.n; 2665 | var value = entry.o; 2666 | 2667 | if (tag === 'a2') 2668 | { 2669 | (key === 'className') 2670 | ? _VirtualDom_addClass(facts, key, _Json_unwrap(value)) 2671 | : facts[key] = _Json_unwrap(value); 2672 | 2673 | continue; 2674 | } 2675 | 2676 | var subFacts = facts[tag] || (facts[tag] = {}); 2677 | (tag === 'a3' && key === 'class') 2678 | ? _VirtualDom_addClass(subFacts, key, value) 2679 | : subFacts[key] = value; 2680 | } 2681 | 2682 | return facts; 2683 | } 2684 | 2685 | function _VirtualDom_addClass(object, key, newClass) 2686 | { 2687 | var classes = object[key]; 2688 | object[key] = classes ? classes + ' ' + newClass : newClass; 2689 | } 2690 | 2691 | 2692 | 2693 | // RENDER 2694 | 2695 | 2696 | function _VirtualDom_render(vNode, eventNode) 2697 | { 2698 | var tag = vNode.$; 2699 | 2700 | if (tag === 5) 2701 | { 2702 | return _VirtualDom_render(vNode.k || (vNode.k = vNode.m()), eventNode); 2703 | } 2704 | 2705 | if (tag === 0) 2706 | { 2707 | return _VirtualDom_doc.createTextNode(vNode.a); 2708 | } 2709 | 2710 | if (tag === 4) 2711 | { 2712 | var subNode = vNode.k; 2713 | var tagger = vNode.j; 2714 | 2715 | while (subNode.$ === 4) 2716 | { 2717 | typeof tagger !== 'object' 2718 | ? tagger = [tagger, subNode.j] 2719 | : tagger.push(subNode.j); 2720 | 2721 | subNode = subNode.k; 2722 | } 2723 | 2724 | var subEventRoot = { j: tagger, p: eventNode }; 2725 | var domNode = _VirtualDom_render(subNode, subEventRoot); 2726 | domNode.elm_event_node_ref = subEventRoot; 2727 | return domNode; 2728 | } 2729 | 2730 | if (tag === 3) 2731 | { 2732 | var domNode = vNode.h(vNode.g); 2733 | _VirtualDom_applyFacts(domNode, eventNode, vNode.d); 2734 | return domNode; 2735 | } 2736 | 2737 | // at this point `tag` must be 1 or 2 2738 | 2739 | var domNode = vNode.f 2740 | ? _VirtualDom_doc.createElementNS(vNode.f, vNode.c) 2741 | : _VirtualDom_doc.createElement(vNode.c); 2742 | 2743 | if (_VirtualDom_divertHrefToApp && vNode.c == 'a') 2744 | { 2745 | domNode.addEventListener('click', _VirtualDom_divertHrefToApp(domNode)); 2746 | } 2747 | 2748 | _VirtualDom_applyFacts(domNode, eventNode, vNode.d); 2749 | 2750 | for (var kids = vNode.e, i = 0; i < kids.length; i++) 2751 | { 2752 | _VirtualDom_appendChild(domNode, _VirtualDom_render(tag === 1 ? kids[i] : kids[i].b, eventNode)); 2753 | } 2754 | 2755 | return domNode; 2756 | } 2757 | 2758 | 2759 | 2760 | // APPLY FACTS 2761 | 2762 | 2763 | function _VirtualDom_applyFacts(domNode, eventNode, facts) 2764 | { 2765 | for (var key in facts) 2766 | { 2767 | var value = facts[key]; 2768 | 2769 | key === 'a1' 2770 | ? _VirtualDom_applyStyles(domNode, value) 2771 | : 2772 | key === 'a0' 2773 | ? _VirtualDom_applyEvents(domNode, eventNode, value) 2774 | : 2775 | key === 'a3' 2776 | ? _VirtualDom_applyAttrs(domNode, value) 2777 | : 2778 | key === 'a4' 2779 | ? _VirtualDom_applyAttrsNS(domNode, value) 2780 | : 2781 | (key !== 'value' || key !== 'checked' || domNode[key] !== value) && (domNode[key] = value); 2782 | } 2783 | } 2784 | 2785 | 2786 | 2787 | // APPLY STYLES 2788 | 2789 | 2790 | function _VirtualDom_applyStyles(domNode, styles) 2791 | { 2792 | var domNodeStyle = domNode.style; 2793 | 2794 | for (var key in styles) 2795 | { 2796 | domNodeStyle[key] = styles[key]; 2797 | } 2798 | } 2799 | 2800 | 2801 | 2802 | // APPLY ATTRS 2803 | 2804 | 2805 | function _VirtualDom_applyAttrs(domNode, attrs) 2806 | { 2807 | for (var key in attrs) 2808 | { 2809 | var value = attrs[key]; 2810 | value 2811 | ? domNode.setAttribute(key, value) 2812 | : domNode.removeAttribute(key); 2813 | } 2814 | } 2815 | 2816 | 2817 | 2818 | // APPLY NAMESPACED ATTRS 2819 | 2820 | 2821 | function _VirtualDom_applyAttrsNS(domNode, nsAttrs) 2822 | { 2823 | for (var key in nsAttrs) 2824 | { 2825 | var pair = nsAttrs[key]; 2826 | var namespace = pair.f; 2827 | var value = pair.o; 2828 | 2829 | value 2830 | ? domNode.setAttributeNS(namespace, key, value) 2831 | : domNode.removeAttributeNS(namespace, key); 2832 | } 2833 | } 2834 | 2835 | 2836 | 2837 | // APPLY EVENTS 2838 | 2839 | 2840 | function _VirtualDom_applyEvents(domNode, eventNode, events) 2841 | { 2842 | var allCallbacks = domNode.elmFs || (domNode.elmFs = {}); 2843 | 2844 | for (var key in events) 2845 | { 2846 | var newHandler = events[key]; 2847 | var oldCallback = allCallbacks[key]; 2848 | 2849 | if (!newHandler) 2850 | { 2851 | domNode.removeEventListener(key, oldCallback); 2852 | allCallbacks[key] = undefined; 2853 | continue; 2854 | } 2855 | 2856 | if (oldCallback) 2857 | { 2858 | var oldHandler = oldCallback.q; 2859 | if (oldHandler.$ === newHandler.$) 2860 | { 2861 | oldCallback.q = newHandler; 2862 | continue; 2863 | } 2864 | domNode.removeEventListener(key, oldCallback); 2865 | } 2866 | 2867 | oldCallback = _VirtualDom_makeCallback(eventNode, newHandler); 2868 | domNode.addEventListener(key, oldCallback, 2869 | _VirtualDom_passiveSupported 2870 | && { passive: elm$virtual_dom$VirtualDom$toHandlerInt(newHandler) < 2 } 2871 | ); 2872 | allCallbacks[key] = oldCallback; 2873 | } 2874 | } 2875 | 2876 | 2877 | 2878 | // PASSIVE EVENTS 2879 | 2880 | 2881 | var _VirtualDom_passiveSupported; 2882 | 2883 | try 2884 | { 2885 | window.addEventListener('t', null, Object.defineProperty({}, 'passive', { 2886 | get: function() { _VirtualDom_passiveSupported = true; } 2887 | })); 2888 | } 2889 | catch(e) {} 2890 | 2891 | 2892 | 2893 | // EVENT HANDLERS 2894 | 2895 | 2896 | function _VirtualDom_makeCallback(eventNode, initialHandler) 2897 | { 2898 | function callback(event) 2899 | { 2900 | var handler = callback.q; 2901 | var result = _Json_runHelp(handler.a, event); 2902 | 2903 | if (!elm$core$Result$isOk(result)) 2904 | { 2905 | return; 2906 | } 2907 | 2908 | var tag = elm$virtual_dom$VirtualDom$toHandlerInt(handler); 2909 | 2910 | // 0 = Normal 2911 | // 1 = MayStopPropagation 2912 | // 2 = MayPreventDefault 2913 | // 3 = Custom 2914 | 2915 | var value = result.a; 2916 | var message = !tag ? value : tag < 3 ? value.a : value.message; 2917 | var stopPropagation = tag == 1 ? value.b : tag == 3 && value.stopPropagation; 2918 | var currentEventNode = ( 2919 | stopPropagation && event.stopPropagation(), 2920 | (tag == 2 ? value.b : tag == 3 && value.preventDefault) && event.preventDefault(), 2921 | eventNode 2922 | ); 2923 | var tagger; 2924 | var i; 2925 | while (tagger = currentEventNode.j) 2926 | { 2927 | if (typeof tagger == 'function') 2928 | { 2929 | message = tagger(message); 2930 | } 2931 | else 2932 | { 2933 | for (var i = tagger.length; i--; ) 2934 | { 2935 | message = tagger[i](message); 2936 | } 2937 | } 2938 | currentEventNode = currentEventNode.p; 2939 | } 2940 | currentEventNode(message, stopPropagation); // stopPropagation implies isSync 2941 | } 2942 | 2943 | callback.q = initialHandler; 2944 | 2945 | return callback; 2946 | } 2947 | 2948 | function _VirtualDom_equalEvents(x, y) 2949 | { 2950 | return x.$ == y.$ && _Json_equality(x.a, y.a); 2951 | } 2952 | 2953 | 2954 | 2955 | // DIFF 2956 | 2957 | 2958 | // TODO: Should we do patches like in iOS? 2959 | // 2960 | // type Patch 2961 | // = At Int Patch 2962 | // | Batch (List Patch) 2963 | // | Change ... 2964 | // 2965 | // How could it not be better? 2966 | // 2967 | function _VirtualDom_diff(x, y) 2968 | { 2969 | var patches = []; 2970 | _VirtualDom_diffHelp(x, y, patches, 0); 2971 | return patches; 2972 | } 2973 | 2974 | 2975 | function _VirtualDom_pushPatch(patches, type, index, data) 2976 | { 2977 | var patch = { 2978 | $: type, 2979 | r: index, 2980 | s: data, 2981 | t: undefined, 2982 | u: undefined 2983 | }; 2984 | patches.push(patch); 2985 | return patch; 2986 | } 2987 | 2988 | 2989 | function _VirtualDom_diffHelp(x, y, patches, index) 2990 | { 2991 | if (x === y) 2992 | { 2993 | return; 2994 | } 2995 | 2996 | var xType = x.$; 2997 | var yType = y.$; 2998 | 2999 | // Bail if you run into different types of nodes. Implies that the 3000 | // structure has changed significantly and it's not worth a diff. 3001 | if (xType !== yType) 3002 | { 3003 | if (xType === 1 && yType === 2) 3004 | { 3005 | y = _VirtualDom_dekey(y); 3006 | yType = 1; 3007 | } 3008 | else 3009 | { 3010 | _VirtualDom_pushPatch(patches, 0, index, y); 3011 | return; 3012 | } 3013 | } 3014 | 3015 | // Now we know that both nodes are the same $. 3016 | switch (yType) 3017 | { 3018 | case 5: 3019 | var xRefs = x.l; 3020 | var yRefs = y.l; 3021 | var i = xRefs.length; 3022 | var same = i === yRefs.length; 3023 | while (same && i--) 3024 | { 3025 | same = xRefs[i] === yRefs[i]; 3026 | } 3027 | if (same) 3028 | { 3029 | y.k = x.k; 3030 | return; 3031 | } 3032 | y.k = y.m(); 3033 | var subPatches = []; 3034 | _VirtualDom_diffHelp(x.k, y.k, subPatches, 0); 3035 | subPatches.length > 0 && _VirtualDom_pushPatch(patches, 1, index, subPatches); 3036 | return; 3037 | 3038 | case 4: 3039 | // gather nested taggers 3040 | var xTaggers = x.j; 3041 | var yTaggers = y.j; 3042 | var nesting = false; 3043 | 3044 | var xSubNode = x.k; 3045 | while (xSubNode.$ === 4) 3046 | { 3047 | nesting = true; 3048 | 3049 | typeof xTaggers !== 'object' 3050 | ? xTaggers = [xTaggers, xSubNode.j] 3051 | : xTaggers.push(xSubNode.j); 3052 | 3053 | xSubNode = xSubNode.k; 3054 | } 3055 | 3056 | var ySubNode = y.k; 3057 | while (ySubNode.$ === 4) 3058 | { 3059 | nesting = true; 3060 | 3061 | typeof yTaggers !== 'object' 3062 | ? yTaggers = [yTaggers, ySubNode.j] 3063 | : yTaggers.push(ySubNode.j); 3064 | 3065 | ySubNode = ySubNode.k; 3066 | } 3067 | 3068 | // Just bail if different numbers of taggers. This implies the 3069 | // structure of the virtual DOM has changed. 3070 | if (nesting && xTaggers.length !== yTaggers.length) 3071 | { 3072 | _VirtualDom_pushPatch(patches, 0, index, y); 3073 | return; 3074 | } 3075 | 3076 | // check if taggers are "the same" 3077 | if (nesting ? !_VirtualDom_pairwiseRefEqual(xTaggers, yTaggers) : xTaggers !== yTaggers) 3078 | { 3079 | _VirtualDom_pushPatch(patches, 2, index, yTaggers); 3080 | } 3081 | 3082 | // diff everything below the taggers 3083 | _VirtualDom_diffHelp(xSubNode, ySubNode, patches, index + 1); 3084 | return; 3085 | 3086 | case 0: 3087 | if (x.a !== y.a) 3088 | { 3089 | _VirtualDom_pushPatch(patches, 3, index, y.a); 3090 | } 3091 | return; 3092 | 3093 | case 1: 3094 | _VirtualDom_diffNodes(x, y, patches, index, _VirtualDom_diffKids); 3095 | return; 3096 | 3097 | case 2: 3098 | _VirtualDom_diffNodes(x, y, patches, index, _VirtualDom_diffKeyedKids); 3099 | return; 3100 | 3101 | case 3: 3102 | if (x.h !== y.h) 3103 | { 3104 | _VirtualDom_pushPatch(patches, 0, index, y); 3105 | return; 3106 | } 3107 | 3108 | var factsDiff = _VirtualDom_diffFacts(x.d, y.d); 3109 | factsDiff && _VirtualDom_pushPatch(patches, 4, index, factsDiff); 3110 | 3111 | var patch = y.i(x.g, y.g); 3112 | patch && _VirtualDom_pushPatch(patches, 5, index, patch); 3113 | 3114 | return; 3115 | } 3116 | } 3117 | 3118 | // assumes the incoming arrays are the same length 3119 | function _VirtualDom_pairwiseRefEqual(as, bs) 3120 | { 3121 | for (var i = 0; i < as.length; i++) 3122 | { 3123 | if (as[i] !== bs[i]) 3124 | { 3125 | return false; 3126 | } 3127 | } 3128 | 3129 | return true; 3130 | } 3131 | 3132 | function _VirtualDom_diffNodes(x, y, patches, index, diffKids) 3133 | { 3134 | // Bail if obvious indicators have changed. Implies more serious 3135 | // structural changes such that it's not worth it to diff. 3136 | if (x.c !== y.c || x.f !== y.f) 3137 | { 3138 | _VirtualDom_pushPatch(patches, 0, index, y); 3139 | return; 3140 | } 3141 | 3142 | var factsDiff = _VirtualDom_diffFacts(x.d, y.d); 3143 | factsDiff && _VirtualDom_pushPatch(patches, 4, index, factsDiff); 3144 | 3145 | diffKids(x, y, patches, index); 3146 | } 3147 | 3148 | 3149 | 3150 | // DIFF FACTS 3151 | 3152 | 3153 | // TODO Instead of creating a new diff object, it's possible to just test if 3154 | // there *is* a diff. During the actual patch, do the diff again and make the 3155 | // modifications directly. This way, there's no new allocations. Worth it? 3156 | function _VirtualDom_diffFacts(x, y, category) 3157 | { 3158 | var diff; 3159 | 3160 | // look for changes and removals 3161 | for (var xKey in x) 3162 | { 3163 | if (xKey === 'a1' || xKey === 'a0' || xKey === 'a3' || xKey === 'a4') 3164 | { 3165 | var subDiff = _VirtualDom_diffFacts(x[xKey], y[xKey] || {}, xKey); 3166 | if (subDiff) 3167 | { 3168 | diff = diff || {}; 3169 | diff[xKey] = subDiff; 3170 | } 3171 | continue; 3172 | } 3173 | 3174 | // remove if not in the new facts 3175 | if (!(xKey in y)) 3176 | { 3177 | diff = diff || {}; 3178 | diff[xKey] = 3179 | !category 3180 | ? (typeof x[xKey] === 'string' ? '' : null) 3181 | : 3182 | (category === 'a1') 3183 | ? '' 3184 | : 3185 | (category === 'a0' || category === 'a3') 3186 | ? undefined 3187 | : 3188 | { f: x[xKey].f, o: undefined }; 3189 | 3190 | continue; 3191 | } 3192 | 3193 | var xValue = x[xKey]; 3194 | var yValue = y[xKey]; 3195 | 3196 | // reference equal, so don't worry about it 3197 | if (xValue === yValue && xKey !== 'value' && xKey !== 'checked' 3198 | || category === 'a0' && _VirtualDom_equalEvents(xValue, yValue)) 3199 | { 3200 | continue; 3201 | } 3202 | 3203 | diff = diff || {}; 3204 | diff[xKey] = yValue; 3205 | } 3206 | 3207 | // add new stuff 3208 | for (var yKey in y) 3209 | { 3210 | if (!(yKey in x)) 3211 | { 3212 | diff = diff || {}; 3213 | diff[yKey] = y[yKey]; 3214 | } 3215 | } 3216 | 3217 | return diff; 3218 | } 3219 | 3220 | 3221 | 3222 | // DIFF KIDS 3223 | 3224 | 3225 | function _VirtualDom_diffKids(xParent, yParent, patches, index) 3226 | { 3227 | var xKids = xParent.e; 3228 | var yKids = yParent.e; 3229 | 3230 | var xLen = xKids.length; 3231 | var yLen = yKids.length; 3232 | 3233 | // FIGURE OUT IF THERE ARE INSERTS OR REMOVALS 3234 | 3235 | if (xLen > yLen) 3236 | { 3237 | _VirtualDom_pushPatch(patches, 6, index, { 3238 | v: yLen, 3239 | i: xLen - yLen 3240 | }); 3241 | } 3242 | else if (xLen < yLen) 3243 | { 3244 | _VirtualDom_pushPatch(patches, 7, index, { 3245 | v: xLen, 3246 | e: yKids 3247 | }); 3248 | } 3249 | 3250 | // PAIRWISE DIFF EVERYTHING ELSE 3251 | 3252 | for (var minLen = xLen < yLen ? xLen : yLen, i = 0; i < minLen; i++) 3253 | { 3254 | var xKid = xKids[i]; 3255 | _VirtualDom_diffHelp(xKid, yKids[i], patches, ++index); 3256 | index += xKid.b || 0; 3257 | } 3258 | } 3259 | 3260 | 3261 | 3262 | // KEYED DIFF 3263 | 3264 | 3265 | function _VirtualDom_diffKeyedKids(xParent, yParent, patches, rootIndex) 3266 | { 3267 | var localPatches = []; 3268 | 3269 | var changes = {}; // Dict String Entry 3270 | var inserts = []; // Array { index : Int, entry : Entry } 3271 | // type Entry = { tag : String, vnode : VNode, index : Int, data : _ } 3272 | 3273 | var xKids = xParent.e; 3274 | var yKids = yParent.e; 3275 | var xLen = xKids.length; 3276 | var yLen = yKids.length; 3277 | var xIndex = 0; 3278 | var yIndex = 0; 3279 | 3280 | var index = rootIndex; 3281 | 3282 | while (xIndex < xLen && yIndex < yLen) 3283 | { 3284 | var x = xKids[xIndex]; 3285 | var y = yKids[yIndex]; 3286 | 3287 | var xKey = x.a; 3288 | var yKey = y.a; 3289 | var xNode = x.b; 3290 | var yNode = y.b; 3291 | 3292 | // check if keys match 3293 | 3294 | if (xKey === yKey) 3295 | { 3296 | index++; 3297 | _VirtualDom_diffHelp(xNode, yNode, localPatches, index); 3298 | index += xNode.b || 0; 3299 | 3300 | xIndex++; 3301 | yIndex++; 3302 | continue; 3303 | } 3304 | 3305 | // look ahead 1 to detect insertions and removals. 3306 | 3307 | var xNext = xKids[xIndex + 1]; 3308 | var yNext = yKids[yIndex + 1]; 3309 | 3310 | if (xNext) 3311 | { 3312 | var xNextKey = xNext.a; 3313 | var xNextNode = xNext.b; 3314 | var oldMatch = yKey === xNextKey; 3315 | } 3316 | 3317 | if (yNext) 3318 | { 3319 | var yNextKey = yNext.a; 3320 | var yNextNode = yNext.b; 3321 | var newMatch = xKey === yNextKey; 3322 | } 3323 | 3324 | 3325 | // swap x and y 3326 | if (newMatch && oldMatch) 3327 | { 3328 | index++; 3329 | _VirtualDom_diffHelp(xNode, yNextNode, localPatches, index); 3330 | _VirtualDom_insertNode(changes, localPatches, xKey, yNode, yIndex, inserts); 3331 | index += xNode.b || 0; 3332 | 3333 | index++; 3334 | _VirtualDom_removeNode(changes, localPatches, xKey, xNextNode, index); 3335 | index += xNextNode.b || 0; 3336 | 3337 | xIndex += 2; 3338 | yIndex += 2; 3339 | continue; 3340 | } 3341 | 3342 | // insert y 3343 | if (newMatch) 3344 | { 3345 | index++; 3346 | _VirtualDom_insertNode(changes, localPatches, yKey, yNode, yIndex, inserts); 3347 | _VirtualDom_diffHelp(xNode, yNextNode, localPatches, index); 3348 | index += xNode.b || 0; 3349 | 3350 | xIndex += 1; 3351 | yIndex += 2; 3352 | continue; 3353 | } 3354 | 3355 | // remove x 3356 | if (oldMatch) 3357 | { 3358 | index++; 3359 | _VirtualDom_removeNode(changes, localPatches, xKey, xNode, index); 3360 | index += xNode.b || 0; 3361 | 3362 | index++; 3363 | _VirtualDom_diffHelp(xNextNode, yNode, localPatches, index); 3364 | index += xNextNode.b || 0; 3365 | 3366 | xIndex += 2; 3367 | yIndex += 1; 3368 | continue; 3369 | } 3370 | 3371 | // remove x, insert y 3372 | if (xNext && xNextKey === yNextKey) 3373 | { 3374 | index++; 3375 | _VirtualDom_removeNode(changes, localPatches, xKey, xNode, index); 3376 | _VirtualDom_insertNode(changes, localPatches, yKey, yNode, yIndex, inserts); 3377 | index += xNode.b || 0; 3378 | 3379 | index++; 3380 | _VirtualDom_diffHelp(xNextNode, yNextNode, localPatches, index); 3381 | index += xNextNode.b || 0; 3382 | 3383 | xIndex += 2; 3384 | yIndex += 2; 3385 | continue; 3386 | } 3387 | 3388 | break; 3389 | } 3390 | 3391 | // eat up any remaining nodes with removeNode and insertNode 3392 | 3393 | while (xIndex < xLen) 3394 | { 3395 | index++; 3396 | var x = xKids[xIndex]; 3397 | var xNode = x.b; 3398 | _VirtualDom_removeNode(changes, localPatches, x.a, xNode, index); 3399 | index += xNode.b || 0; 3400 | xIndex++; 3401 | } 3402 | 3403 | while (yIndex < yLen) 3404 | { 3405 | var endInserts = endInserts || []; 3406 | var y = yKids[yIndex]; 3407 | _VirtualDom_insertNode(changes, localPatches, y.a, y.b, undefined, endInserts); 3408 | yIndex++; 3409 | } 3410 | 3411 | if (localPatches.length > 0 || inserts.length > 0 || endInserts) 3412 | { 3413 | _VirtualDom_pushPatch(patches, 8, rootIndex, { 3414 | w: localPatches, 3415 | x: inserts, 3416 | y: endInserts 3417 | }); 3418 | } 3419 | } 3420 | 3421 | 3422 | 3423 | // CHANGES FROM KEYED DIFF 3424 | 3425 | 3426 | var _VirtualDom_POSTFIX = '_elmW6BL'; 3427 | 3428 | 3429 | function _VirtualDom_insertNode(changes, localPatches, key, vnode, yIndex, inserts) 3430 | { 3431 | var entry = changes[key]; 3432 | 3433 | // never seen this key before 3434 | if (!entry) 3435 | { 3436 | entry = { 3437 | c: 0, 3438 | z: vnode, 3439 | r: yIndex, 3440 | s: undefined 3441 | }; 3442 | 3443 | inserts.push({ r: yIndex, A: entry }); 3444 | changes[key] = entry; 3445 | 3446 | return; 3447 | } 3448 | 3449 | // this key was removed earlier, a match! 3450 | if (entry.c === 1) 3451 | { 3452 | inserts.push({ r: yIndex, A: entry }); 3453 | 3454 | entry.c = 2; 3455 | var subPatches = []; 3456 | _VirtualDom_diffHelp(entry.z, vnode, subPatches, entry.r); 3457 | entry.r = yIndex; 3458 | entry.s.s = { 3459 | w: subPatches, 3460 | A: entry 3461 | }; 3462 | 3463 | return; 3464 | } 3465 | 3466 | // this key has already been inserted or moved, a duplicate! 3467 | _VirtualDom_insertNode(changes, localPatches, key + _VirtualDom_POSTFIX, vnode, yIndex, inserts); 3468 | } 3469 | 3470 | 3471 | function _VirtualDom_removeNode(changes, localPatches, key, vnode, index) 3472 | { 3473 | var entry = changes[key]; 3474 | 3475 | // never seen this key before 3476 | if (!entry) 3477 | { 3478 | var patch = _VirtualDom_pushPatch(localPatches, 9, index, undefined); 3479 | 3480 | changes[key] = { 3481 | c: 1, 3482 | z: vnode, 3483 | r: index, 3484 | s: patch 3485 | }; 3486 | 3487 | return; 3488 | } 3489 | 3490 | // this key was inserted earlier, a match! 3491 | if (entry.c === 0) 3492 | { 3493 | entry.c = 2; 3494 | var subPatches = []; 3495 | _VirtualDom_diffHelp(vnode, entry.z, subPatches, index); 3496 | 3497 | _VirtualDom_pushPatch(localPatches, 9, index, { 3498 | w: subPatches, 3499 | A: entry 3500 | }); 3501 | 3502 | return; 3503 | } 3504 | 3505 | // this key has already been removed or moved, a duplicate! 3506 | _VirtualDom_removeNode(changes, localPatches, key + _VirtualDom_POSTFIX, vnode, index); 3507 | } 3508 | 3509 | 3510 | 3511 | // ADD DOM NODES 3512 | // 3513 | // Each DOM node has an "index" assigned in order of traversal. It is important 3514 | // to minimize our crawl over the actual DOM, so these indexes (along with the 3515 | // descendantsCount of virtual nodes) let us skip touching entire subtrees of 3516 | // the DOM if we know there are no patches there. 3517 | 3518 | 3519 | function _VirtualDom_addDomNodes(domNode, vNode, patches, eventNode) 3520 | { 3521 | _VirtualDom_addDomNodesHelp(domNode, vNode, patches, 0, 0, vNode.b, eventNode); 3522 | } 3523 | 3524 | 3525 | // assumes `patches` is non-empty and indexes increase monotonically. 3526 | function _VirtualDom_addDomNodesHelp(domNode, vNode, patches, i, low, high, eventNode) 3527 | { 3528 | var patch = patches[i]; 3529 | var index = patch.r; 3530 | 3531 | while (index === low) 3532 | { 3533 | var patchType = patch.$; 3534 | 3535 | if (patchType === 1) 3536 | { 3537 | _VirtualDom_addDomNodes(domNode, vNode.k, patch.s, eventNode); 3538 | } 3539 | else if (patchType === 8) 3540 | { 3541 | patch.t = domNode; 3542 | patch.u = eventNode; 3543 | 3544 | var subPatches = patch.s.w; 3545 | if (subPatches.length > 0) 3546 | { 3547 | _VirtualDom_addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); 3548 | } 3549 | } 3550 | else if (patchType === 9) 3551 | { 3552 | patch.t = domNode; 3553 | patch.u = eventNode; 3554 | 3555 | var data = patch.s; 3556 | if (data) 3557 | { 3558 | data.A.s = domNode; 3559 | var subPatches = data.w; 3560 | if (subPatches.length > 0) 3561 | { 3562 | _VirtualDom_addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode); 3563 | } 3564 | } 3565 | } 3566 | else 3567 | { 3568 | patch.t = domNode; 3569 | patch.u = eventNode; 3570 | } 3571 | 3572 | i++; 3573 | 3574 | if (!(patch = patches[i]) || (index = patch.r) > high) 3575 | { 3576 | return i; 3577 | } 3578 | } 3579 | 3580 | var tag = vNode.$; 3581 | 3582 | if (tag === 4) 3583 | { 3584 | var subNode = vNode.k; 3585 | 3586 | while (subNode.$ === 4) 3587 | { 3588 | subNode = subNode.k; 3589 | } 3590 | 3591 | return _VirtualDom_addDomNodesHelp(domNode, subNode, patches, i, low + 1, high, domNode.elm_event_node_ref); 3592 | } 3593 | 3594 | // tag must be 1 or 2 at this point 3595 | 3596 | var vKids = vNode.e; 3597 | var childNodes = domNode.childNodes; 3598 | for (var j = 0; j < vKids.length; j++) 3599 | { 3600 | low++; 3601 | var vKid = tag === 1 ? vKids[j] : vKids[j].b; 3602 | var nextLow = low + (vKid.b || 0); 3603 | if (low <= index && index <= nextLow) 3604 | { 3605 | i = _VirtualDom_addDomNodesHelp(childNodes[j], vKid, patches, i, low, nextLow, eventNode); 3606 | if (!(patch = patches[i]) || (index = patch.r) > high) 3607 | { 3608 | return i; 3609 | } 3610 | } 3611 | low = nextLow; 3612 | } 3613 | return i; 3614 | } 3615 | 3616 | 3617 | 3618 | // APPLY PATCHES 3619 | 3620 | 3621 | function _VirtualDom_applyPatches(rootDomNode, oldVirtualNode, patches, eventNode) 3622 | { 3623 | if (patches.length === 0) 3624 | { 3625 | return rootDomNode; 3626 | } 3627 | 3628 | _VirtualDom_addDomNodes(rootDomNode, oldVirtualNode, patches, eventNode); 3629 | return _VirtualDom_applyPatchesHelp(rootDomNode, patches); 3630 | } 3631 | 3632 | function _VirtualDom_applyPatchesHelp(rootDomNode, patches) 3633 | { 3634 | for (var i = 0; i < patches.length; i++) 3635 | { 3636 | var patch = patches[i]; 3637 | var localDomNode = patch.t 3638 | var newNode = _VirtualDom_applyPatch(localDomNode, patch); 3639 | if (localDomNode === rootDomNode) 3640 | { 3641 | rootDomNode = newNode; 3642 | } 3643 | } 3644 | return rootDomNode; 3645 | } 3646 | 3647 | function _VirtualDom_applyPatch(domNode, patch) 3648 | { 3649 | switch (patch.$) 3650 | { 3651 | case 0: 3652 | return _VirtualDom_applyPatchRedraw(domNode, patch.s, patch.u); 3653 | 3654 | case 4: 3655 | _VirtualDom_applyFacts(domNode, patch.u, patch.s); 3656 | return domNode; 3657 | 3658 | case 3: 3659 | domNode.replaceData(0, domNode.length, patch.s); 3660 | return domNode; 3661 | 3662 | case 1: 3663 | return _VirtualDom_applyPatchesHelp(domNode, patch.s); 3664 | 3665 | case 2: 3666 | if (domNode.elm_event_node_ref) 3667 | { 3668 | domNode.elm_event_node_ref.j = patch.s; 3669 | } 3670 | else 3671 | { 3672 | domNode.elm_event_node_ref = { j: patch.s, p: patch.u }; 3673 | } 3674 | return domNode; 3675 | 3676 | case 6: 3677 | var data = patch.s; 3678 | for (var i = 0; i < data.i; i++) 3679 | { 3680 | domNode.removeChild(domNode.childNodes[data.v]); 3681 | } 3682 | return domNode; 3683 | 3684 | case 7: 3685 | var data = patch.s; 3686 | var kids = data.e; 3687 | var i = data.v; 3688 | var theEnd = domNode.childNodes[i]; 3689 | for (; i < kids.length; i++) 3690 | { 3691 | domNode.insertBefore(_VirtualDom_render(kids[i], patch.u), theEnd); 3692 | } 3693 | return domNode; 3694 | 3695 | case 9: 3696 | var data = patch.s; 3697 | if (!data) 3698 | { 3699 | domNode.parentNode.removeChild(domNode); 3700 | return domNode; 3701 | } 3702 | var entry = data.A; 3703 | if (typeof entry.r !== 'undefined') 3704 | { 3705 | domNode.parentNode.removeChild(domNode); 3706 | } 3707 | entry.s = _VirtualDom_applyPatchesHelp(domNode, data.w); 3708 | return domNode; 3709 | 3710 | case 8: 3711 | return _VirtualDom_applyPatchReorder(domNode, patch); 3712 | 3713 | case 5: 3714 | return patch.s(domNode); 3715 | 3716 | default: 3717 | _Debug_crash(10); // 'Ran into an unknown patch!' 3718 | } 3719 | } 3720 | 3721 | 3722 | function _VirtualDom_applyPatchRedraw(domNode, vNode, eventNode) 3723 | { 3724 | var parentNode = domNode.parentNode; 3725 | var newNode = _VirtualDom_render(vNode, eventNode); 3726 | 3727 | if (!newNode.elm_event_node_ref) 3728 | { 3729 | newNode.elm_event_node_ref = domNode.elm_event_node_ref; 3730 | } 3731 | 3732 | if (parentNode && newNode !== domNode) 3733 | { 3734 | parentNode.replaceChild(newNode, domNode); 3735 | } 3736 | return newNode; 3737 | } 3738 | 3739 | 3740 | function _VirtualDom_applyPatchReorder(domNode, patch) 3741 | { 3742 | var data = patch.s; 3743 | 3744 | // remove end inserts 3745 | var frag = _VirtualDom_applyPatchReorderEndInsertsHelp(data.y, patch); 3746 | 3747 | // removals 3748 | domNode = _VirtualDom_applyPatchesHelp(domNode, data.w); 3749 | 3750 | // inserts 3751 | var inserts = data.x; 3752 | for (var i = 0; i < inserts.length; i++) 3753 | { 3754 | var insert = inserts[i]; 3755 | var entry = insert.A; 3756 | var node = entry.c === 2 3757 | ? entry.s 3758 | : _VirtualDom_render(entry.z, patch.u); 3759 | domNode.insertBefore(node, domNode.childNodes[insert.r]); 3760 | } 3761 | 3762 | // add end inserts 3763 | if (frag) 3764 | { 3765 | _VirtualDom_appendChild(domNode, frag); 3766 | } 3767 | 3768 | return domNode; 3769 | } 3770 | 3771 | 3772 | function _VirtualDom_applyPatchReorderEndInsertsHelp(endInserts, patch) 3773 | { 3774 | if (!endInserts) 3775 | { 3776 | return; 3777 | } 3778 | 3779 | var frag = _VirtualDom_doc.createDocumentFragment(); 3780 | for (var i = 0; i < endInserts.length; i++) 3781 | { 3782 | var insert = endInserts[i]; 3783 | var entry = insert.A; 3784 | _VirtualDom_appendChild(frag, entry.c === 2 3785 | ? entry.s 3786 | : _VirtualDom_render(entry.z, patch.u) 3787 | ); 3788 | } 3789 | return frag; 3790 | } 3791 | 3792 | 3793 | function _VirtualDom_virtualize(node) 3794 | { 3795 | // TEXT NODES 3796 | 3797 | if (node.nodeType === 3) 3798 | { 3799 | return _VirtualDom_text(node.textContent); 3800 | } 3801 | 3802 | 3803 | // WEIRD NODES 3804 | 3805 | if (node.nodeType !== 1) 3806 | { 3807 | return _VirtualDom_text(''); 3808 | } 3809 | 3810 | 3811 | // ELEMENT NODES 3812 | 3813 | var attrList = _List_Nil; 3814 | var attrs = node.attributes; 3815 | for (var i = attrs.length; i--; ) 3816 | { 3817 | var attr = attrs[i]; 3818 | var name = attr.name; 3819 | var value = attr.value; 3820 | attrList = _List_Cons( A2(_VirtualDom_attribute, name, value), attrList ); 3821 | } 3822 | 3823 | var tag = node.tagName.toLowerCase(); 3824 | var kidList = _List_Nil; 3825 | var kids = node.childNodes; 3826 | 3827 | for (var i = kids.length; i--; ) 3828 | { 3829 | kidList = _List_Cons(_VirtualDom_virtualize(kids[i]), kidList); 3830 | } 3831 | return A3(_VirtualDom_node, tag, attrList, kidList); 3832 | } 3833 | 3834 | function _VirtualDom_dekey(keyedNode) 3835 | { 3836 | var keyedKids = keyedNode.e; 3837 | var len = keyedKids.length; 3838 | var kids = new Array(len); 3839 | for (var i = 0; i < len; i++) 3840 | { 3841 | kids[i] = keyedKids[i].b; 3842 | } 3843 | 3844 | return { 3845 | $: 1, 3846 | c: keyedNode.c, 3847 | d: keyedNode.d, 3848 | e: kids, 3849 | f: keyedNode.f, 3850 | b: keyedNode.b 3851 | }; 3852 | } 3853 | 3854 | 3855 | 3856 | // ELEMENT 3857 | 3858 | 3859 | var _Debugger_element; 3860 | 3861 | var _Browser_element = _Debugger_element || F4(function(impl, flagDecoder, debugMetadata, args) 3862 | { 3863 | return _Platform_initialize( 3864 | flagDecoder, 3865 | args, 3866 | impl.init, 3867 | impl.update, 3868 | impl.subscriptions, 3869 | function(sendToApp, initialModel) { 3870 | var view = impl.view; 3871 | /**_UNUSED/ 3872 | var domNode = args['node']; 3873 | //*/ 3874 | /**/ 3875 | var domNode = args && args['node'] ? args['node'] : _Debug_crash(0); 3876 | //*/ 3877 | var currNode = _VirtualDom_virtualize(domNode); 3878 | 3879 | return _Browser_makeAnimator(initialModel, function(model) 3880 | { 3881 | var nextNode = view(model); 3882 | var patches = _VirtualDom_diff(currNode, nextNode); 3883 | domNode = _VirtualDom_applyPatches(domNode, currNode, patches, sendToApp); 3884 | currNode = nextNode; 3885 | }); 3886 | } 3887 | ); 3888 | }); 3889 | 3890 | 3891 | 3892 | // DOCUMENT 3893 | 3894 | 3895 | var _Debugger_document; 3896 | 3897 | var _Browser_document = _Debugger_document || F4(function(impl, flagDecoder, debugMetadata, args) 3898 | { 3899 | return _Platform_initialize( 3900 | flagDecoder, 3901 | args, 3902 | impl.init, 3903 | impl.update, 3904 | impl.subscriptions, 3905 | function(sendToApp, initialModel) { 3906 | var divertHrefToApp = impl.setup && impl.setup(sendToApp) 3907 | var view = impl.view; 3908 | var title = _VirtualDom_doc.title; 3909 | var bodyNode = _VirtualDom_doc.body; 3910 | var currNode = _VirtualDom_virtualize(bodyNode); 3911 | return _Browser_makeAnimator(initialModel, function(model) 3912 | { 3913 | _VirtualDom_divertHrefToApp = divertHrefToApp; 3914 | var doc = view(model); 3915 | var nextNode = _VirtualDom_node('body')(_List_Nil)(doc.body); 3916 | var patches = _VirtualDom_diff(currNode, nextNode); 3917 | bodyNode = _VirtualDom_applyPatches(bodyNode, currNode, patches, sendToApp); 3918 | currNode = nextNode; 3919 | _VirtualDom_divertHrefToApp = 0; 3920 | (title !== doc.title) && (_VirtualDom_doc.title = title = doc.title); 3921 | }); 3922 | } 3923 | ); 3924 | }); 3925 | 3926 | 3927 | 3928 | // ANIMATION 3929 | 3930 | 3931 | var _Browser_requestAnimationFrame = 3932 | typeof requestAnimationFrame !== 'undefined' 3933 | ? requestAnimationFrame 3934 | : function(callback) { setTimeout(callback, 1000 / 60); }; 3935 | 3936 | 3937 | function _Browser_makeAnimator(model, draw) 3938 | { 3939 | draw(model); 3940 | 3941 | var state = 0; 3942 | 3943 | function updateIfNeeded() 3944 | { 3945 | state = state === 1 3946 | ? 0 3947 | : ( _Browser_requestAnimationFrame(updateIfNeeded), draw(model), 1 ); 3948 | } 3949 | 3950 | return function(nextModel, isSync) 3951 | { 3952 | model = nextModel; 3953 | 3954 | isSync 3955 | ? ( draw(model), 3956 | state === 2 && (state = 1) 3957 | ) 3958 | : ( state === 0 && _Browser_requestAnimationFrame(updateIfNeeded), 3959 | state = 2 3960 | ); 3961 | }; 3962 | } 3963 | 3964 | 3965 | 3966 | // APPLICATION 3967 | 3968 | 3969 | function _Browser_application(impl) 3970 | { 3971 | var onUrlChange = impl.onUrlChange; 3972 | var onUrlRequest = impl.onUrlRequest; 3973 | var key = function() { key.a(onUrlChange(_Browser_getUrl())); }; 3974 | 3975 | return _Browser_document({ 3976 | setup: function(sendToApp) 3977 | { 3978 | key.a = sendToApp; 3979 | _Browser_window.addEventListener('popstate', key); 3980 | _Browser_window.navigator.userAgent.indexOf('Trident') < 0 || _Browser_window.addEventListener('hashchange', key); 3981 | 3982 | return F2(function(domNode, event) 3983 | { 3984 | if (!event.ctrlKey && !event.metaKey && !event.shiftKey && event.button < 1 && !domNode.target && !domNode.download) 3985 | { 3986 | event.preventDefault(); 3987 | var href = domNode.href; 3988 | var curr = _Browser_getUrl(); 3989 | var next = elm$url$Url$fromString(href).a; 3990 | sendToApp(onUrlRequest( 3991 | (next 3992 | && curr.protocol === next.protocol 3993 | && curr.host === next.host 3994 | && curr.port_.a === next.port_.a 3995 | ) 3996 | ? elm$browser$Browser$Internal(next) 3997 | : elm$browser$Browser$External(href) 3998 | )); 3999 | } 4000 | }); 4001 | }, 4002 | init: function(flags) 4003 | { 4004 | return A3(impl.init, flags, _Browser_getUrl(), key); 4005 | }, 4006 | view: impl.view, 4007 | update: impl.update, 4008 | subscriptions: impl.subscriptions 4009 | }); 4010 | } 4011 | 4012 | function _Browser_getUrl() 4013 | { 4014 | return elm$url$Url$fromString(_VirtualDom_doc.location.href).a || _Debug_crash(1); 4015 | } 4016 | 4017 | var _Browser_go = F2(function(key, n) 4018 | { 4019 | return A2(elm$core$Task$perform, elm$core$Basics$never, _Scheduler_binding(function() { 4020 | n && history.go(n); 4021 | key(); 4022 | })); 4023 | }); 4024 | 4025 | var _Browser_pushUrl = F2(function(key, url) 4026 | { 4027 | return A2(elm$core$Task$perform, elm$core$Basics$never, _Scheduler_binding(function() { 4028 | history.pushState({}, '', url); 4029 | key(); 4030 | })); 4031 | }); 4032 | 4033 | var _Browser_replaceUrl = F2(function(key, url) 4034 | { 4035 | return A2(elm$core$Task$perform, elm$core$Basics$never, _Scheduler_binding(function() { 4036 | history.replaceState({}, '', url); 4037 | key(); 4038 | })); 4039 | }); 4040 | 4041 | 4042 | 4043 | // GLOBAL EVENTS 4044 | 4045 | 4046 | var _Browser_fakeNode = { addEventListener: function() {}, removeEventListener: function() {} }; 4047 | var _Browser_doc = typeof document !== 'undefined' ? document : _Browser_fakeNode; 4048 | var _Browser_window = typeof window !== 'undefined' ? window : _Browser_fakeNode; 4049 | 4050 | var _Browser_on = F3(function(node, eventName, sendToSelf) 4051 | { 4052 | return _Scheduler_spawn(_Scheduler_binding(function(callback) 4053 | { 4054 | function handler(event) { _Scheduler_rawSpawn(sendToSelf(event)); } 4055 | node.addEventListener(eventName, handler, _VirtualDom_passiveSupported && { passive: true }); 4056 | return function() { node.removeEventListener(eventName, handler); }; 4057 | })); 4058 | }); 4059 | 4060 | var _Browser_decodeEvent = F2(function(decoder, event) 4061 | { 4062 | var result = _Json_runHelp(decoder, event); 4063 | return elm$core$Result$isOk(result) ? elm$core$Maybe$Just(result.a) : elm$core$Maybe$Nothing; 4064 | }); 4065 | 4066 | 4067 | 4068 | // PAGE VISIBILITY 4069 | 4070 | 4071 | function _Browser_visibilityInfo() 4072 | { 4073 | return (typeof _VirtualDom_doc.hidden !== 'undefined') 4074 | ? { hidden: 'hidden', change: 'visibilitychange' } 4075 | : 4076 | (typeof _VirtualDom_doc.mozHidden !== 'undefined') 4077 | ? { hidden: 'mozHidden', change: 'mozvisibilitychange' } 4078 | : 4079 | (typeof _VirtualDom_doc.msHidden !== 'undefined') 4080 | ? { hidden: 'msHidden', change: 'msvisibilitychange' } 4081 | : 4082 | (typeof _VirtualDom_doc.webkitHidden !== 'undefined') 4083 | ? { hidden: 'webkitHidden', change: 'webkitvisibilitychange' } 4084 | : { hidden: 'hidden', change: 'visibilitychange' }; 4085 | } 4086 | 4087 | 4088 | 4089 | // ANIMATION FRAMES 4090 | 4091 | 4092 | function _Browser_rAF() 4093 | { 4094 | return _Scheduler_binding(function(callback) 4095 | { 4096 | var id = requestAnimationFrame(function() { 4097 | callback(_Scheduler_succeed(Date.now())); 4098 | }); 4099 | 4100 | return function() { 4101 | cancelAnimationFrame(id); 4102 | }; 4103 | }); 4104 | } 4105 | 4106 | 4107 | function _Browser_now() 4108 | { 4109 | return _Scheduler_binding(function(callback) 4110 | { 4111 | callback(_Scheduler_succeed(Date.now())); 4112 | }); 4113 | } 4114 | 4115 | 4116 | 4117 | // DOM STUFF 4118 | 4119 | 4120 | function _Browser_withNode(id, doStuff) 4121 | { 4122 | return _Scheduler_binding(function(callback) 4123 | { 4124 | _Browser_requestAnimationFrame(function() { 4125 | var node = document.getElementById(id); 4126 | callback(node 4127 | ? _Scheduler_succeed(doStuff(node)) 4128 | : _Scheduler_fail(elm$browser$Browser$Dom$NotFound(id)) 4129 | ); 4130 | }); 4131 | }); 4132 | } 4133 | 4134 | 4135 | function _Browser_withWindow(doStuff) 4136 | { 4137 | return _Scheduler_binding(function(callback) 4138 | { 4139 | _Browser_requestAnimationFrame(function() { 4140 | callback(_Scheduler_succeed(doStuff())); 4141 | }); 4142 | }); 4143 | } 4144 | 4145 | 4146 | // FOCUS and BLUR 4147 | 4148 | 4149 | var _Browser_call = F2(function(functionName, id) 4150 | { 4151 | return _Browser_withNode(id, function(node) { 4152 | node[functionName](); 4153 | return _Utils_Tuple0; 4154 | }); 4155 | }); 4156 | 4157 | 4158 | 4159 | // WINDOW VIEWPORT 4160 | 4161 | 4162 | function _Browser_getViewport() 4163 | { 4164 | return { 4165 | scene: _Browser_getScene(), 4166 | viewport: { 4167 | x: _Browser_window.pageXOffset, 4168 | y: _Browser_window.pageYOffset, 4169 | width: _Browser_doc.documentElement.clientWidth, 4170 | height: _Browser_doc.documentElement.clientHeight 4171 | } 4172 | }; 4173 | } 4174 | 4175 | function _Browser_getScene() 4176 | { 4177 | var body = _Browser_doc.body; 4178 | var elem = _Browser_doc.documentElement; 4179 | return { 4180 | width: Math.max(body.scrollWidth, body.offsetWidth, elem.scrollWidth, elem.offsetWidth, elem.clientWidth), 4181 | height: Math.max(body.scrollHeight, body.offsetHeight, elem.scrollHeight, elem.offsetHeight, elem.clientHeight) 4182 | }; 4183 | } 4184 | 4185 | var _Browser_setViewport = F2(function(x, y) 4186 | { 4187 | return _Browser_withWindow(function() 4188 | { 4189 | _Browser_window.scroll(x, y); 4190 | return _Utils_Tuple0; 4191 | }); 4192 | }); 4193 | 4194 | 4195 | 4196 | // ELEMENT VIEWPORT 4197 | 4198 | 4199 | function _Browser_getViewportOf(id) 4200 | { 4201 | return _Browser_withNode(id, function(node) 4202 | { 4203 | return { 4204 | scene: { 4205 | width: node.scrollWidth, 4206 | height: node.scrollHeight 4207 | }, 4208 | viewport: { 4209 | x: node.scrollLeft, 4210 | y: node.scrollTop, 4211 | width: node.clientWidth, 4212 | height: node.clientHeight 4213 | } 4214 | }; 4215 | }); 4216 | } 4217 | 4218 | 4219 | var _Browser_setViewportOf = F3(function(id, x, y) 4220 | { 4221 | return _Browser_withNode(id, function(node) 4222 | { 4223 | node.scrollLeft = x; 4224 | node.scrollTop = y; 4225 | return _Utils_Tuple0; 4226 | }); 4227 | }); 4228 | 4229 | 4230 | 4231 | // ELEMENT 4232 | 4233 | 4234 | function _Browser_getElement(id) 4235 | { 4236 | return _Browser_withNode(id, function(node) 4237 | { 4238 | var rect = node.getBoundingClientRect(); 4239 | var x = _Browser_window.pageXOffset; 4240 | var y = _Browser_window.pageYOffset; 4241 | return { 4242 | scene: _Browser_getScene(), 4243 | viewport: { 4244 | x: x, 4245 | y: y, 4246 | width: _Browser_doc.documentElement.clientWidth, 4247 | height: _Browser_doc.documentElement.clientHeight 4248 | }, 4249 | element: { 4250 | x: x + rect.left, 4251 | y: y + rect.top, 4252 | width: rect.width, 4253 | height: rect.height 4254 | } 4255 | }; 4256 | }); 4257 | } 4258 | 4259 | 4260 | 4261 | // LOAD and RELOAD 4262 | 4263 | 4264 | function _Browser_reload(skipCache) 4265 | { 4266 | return A2(elm$core$Task$perform, elm$core$Basics$never, _Scheduler_binding(function(callback) 4267 | { 4268 | _VirtualDom_doc.location.reload(skipCache); 4269 | })); 4270 | } 4271 | 4272 | function _Browser_load(url) 4273 | { 4274 | return A2(elm$core$Task$perform, elm$core$Basics$never, _Scheduler_binding(function(callback) 4275 | { 4276 | try 4277 | { 4278 | _Browser_window.location = url; 4279 | } 4280 | catch(err) 4281 | { 4282 | // Only Firefox can throw a NS_ERROR_MALFORMED_URI exception here. 4283 | // Other browsers reload the page, so let's be consistent about that. 4284 | _VirtualDom_doc.location.reload(false); 4285 | } 4286 | })); 4287 | } 4288 | var author$project$Configs$lightGray = 'rgb(238, 238, 238)'; 4289 | var author$project$Configs$white = 'rgb(255, 255, 255)'; 4290 | var author$project$ContextMenu$Arrow = {$: 'Arrow'}; 4291 | var author$project$ContextMenu$Mirror = {$: 'Mirror'}; 4292 | var author$project$ContextMenu$RightBottom = {$: 'RightBottom'}; 4293 | var author$project$ContextMenu$Shift = {$: 'Shift'}; 4294 | var author$project$ContextMenu$Pointer = {$: 'Pointer'}; 4295 | var elm$core$Basics$False = {$: 'False'}; 4296 | var author$project$ContextMenu$defaultConfig = {containerColor: 'white', cursor: author$project$ContextMenu$Pointer, direction: author$project$ContextMenu$RightBottom, fontFamily: 'initial', hoverColor: 'rgb(240 240 240)', invertText: false, overflowX: author$project$ContextMenu$Mirror, overflowY: author$project$ContextMenu$Mirror, rounded: false, width: 300}; 4297 | var author$project$Configs$winChrome = _Utils_update( 4298 | author$project$ContextMenu$defaultConfig, 4299 | {containerColor: author$project$Configs$white, cursor: author$project$ContextMenu$Arrow, direction: author$project$ContextMenu$RightBottom, hoverColor: author$project$Configs$lightGray, invertText: false, overflowX: author$project$ContextMenu$Shift, overflowY: author$project$ContextMenu$Mirror, rounded: false}); 4300 | var author$project$ContextMenu$ContextMenu = function (a) { 4301 | return {$: 'ContextMenu', a: a}; 4302 | }; 4303 | var elm$core$Basics$identity = function (x) { 4304 | return x; 4305 | }; 4306 | var elm$core$Maybe$Nothing = {$: 'Nothing'}; 4307 | var elm$core$Basics$True = {$: 'True'}; 4308 | var elm$core$Result$isOk = function (result) { 4309 | if (result.$ === 'Ok') { 4310 | return true; 4311 | } else { 4312 | return false; 4313 | } 4314 | }; 4315 | var elm$core$Basics$EQ = {$: 'EQ'}; 4316 | var elm$core$Basics$GT = {$: 'GT'}; 4317 | var elm$core$Basics$LT = {$: 'LT'}; 4318 | var elm$core$Dict$foldr = F3( 4319 | function (func, acc, t) { 4320 | foldr: 4321 | while (true) { 4322 | if (t.$ === 'RBEmpty_elm_builtin') { 4323 | return acc; 4324 | } else { 4325 | var key = t.b; 4326 | var value = t.c; 4327 | var left = t.d; 4328 | var right = t.e; 4329 | var $temp$func = func, 4330 | $temp$acc = A3( 4331 | func, 4332 | key, 4333 | value, 4334 | A3(elm$core$Dict$foldr, func, acc, right)), 4335 | $temp$t = left; 4336 | func = $temp$func; 4337 | acc = $temp$acc; 4338 | t = $temp$t; 4339 | continue foldr; 4340 | } 4341 | } 4342 | }); 4343 | var elm$core$List$cons = _List_cons; 4344 | var elm$core$Dict$toList = function (dict) { 4345 | return A3( 4346 | elm$core$Dict$foldr, 4347 | F3( 4348 | function (key, value, list) { 4349 | return A2( 4350 | elm$core$List$cons, 4351 | _Utils_Tuple2(key, value), 4352 | list); 4353 | }), 4354 | _List_Nil, 4355 | dict); 4356 | }; 4357 | var elm$core$Dict$keys = function (dict) { 4358 | return A3( 4359 | elm$core$Dict$foldr, 4360 | F3( 4361 | function (key, value, keyList) { 4362 | return A2(elm$core$List$cons, key, keyList); 4363 | }), 4364 | _List_Nil, 4365 | dict); 4366 | }; 4367 | var elm$core$Set$toList = function (_n0) { 4368 | var dict = _n0.a; 4369 | return elm$core$Dict$keys(dict); 4370 | }; 4371 | var elm$core$Elm$JsArray$foldr = _JsArray_foldr; 4372 | var elm$core$Array$foldr = F3( 4373 | function (func, baseCase, _n0) { 4374 | var tree = _n0.c; 4375 | var tail = _n0.d; 4376 | var helper = F2( 4377 | function (node, acc) { 4378 | if (node.$ === 'SubTree') { 4379 | var subTree = node.a; 4380 | return A3(elm$core$Elm$JsArray$foldr, helper, acc, subTree); 4381 | } else { 4382 | var values = node.a; 4383 | return A3(elm$core$Elm$JsArray$foldr, func, acc, values); 4384 | } 4385 | }); 4386 | return A3( 4387 | elm$core$Elm$JsArray$foldr, 4388 | helper, 4389 | A3(elm$core$Elm$JsArray$foldr, func, baseCase, tail), 4390 | tree); 4391 | }); 4392 | var elm$core$Array$toList = function (array) { 4393 | return A3(elm$core$Array$foldr, elm$core$List$cons, _List_Nil, array); 4394 | }; 4395 | var elm$core$Array$branchFactor = 32; 4396 | var elm$core$Array$Array_elm_builtin = F4( 4397 | function (a, b, c, d) { 4398 | return {$: 'Array_elm_builtin', a: a, b: b, c: c, d: d}; 4399 | }); 4400 | var elm$core$Basics$ceiling = _Basics_ceiling; 4401 | var elm$core$Basics$fdiv = _Basics_fdiv; 4402 | var elm$core$Basics$logBase = F2( 4403 | function (base, number) { 4404 | return _Basics_log(number) / _Basics_log(base); 4405 | }); 4406 | var elm$core$Basics$toFloat = _Basics_toFloat; 4407 | var elm$core$Array$shiftStep = elm$core$Basics$ceiling( 4408 | A2(elm$core$Basics$logBase, 2, elm$core$Array$branchFactor)); 4409 | var elm$core$Elm$JsArray$empty = _JsArray_empty; 4410 | var elm$core$Array$empty = A4(elm$core$Array$Array_elm_builtin, 0, elm$core$Array$shiftStep, elm$core$Elm$JsArray$empty, elm$core$Elm$JsArray$empty); 4411 | var elm$core$Array$Leaf = function (a) { 4412 | return {$: 'Leaf', a: a}; 4413 | }; 4414 | var elm$core$Array$SubTree = function (a) { 4415 | return {$: 'SubTree', a: a}; 4416 | }; 4417 | var elm$core$Elm$JsArray$initializeFromList = _JsArray_initializeFromList; 4418 | var elm$core$List$foldl = F3( 4419 | function (func, acc, list) { 4420 | foldl: 4421 | while (true) { 4422 | if (!list.b) { 4423 | return acc; 4424 | } else { 4425 | var x = list.a; 4426 | var xs = list.b; 4427 | var $temp$func = func, 4428 | $temp$acc = A2(func, x, acc), 4429 | $temp$list = xs; 4430 | func = $temp$func; 4431 | acc = $temp$acc; 4432 | list = $temp$list; 4433 | continue foldl; 4434 | } 4435 | } 4436 | }); 4437 | var elm$core$List$reverse = function (list) { 4438 | return A3(elm$core$List$foldl, elm$core$List$cons, _List_Nil, list); 4439 | }; 4440 | var elm$core$Array$compressNodes = F2( 4441 | function (nodes, acc) { 4442 | compressNodes: 4443 | while (true) { 4444 | var _n0 = A2(elm$core$Elm$JsArray$initializeFromList, elm$core$Array$branchFactor, nodes); 4445 | var node = _n0.a; 4446 | var remainingNodes = _n0.b; 4447 | var newAcc = A2( 4448 | elm$core$List$cons, 4449 | elm$core$Array$SubTree(node), 4450 | acc); 4451 | if (!remainingNodes.b) { 4452 | return elm$core$List$reverse(newAcc); 4453 | } else { 4454 | var $temp$nodes = remainingNodes, 4455 | $temp$acc = newAcc; 4456 | nodes = $temp$nodes; 4457 | acc = $temp$acc; 4458 | continue compressNodes; 4459 | } 4460 | } 4461 | }); 4462 | var elm$core$Basics$apR = F2( 4463 | function (x, f) { 4464 | return f(x); 4465 | }); 4466 | var elm$core$Basics$eq = _Utils_equal; 4467 | var elm$core$Tuple$first = function (_n0) { 4468 | var x = _n0.a; 4469 | return x; 4470 | }; 4471 | var elm$core$Array$treeFromBuilder = F2( 4472 | function (nodeList, nodeListSize) { 4473 | treeFromBuilder: 4474 | while (true) { 4475 | var newNodeSize = elm$core$Basics$ceiling(nodeListSize / elm$core$Array$branchFactor); 4476 | if (newNodeSize === 1) { 4477 | return A2(elm$core$Elm$JsArray$initializeFromList, elm$core$Array$branchFactor, nodeList).a; 4478 | } else { 4479 | var $temp$nodeList = A2(elm$core$Array$compressNodes, nodeList, _List_Nil), 4480 | $temp$nodeListSize = newNodeSize; 4481 | nodeList = $temp$nodeList; 4482 | nodeListSize = $temp$nodeListSize; 4483 | continue treeFromBuilder; 4484 | } 4485 | } 4486 | }); 4487 | var elm$core$Basics$add = _Basics_add; 4488 | var elm$core$Basics$apL = F2( 4489 | function (f, x) { 4490 | return f(x); 4491 | }); 4492 | var elm$core$Basics$floor = _Basics_floor; 4493 | var elm$core$Basics$gt = _Utils_gt; 4494 | var elm$core$Basics$max = F2( 4495 | function (x, y) { 4496 | return (_Utils_cmp(x, y) > 0) ? x : y; 4497 | }); 4498 | var elm$core$Basics$mul = _Basics_mul; 4499 | var elm$core$Basics$sub = _Basics_sub; 4500 | var elm$core$Elm$JsArray$length = _JsArray_length; 4501 | var elm$core$Array$builderToArray = F2( 4502 | function (reverseNodeList, builder) { 4503 | if (!builder.nodeListSize) { 4504 | return A4( 4505 | elm$core$Array$Array_elm_builtin, 4506 | elm$core$Elm$JsArray$length(builder.tail), 4507 | elm$core$Array$shiftStep, 4508 | elm$core$Elm$JsArray$empty, 4509 | builder.tail); 4510 | } else { 4511 | var treeLen = builder.nodeListSize * elm$core$Array$branchFactor; 4512 | var depth = elm$core$Basics$floor( 4513 | A2(elm$core$Basics$logBase, elm$core$Array$branchFactor, treeLen - 1)); 4514 | var correctNodeList = reverseNodeList ? elm$core$List$reverse(builder.nodeList) : builder.nodeList; 4515 | var tree = A2(elm$core$Array$treeFromBuilder, correctNodeList, builder.nodeListSize); 4516 | return A4( 4517 | elm$core$Array$Array_elm_builtin, 4518 | elm$core$Elm$JsArray$length(builder.tail) + treeLen, 4519 | A2(elm$core$Basics$max, 5, depth * elm$core$Array$shiftStep), 4520 | tree, 4521 | builder.tail); 4522 | } 4523 | }); 4524 | var elm$core$Basics$idiv = _Basics_idiv; 4525 | var elm$core$Basics$lt = _Utils_lt; 4526 | var elm$core$Elm$JsArray$initialize = _JsArray_initialize; 4527 | var elm$core$Array$initializeHelp = F5( 4528 | function (fn, fromIndex, len, nodeList, tail) { 4529 | initializeHelp: 4530 | while (true) { 4531 | if (fromIndex < 0) { 4532 | return A2( 4533 | elm$core$Array$builderToArray, 4534 | false, 4535 | {nodeList: nodeList, nodeListSize: (len / elm$core$Array$branchFactor) | 0, tail: tail}); 4536 | } else { 4537 | var leaf = elm$core$Array$Leaf( 4538 | A3(elm$core$Elm$JsArray$initialize, elm$core$Array$branchFactor, fromIndex, fn)); 4539 | var $temp$fn = fn, 4540 | $temp$fromIndex = fromIndex - elm$core$Array$branchFactor, 4541 | $temp$len = len, 4542 | $temp$nodeList = A2(elm$core$List$cons, leaf, nodeList), 4543 | $temp$tail = tail; 4544 | fn = $temp$fn; 4545 | fromIndex = $temp$fromIndex; 4546 | len = $temp$len; 4547 | nodeList = $temp$nodeList; 4548 | tail = $temp$tail; 4549 | continue initializeHelp; 4550 | } 4551 | } 4552 | }); 4553 | var elm$core$Basics$le = _Utils_le; 4554 | var elm$core$Basics$remainderBy = _Basics_remainderBy; 4555 | var elm$core$Array$initialize = F2( 4556 | function (len, fn) { 4557 | if (len <= 0) { 4558 | return elm$core$Array$empty; 4559 | } else { 4560 | var tailLen = len % elm$core$Array$branchFactor; 4561 | var tail = A3(elm$core$Elm$JsArray$initialize, tailLen, len - tailLen, fn); 4562 | var initialFromIndex = (len - tailLen) - elm$core$Array$branchFactor; 4563 | return A5(elm$core$Array$initializeHelp, fn, initialFromIndex, len, _List_Nil, tail); 4564 | } 4565 | }); 4566 | var elm$core$Maybe$Just = function (a) { 4567 | return {$: 'Just', a: a}; 4568 | }; 4569 | var elm$core$Result$Err = function (a) { 4570 | return {$: 'Err', a: a}; 4571 | }; 4572 | var elm$core$Result$Ok = function (a) { 4573 | return {$: 'Ok', a: a}; 4574 | }; 4575 | var elm$json$Json$Decode$Failure = F2( 4576 | function (a, b) { 4577 | return {$: 'Failure', a: a, b: b}; 4578 | }); 4579 | var elm$json$Json$Decode$Field = F2( 4580 | function (a, b) { 4581 | return {$: 'Field', a: a, b: b}; 4582 | }); 4583 | var elm$json$Json$Decode$Index = F2( 4584 | function (a, b) { 4585 | return {$: 'Index', a: a, b: b}; 4586 | }); 4587 | var elm$json$Json$Decode$OneOf = function (a) { 4588 | return {$: 'OneOf', a: a}; 4589 | }; 4590 | var elm$core$Basics$and = _Basics_and; 4591 | var elm$core$Basics$append = _Utils_append; 4592 | var elm$core$Basics$or = _Basics_or; 4593 | var elm$core$Char$toCode = _Char_toCode; 4594 | var elm$core$Char$isLower = function (_char) { 4595 | var code = elm$core$Char$toCode(_char); 4596 | return (97 <= code) && (code <= 122); 4597 | }; 4598 | var elm$core$Char$isUpper = function (_char) { 4599 | var code = elm$core$Char$toCode(_char); 4600 | return (code <= 90) && (65 <= code); 4601 | }; 4602 | var elm$core$Char$isAlpha = function (_char) { 4603 | return elm$core$Char$isLower(_char) || elm$core$Char$isUpper(_char); 4604 | }; 4605 | var elm$core$Char$isDigit = function (_char) { 4606 | var code = elm$core$Char$toCode(_char); 4607 | return (code <= 57) && (48 <= code); 4608 | }; 4609 | var elm$core$Char$isAlphaNum = function (_char) { 4610 | return elm$core$Char$isLower(_char) || (elm$core$Char$isUpper(_char) || elm$core$Char$isDigit(_char)); 4611 | }; 4612 | var elm$core$List$length = function (xs) { 4613 | return A3( 4614 | elm$core$List$foldl, 4615 | F2( 4616 | function (_n0, i) { 4617 | return i + 1; 4618 | }), 4619 | 0, 4620 | xs); 4621 | }; 4622 | var elm$core$List$map2 = _List_map2; 4623 | var elm$core$List$rangeHelp = F3( 4624 | function (lo, hi, list) { 4625 | rangeHelp: 4626 | while (true) { 4627 | if (_Utils_cmp(lo, hi) < 1) { 4628 | var $temp$lo = lo, 4629 | $temp$hi = hi - 1, 4630 | $temp$list = A2(elm$core$List$cons, hi, list); 4631 | lo = $temp$lo; 4632 | hi = $temp$hi; 4633 | list = $temp$list; 4634 | continue rangeHelp; 4635 | } else { 4636 | return list; 4637 | } 4638 | } 4639 | }); 4640 | var elm$core$List$range = F2( 4641 | function (lo, hi) { 4642 | return A3(elm$core$List$rangeHelp, lo, hi, _List_Nil); 4643 | }); 4644 | var elm$core$List$indexedMap = F2( 4645 | function (f, xs) { 4646 | return A3( 4647 | elm$core$List$map2, 4648 | f, 4649 | A2( 4650 | elm$core$List$range, 4651 | 0, 4652 | elm$core$List$length(xs) - 1), 4653 | xs); 4654 | }); 4655 | var elm$core$String$all = _String_all; 4656 | var elm$core$String$fromInt = _String_fromNumber; 4657 | var elm$core$String$join = F2( 4658 | function (sep, chunks) { 4659 | return A2( 4660 | _String_join, 4661 | sep, 4662 | _List_toArray(chunks)); 4663 | }); 4664 | var elm$core$String$uncons = _String_uncons; 4665 | var elm$core$String$split = F2( 4666 | function (sep, string) { 4667 | return _List_fromArray( 4668 | A2(_String_split, sep, string)); 4669 | }); 4670 | var elm$json$Json$Decode$indent = function (str) { 4671 | return A2( 4672 | elm$core$String$join, 4673 | '\n ', 4674 | A2(elm$core$String$split, '\n', str)); 4675 | }; 4676 | var elm$json$Json$Encode$encode = _Json_encode; 4677 | var elm$json$Json$Decode$errorOneOf = F2( 4678 | function (i, error) { 4679 | return '\n\n(' + (elm$core$String$fromInt(i + 1) + (') ' + elm$json$Json$Decode$indent( 4680 | elm$json$Json$Decode$errorToString(error)))); 4681 | }); 4682 | var elm$json$Json$Decode$errorToString = function (error) { 4683 | return A2(elm$json$Json$Decode$errorToStringHelp, error, _List_Nil); 4684 | }; 4685 | var elm$json$Json$Decode$errorToStringHelp = F2( 4686 | function (error, context) { 4687 | errorToStringHelp: 4688 | while (true) { 4689 | switch (error.$) { 4690 | case 'Field': 4691 | var f = error.a; 4692 | var err = error.b; 4693 | var isSimple = function () { 4694 | var _n1 = elm$core$String$uncons(f); 4695 | if (_n1.$ === 'Nothing') { 4696 | return false; 4697 | } else { 4698 | var _n2 = _n1.a; 4699 | var _char = _n2.a; 4700 | var rest = _n2.b; 4701 | return elm$core$Char$isAlpha(_char) && A2(elm$core$String$all, elm$core$Char$isAlphaNum, rest); 4702 | } 4703 | }(); 4704 | var fieldName = isSimple ? ('.' + f) : ('[\'' + (f + '\']')); 4705 | var $temp$error = err, 4706 | $temp$context = A2(elm$core$List$cons, fieldName, context); 4707 | error = $temp$error; 4708 | context = $temp$context; 4709 | continue errorToStringHelp; 4710 | case 'Index': 4711 | var i = error.a; 4712 | var err = error.b; 4713 | var indexName = '[' + (elm$core$String$fromInt(i) + ']'); 4714 | var $temp$error = err, 4715 | $temp$context = A2(elm$core$List$cons, indexName, context); 4716 | error = $temp$error; 4717 | context = $temp$context; 4718 | continue errorToStringHelp; 4719 | case 'OneOf': 4720 | var errors = error.a; 4721 | if (!errors.b) { 4722 | return 'Ran into a Json.Decode.oneOf with no possibilities' + function () { 4723 | if (!context.b) { 4724 | return '!'; 4725 | } else { 4726 | return ' at json' + A2( 4727 | elm$core$String$join, 4728 | '', 4729 | elm$core$List$reverse(context)); 4730 | } 4731 | }(); 4732 | } else { 4733 | if (!errors.b.b) { 4734 | var err = errors.a; 4735 | var $temp$error = err, 4736 | $temp$context = context; 4737 | error = $temp$error; 4738 | context = $temp$context; 4739 | continue errorToStringHelp; 4740 | } else { 4741 | var starter = function () { 4742 | if (!context.b) { 4743 | return 'Json.Decode.oneOf'; 4744 | } else { 4745 | return 'The Json.Decode.oneOf at json' + A2( 4746 | elm$core$String$join, 4747 | '', 4748 | elm$core$List$reverse(context)); 4749 | } 4750 | }(); 4751 | var introduction = starter + (' failed in the following ' + (elm$core$String$fromInt( 4752 | elm$core$List$length(errors)) + ' ways:')); 4753 | return A2( 4754 | elm$core$String$join, 4755 | '\n\n', 4756 | A2( 4757 | elm$core$List$cons, 4758 | introduction, 4759 | A2(elm$core$List$indexedMap, elm$json$Json$Decode$errorOneOf, errors))); 4760 | } 4761 | } 4762 | default: 4763 | var msg = error.a; 4764 | var json = error.b; 4765 | var introduction = function () { 4766 | if (!context.b) { 4767 | return 'Problem with the given value:\n\n'; 4768 | } else { 4769 | return 'Problem with the value at json' + (A2( 4770 | elm$core$String$join, 4771 | '', 4772 | elm$core$List$reverse(context)) + ':\n\n '); 4773 | } 4774 | }(); 4775 | return introduction + (elm$json$Json$Decode$indent( 4776 | A2(elm$json$Json$Encode$encode, 4, json)) + ('\n\n' + msg)); 4777 | } 4778 | } 4779 | }); 4780 | var elm$core$Platform$Cmd$batch = _Platform_batch; 4781 | var elm$core$Platform$Cmd$none = elm$core$Platform$Cmd$batch(_List_Nil); 4782 | var author$project$ContextMenu$init = _Utils_Tuple2( 4783 | author$project$ContextMenu$ContextMenu( 4784 | {closeOnDehover: false, openState: elm$core$Maybe$Nothing}), 4785 | elm$core$Platform$Cmd$none); 4786 | var author$project$Main$ContextMenuMsg = function (a) { 4787 | return {$: 'ContextMenuMsg', a: a}; 4788 | }; 4789 | var elm$core$Platform$Cmd$map = _Platform_map; 4790 | var author$project$Main$init = function (_n0) { 4791 | var _n1 = author$project$ContextMenu$init; 4792 | var contextMenu = _n1.a; 4793 | var msg = _n1.b; 4794 | return _Utils_Tuple2( 4795 | {config: author$project$Configs$winChrome, contextMenu: contextMenu, message: ''}, 4796 | A2(elm$core$Platform$Cmd$map, author$project$Main$ContextMenuMsg, msg)); 4797 | }; 4798 | var author$project$ContextMenu$Close = {$: 'Close'}; 4799 | var author$project$ContextMenu$Container = {$: 'Container'}; 4800 | var elm$core$Basics$neq = _Utils_notEqual; 4801 | var author$project$ContextMenu$shouldCloseOnClick = F2( 4802 | function (closeOnDehover, openState) { 4803 | if (openState.$ === 'Just') { 4804 | var hover = openState.a.hover; 4805 | return closeOnDehover ? false : (!_Utils_eq(hover, author$project$ContextMenu$Container)); 4806 | } else { 4807 | return true; 4808 | } 4809 | }); 4810 | var elm$browser$Browser$Events$Document = {$: 'Document'}; 4811 | var elm$browser$Browser$Events$MySub = F3( 4812 | function (a, b, c) { 4813 | return {$: 'MySub', a: a, b: b, c: c}; 4814 | }); 4815 | var elm$browser$Browser$Events$State = F2( 4816 | function (subs, pids) { 4817 | return {pids: pids, subs: subs}; 4818 | }); 4819 | var elm$core$Dict$RBEmpty_elm_builtin = {$: 'RBEmpty_elm_builtin'}; 4820 | var elm$core$Dict$empty = elm$core$Dict$RBEmpty_elm_builtin; 4821 | var elm$core$Task$succeed = _Scheduler_succeed; 4822 | var elm$browser$Browser$Events$init = elm$core$Task$succeed( 4823 | A2(elm$browser$Browser$Events$State, _List_Nil, elm$core$Dict$empty)); 4824 | var elm$browser$Browser$Events$nodeToKey = function (node) { 4825 | if (node.$ === 'Document') { 4826 | return 'd_'; 4827 | } else { 4828 | return 'w_'; 4829 | } 4830 | }; 4831 | var elm$browser$Browser$Events$addKey = function (sub) { 4832 | var node = sub.a; 4833 | var name = sub.b; 4834 | return _Utils_Tuple2( 4835 | _Utils_ap( 4836 | elm$browser$Browser$Events$nodeToKey(node), 4837 | name), 4838 | sub); 4839 | }; 4840 | var elm$browser$Browser$Events$Event = F2( 4841 | function (key, event) { 4842 | return {event: event, key: key}; 4843 | }); 4844 | var elm$core$Platform$sendToSelf = _Platform_sendToSelf; 4845 | var elm$core$Task$andThen = _Scheduler_andThen; 4846 | var elm$core$Task$map = F2( 4847 | function (func, taskA) { 4848 | return A2( 4849 | elm$core$Task$andThen, 4850 | function (a) { 4851 | return elm$core$Task$succeed( 4852 | func(a)); 4853 | }, 4854 | taskA); 4855 | }); 4856 | var elm$browser$Browser$External = function (a) { 4857 | return {$: 'External', a: a}; 4858 | }; 4859 | var elm$browser$Browser$Internal = function (a) { 4860 | return {$: 'Internal', a: a}; 4861 | }; 4862 | var elm$browser$Browser$Dom$NotFound = function (a) { 4863 | return {$: 'NotFound', a: a}; 4864 | }; 4865 | var elm$core$Basics$never = function (_n0) { 4866 | never: 4867 | while (true) { 4868 | var nvr = _n0.a; 4869 | var $temp$_n0 = nvr; 4870 | _n0 = $temp$_n0; 4871 | continue never; 4872 | } 4873 | }; 4874 | var elm$core$Task$Perform = function (a) { 4875 | return {$: 'Perform', a: a}; 4876 | }; 4877 | var elm$core$Task$init = elm$core$Task$succeed(_Utils_Tuple0); 4878 | var elm$core$List$foldrHelper = F4( 4879 | function (fn, acc, ctr, ls) { 4880 | if (!ls.b) { 4881 | return acc; 4882 | } else { 4883 | var a = ls.a; 4884 | var r1 = ls.b; 4885 | if (!r1.b) { 4886 | return A2(fn, a, acc); 4887 | } else { 4888 | var b = r1.a; 4889 | var r2 = r1.b; 4890 | if (!r2.b) { 4891 | return A2( 4892 | fn, 4893 | a, 4894 | A2(fn, b, acc)); 4895 | } else { 4896 | var c = r2.a; 4897 | var r3 = r2.b; 4898 | if (!r3.b) { 4899 | return A2( 4900 | fn, 4901 | a, 4902 | A2( 4903 | fn, 4904 | b, 4905 | A2(fn, c, acc))); 4906 | } else { 4907 | var d = r3.a; 4908 | var r4 = r3.b; 4909 | var res = (ctr > 500) ? A3( 4910 | elm$core$List$foldl, 4911 | fn, 4912 | acc, 4913 | elm$core$List$reverse(r4)) : A4(elm$core$List$foldrHelper, fn, acc, ctr + 1, r4); 4914 | return A2( 4915 | fn, 4916 | a, 4917 | A2( 4918 | fn, 4919 | b, 4920 | A2( 4921 | fn, 4922 | c, 4923 | A2(fn, d, res)))); 4924 | } 4925 | } 4926 | } 4927 | } 4928 | }); 4929 | var elm$core$List$foldr = F3( 4930 | function (fn, acc, ls) { 4931 | return A4(elm$core$List$foldrHelper, fn, acc, 0, ls); 4932 | }); 4933 | var elm$core$List$map = F2( 4934 | function (f, xs) { 4935 | return A3( 4936 | elm$core$List$foldr, 4937 | F2( 4938 | function (x, acc) { 4939 | return A2( 4940 | elm$core$List$cons, 4941 | f(x), 4942 | acc); 4943 | }), 4944 | _List_Nil, 4945 | xs); 4946 | }); 4947 | var elm$core$Task$map2 = F3( 4948 | function (func, taskA, taskB) { 4949 | return A2( 4950 | elm$core$Task$andThen, 4951 | function (a) { 4952 | return A2( 4953 | elm$core$Task$andThen, 4954 | function (b) { 4955 | return elm$core$Task$succeed( 4956 | A2(func, a, b)); 4957 | }, 4958 | taskB); 4959 | }, 4960 | taskA); 4961 | }); 4962 | var elm$core$Task$sequence = function (tasks) { 4963 | return A3( 4964 | elm$core$List$foldr, 4965 | elm$core$Task$map2(elm$core$List$cons), 4966 | elm$core$Task$succeed(_List_Nil), 4967 | tasks); 4968 | }; 4969 | var elm$core$Platform$sendToApp = _Platform_sendToApp; 4970 | var elm$core$Task$spawnCmd = F2( 4971 | function (router, _n0) { 4972 | var task = _n0.a; 4973 | return _Scheduler_spawn( 4974 | A2( 4975 | elm$core$Task$andThen, 4976 | elm$core$Platform$sendToApp(router), 4977 | task)); 4978 | }); 4979 | var elm$core$Task$onEffects = F3( 4980 | function (router, commands, state) { 4981 | return A2( 4982 | elm$core$Task$map, 4983 | function (_n0) { 4984 | return _Utils_Tuple0; 4985 | }, 4986 | elm$core$Task$sequence( 4987 | A2( 4988 | elm$core$List$map, 4989 | elm$core$Task$spawnCmd(router), 4990 | commands))); 4991 | }); 4992 | var elm$core$Task$onSelfMsg = F3( 4993 | function (_n0, _n1, _n2) { 4994 | return elm$core$Task$succeed(_Utils_Tuple0); 4995 | }); 4996 | var elm$core$Task$cmdMap = F2( 4997 | function (tagger, _n0) { 4998 | var task = _n0.a; 4999 | return elm$core$Task$Perform( 5000 | A2(elm$core$Task$map, tagger, task)); 5001 | }); 5002 | _Platform_effectManagers['Task'] = _Platform_createManager(elm$core$Task$init, elm$core$Task$onEffects, elm$core$Task$onSelfMsg, elm$core$Task$cmdMap); 5003 | var elm$core$Task$command = _Platform_leaf('Task'); 5004 | var elm$core$Task$perform = F2( 5005 | function (toMessage, task) { 5006 | return elm$core$Task$command( 5007 | elm$core$Task$Perform( 5008 | A2(elm$core$Task$map, toMessage, task))); 5009 | }); 5010 | var elm$json$Json$Decode$map = _Json_map1; 5011 | var elm$json$Json$Decode$map2 = _Json_map2; 5012 | var elm$json$Json$Decode$succeed = _Json_succeed; 5013 | var elm$virtual_dom$VirtualDom$toHandlerInt = function (handler) { 5014 | switch (handler.$) { 5015 | case 'Normal': 5016 | return 0; 5017 | case 'MayStopPropagation': 5018 | return 1; 5019 | case 'MayPreventDefault': 5020 | return 2; 5021 | default: 5022 | return 3; 5023 | } 5024 | }; 5025 | var elm$core$String$length = _String_length; 5026 | var elm$core$String$slice = _String_slice; 5027 | var elm$core$String$dropLeft = F2( 5028 | function (n, string) { 5029 | return (n < 1) ? string : A3( 5030 | elm$core$String$slice, 5031 | n, 5032 | elm$core$String$length(string), 5033 | string); 5034 | }); 5035 | var elm$core$String$startsWith = _String_startsWith; 5036 | var elm$url$Url$Http = {$: 'Http'}; 5037 | var elm$url$Url$Https = {$: 'Https'}; 5038 | var elm$core$String$indexes = _String_indexes; 5039 | var elm$core$String$isEmpty = function (string) { 5040 | return string === ''; 5041 | }; 5042 | var elm$core$String$left = F2( 5043 | function (n, string) { 5044 | return (n < 1) ? '' : A3(elm$core$String$slice, 0, n, string); 5045 | }); 5046 | var elm$core$String$contains = _String_contains; 5047 | var elm$core$String$toInt = _String_toInt; 5048 | var elm$url$Url$Url = F6( 5049 | function (protocol, host, port_, path, query, fragment) { 5050 | return {fragment: fragment, host: host, path: path, port_: port_, protocol: protocol, query: query}; 5051 | }); 5052 | var elm$url$Url$chompBeforePath = F5( 5053 | function (protocol, path, params, frag, str) { 5054 | if (elm$core$String$isEmpty(str) || A2(elm$core$String$contains, '@', str)) { 5055 | return elm$core$Maybe$Nothing; 5056 | } else { 5057 | var _n0 = A2(elm$core$String$indexes, ':', str); 5058 | if (!_n0.b) { 5059 | return elm$core$Maybe$Just( 5060 | A6(elm$url$Url$Url, protocol, str, elm$core$Maybe$Nothing, path, params, frag)); 5061 | } else { 5062 | if (!_n0.b.b) { 5063 | var i = _n0.a; 5064 | var _n1 = elm$core$String$toInt( 5065 | A2(elm$core$String$dropLeft, i + 1, str)); 5066 | if (_n1.$ === 'Nothing') { 5067 | return elm$core$Maybe$Nothing; 5068 | } else { 5069 | var port_ = _n1; 5070 | return elm$core$Maybe$Just( 5071 | A6( 5072 | elm$url$Url$Url, 5073 | protocol, 5074 | A2(elm$core$String$left, i, str), 5075 | port_, 5076 | path, 5077 | params, 5078 | frag)); 5079 | } 5080 | } else { 5081 | return elm$core$Maybe$Nothing; 5082 | } 5083 | } 5084 | } 5085 | }); 5086 | var elm$url$Url$chompBeforeQuery = F4( 5087 | function (protocol, params, frag, str) { 5088 | if (elm$core$String$isEmpty(str)) { 5089 | return elm$core$Maybe$Nothing; 5090 | } else { 5091 | var _n0 = A2(elm$core$String$indexes, '/', str); 5092 | if (!_n0.b) { 5093 | return A5(elm$url$Url$chompBeforePath, protocol, '/', params, frag, str); 5094 | } else { 5095 | var i = _n0.a; 5096 | return A5( 5097 | elm$url$Url$chompBeforePath, 5098 | protocol, 5099 | A2(elm$core$String$dropLeft, i, str), 5100 | params, 5101 | frag, 5102 | A2(elm$core$String$left, i, str)); 5103 | } 5104 | } 5105 | }); 5106 | var elm$url$Url$chompBeforeFragment = F3( 5107 | function (protocol, frag, str) { 5108 | if (elm$core$String$isEmpty(str)) { 5109 | return elm$core$Maybe$Nothing; 5110 | } else { 5111 | var _n0 = A2(elm$core$String$indexes, '?', str); 5112 | if (!_n0.b) { 5113 | return A4(elm$url$Url$chompBeforeQuery, protocol, elm$core$Maybe$Nothing, frag, str); 5114 | } else { 5115 | var i = _n0.a; 5116 | return A4( 5117 | elm$url$Url$chompBeforeQuery, 5118 | protocol, 5119 | elm$core$Maybe$Just( 5120 | A2(elm$core$String$dropLeft, i + 1, str)), 5121 | frag, 5122 | A2(elm$core$String$left, i, str)); 5123 | } 5124 | } 5125 | }); 5126 | var elm$url$Url$chompAfterProtocol = F2( 5127 | function (protocol, str) { 5128 | if (elm$core$String$isEmpty(str)) { 5129 | return elm$core$Maybe$Nothing; 5130 | } else { 5131 | var _n0 = A2(elm$core$String$indexes, '#', str); 5132 | if (!_n0.b) { 5133 | return A3(elm$url$Url$chompBeforeFragment, protocol, elm$core$Maybe$Nothing, str); 5134 | } else { 5135 | var i = _n0.a; 5136 | return A3( 5137 | elm$url$Url$chompBeforeFragment, 5138 | protocol, 5139 | elm$core$Maybe$Just( 5140 | A2(elm$core$String$dropLeft, i + 1, str)), 5141 | A2(elm$core$String$left, i, str)); 5142 | } 5143 | } 5144 | }); 5145 | var elm$url$Url$fromString = function (str) { 5146 | return A2(elm$core$String$startsWith, 'http://', str) ? A2( 5147 | elm$url$Url$chompAfterProtocol, 5148 | elm$url$Url$Http, 5149 | A2(elm$core$String$dropLeft, 7, str)) : (A2(elm$core$String$startsWith, 'https://', str) ? A2( 5150 | elm$url$Url$chompAfterProtocol, 5151 | elm$url$Url$Https, 5152 | A2(elm$core$String$dropLeft, 8, str)) : elm$core$Maybe$Nothing); 5153 | }; 5154 | var elm$browser$Browser$Events$spawn = F3( 5155 | function (router, key, _n0) { 5156 | var node = _n0.a; 5157 | var name = _n0.b; 5158 | var actualNode = function () { 5159 | if (node.$ === 'Document') { 5160 | return _Browser_doc; 5161 | } else { 5162 | return _Browser_window; 5163 | } 5164 | }(); 5165 | return A2( 5166 | elm$core$Task$map, 5167 | function (value) { 5168 | return _Utils_Tuple2(key, value); 5169 | }, 5170 | A3( 5171 | _Browser_on, 5172 | actualNode, 5173 | name, 5174 | function (event) { 5175 | return A2( 5176 | elm$core$Platform$sendToSelf, 5177 | router, 5178 | A2(elm$browser$Browser$Events$Event, key, event)); 5179 | })); 5180 | }); 5181 | var elm$core$Dict$Black = {$: 'Black'}; 5182 | var elm$core$Dict$RBNode_elm_builtin = F5( 5183 | function (a, b, c, d, e) { 5184 | return {$: 'RBNode_elm_builtin', a: a, b: b, c: c, d: d, e: e}; 5185 | }); 5186 | var elm$core$Basics$compare = _Utils_compare; 5187 | var elm$core$Dict$Red = {$: 'Red'}; 5188 | var elm$core$Dict$balance = F5( 5189 | function (color, key, value, left, right) { 5190 | if ((right.$ === 'RBNode_elm_builtin') && (right.a.$ === 'Red')) { 5191 | var _n1 = right.a; 5192 | var rK = right.b; 5193 | var rV = right.c; 5194 | var rLeft = right.d; 5195 | var rRight = right.e; 5196 | if ((left.$ === 'RBNode_elm_builtin') && (left.a.$ === 'Red')) { 5197 | var _n3 = left.a; 5198 | var lK = left.b; 5199 | var lV = left.c; 5200 | var lLeft = left.d; 5201 | var lRight = left.e; 5202 | return A5( 5203 | elm$core$Dict$RBNode_elm_builtin, 5204 | elm$core$Dict$Red, 5205 | key, 5206 | value, 5207 | A5(elm$core$Dict$RBNode_elm_builtin, elm$core$Dict$Black, lK, lV, lLeft, lRight), 5208 | A5(elm$core$Dict$RBNode_elm_builtin, elm$core$Dict$Black, rK, rV, rLeft, rRight)); 5209 | } else { 5210 | return A5( 5211 | elm$core$Dict$RBNode_elm_builtin, 5212 | color, 5213 | rK, 5214 | rV, 5215 | A5(elm$core$Dict$RBNode_elm_builtin, elm$core$Dict$Red, key, value, left, rLeft), 5216 | rRight); 5217 | } 5218 | } else { 5219 | if ((((left.$ === 'RBNode_elm_builtin') && (left.a.$ === 'Red')) && (left.d.$ === 'RBNode_elm_builtin')) && (left.d.a.$ === 'Red')) { 5220 | var _n5 = left.a; 5221 | var lK = left.b; 5222 | var lV = left.c; 5223 | var _n6 = left.d; 5224 | var _n7 = _n6.a; 5225 | var llK = _n6.b; 5226 | var llV = _n6.c; 5227 | var llLeft = _n6.d; 5228 | var llRight = _n6.e; 5229 | var lRight = left.e; 5230 | return A5( 5231 | elm$core$Dict$RBNode_elm_builtin, 5232 | elm$core$Dict$Red, 5233 | lK, 5234 | lV, 5235 | A5(elm$core$Dict$RBNode_elm_builtin, elm$core$Dict$Black, llK, llV, llLeft, llRight), 5236 | A5(elm$core$Dict$RBNode_elm_builtin, elm$core$Dict$Black, key, value, lRight, right)); 5237 | } else { 5238 | return A5(elm$core$Dict$RBNode_elm_builtin, color, key, value, left, right); 5239 | } 5240 | } 5241 | }); 5242 | var elm$core$Dict$insertHelp = F3( 5243 | function (key, value, dict) { 5244 | if (dict.$ === 'RBEmpty_elm_builtin') { 5245 | return A5(elm$core$Dict$RBNode_elm_builtin, elm$core$Dict$Red, key, value, elm$core$Dict$RBEmpty_elm_builtin, elm$core$Dict$RBEmpty_elm_builtin); 5246 | } else { 5247 | var nColor = dict.a; 5248 | var nKey = dict.b; 5249 | var nValue = dict.c; 5250 | var nLeft = dict.d; 5251 | var nRight = dict.e; 5252 | var _n1 = A2(elm$core$Basics$compare, key, nKey); 5253 | switch (_n1.$) { 5254 | case 'LT': 5255 | return A5( 5256 | elm$core$Dict$balance, 5257 | nColor, 5258 | nKey, 5259 | nValue, 5260 | A3(elm$core$Dict$insertHelp, key, value, nLeft), 5261 | nRight); 5262 | case 'EQ': 5263 | return A5(elm$core$Dict$RBNode_elm_builtin, nColor, nKey, value, nLeft, nRight); 5264 | default: 5265 | return A5( 5266 | elm$core$Dict$balance, 5267 | nColor, 5268 | nKey, 5269 | nValue, 5270 | nLeft, 5271 | A3(elm$core$Dict$insertHelp, key, value, nRight)); 5272 | } 5273 | } 5274 | }); 5275 | var elm$core$Dict$insert = F3( 5276 | function (key, value, dict) { 5277 | var _n0 = A3(elm$core$Dict$insertHelp, key, value, dict); 5278 | if ((_n0.$ === 'RBNode_elm_builtin') && (_n0.a.$ === 'Red')) { 5279 | var _n1 = _n0.a; 5280 | var k = _n0.b; 5281 | var v = _n0.c; 5282 | var l = _n0.d; 5283 | var r = _n0.e; 5284 | return A5(elm$core$Dict$RBNode_elm_builtin, elm$core$Dict$Black, k, v, l, r); 5285 | } else { 5286 | var x = _n0; 5287 | return x; 5288 | } 5289 | }); 5290 | var elm$core$Dict$fromList = function (assocs) { 5291 | return A3( 5292 | elm$core$List$foldl, 5293 | F2( 5294 | function (_n0, dict) { 5295 | var key = _n0.a; 5296 | var value = _n0.b; 5297 | return A3(elm$core$Dict$insert, key, value, dict); 5298 | }), 5299 | elm$core$Dict$empty, 5300 | assocs); 5301 | }; 5302 | var elm$core$Dict$foldl = F3( 5303 | function (func, acc, dict) { 5304 | foldl: 5305 | while (true) { 5306 | if (dict.$ === 'RBEmpty_elm_builtin') { 5307 | return acc; 5308 | } else { 5309 | var key = dict.b; 5310 | var value = dict.c; 5311 | var left = dict.d; 5312 | var right = dict.e; 5313 | var $temp$func = func, 5314 | $temp$acc = A3( 5315 | func, 5316 | key, 5317 | value, 5318 | A3(elm$core$Dict$foldl, func, acc, left)), 5319 | $temp$dict = right; 5320 | func = $temp$func; 5321 | acc = $temp$acc; 5322 | dict = $temp$dict; 5323 | continue foldl; 5324 | } 5325 | } 5326 | }); 5327 | var elm$core$Dict$merge = F6( 5328 | function (leftStep, bothStep, rightStep, leftDict, rightDict, initialResult) { 5329 | var stepState = F3( 5330 | function (rKey, rValue, _n0) { 5331 | stepState: 5332 | while (true) { 5333 | var list = _n0.a; 5334 | var result = _n0.b; 5335 | if (!list.b) { 5336 | return _Utils_Tuple2( 5337 | list, 5338 | A3(rightStep, rKey, rValue, result)); 5339 | } else { 5340 | var _n2 = list.a; 5341 | var lKey = _n2.a; 5342 | var lValue = _n2.b; 5343 | var rest = list.b; 5344 | if (_Utils_cmp(lKey, rKey) < 0) { 5345 | var $temp$rKey = rKey, 5346 | $temp$rValue = rValue, 5347 | $temp$_n0 = _Utils_Tuple2( 5348 | rest, 5349 | A3(leftStep, lKey, lValue, result)); 5350 | rKey = $temp$rKey; 5351 | rValue = $temp$rValue; 5352 | _n0 = $temp$_n0; 5353 | continue stepState; 5354 | } else { 5355 | if (_Utils_cmp(lKey, rKey) > 0) { 5356 | return _Utils_Tuple2( 5357 | list, 5358 | A3(rightStep, rKey, rValue, result)); 5359 | } else { 5360 | return _Utils_Tuple2( 5361 | rest, 5362 | A4(bothStep, lKey, lValue, rValue, result)); 5363 | } 5364 | } 5365 | } 5366 | } 5367 | }); 5368 | var _n3 = A3( 5369 | elm$core$Dict$foldl, 5370 | stepState, 5371 | _Utils_Tuple2( 5372 | elm$core$Dict$toList(leftDict), 5373 | initialResult), 5374 | rightDict); 5375 | var leftovers = _n3.a; 5376 | var intermediateResult = _n3.b; 5377 | return A3( 5378 | elm$core$List$foldl, 5379 | F2( 5380 | function (_n4, result) { 5381 | var k = _n4.a; 5382 | var v = _n4.b; 5383 | return A3(leftStep, k, v, result); 5384 | }), 5385 | intermediateResult, 5386 | leftovers); 5387 | }); 5388 | var elm$core$Dict$union = F2( 5389 | function (t1, t2) { 5390 | return A3(elm$core$Dict$foldl, elm$core$Dict$insert, t2, t1); 5391 | }); 5392 | var elm$core$Process$kill = _Scheduler_kill; 5393 | var elm$browser$Browser$Events$onEffects = F3( 5394 | function (router, subs, state) { 5395 | var stepRight = F3( 5396 | function (key, sub, _n6) { 5397 | var deads = _n6.a; 5398 | var lives = _n6.b; 5399 | var news = _n6.c; 5400 | return _Utils_Tuple3( 5401 | deads, 5402 | lives, 5403 | A2( 5404 | elm$core$List$cons, 5405 | A3(elm$browser$Browser$Events$spawn, router, key, sub), 5406 | news)); 5407 | }); 5408 | var stepLeft = F3( 5409 | function (_n4, pid, _n5) { 5410 | var deads = _n5.a; 5411 | var lives = _n5.b; 5412 | var news = _n5.c; 5413 | return _Utils_Tuple3( 5414 | A2(elm$core$List$cons, pid, deads), 5415 | lives, 5416 | news); 5417 | }); 5418 | var stepBoth = F4( 5419 | function (key, pid, _n2, _n3) { 5420 | var deads = _n3.a; 5421 | var lives = _n3.b; 5422 | var news = _n3.c; 5423 | return _Utils_Tuple3( 5424 | deads, 5425 | A3(elm$core$Dict$insert, key, pid, lives), 5426 | news); 5427 | }); 5428 | var newSubs = A2(elm$core$List$map, elm$browser$Browser$Events$addKey, subs); 5429 | var _n0 = A6( 5430 | elm$core$Dict$merge, 5431 | stepLeft, 5432 | stepBoth, 5433 | stepRight, 5434 | state.pids, 5435 | elm$core$Dict$fromList(newSubs), 5436 | _Utils_Tuple3(_List_Nil, elm$core$Dict$empty, _List_Nil)); 5437 | var deadPids = _n0.a; 5438 | var livePids = _n0.b; 5439 | var makeNewPids = _n0.c; 5440 | return A2( 5441 | elm$core$Task$andThen, 5442 | function (pids) { 5443 | return elm$core$Task$succeed( 5444 | A2( 5445 | elm$browser$Browser$Events$State, 5446 | newSubs, 5447 | A2( 5448 | elm$core$Dict$union, 5449 | livePids, 5450 | elm$core$Dict$fromList(pids)))); 5451 | }, 5452 | A2( 5453 | elm$core$Task$andThen, 5454 | function (_n1) { 5455 | return elm$core$Task$sequence(makeNewPids); 5456 | }, 5457 | elm$core$Task$sequence( 5458 | A2(elm$core$List$map, elm$core$Process$kill, deadPids)))); 5459 | }); 5460 | var elm$core$List$maybeCons = F3( 5461 | function (f, mx, xs) { 5462 | var _n0 = f(mx); 5463 | if (_n0.$ === 'Just') { 5464 | var x = _n0.a; 5465 | return A2(elm$core$List$cons, x, xs); 5466 | } else { 5467 | return xs; 5468 | } 5469 | }); 5470 | var elm$core$List$filterMap = F2( 5471 | function (f, xs) { 5472 | return A3( 5473 | elm$core$List$foldr, 5474 | elm$core$List$maybeCons(f), 5475 | _List_Nil, 5476 | xs); 5477 | }); 5478 | var elm$browser$Browser$Events$onSelfMsg = F3( 5479 | function (router, _n0, state) { 5480 | var key = _n0.key; 5481 | var event = _n0.event; 5482 | var toMessage = function (_n2) { 5483 | var subKey = _n2.a; 5484 | var _n3 = _n2.b; 5485 | var node = _n3.a; 5486 | var name = _n3.b; 5487 | var decoder = _n3.c; 5488 | return _Utils_eq(subKey, key) ? A2(_Browser_decodeEvent, decoder, event) : elm$core$Maybe$Nothing; 5489 | }; 5490 | var messages = A2(elm$core$List$filterMap, toMessage, state.subs); 5491 | return A2( 5492 | elm$core$Task$andThen, 5493 | function (_n1) { 5494 | return elm$core$Task$succeed(state); 5495 | }, 5496 | elm$core$Task$sequence( 5497 | A2( 5498 | elm$core$List$map, 5499 | elm$core$Platform$sendToApp(router), 5500 | messages))); 5501 | }); 5502 | var elm$browser$Browser$Events$subMap = F2( 5503 | function (func, _n0) { 5504 | var node = _n0.a; 5505 | var name = _n0.b; 5506 | var decoder = _n0.c; 5507 | return A3( 5508 | elm$browser$Browser$Events$MySub, 5509 | node, 5510 | name, 5511 | A2(elm$json$Json$Decode$map, func, decoder)); 5512 | }); 5513 | _Platform_effectManagers['Browser.Events'] = _Platform_createManager(elm$browser$Browser$Events$init, elm$browser$Browser$Events$onEffects, elm$browser$Browser$Events$onSelfMsg, 0, elm$browser$Browser$Events$subMap); 5514 | var elm$browser$Browser$Events$subscription = _Platform_leaf('Browser.Events'); 5515 | var elm$browser$Browser$Events$on = F3( 5516 | function (node, name, decoder) { 5517 | return elm$browser$Browser$Events$subscription( 5518 | A3(elm$browser$Browser$Events$MySub, node, name, decoder)); 5519 | }); 5520 | var elm$browser$Browser$Events$onMouseDown = A2(elm$browser$Browser$Events$on, elm$browser$Browser$Events$Document, 'mousedown'); 5521 | var elm$core$Platform$Sub$batch = _Platform_batch; 5522 | var elm$core$Platform$Sub$none = elm$core$Platform$Sub$batch(_List_Nil); 5523 | var author$project$ContextMenu$subscriptions = function (_n0) { 5524 | var model = _n0.a; 5525 | return elm$core$Platform$Sub$batch( 5526 | _List_fromArray( 5527 | [ 5528 | A2(author$project$ContextMenu$shouldCloseOnClick, model.closeOnDehover, model.openState) ? elm$browser$Browser$Events$onMouseDown( 5529 | elm$json$Json$Decode$succeed(author$project$ContextMenu$Close)) : elm$core$Platform$Sub$none 5530 | ])); 5531 | }; 5532 | var elm$core$Platform$Sub$map = _Platform_map; 5533 | var author$project$Main$subscriptions = function (model) { 5534 | return A2( 5535 | elm$core$Platform$Sub$map, 5536 | author$project$Main$ContextMenuMsg, 5537 | author$project$ContextMenu$subscriptions(model.contextMenu)); 5538 | }; 5539 | var author$project$ContextMenu$None = {$: 'None'}; 5540 | var author$project$ContextMenu$Open = F3( 5541 | function (a, b, c) { 5542 | return {$: 'Open', a: a, b: b, c: c}; 5543 | }); 5544 | var elm$core$Maybe$map = F2( 5545 | function (f, maybe) { 5546 | if (maybe.$ === 'Just') { 5547 | var value = maybe.a; 5548 | return elm$core$Maybe$Just( 5549 | f(value)); 5550 | } else { 5551 | return elm$core$Maybe$Nothing; 5552 | } 5553 | }); 5554 | var author$project$ContextMenu$setHoverState = F2( 5555 | function (hover, openState) { 5556 | return A2( 5557 | elm$core$Maybe$map, 5558 | function (_n0) { 5559 | var mouse = _n0.mouse; 5560 | var window = _n0.window; 5561 | var context = _n0.context; 5562 | return {context: context, hover: hover, mouse: mouse, window: window}; 5563 | }, 5564 | openState); 5565 | }); 5566 | var author$project$ContextMenu$enterContainer = function (openState) { 5567 | return A2(author$project$ContextMenu$setHoverState, author$project$ContextMenu$Container, openState); 5568 | }; 5569 | var author$project$ContextMenu$ItemIndex = function (a) { 5570 | return {$: 'ItemIndex', a: a}; 5571 | }; 5572 | var author$project$ContextMenu$enterItem = F2( 5573 | function (index, openState) { 5574 | return A2( 5575 | author$project$ContextMenu$setHoverState, 5576 | author$project$ContextMenu$ItemIndex(index), 5577 | openState); 5578 | }); 5579 | var author$project$ContextMenu$leaveContainer = function (openState) { 5580 | return A2(author$project$ContextMenu$setHoverState, author$project$ContextMenu$None, openState); 5581 | }; 5582 | var author$project$ContextMenu$leaveItem = function (openState) { 5583 | return A2(author$project$ContextMenu$setHoverState, author$project$ContextMenu$Container, openState); 5584 | }; 5585 | var author$project$ContextMenu$Size = F2( 5586 | function (width, height) { 5587 | return {height: height, width: width}; 5588 | }); 5589 | var elm$browser$Browser$Dom$getViewport = _Browser_withWindow(_Browser_getViewport); 5590 | var author$project$ContextMenu$windowSize = A2( 5591 | elm$core$Task$map, 5592 | function (v) { 5593 | return A2(author$project$ContextMenu$Size, v.viewport.width, v.viewport.height); 5594 | }, 5595 | elm$browser$Browser$Dom$getViewport); 5596 | var author$project$ContextMenu$update = F2( 5597 | function (msg, _n0) { 5598 | update: 5599 | while (true) { 5600 | var model = _n0.a; 5601 | switch (msg.$) { 5602 | case 'NoOp': 5603 | return _Utils_Tuple2( 5604 | author$project$ContextMenu$ContextMenu(model), 5605 | elm$core$Platform$Cmd$none); 5606 | case 'RequestOpen': 5607 | var context = msg.a; 5608 | var mouse = msg.b; 5609 | return _Utils_Tuple2( 5610 | author$project$ContextMenu$ContextMenu(model), 5611 | A2( 5612 | elm$core$Task$perform, 5613 | A2(author$project$ContextMenu$Open, context, mouse), 5614 | author$project$ContextMenu$windowSize)); 5615 | case 'Open': 5616 | var context = msg.a; 5617 | var mouse = msg.b; 5618 | var window = msg.c; 5619 | return _Utils_Tuple2( 5620 | author$project$ContextMenu$ContextMenu( 5621 | _Utils_update( 5622 | model, 5623 | { 5624 | openState: elm$core$Maybe$Just( 5625 | {context: context, hover: author$project$ContextMenu$None, mouse: mouse, window: window}) 5626 | })), 5627 | elm$core$Platform$Cmd$none); 5628 | case 'Close': 5629 | return _Utils_Tuple2( 5630 | author$project$ContextMenu$ContextMenu( 5631 | _Utils_update( 5632 | model, 5633 | {openState: elm$core$Maybe$Nothing})), 5634 | elm$core$Platform$Cmd$none); 5635 | case 'EnterItem': 5636 | var index = msg.a; 5637 | return _Utils_Tuple2( 5638 | author$project$ContextMenu$ContextMenu( 5639 | _Utils_update( 5640 | model, 5641 | { 5642 | openState: A2(author$project$ContextMenu$enterItem, index, model.openState) 5643 | })), 5644 | elm$core$Platform$Cmd$none); 5645 | case 'LeaveItem': 5646 | return _Utils_Tuple2( 5647 | author$project$ContextMenu$ContextMenu( 5648 | _Utils_update( 5649 | model, 5650 | { 5651 | openState: author$project$ContextMenu$leaveItem(model.openState) 5652 | })), 5653 | elm$core$Platform$Cmd$none); 5654 | case 'EnterContainer': 5655 | return _Utils_Tuple2( 5656 | author$project$ContextMenu$ContextMenu( 5657 | _Utils_update( 5658 | model, 5659 | { 5660 | openState: author$project$ContextMenu$enterContainer(model.openState) 5661 | })), 5662 | elm$core$Platform$Cmd$none); 5663 | default: 5664 | if (model.closeOnDehover) { 5665 | var $temp$msg = author$project$ContextMenu$Close, 5666 | $temp$_n0 = author$project$ContextMenu$ContextMenu( 5667 | _Utils_update( 5668 | model, 5669 | { 5670 | openState: author$project$ContextMenu$leaveContainer(model.openState) 5671 | })); 5672 | msg = $temp$msg; 5673 | _n0 = $temp$_n0; 5674 | continue update; 5675 | } else { 5676 | return _Utils_Tuple2( 5677 | author$project$ContextMenu$ContextMenu( 5678 | _Utils_update( 5679 | model, 5680 | { 5681 | openState: author$project$ContextMenu$leaveContainer(model.openState) 5682 | })), 5683 | elm$core$Platform$Cmd$none); 5684 | } 5685 | } 5686 | } 5687 | }); 5688 | var author$project$Main$update = F2( 5689 | function (msg, model) { 5690 | if (msg.$ === 'ContextMenuMsg') { 5691 | var msg_ = msg.a; 5692 | var _n1 = A2(author$project$ContextMenu$update, msg_, model.contextMenu); 5693 | var contextMenu = _n1.a; 5694 | var cmd = _n1.b; 5695 | return _Utils_Tuple2( 5696 | _Utils_update( 5697 | model, 5698 | {contextMenu: contextMenu}), 5699 | A2(elm$core$Platform$Cmd$map, author$project$Main$ContextMenuMsg, cmd)); 5700 | } else { 5701 | var num = msg.a; 5702 | return _Utils_Tuple2( 5703 | _Utils_update( 5704 | model, 5705 | { 5706 | message: 'Item[' + (elm$core$String$fromInt(num) + '] was clicked.') 5707 | }), 5708 | elm$core$Platform$Cmd$none); 5709 | } 5710 | }); 5711 | var author$project$ContextMenu$NoOp = {$: 'NoOp'}; 5712 | var author$project$ContextMenu$RequestOpen = F2( 5713 | function (a, b) { 5714 | return {$: 'RequestOpen', a: a, b: b}; 5715 | }); 5716 | var author$project$ContextMenu$Position = F2( 5717 | function (x, y) { 5718 | return {x: x, y: y}; 5719 | }); 5720 | var elm$json$Json$Decode$field = _Json_decodeField; 5721 | var elm$json$Json$Decode$float = _Json_decodeFloat; 5722 | var author$project$ContextMenu$position = A3( 5723 | elm$json$Json$Decode$map2, 5724 | author$project$ContextMenu$Position, 5725 | A2(elm$json$Json$Decode$field, 'clientX', elm$json$Json$Decode$float), 5726 | A2(elm$json$Json$Decode$field, 'clientY', elm$json$Json$Decode$float)); 5727 | var elm$virtual_dom$VirtualDom$Custom = function (a) { 5728 | return {$: 'Custom', a: a}; 5729 | }; 5730 | var elm$virtual_dom$VirtualDom$on = _VirtualDom_on; 5731 | var elm$html$Html$Events$custom = F2( 5732 | function (event, decoder) { 5733 | return A2( 5734 | elm$virtual_dom$VirtualDom$on, 5735 | event, 5736 | elm$virtual_dom$VirtualDom$Custom(decoder)); 5737 | }); 5738 | var elm$virtual_dom$VirtualDom$Normal = function (a) { 5739 | return {$: 'Normal', a: a}; 5740 | }; 5741 | var elm$html$Html$Events$on = F2( 5742 | function (event, decoder) { 5743 | return A2( 5744 | elm$virtual_dom$VirtualDom$on, 5745 | event, 5746 | elm$virtual_dom$VirtualDom$Normal(decoder)); 5747 | }); 5748 | var author$project$ContextMenu$openIf = F3( 5749 | function (condition, transform, context) { 5750 | return condition ? A2( 5751 | elm$html$Html$Events$custom, 5752 | 'contextmenu', 5753 | A2( 5754 | elm$json$Json$Decode$map, 5755 | function (msg) { 5756 | return {message: msg, preventDefault: true, stopPropagation: true}; 5757 | }, 5758 | A2( 5759 | elm$json$Json$Decode$map, 5760 | transform, 5761 | A2( 5762 | elm$json$Json$Decode$map, 5763 | author$project$ContextMenu$RequestOpen(context), 5764 | author$project$ContextMenu$position)))) : A2( 5765 | elm$html$Html$Events$on, 5766 | 'contextmenu', 5767 | elm$json$Json$Decode$succeed( 5768 | transform(author$project$ContextMenu$NoOp))); 5769 | }); 5770 | var author$project$ContextMenu$open = F2( 5771 | function (transform, context) { 5772 | return A3(author$project$ContextMenu$openIf, true, transform, context); 5773 | }); 5774 | var author$project$ContextMenu$EnterContainer = {$: 'EnterContainer'}; 5775 | var author$project$ContextMenu$LeaveContainer = {$: 'LeaveContainer'}; 5776 | var author$project$ContextMenu$containerBorderWidth = 1; 5777 | var author$project$ContextMenu$containerPadding = 4; 5778 | var author$project$ContextMenu$partitionMargin = 6; 5779 | var author$project$ContextMenu$partitionWidth = 1; 5780 | var elm$core$List$sum = function (numbers) { 5781 | return A3(elm$core$List$foldl, elm$core$Basics$add, 0, numbers); 5782 | }; 5783 | var author$project$ContextMenu$calculateMenuHeight = function (groups) { 5784 | var partitions = (elm$core$List$length(groups) - 1) * ((author$project$ContextMenu$partitionMargin * 2) + author$project$ContextMenu$partitionWidth); 5785 | var items = elm$core$List$sum( 5786 | A2( 5787 | elm$core$List$map, 5788 | function (items_) { 5789 | return elm$core$List$sum( 5790 | A2( 5791 | elm$core$List$map, 5792 | function (_n0) { 5793 | var item_ = _n0.a; 5794 | return item_.height; 5795 | }, 5796 | items_)); 5797 | }, 5798 | groups)); 5799 | var containerPaddings = author$project$ContextMenu$containerPadding * 2; 5800 | var containerBorders = author$project$ContextMenu$containerBorderWidth * 2; 5801 | return ((containerBorders + containerPaddings) + partitions) + items; 5802 | }; 5803 | var author$project$ContextMenu$calculateX = F5( 5804 | function (direction, overflow, windowWidth, menuWidth, x) { 5805 | return A2( 5806 | elm$core$Basics$max, 5807 | 0, 5808 | function () { 5809 | if (direction.$ === 'LeftBottom') { 5810 | return ((x - menuWidth) < 0) ? (_Utils_eq(overflow, author$project$ContextMenu$Shift) ? 0 : x) : (x - menuWidth); 5811 | } else { 5812 | return (_Utils_cmp(x + menuWidth, windowWidth) > 0) ? (_Utils_eq(overflow, author$project$ContextMenu$Shift) ? (windowWidth - menuWidth) : (x - menuWidth)) : x; 5813 | } 5814 | }()); 5815 | }); 5816 | var author$project$ContextMenu$calculateY = F4( 5817 | function (overflow, windowHeight, menuHeight, y) { 5818 | return A2( 5819 | elm$core$Basics$max, 5820 | 0, 5821 | (_Utils_cmp(y + menuHeight, windowHeight) > 0) ? (_Utils_eq(overflow, author$project$ContextMenu$Shift) ? (windowHeight - menuHeight) : (y - menuHeight)) : y); 5822 | }); 5823 | var author$project$ContextMenu$fontSize = 13; 5824 | var author$project$ContextMenu$getItemIndex = function (hover) { 5825 | if (hover.$ === 'ItemIndex') { 5826 | var index = hover.a; 5827 | return elm$core$Maybe$Just(index); 5828 | } else { 5829 | return elm$core$Maybe$Nothing; 5830 | } 5831 | }; 5832 | var author$project$ContextMenu$EnterItem = function (a) { 5833 | return {$: 'EnterItem', a: a}; 5834 | }; 5835 | var author$project$ContextMenu$LeaveItem = {$: 'LeaveItem'}; 5836 | var author$project$ContextMenu$disabledTextColor = 'rgb(200, 200, 200)'; 5837 | var author$project$ContextMenu$shortcutTextColor = 'rgb(200, 200, 200)'; 5838 | var elm$core$String$fromFloat = _String_fromNumber; 5839 | var author$project$Styles$px = function (n) { 5840 | return elm$core$String$fromFloat(n) + 'px'; 5841 | }; 5842 | var elm$core$Basics$negate = function (n) { 5843 | return -n; 5844 | }; 5845 | var elm$virtual_dom$VirtualDom$style = _VirtualDom_style; 5846 | var elm$html$Html$Attributes$style = elm$virtual_dom$VirtualDom$style; 5847 | var author$project$Styles$icon = function (size) { 5848 | return _List_fromArray( 5849 | [ 5850 | A2(elm$html$Html$Attributes$style, 'position', 'absolute'), 5851 | A2( 5852 | elm$html$Html$Attributes$style, 5853 | 'margin-left', 5854 | author$project$Styles$px((-size) - 4)), 5855 | A2(elm$html$Html$Attributes$style, 'top', '2px') 5856 | ]); 5857 | }; 5858 | var elm$core$Basics$not = _Basics_not; 5859 | var author$project$Styles$row = F8( 5860 | function (hoverColor, disabledTextColor, invertText, usePointer, lineHeight, hovered, disabled, hasShortCut) { 5861 | return _List_fromArray( 5862 | [ 5863 | A2(elm$html$Html$Attributes$style, 'position', 'relative'), 5864 | A2(elm$html$Html$Attributes$style, 'padding', '0 18px 0 28px'), 5865 | A2( 5866 | elm$html$Html$Attributes$style, 5867 | 'background-color', 5868 | hovered ? hoverColor : ''), 5869 | A2( 5870 | elm$html$Html$Attributes$style, 5871 | 'height', 5872 | author$project$Styles$px(lineHeight)), 5873 | A2( 5874 | elm$html$Html$Attributes$style, 5875 | 'color', 5876 | disabled ? disabledTextColor : ((hovered && invertText) ? '#fff' : '')), 5877 | A2( 5878 | elm$html$Html$Attributes$style, 5879 | 'cursor', 5880 | ((!disabled) && usePointer) ? 'pointer' : ''), 5881 | A2(elm$html$Html$Attributes$style, 'display', 'flex'), 5882 | A2( 5883 | elm$html$Html$Attributes$style, 5884 | 'justify-content', 5885 | hasShortCut ? 'space-between' : '') 5886 | ]); 5887 | }); 5888 | var author$project$Styles$shortcut = F3( 5889 | function (color, lineHeight, hovered) { 5890 | return _List_fromArray( 5891 | [ 5892 | A2( 5893 | elm$html$Html$Attributes$style, 5894 | 'line-height', 5895 | author$project$Styles$px(lineHeight)), 5896 | A2( 5897 | elm$html$Html$Attributes$style, 5898 | 'color', 5899 | hovered ? '' : color) 5900 | ]); 5901 | }); 5902 | var author$project$Styles$text = function (lineHeight) { 5903 | return _List_fromArray( 5904 | [ 5905 | A2( 5906 | elm$html$Html$Attributes$style, 5907 | 'line-height', 5908 | author$project$Styles$px(lineHeight)), 5909 | A2(elm$html$Html$Attributes$style, 'text-overflow', 'ellipsis'), 5910 | A2(elm$html$Html$Attributes$style, 'overflow', 'hidden'), 5911 | A2(elm$html$Html$Attributes$style, 'white-space', 'nowrap') 5912 | ]); 5913 | }; 5914 | var elm$core$String$trim = _String_trim; 5915 | var elm$html$Html$div = _VirtualDom_node('div'); 5916 | var elm$virtual_dom$VirtualDom$map = _VirtualDom_map; 5917 | var elm$html$Html$map = elm$virtual_dom$VirtualDom$map; 5918 | var elm$virtual_dom$VirtualDom$text = _VirtualDom_text; 5919 | var elm$html$Html$text = elm$virtual_dom$VirtualDom$text; 5920 | var elm$html$Html$Events$onMouseDown = function (msg) { 5921 | return A2( 5922 | elm$html$Html$Events$on, 5923 | 'mousedown', 5924 | elm$json$Json$Decode$succeed(msg)); 5925 | }; 5926 | var elm$html$Html$Events$onMouseEnter = function (msg) { 5927 | return A2( 5928 | elm$html$Html$Events$on, 5929 | 'mouseenter', 5930 | elm$json$Json$Decode$succeed(msg)); 5931 | }; 5932 | var elm$html$Html$Events$onMouseLeave = function (msg) { 5933 | return A2( 5934 | elm$html$Html$Events$on, 5935 | 'mouseleave', 5936 | elm$json$Json$Decode$succeed(msg)); 5937 | }; 5938 | var author$project$ContextMenu$itemView = F6( 5939 | function (config, transform, hoverIndex, groupIndex, index, _n0) { 5940 | var item_ = _n0.a.a; 5941 | var msg = _n0.b; 5942 | var icon_ = function () { 5943 | var _n2 = item_.icon; 5944 | if (_n2.$ === 'Just') { 5945 | var _n3 = _n2.a; 5946 | var icon__ = _n3.a; 5947 | var color = _n3.b; 5948 | return A2( 5949 | elm$html$Html$map, 5950 | elm$core$Basics$never, 5951 | A2( 5952 | elm$html$Html$div, 5953 | author$project$Styles$icon(author$project$ContextMenu$fontSize), 5954 | _List_fromArray( 5955 | [ 5956 | A2( 5957 | icon__, 5958 | item_.disabled ? author$project$ContextMenu$disabledTextColor : color, 5959 | elm$core$Basics$floor(author$project$ContextMenu$fontSize)) 5960 | ]))); 5961 | } else { 5962 | return elm$html$Html$text(''); 5963 | } 5964 | }(); 5965 | var hovered = _Utils_eq( 5966 | hoverIndex, 5967 | elm$core$Maybe$Just( 5968 | _Utils_Tuple2(groupIndex, index))); 5969 | var shortCut = A2( 5970 | elm$html$Html$div, 5971 | A3(author$project$Styles$shortcut, author$project$ContextMenu$shortcutTextColor, item_.height, hovered), 5972 | _List_fromArray( 5973 | [ 5974 | elm$html$Html$text(item_.shortcut) 5975 | ])); 5976 | var styles = A8( 5977 | author$project$Styles$row, 5978 | config.hoverColor, 5979 | author$project$ContextMenu$disabledTextColor, 5980 | config.invertText, 5981 | _Utils_eq(config.cursor, author$project$ContextMenu$Pointer), 5982 | item_.height, 5983 | hovered, 5984 | item_.disabled, 5985 | elm$core$String$trim(item_.shortcut) !== ''); 5986 | var events = item_.disabled ? _List_Nil : _List_fromArray( 5987 | [ 5988 | elm$html$Html$Events$onMouseEnter( 5989 | transform( 5990 | author$project$ContextMenu$EnterItem( 5991 | _Utils_Tuple2(groupIndex, index)))), 5992 | elm$html$Html$Events$onMouseLeave( 5993 | transform(author$project$ContextMenu$LeaveItem)), 5994 | elm$html$Html$Events$onMouseDown(msg) 5995 | ]); 5996 | var content = function () { 5997 | var _n1 = item_.content; 5998 | if (_n1.$ === 'Text') { 5999 | var s = _n1.a; 6000 | return A2( 6001 | elm$html$Html$div, 6002 | author$project$Styles$text(item_.height), 6003 | _List_fromArray( 6004 | [ 6005 | elm$html$Html$text(s) 6006 | ])); 6007 | } else { 6008 | var toHtml = _n1.a; 6009 | return toHtml(item_.disabled); 6010 | } 6011 | }(); 6012 | return A2( 6013 | elm$html$Html$div, 6014 | _Utils_ap(styles, events), 6015 | _List_fromArray( 6016 | [ 6017 | icon_, 6018 | A2(elm$html$Html$map, elm$core$Basics$never, content), 6019 | shortCut 6020 | ])); 6021 | }); 6022 | var author$project$ContextMenu$itemGroupView = F5( 6023 | function (config, transform, hoverIndex, groupIndex, items) { 6024 | return A2( 6025 | elm$core$List$indexedMap, 6026 | A4(author$project$ContextMenu$itemView, config, transform, hoverIndex, groupIndex), 6027 | items); 6028 | }); 6029 | var author$project$Styles$borderColor = '#ccc'; 6030 | var author$project$Styles$partition = F2( 6031 | function (borderWidth, margin) { 6032 | return _List_fromArray( 6033 | [ 6034 | A2(elm$html$Html$Attributes$style, 'border-bottom-style', 'solid'), 6035 | A2( 6036 | elm$html$Html$Attributes$style, 6037 | 'border-bottom-width', 6038 | author$project$Styles$px(1)), 6039 | A2(elm$html$Html$Attributes$style, 'border-bottom-color', author$project$Styles$borderColor), 6040 | A2(elm$html$Html$Attributes$style, 'border-top', 'none'), 6041 | A2( 6042 | elm$html$Html$Attributes$style, 6043 | 'margin', 6044 | author$project$Styles$px(margin) + ' 0') 6045 | ]); 6046 | }); 6047 | var elm$html$Html$hr = _VirtualDom_node('hr'); 6048 | var author$project$ContextMenu$partition = A2( 6049 | elm$html$Html$hr, 6050 | A2(author$project$Styles$partition, author$project$ContextMenu$partitionWidth, author$project$ContextMenu$partitionMargin), 6051 | _List_Nil); 6052 | var author$project$ContextMenu$joinGroupsWithPartition = function (groups) { 6053 | return A3( 6054 | elm$core$List$foldr, 6055 | F2( 6056 | function (group, prev) { 6057 | if (prev.$ === 'Just') { 6058 | var items = prev.a; 6059 | return elm$core$Maybe$Just( 6060 | _Utils_ap( 6061 | group, 6062 | A2(elm$core$List$cons, author$project$ContextMenu$partition, items))); 6063 | } else { 6064 | return elm$core$Maybe$Just(group); 6065 | } 6066 | }), 6067 | elm$core$Maybe$Nothing, 6068 | groups); 6069 | }; 6070 | var author$project$ContextMenu$menuWidthWithBorders = function (menuWidth) { 6071 | return menuWidth + (author$project$ContextMenu$containerBorderWidth * 2); 6072 | }; 6073 | var author$project$Styles$container = F9( 6074 | function (containerColor, borderWidth, padding, rounded, width, left, top, fontFamily, fontSize) { 6075 | return _List_fromArray( 6076 | [ 6077 | A2(elm$html$Html$Attributes$style, 'border-style', 'solid'), 6078 | A2( 6079 | elm$html$Html$Attributes$style, 6080 | 'border-width', 6081 | author$project$Styles$px(borderWidth)), 6082 | A2(elm$html$Html$Attributes$style, 'border-color', author$project$Styles$borderColor), 6083 | A2(elm$html$Html$Attributes$style, 'position', 'fixed'), 6084 | A2( 6085 | elm$html$Html$Attributes$style, 6086 | 'top', 6087 | author$project$Styles$px(top)), 6088 | A2( 6089 | elm$html$Html$Attributes$style, 6090 | 'left', 6091 | author$project$Styles$px(left)), 6092 | A2( 6093 | elm$html$Html$Attributes$style, 6094 | 'width', 6095 | author$project$Styles$px(width)), 6096 | A2( 6097 | elm$html$Html$Attributes$style, 6098 | 'z-index', 6099 | elm$core$String$fromFloat(2147483647 - 10)), 6100 | A2(elm$html$Html$Attributes$style, 'background-color', containerColor), 6101 | A2(elm$html$Html$Attributes$style, 'cursor', 'default'), 6102 | A2(elm$html$Html$Attributes$style, 'box-shadow', '0px 3px 8px 0px rgba(0,0,0,0.3)'), 6103 | A2( 6104 | elm$html$Html$Attributes$style, 6105 | 'padding', 6106 | author$project$Styles$px(padding) + ' 0'), 6107 | A2( 6108 | elm$html$Html$Attributes$style, 6109 | 'border-radius', 6110 | rounded ? author$project$Styles$px(padding) : ''), 6111 | A2(elm$html$Html$Attributes$style, 'font-family', fontFamily), 6112 | A2( 6113 | elm$html$Html$Attributes$style, 6114 | 'font-size', 6115 | author$project$Styles$px(fontSize)) 6116 | ]); 6117 | }); 6118 | var author$project$ContextMenu$view = F4( 6119 | function (config, transform, toItemGroups, _n0) { 6120 | var model = _n0.a; 6121 | var _n1 = model.openState; 6122 | if (_n1.$ === 'Just') { 6123 | var mouse = _n1.a.mouse; 6124 | var window = _n1.a.window; 6125 | var hover = _n1.a.hover; 6126 | var context = _n1.a.context; 6127 | var groups = toItemGroups(context); 6128 | var groupsView = A2( 6129 | elm$core$List$indexedMap, 6130 | A3( 6131 | author$project$ContextMenu$itemGroupView, 6132 | config, 6133 | transform, 6134 | author$project$ContextMenu$getItemIndex(hover)), 6135 | groups); 6136 | var itemGroups = A2( 6137 | elm$core$List$map, 6138 | elm$core$List$map(elm$core$Tuple$first), 6139 | groups); 6140 | var _n2 = author$project$ContextMenu$joinGroupsWithPartition(groupsView); 6141 | if (_n2.$ === 'Just') { 6142 | var items = _n2.a; 6143 | var y_ = A4( 6144 | author$project$ContextMenu$calculateY, 6145 | config.overflowY, 6146 | window.height, 6147 | author$project$ContextMenu$calculateMenuHeight(itemGroups), 6148 | mouse.y); 6149 | var x_ = A5( 6150 | author$project$ContextMenu$calculateX, 6151 | config.direction, 6152 | config.overflowX, 6153 | window.width, 6154 | author$project$ContextMenu$menuWidthWithBorders(config.width), 6155 | mouse.x); 6156 | return A2( 6157 | elm$html$Html$div, 6158 | _Utils_ap( 6159 | A9(author$project$Styles$container, config.containerColor, author$project$ContextMenu$containerBorderWidth, author$project$ContextMenu$containerPadding, config.rounded, config.width, x_, y_, config.fontFamily, author$project$ContextMenu$fontSize), 6160 | _List_fromArray( 6161 | [ 6162 | elm$html$Html$Events$onMouseEnter( 6163 | transform(author$project$ContextMenu$EnterContainer)), 6164 | elm$html$Html$Events$onMouseLeave( 6165 | transform(author$project$ContextMenu$LeaveContainer)) 6166 | ])), 6167 | items); 6168 | } else { 6169 | return elm$html$Html$text(''); 6170 | } 6171 | } else { 6172 | return elm$html$Html$text(''); 6173 | } 6174 | }); 6175 | var author$project$Main$Background = {$: 'Background'}; 6176 | var author$project$Main$Object = {$: 'Object'}; 6177 | var author$project$Main$backgroundStyles = _List_fromArray( 6178 | [ 6179 | A2(elm$html$Html$Attributes$style, 'left', '10%'), 6180 | A2(elm$html$Html$Attributes$style, 'right', '10%'), 6181 | A2(elm$html$Html$Attributes$style, 'top', '10%'), 6182 | A2(elm$html$Html$Attributes$style, 'bottom', '-10%'), 6183 | A2(elm$html$Html$Attributes$style, 'position', 'absolute'), 6184 | A2(elm$html$Html$Attributes$style, 'background-color', '#cdb') 6185 | ]); 6186 | var author$project$Main$objectStyles = _List_fromArray( 6187 | [ 6188 | A2(elm$html$Html$Attributes$style, 'position', 'absolute'), 6189 | A2(elm$html$Html$Attributes$style, 'top', '100px'), 6190 | A2(elm$html$Html$Attributes$style, 'left', '150px'), 6191 | A2(elm$html$Html$Attributes$style, 'width', '100px'), 6192 | A2(elm$html$Html$Attributes$style, 'height', '100px'), 6193 | A2(elm$html$Html$Attributes$style, 'background-color', '#976') 6194 | ]); 6195 | var author$project$ContextMenu$Item = function (a) { 6196 | return {$: 'Item', a: a}; 6197 | }; 6198 | var author$project$ContextMenu$disabled = F2( 6199 | function (disabled_, _n0) { 6200 | var item_ = _n0.a; 6201 | return author$project$ContextMenu$Item( 6202 | _Utils_update( 6203 | item_, 6204 | {disabled: disabled_})); 6205 | }); 6206 | var author$project$ContextMenu$Text = function (a) { 6207 | return {$: 'Text', a: a}; 6208 | }; 6209 | var author$project$ContextMenu$defaultItemHeight = 20; 6210 | var author$project$ContextMenu$item = function (s) { 6211 | return author$project$ContextMenu$Item( 6212 | { 6213 | content: author$project$ContextMenu$Text(s), 6214 | disabled: false, 6215 | height: elm$core$Basics$floor(author$project$ContextMenu$defaultItemHeight), 6216 | icon: elm$core$Maybe$Nothing, 6217 | shortcut: '' 6218 | }); 6219 | }; 6220 | var author$project$ContextMenu$annotationHeight = 12; 6221 | var author$project$ContextMenu$annotationFontSize = 10; 6222 | var author$project$ContextMenu$annotationTextColor = 'rgb(200, 200, 200)'; 6223 | var author$project$Styles$annotation = F4( 6224 | function (color, annotationHeight, fontSize, disabled) { 6225 | return _List_fromArray( 6226 | [ 6227 | A2(elm$html$Html$Attributes$style, 'margin-top', '-2px'), 6228 | A2( 6229 | elm$html$Html$Attributes$style, 6230 | 'line-height', 6231 | author$project$Styles$px(annotationHeight)), 6232 | A2( 6233 | elm$html$Html$Attributes$style, 6234 | 'font-size', 6235 | author$project$Styles$px(fontSize)), 6236 | A2(elm$html$Html$Attributes$style, 'color', color) 6237 | ]); 6238 | }); 6239 | var author$project$ContextMenu$annotationView = F3( 6240 | function (s, ann, disabled_) { 6241 | return A2( 6242 | elm$html$Html$div, 6243 | _List_Nil, 6244 | _List_fromArray( 6245 | [ 6246 | A2( 6247 | elm$html$Html$div, 6248 | author$project$Styles$text(author$project$ContextMenu$defaultItemHeight), 6249 | _List_fromArray( 6250 | [ 6251 | elm$html$Html$text(s) 6252 | ])), 6253 | A2( 6254 | elm$html$Html$div, 6255 | A4(author$project$Styles$annotation, author$project$ContextMenu$annotationTextColor, author$project$ContextMenu$annotationHeight, author$project$ContextMenu$annotationFontSize, disabled_), 6256 | _List_fromArray( 6257 | [ 6258 | elm$html$Html$text(ann) 6259 | ])) 6260 | ])); 6261 | }); 6262 | var author$project$ContextMenu$Custom = function (a) { 6263 | return {$: 'Custom', a: a}; 6264 | }; 6265 | var author$project$ContextMenu$custom = F2( 6266 | function (height, content) { 6267 | return author$project$ContextMenu$Item( 6268 | { 6269 | content: author$project$ContextMenu$Custom(content), 6270 | disabled: false, 6271 | height: A2( 6272 | elm$core$Basics$max, 6273 | elm$core$Basics$floor(author$project$ContextMenu$defaultItemHeight), 6274 | height), 6275 | icon: elm$core$Maybe$Nothing, 6276 | shortcut: '' 6277 | }); 6278 | }); 6279 | var author$project$ContextMenu$itemWithAnnotation = F2( 6280 | function (s, ann) { 6281 | return A2( 6282 | author$project$ContextMenu$custom, 6283 | elm$core$Basics$floor((author$project$ContextMenu$defaultItemHeight + author$project$ContextMenu$annotationHeight) - 2), 6284 | A2(author$project$ContextMenu$annotationView, s, ann)); 6285 | }); 6286 | var author$project$ContextMenu$shortcut = F2( 6287 | function (shortcutName, _n0) { 6288 | var item_ = _n0.a; 6289 | return author$project$ContextMenu$Item( 6290 | _Utils_update( 6291 | item_, 6292 | {shortcut: shortcutName})); 6293 | }); 6294 | var author$project$Main$Item = function (a) { 6295 | return {$: 'Item', a: a}; 6296 | }; 6297 | var author$project$Main$toItemGroups = function (context) { 6298 | if (context.$ === 'Background') { 6299 | return _List_fromArray( 6300 | [ 6301 | _List_fromArray( 6302 | [ 6303 | _Utils_Tuple2( 6304 | author$project$ContextMenu$item('Hey'), 6305 | author$project$Main$Item(1)), 6306 | _Utils_Tuple2( 6307 | author$project$ContextMenu$item('Yo!'), 6308 | author$project$Main$Item(2)) 6309 | ]), 6310 | _List_fromArray( 6311 | [ 6312 | _Utils_Tuple2( 6313 | A2( 6314 | author$project$ContextMenu$disabled, 6315 | true, 6316 | author$project$ContextMenu$item('Take photos')), 6317 | author$project$Main$Item(3)), 6318 | _Utils_Tuple2( 6319 | A2( 6320 | author$project$ContextMenu$disabled, 6321 | false, 6322 | author$project$ContextMenu$item('Have a break')), 6323 | author$project$Main$Item(4)), 6324 | _Utils_Tuple2( 6325 | author$project$ContextMenu$item('Pneumonoultramicroscopicsilicovolcanoconiosis'), 6326 | author$project$Main$Item(5)), 6327 | _Utils_Tuple2( 6328 | A2( 6329 | author$project$ContextMenu$shortcut, 6330 | 'Ctrl+S', 6331 | author$project$ContextMenu$item('Save')), 6332 | author$project$Main$Item(6)), 6333 | _Utils_Tuple2( 6334 | A2( 6335 | author$project$ContextMenu$disabled, 6336 | false, 6337 | A2(author$project$ContextMenu$itemWithAnnotation, 'Item with annotation', 'Some annotation here')), 6338 | author$project$Main$Item(7)) 6339 | ]) 6340 | ]); 6341 | } else { 6342 | return _List_fromArray( 6343 | [ 6344 | _List_fromArray( 6345 | [ 6346 | _Utils_Tuple2( 6347 | author$project$ContextMenu$item('Pen'), 6348 | author$project$Main$Item(8)), 6349 | _Utils_Tuple2( 6350 | author$project$ContextMenu$item('Pineapple'), 6351 | author$project$Main$Item(9)), 6352 | _Utils_Tuple2( 6353 | author$project$ContextMenu$item('Apple'), 6354 | author$project$Main$Item(10)) 6355 | ]) 6356 | ]); 6357 | } 6358 | }; 6359 | var author$project$Main$view = function (model) { 6360 | return A2( 6361 | elm$html$Html$div, 6362 | _List_Nil, 6363 | _List_fromArray( 6364 | [ 6365 | A2( 6366 | elm$html$Html$div, 6367 | A2( 6368 | elm$core$List$cons, 6369 | A2(author$project$ContextMenu$open, author$project$Main$ContextMenuMsg, author$project$Main$Background), 6370 | author$project$Main$backgroundStyles), 6371 | _List_fromArray( 6372 | [ 6373 | A2( 6374 | elm$html$Html$div, 6375 | A2( 6376 | elm$core$List$cons, 6377 | A2(author$project$ContextMenu$open, author$project$Main$ContextMenuMsg, author$project$Main$Object), 6378 | author$project$Main$objectStyles), 6379 | _List_Nil) 6380 | ])), 6381 | A2( 6382 | elm$html$Html$div, 6383 | _List_Nil, 6384 | _List_fromArray( 6385 | [ 6386 | elm$html$Html$text(model.message) 6387 | ])), 6388 | A4(author$project$ContextMenu$view, model.config, author$project$Main$ContextMenuMsg, author$project$Main$toItemGroups, model.contextMenu) 6389 | ])); 6390 | }; 6391 | var elm$browser$Browser$element = _Browser_element; 6392 | var author$project$Main$main = elm$browser$Browser$element( 6393 | {init: author$project$Main$init, subscriptions: author$project$Main$subscriptions, update: author$project$Main$update, view: author$project$Main$view}); 6394 | _Platform_export({'Main':{'init':author$project$Main$main( 6395 | elm$json$Json$Decode$succeed(_Utils_Tuple0))(0)}});}(this)); --------------------------------------------------------------------------------