Permalink
Browse files

Added Henry Laxen's example

  • Loading branch information...
1 parent b3dea28 commit eb953d71518455fb359219933cbeaa67bb4e1639 @davidsd committed Sep 13, 2012
View
@@ -0,0 +1,81 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+{-
+
+Author: Henry Laxen (http://nadineloveshenry.com/)
+
+1. Obviously you have already unpacked this file in a directory.
+2. Now compile with ghc as follows:
+ ghc --make add.hs
+3. Now run ./add
+4. Go to your browser and enter the url:
+ http://localhost.localdomain:8000/ajax
+5. The rest is silence
+
+-}
+
+import Control.Applicative ( Applicative((<*>)), (<$>) )
+import Data.Monoid ( (<>) )
+import Data.Text ( Text )
+import qualified Data.Text as T ( pack, intercalate )
+import Language.Javascript.JMacro ( JStat )
+import Snap
+ ( Snaplet,
+ Handler,
+ SnapletInit,
+ defaultConfig,
+ subSnaplet,
+ serveSnaplet,
+ nestSnaplet,
+ makeSnaplet,
+ addRoutes,
+ makeLens )
+import Snap.Snaplet.Heist
+ ( Heist, HasHeist(..), liftHeist, heistInit, addSplices )
+import Snap.Util.FileServe ( serveDirectory )
+import Snap.Snaplet.LiftAjax.Js ( alert )
+import Snap.Snaplet.LiftAjax.Splice ( formWithSplices )
+import Text.Digestive ( Form, View, childErrors, (.:), stringRead )
+import Text.Digestive.Heist ( digestiveSplices )
+import Text.Templating.Heist ( Splice )
+import Snap.Snaplet.LiftAjax
+ ( Ajax, HasAjax(..), defaultAjaxState, ajaxInit )
+
+type AppHandler = Handler App App
+
+addInts :: Monad m => Form Text m Int
+addInts = (+)
+ <$> "x" .: stringRead "x must be an integer" Nothing
+ <*> "y" .: stringRead "y must be an integer" Nothing
+
+addIntsSplice :: Splice AppHandler
+addIntsSplice = formWithSplices digestiveSplices addInts process
+ where
+ process :: Either (View Text) Int -> AppHandler JStat
+ process (Right z) = return $ alert $ "the sum is " <> T.pack (show z)
+ process (Left v) = return $ alert $ T.intercalate ", " $ childErrors "" v
+
+data App = App
+ { _heist :: Snaplet (Heist App)
+ , _ajax :: Snaplet (Ajax App)
+ }
+makeLens ''App
+
+instance HasHeist App where
+ heistLens = subSnaplet heist
+
+instance HasAjax App where
+ ajaxLens = ajax
+
+
+app :: SnapletInit App App
+app = makeSnaplet "app" "An snaplet example application." Nothing $ do
+ h <- nestSnaplet "" heist $ heistInit "templates"
+ a <- nestSnaplet "ajax" ajax $ ajaxInit defaultAjaxState
+ addRoutes [("/", serveDirectory "static")]
+ addSplices [("addIntsForm", liftHeist addIntsSplice)]
+ return $ App h a
+
+main :: IO ()
+main = serveSnaplet defaultConfig app
@@ -0,0 +1,23 @@
+<html>
+<head>
+<script type="text/javascript" src="/jquery-min.js"></script>
+<script type="text/javascript" src="/liftAjax.js"></script>
+
+
+<title>LiftAjax Example</title>
+</head>
+
+<body>
+<h1>LiftAjax Example</h1>
+
+<addIntsForm class="classes for styling">
+x = <dfInputText ref="x" />,
+y = <dfInputText ref="y" />
+<input type="submit" value="Add" />
+</addIntsForm>
+
+
+<hr>
+
+<ajaxFooter />
+</body> </html>

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,172 @@
+(function() {
+
+ window.liftAjax = {
+ lift_ajaxQueue: [],
+ lift_ajaxInProcess: null,
+ lift_doCycleQueueCnt: 0,
+ lift_ajaxShowing: false,
+ lift_ajaxRetryCount: 3,
+
+ lift_ajaxHandler: function(theData, theSuccess, theFailure, responseType){
+ var toSend = {retryCnt: 0};
+ toSend.when = (new Date()).getTime();
+ toSend.theData = theData;
+ toSend.onSuccess = theSuccess;
+ toSend.onFailure = theFailure;
+ toSend.responseType = responseType;
+
+ liftAjax.lift_ajaxQueue.push(toSend);
+ liftAjax.lift_ajaxQueueSort();
+ liftAjax.lift_doCycleQueueCnt++;
+ liftAjax.lift_doAjaxCycle();
+ return false; // buttons in forms don't trigger the form
+
+ },
+
+ lift_uriSuffix: undefined,
+
+ lift_ajaxQueueSort: function() {
+ liftAjax.lift_ajaxQueue.sort(function (a, b) {return a.when - b.when;});
+ },
+
+ lift_defaultFailure: function() {
+ alert("The server cannot be contacted at this time. Try reloading the page.");
+ },
+
+ lift_startAjax: function() {
+ liftAjax.lift_ajaxShowing = true;
+ jQuery('#'+"ajax-loader").show();
+ },
+
+ lift_endAjax: function() {
+ liftAjax.lift_ajaxShowing = false;
+ jQuery('#'+"ajax-loader").hide();
+ },
+
+ lift_testAndShowAjax: function() {
+ if (liftAjax.lift_ajaxShowing && liftAjax.lift_ajaxQueue.length == 0 && liftAjax.lift_ajaxInProcess == null) {
+ liftAjax.lift_endAjax();
+ } else if (!liftAjax.lift_ajaxShowing && (liftAjax.lift_ajaxQueue.length > 0 || liftAjax.lift_ajaxInProcess != null)) {
+ liftAjax.lift_startAjax();
+ }
+ },
+
+ lift_traverseAndCall: function(node, func) {
+ if (node.nodeType == 1) func(node);
+ var i = 0;
+ var cn = node.childNodes;
+
+ for (i = 0; i < cn.length; i++) {
+ liftAjax.lift_traverseAndCall(cn.item(i), func);
+ }
+ },
+
+ lift_successRegisterGC: function() {
+ setTimeout("liftAjax.lift_registerGC()", 75000);
+ },
+
+ lift_failRegisterGC: function() {
+ setTimeout("liftAjax.lift_registerGC()", 15000);
+ },
+
+ lift_registerGC: function() {
+ var data = "__lift__GC=_"
+ jQuery.ajax({ url : liftAjax.addPageName("/" + lift_ajaxUrl + "/request/"), data : data, type : "POST", dataType : "script", timeout : 5000, cache : false, success : liftAjax.lift_successRegisterGC, error : liftAjax.lift_failRegisterGC });
+ },
+
+ lift_doAjaxCycle: function() {
+ if (liftAjax.lift_doCycleQueueCnt > 0) liftAjax.lift_doCycleQueueCnt--;
+ var queue = liftAjax.lift_ajaxQueue;
+ if (queue.length > 0) {
+ var now = (new Date()).getTime();
+ if (liftAjax.lift_ajaxInProcess == null && queue[0].when <= now) {
+ var aboutToSend = queue.shift();
+
+ liftAjax.lift_ajaxInProcess = aboutToSend;
+
+ var successFunc = function(data) {
+ liftAjax.lift_ajaxInProcess = null;
+ if (aboutToSend.onSuccess) {
+ aboutToSend.onSuccess(data);
+ }
+ liftAjax.lift_doCycleQueueCnt++;
+ liftAjax.lift_doAjaxCycle();
+ };
+
+ var failureFunc = function() {
+ liftAjax.lift_ajaxInProcess = null;
+ var cnt = aboutToSend.retryCnt;
+ if (cnt < liftAjax.lift_ajaxRetryCount) {
+ aboutToSend.retryCnt = cnt + 1;
+ var now = (new Date()).getTime();
+ aboutToSend.when = now + (1000 * Math.pow(2, cnt));
+ queue.push(aboutToSend);
+ liftAjax.lift_ajaxQueueSort();
+ } else {
+ if (aboutToSend.onFailure) {
+ aboutToSend.onFailure();
+ } else {
+ liftAjax.lift_defaultFailure();
+ }
+ }
+ liftAjax.lift_doCycleQueueCnt++;
+ liftAjax.lift_doAjaxCycle();
+ };
+
+ if (aboutToSend.responseType != undefined &&
+ aboutToSend.responseType != null &&
+ aboutToSend.responseType.toLowerCase() === "json") {
+ liftAjax.lift_actualJSONCall(aboutToSend.theData, successFunc, failureFunc);
+ } else {
+ var theData = aboutToSend.theData;
+ if (liftAjax.lift_uriSuffix) {
+ theData += '&' + liftAjax.lift_uriSuffix;
+ liftAjax.lift_uriSuffix = undefined;
+ }
+ liftAjax.lift_actualAjaxCall(theData, successFunc, failureFunc);
+ }
+ }
+ }
+
+ liftAjax.lift_testAndShowAjax();
+ if (liftAjax.lift_doCycleQueueCnt <= 0) liftAjax.lift_doCycleIn200()
+ },
+
+ lift_doCycleIn200: function() {
+ liftAjax.lift_doCycleQueueCnt++;
+ setTimeout("liftAjax.lift_doAjaxCycle();", 200);
+ },
+
+ addPageName: function(url) {
+ return url.replace(lift_ajaxUrl + '/request', lift_ajaxUrl + '/request/'+lift_page);
+ },
+
+ lift_actualAjaxCall: function(data, onSuccess, onFailure) {
+ jQuery.ajax({ url : liftAjax.addPageName("/" + lift_ajaxUrl + "/request/"), data : data, type : "POST", dataType : "script", timeout : 5000, cache : false, success : onSuccess, error : onFailure });
+ },
+
+ lift_actualJSONCall: function(data, onSuccess, onFailure) {
+ jQuery.ajax({ url : liftAjax.addPageName("/" + lift_ajaxUrl + "/request/"), data : data, type : "POST", dataType : "json", timeout : 5000, cache : false, success : onSuccess, error : onFailure });
+ }
+ };
+
+ window.liftUtils = {
+ lift_blurIfReturn: function(e) {
+ var code;
+ if (!e) var e = window.event;
+ if (e.keyCode) code = e.keyCode;
+ else if (e.which) code = e.which;
+
+ var targ;
+
+ if (e.target) targ = e.target;
+ else if (e.srcElement) targ = e.srcElement;
+ if (targ.nodeType == 3) // defeat Safari bug
+ targ = targ.parentNode;
+ if (code == 13) {targ.blur(); return false;} else {return true;};
+ }
+ };
+
+
+})();
+jQuery(document).ready(function() {liftAjax.lift_doCycleIn200();});

0 comments on commit eb953d7

Please sign in to comment.