diff options
author | Joey Hess <joey@kitenet.net> | 2012-07-26 21:03:46 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-07-26 21:03:46 -0400 |
commit | f5ef46d01eb7bbaac45eec162267bcbf2500d511 (patch) | |
tree | 0e2fd9d872919d08f70d09d169d65d13c1305a6c | |
parent | 9b2eec2e7af34e107bcb438a501286996fe0eb41 (diff) |
cleaned up refreshing code into a widget
Very happy to have a reusable autoUpdate widget that can make any Yesod
widget automatically refresh!
Also added support for non-javascript browsers, falling back to meta
refresh.
Also, the home page is now rendered with the webapp status on it, before
any refreshing is done.
-rw-r--r-- | Assistant/Threads/WebApp.hs | 58 | ||||
-rw-r--r-- | templates/longpolling.julius | 16 | ||||
-rw-r--r-- | templates/metarefresh.hamlet | 2 | ||||
-rw-r--r-- | templates/status.hamlet (renamed from templates/poll.hamlet) | 2 |
4 files changed, 62 insertions, 16 deletions
diff --git a/Assistant/Threads/WebApp.hs b/Assistant/Threads/WebApp.hs index 2d78609e8..0e1f9ba95 100644 --- a/Assistant/Threads/WebApp.hs +++ b/Assistant/Threads/WebApp.hs @@ -41,7 +41,7 @@ staticFiles "static" mkYesod "WebApp" [parseRoutes| / HomeR GET -/poll PollR GET +/status StatusR GET /config ConfigR GET /static StaticR Static getStatic |] @@ -66,23 +66,63 @@ instance Yesod WebApp where makeSessionBackend = webAppSessionBackend jsLoader _ = BottomOfHeadBlocking +{- Add to any widget to make it auto-update. + - + - The widget should have a html element with id=poll, which will be + - replaced when it's updated. + - + - Updating is done by getting html from the gethtml route. + - Or, the home route is used if the whole page has to be refreshed to + - update. + - + - ms_delay is how long to delay between updates. + - ms_startdelay is how long to delay before updating the widget at the + - state. + -} +autoUpdate :: Text -> Route WebApp -> Route WebApp -> Int -> Int -> Widget +autoUpdate poll gethtml home ms_delay ms_startdelay = do + {- Fallback refreshing is provided for non-javascript browsers. -} + let delayseconds = show $ ms_to_seconds ms_delay + toWidgetHead $(hamletFile $ hamletTemplate "metarefresh") + + {- Use long polling to update the status display. -} + let delay = show ms_delay + let startdelay = show ms_startdelay + addScriptRemote "http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" + toWidgetHead $(juliusFile $ juliusTemplate "longpolling") + where + ms_to_seconds :: Int -> Int + ms_to_seconds ms = ceiling ((fromIntegral ms :: Double) / 1000) + +{- Continually updating status display. -} +statusDisplay :: Widget +statusDisplay = do + webapp <- lift getYesod + time <- show <$> liftIO getCurrentTime + + poll <- lift newIdent + $(whamletFile $ hamletTemplate "status") + + autoUpdate poll StatusR HomeR (3000 :: Int) (40 :: Int) + getHomeR :: Handler RepHtml getHomeR = defaultLayout $ do - [whamlet|<div id="poll">Starting ...|] - addScriptRemote "http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" - toWidgetBody $(juliusFile $ juliusTemplate "longpolling") + statusDisplay [whamlet|<p><a href="@{ConfigR}">config|] {- Called by client to poll for a new webapp status display. - - Should block until the status has changed, and then return a div - containing the new status, which will be inserted into the calling page. + - + - Note that the head of the widget is not included, only its + - body is. To get the widget head content, the widget is also + - inserted onto the getHomeR page. -} -getPollR :: Handler RepHtml -getPollR = do - webapp <- getYesod - time <- show <$> liftIO getCurrentTime - hamletToRepHtml $(hamletFile $ hamletTemplate "poll") +getStatusR :: Handler RepHtml +getStatusR = do + page <- widgetToPageContent statusDisplay + hamletToRepHtml $ [hamlet|^{pageBody page}|] getConfigR :: Handler RepHtml getConfigR = defaultLayout $ do diff --git a/templates/longpolling.julius b/templates/longpolling.julius index 38ecbc77d..26356f5e9 100644 --- a/templates/longpolling.julius +++ b/templates/longpolling.julius @@ -1,5 +1,9 @@ -// Uses long-polling to update a div with id=poll. -// The PollR route should return a new div, also with id=poll. + +// Uses long-polling to update a div with id=#{poll} +// The gethtml route should return a new div, with the same id. +// +// Maximum update frequency is controlled by #{startdelay} +// and #{delay}, both in milliseconds. (function( $ ) { @@ -7,11 +11,11 @@ $.LongPoll = (function() { return { send : function() { $.ajax({ - 'url': '@{PollR}', + 'url': '@{gethtml}', 'dataType': 'html', 'success': function(data, status, jqxhr) { - $('#poll').replaceWith(data); - setTimeout($.LongPoll.send, 3000); + $('##{poll}').replaceWith(data); + setTimeout($.LongPoll.send, #{delay}); }, }); } @@ -19,7 +23,7 @@ $.LongPoll = (function() { }()); $(document).bind('ready.app', function() { - setTimeout($.LongPoll.send, 40); + setTimeout($.LongPoll.send, #{startdelay}); }); })( jQuery ); diff --git a/templates/metarefresh.hamlet b/templates/metarefresh.hamlet new file mode 100644 index 000000000..be22aa899 --- /dev/null +++ b/templates/metarefresh.hamlet @@ -0,0 +1,2 @@ +<noscript> + <meta http-equiv="refresh" content="#{delayseconds}; URL=@{home}"> diff --git a/templates/poll.hamlet b/templates/status.hamlet index fcdd705b6..1f975b35f 100644 --- a/templates/poll.hamlet +++ b/templates/status.hamlet @@ -1,2 +1,2 @@ -<div id="poll"> +<div id="#{poll}"> polled at #{time} |