Hello,
I have a board game made in SVG. Each pieces is an SVG element.
I would like to do actions on the pieces using mouse and keyboard.
For now, I have:
data Action = Initialize
| Select (Maybe Piece)
| Rotate Piece
| Move Piece Dir
| ...
data Dir = N | E | S | W
Piece = ...
-- Get the tile with position, events and highlight
getTile :: forall w. Piece -> HTML w Action
getTile piece =
g [
onClick \_ -> Select $ Just piece, -- left click to select the piece
onContextMenu \_ -> Rotate piece, -- right click to rotate the piece
onKeyDown $ onKeyDown piece, -- arrow keys to move the piece, "r" to rotate
tabIndex 0 -- allows to tab through elements and receive keyboard inputs
]
[
SE.svg [] $
...
]
onKeyDown :: Piece -> KeyboardEvent -> Action
onKeyDown p ke = case key ke of
"ArrowDown" -> Move p S
"ArrowUp" -> Move p N
"ArrowRight" -> Move p E
"ArrowLeft" -> Move p W
"r" -> Rotate p
handleAction :: forall output m. MonadAff m => Action -> H.HalogenM UI Action () output m Unit
handleAction a = case a of
Initialize -> do
...
Select se -> H.modify_ $ updateUI se select
Rotate se -> H.modify_ $ updateUI se rotate
Move se d -> H.modify_ $ updateUI se (move d)
The problem I have is that events “ContextMenu” and “KeyDown” are bubbling: I would like to prevent that.
For instance right clicking will open the context menu.
I understood that I should use stopPropagation
in my event handler.
However this is not ideal because I will need to pass the Event
in my Action
(for some of them anyway):
data Action =
Select Piece
KeyDown KeyboardEvent
I would prefer to keep Action
as everything you can do in the game.
Any suggestions?
Thanks