packages feed

haste-lib-0.6.0.0: src/Haste/Hash.hs

{-# LANGUAGE FlexibleInstances, FlexibleContexts, GADTs, OverloadedStrings #-}
-- | Hash manipulation and callbacks.
module Haste.Hash (
    onHashChange, setHash, getHash
  ) where
import Haste.Prim.Foreign
import Control.Monad.IO.Class
import Haste.Prim
import Haste.Events.Core

-- | Register a callback to be run whenever the URL hash changes.
--   The first and second argument of the callback are the old and new and
--   hash respectively.
onHashChange :: MonadEvent m
              => (JSString -> JSString -> m ())
              -> m ()
onHashChange f = do
  f' <- mkHandler $ uncurry f
  firsthash <- getHash
  liftIO $ jsOnHashChange firsthash f'

jsOnHashChange :: JSString -> ((JSString, JSString) -> IO ()) -> IO ()
jsOnHashChange =
  ffi "(function(firsthash,cb){\
          \window.__old_hash = firsthash;\
          \window.onhashchange = function(e){\
            \var oldhash = window.__old_hash;\
            \var newhash = window.location.hash.split('#')[1] || '';\
            \window.__old_hash = newhash;\
            \cb([oldhash,newhash]);\
          \};\
       \})"

-- | Set the hash part of the current URL.
setHash :: MonadIO m => JSString -> m ()
setHash = liftIO . jsSetHash

jsSetHash :: JSString -> IO ()
jsSetHash = ffi "(function(h) {location.hash = '#'+h;})"

-- | Read the hash part of the current URL.
getHash :: MonadIO m => m JSString
getHash = liftIO jsGetHash

jsGetHash :: IO JSString
jsGetHash = ffi "(function() {return location.hash.substring(1);})"