happstack-fay 0.1.0.0 → 0.2.0
raw patch · 5 files changed
+28/−176 lines, 5 filesdep +happstack-fay-ajaxdep +mtldep −fay-jquerydep ~basedep ~faysetup-changed
Dependencies added: happstack-fay-ajax, mtl
Dependencies removed: fay-jquery
Dependency ranges changed: base, fay
Files
- Happstack/Fay.hs +16/−5
- Language/Fay/AJAX.hs +0/−82
- Language/Fay/HTML.hs +0/−75
- Setup.hs +1/−0
- happstack-fay.cabal +11/−14
Happstack/Fay.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings, NoImplicitPrelude, PackageImports #-} {- | The server-side half of a typed AJAX communication channel.@@ -42,16 +42,24 @@ 'ResponseType' argument and passes it to 'fayResponse'. This is how we ensure that each commend handler is returning the right type. -See also "Language.Fay.AJAX".+See also @AJAX@ from the @happstack-client-fay@ package. -} module Happstack.Fay where +-- NOTE: we do not really need to use NoImplicitPrelude and+-- PackageImports here since this module only needs things from "base"+-- and we do not compile against "fay-base". However, when debugging+-- things in GHCi, we might have both "base" and "fay-base"+-- loaded. So, using PackageImports just makes things easier.++import "base" Prelude+import Control.Monad.Trans (liftIO) import Data.Aeson-import Data.Data+import "base" Data.Data import Happstack.Server-import Language.Fay.AJAX-import Language.Fay.Convert+import ResponseType+import Fay.Convert -- | decode the 'cmd' and call the response handler. --@@ -61,8 +69,11 @@ -> m Response handleCommand handler = do json <- lookBS "json"+ liftIO $ print json let val = (decode' json) mCmd = readFromFay =<< val+ liftIO $ print val+ liftIO $ print mCmd case mCmd of Nothing -> badRequest $ toResponse ("Failed to turn this into a command: " ++ show (val)) (Just cmd) -> handler cmd
− Language/Fay/AJAX.hs
@@ -1,82 +0,0 @@-{-# LANGUAGE DeriveDataTypeable, NoImplicitPrelude #-}-{- |--client-side half of a typed AJAX communication channel.--To use this library, you could start by defining a type in a file that-can be shared between the Haskell Server and Fay client. For example:--@- data Command- = SendGuess Guess (ResponseType (Maybe Row))- | FetchBoard (ResponseType (Maybe Board))- deriving (Read, Show, Data, Typeable)- instance Foreign Command-@--The 'ResponseType' argument specifies what type each command should-return. Using GADTs would be cleaner, but Fay does not support GADTs-yet.--To execute a remote function we use the 'call' function:--@- call "/ajax" FetchBoard $ \mboard -> ...-@--Due to the single-threaded nature of Javascript, we do not want to-block until the 'call' returns a value, so we perform the AJAX request-asynchronously. The third argument to 'call' is the callback function-to run when the response is received.--See also: "Happstack.Fay"---}-module Language.Fay.AJAX where--import Language.Fay.FFI-import Language.Fay.Prelude---- | 'ResponseType' is used in lieu of `GADTs` as a mechanism for--- specifying the expected return type of remote AJAX calls.-data ResponseType a = ResponseType- deriving (Eq, Read, Show, Data, Typeable)-instance Foreign (ResponseType a)---- | Asynchronously call a command------ Note: if the server returns 404 or some other non-success exit--- code, the callback function will never be run.------ This function is just a wrapper around 'ajaxCommand' which uses the--- 'ResponseType res' phantom-typed parameter for added type safety.-call :: (Foreign cmd, Foreign res) =>- String -- ^ URL to 'POST' AJAX request to- -> (ResponseType res -> cmd) -- ^ AJAX command to send to server- -> (res -> Fay ()) -- ^ callback function to handle response- -> Fay ()-call uri f g =- ajaxCommand uri (f ResponseType) g---- | Run the AJAX command. (internal)------ You probably want to use 'call' which provides additional--- type-safety.------ Note: if the server returns 404 or some other non-success exit--- code, the callback function will never be run.------ see also: 'call'-ajaxCommand :: (Foreign cmd, Foreign res) =>- String- -> cmd- -> (res -> Fay ())- -> Fay ()-ajaxCommand =- ffi "jQuery['ajax']({\- \ \"url\": %1, \- \ \"type\": 'POST', \- \ \"data\": { \"json\": JSON.stringify(%2) }, \- \ \"dataType\": 'json', \- \ \"success\" : %3 \- \})"
− Language/Fay/HTML.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{- |--A simple library for client-side HTML generation.---}-module Language.Fay.HTML where--import Language.Fay.FFI-import Language.Fay.Prelude-import Language.Fay.JQuery----- | ADT for 'HTML'-data HTML- = Element String [(String, String)] [HTML] -- ^ Element name attributes children- | CDATA Bool String -- ^ CDATA needEscaping value---- | generate an HTML element-genElement :: String -- ^ Element name- -> [Fay (String, String)] -- ^ list of attributes- -> [Fay HTML] -- ^ list of children- -> Fay HTML-genElement n genAttrs genChildren =- do attrs <- sequence $ genAttrs- children <- sequence $ genChildren- return (Element n attrs children)---- | render the 'HTML' into a JQuery DOM tree. You still need to--- append the result somewhere.------ NOTE: This function requires 'jQuery'-renderHTML :: HTML- -> Fay JQuery-renderHTML (Element n attrs children) =- do elem <- selectElement =<< createElement n- mapM_ (\(n, v) -> setAttr n v elem) attrs- mapM_ (\child ->- do cElem <- renderHTML child- append cElem elem) children- return elem----------------------------------------------------------------------------------- HTML Combinators---- | \<tr\>-tr :: [Fay (String, String)] -- ^ attributes- -> [Fay HTML] -- ^ children- -> Fay HTML-tr = genElement "tr"---- | \<td\>-td :: [Fay (String, String)] -- ^ attributes- -> [Fay HTML] -- ^ children- -> Fay HTML-td = genElement "td"---- | \<span\>-span :: [Fay (String, String)] -- ^ attributes- -> [Fay HTML] -- ^ children- -> Fay HTML-span = genElement "span"---- | create a text node from the 'String'. The 'String' will be--- automatically escaped.-pcdata :: String -> Fay HTML-pcdata = return . CDATA True----------------------------------------------------------------------------------- HTML Combinators---- | create a new 'Element'-createElement :: String -- ^ name of the element- -> Fay Element-createElement = ffi "document.createElement(%1)"
Setup.hs view
@@ -1,2 +1,3 @@+#!/usr/bin/env runhaskell import Distribution.Simple main = defaultMain
happstack-fay.cabal view
@@ -1,9 +1,11 @@ name: happstack-fay-version: 0.1.0.0+version: 0.2.0 synopsis: Support for using Fay with Happstack description: Fay is strict subset of Happstack which can be compiled to Javascript. This library provides some utilities for client-server communication, client-side HTML generation, and more.+ .+ This package provides the server-side libraries for happstack-fay homepage: http://www.happstack.com/ license: BSD3 license-file: LICENSE@@ -13,17 +15,12 @@ build-type: Simple cabal-version: >=1.8 -data-files:- Language/Fay/AJAX.hs,- Language/Fay/HTML.hs- library- exposed-modules: Language.Fay.AJAX,- Language.Fay.HTML,- Happstack.Fay,- Paths_happstack_fay- build-depends: base > 4 && <5,- fay == 0.9.*,- fay-jquery == 0.1.*,- aeson == 0.6.*,- happstack-server >= 7.0 && <7.2+ exposed-modules: Happstack.Fay++ build-depends: base > 4.5 && <5,+ fay == 0.14.*,+ happstack-fay-ajax == 0.2.*,+ aeson == 0.6.*,+ mtl >= 2.0 && < 2.2,+ happstack-server >= 7.0 && <7.2