{-# LANGUAGE OverloadedStrings, StandaloneDeriving, DeriveGeneric #-} module Lucid.Leaflet where import qualified Data.Aeson as Aeson import qualified Data.ByteString.Lazy as BSL import Lucid import qualified Data.Text as T import qualified Data.Text.Encoding as T import Lucid.PreEscaped import Data.Monoid import GHC.Generics leafletCDN :: Monad m => HtmlT m () leafletCDN = scriptSrc "https://unpkg.com/leaflet@1.2.0/dist/leaflet.js" data LMap = LMap T.Text | SetView (Double, Double) Double LMap data LMapElement = TileLayer T.Text TileLayerProperties | Marker (Double, Double) | BindPopup T.Text LMapElement data TileLayerProperties = TileLayerProperties { attribution :: T.Text } deriving (Generic) instance Aeson.ToJSON TileLayerProperties mapElementToJS :: LMapElement -> T.Text mapElementToJS e' = "\n" <> f e' <> ".addTo(lmap);" where tshow = T.pack . show f (Marker (x, y)) = "L.marker(["<> tshow x<>", "<> tshow y<>"])" f (BindPopup t e) = f e <> ".bindPopup('"<>t<>"')" f (TileLayer url ps) = "L.tileLayer('"<>url<>"',"<>g ps<>")" g = T.decodeUtf8 . BSL.toStrict . Aeson.encode osmTileLayer :: LMapElement osmTileLayer = TileLayer "http://{s}.tile.osm.org/{z}/{x}/{y}.png" $ TileLayerProperties "© OpenStreetMap contributors" leafletCssCDN :: Monad m => HtmlT m () leafletCssCDN = link_ [rel_ "stylesheet", href_ "https://unpkg.com/leaflet@1.2.0/dist/leaflet.css"] leafletMap :: Monad m => LMap -> [LMapElement] -> HtmlT m () leafletMap mp elms = script_ $ writeMap mp <> writeElems elms where writeMap m = "\nvar lmap = " <> writeMap' m <> ";" writeMap' (LMap e) = "L.map('"<>e<>"')" writeMap' (SetView (x,y) z m) = writeMap' m <> ".setView(["<> tshow x<>", "<> tshow y<>"], "<> tshow z<>")" writeElems = T.unlines . map mapElementToJS tshow = T.pack . show