Wednesday, June 26, 2013

And finally... Widget auto refreshing

In the previous post I said:

Dinamic formlets are composable in MFlow ... But the entire page must be refreshed to achieve dynamic behavior. The next step is to try to avoid the need to refreshing the entire page by using ajax to refresh just the widget that has changed. ...

Now I did it with

autoRefresh :: View format monad result -> View format monad result

autoRefresh capture the form submissions and the links of the enclosed widget and send them via AJAX. The response is the new presentation of the widget, that is updated. No navigation occur. So a widget with autoRefresh can be used in heavyweight pages. If AJAX or javascript is not available, the widget is refreshed normally, via a new page.

This example, from :

combination = ask $
     p << "Login widget (use admin/admin)" ++> autoRefresh(pageFlow "r" wlogin)  <++ hr
     **> p << "Counter widget" ++> autoRefresh (pageFlow "c" (counterWidget 0))  <++ hr
     **> p << "Dynamic form widget" ++> autoRefresh(pageFlow "f" formWidget) <++ hr
     **> wlink () << b << "exit"

Has three active widgets (monadic formlets) with autoRefresh : A login widget, a counter and the dynamic form. They are examples  defined in the previous posts. Each of these widgets express his own flow within the page.

Thursday, June 20, 2013

The promising land of monadic formlets. Or: "Look ma! no JavaScript!"

Formlets are about applicative instances, but what about monadic instances? What a Monad instance of formlets means? I recently experimented with this and the results are very interesting -and powerful-. It mixes the best of web forms, with the flexibility of console applications.


What I mean with that? There are two fundamental questions for usability and high level programming of user interfaces.  Here are with my responses:

  1. What is the best interface? A dynamic, window-oriented or document oriented interface for some applications  and optional console-style presentation and interaction for others
  2. What is the most intuitive way of programming interfaces? The sequential style of console applications.

What if I say that monadic formlets have the potential to realize the two (or three) whishes with no compromises?
Let´s look at an example. There is a video of the execution below. Although this example is for the formlets of the MFlow framework , it can be ported to other formlet implementations. The MFLow formlets includes operators for web formatting that is not supported in other formlets implementations. Static HTML templating don´t work well with monadic formlets, so it is important to include the formatting as a part of the computation:

formWidget= wform $ do
      (n,s) <- (,) <$> p << "Who are you?"
                   ++> getString Nothing  <! hint "name"     <++ br
                   <*> getString Nothing  <! hint "surname"  <++ br
                   <** submitButton "ok" <++ br
      flag <- b << "Do you " ++> getRadio[radiob "work?",radiob "study?"] <++ br
      r<-case flag of
         "work?" -> pageFlow "l"
                     $ Left  <$> b << "do you enjoy your work? "
                             ++> getBool True "yes" "no" 
                             <** submitButton "ok"  <++ br
         "study?"-> pageFlow "r"
                     $ Right <$> b << "do you study in "
                             ++> getRadio[radiob "University"
                                         ,radiob "High School"]
      u <-  getCurrentUser                                     
      p << ("You are "++n++" "++s) ++>
       p << ("And your user is: "++ u) ++>
       case r of
         Left fl ->   p << ("You work and it is " ++ show fl ++ " that you enjoy your work")
                        ++> noWidget

         Right stu -> p << ("You study at the " ++ stu)
                        ++> noWidget

hint s= [("placeholder",s)]
onClickSubmit= [("onclick","this.form.submit()")]
radiob s n= text s ++&gt setRadio s n <! onClickSubmit

 Here wform, getBool, getString , getRadio etc are formlet elements

The first sentence is an applicative composition that generate a 2 tuple, to show that applicative and monadic can be mixed.  The operations ++> add html to the formlet. The operatior <! add attributes to the formlet element.. noWidget is a dumb formlet that does not validate.

The second monadic statement is an election between two options. The beauty of the monadic instance is that the rest of the form can vary depending on the previous answers. Since the formlets validate the input, unless the election is made, the radio will not validate, so the monadic execution will be aborted beyond any unanswered question, so nothing will appear after the question. The rest of the form will appear when the user choose one of the two options. once one or the other option is chosen, then another binary question is presented. (either he likes his work or where he study). When the questions are finised, the results are presented. This kind of presentation is similar to what we would see in a console application.

I hope that you get the idea. The benefit is not only the familiar coding and presentation of a sequential console application: Since the form encloses all the fields, At any time the user can change previous inputs and the form will reflect these changes. For example if the user change from work to study (second statements) the "where do you study will appear and the work related questions and answers will disappear. That is wonderfully useful for heavily interactive applications.

There is a problem however and it is the issue of the formlet identifiers. Unlike in an applicative presentation, now the number and type of the formlets will vary, so the response to a previous form create a new kind of form with different fields. And, because the form identifiers, assigned sequentially, vary, the post response can be misinterpreted. To avoid that , the pageFlow call creates fixed sequences of identifiers for each branch of execution.

I will release a version of MFlow that support this kind of monadic composition of fomlets, but In essence it is nothing but a Monad instance for formlets. A single server procedure, that executes the formlet code can support all the interaction so any framework can do it. The usability of that is huge: It is possible to interact in a web page in a console style with questions and answers with the versatitly of a dynamic foms: Any modification in the form change the subsequent flow of interaction. Another application of this monadic style is to ease multistep processes such are registration, check-out and payment ad so on. Even a entire interactive dynamic application can be coded in a single page.

And no javascript is needed!.

This page flow is simple, but imagine a flow where the first line includes formlets for tabs or menus An entire application can be controlled in this way.

To run this formlet in MFlow:


       [(""    , transient $ runFlow  $ ask dynamicForm )]

  wait $ run port waiMessageFlow

This video show how the presentation of this example vary with the user input:

 This other video has a better resolution:

I hope that you find the idea interesting. If you want to experiment with this in MFlow, I have to say that the implementation of this feature is in an early stage. The code is in the head branch

The code of the example, that was executed in the video, is part of a demo:

The next step: Selective refreshing.

Dinamic formlets are composable in MFlow . The video shows a counter, a login widget and this formlet working in the same page (see the code of these widgets in previous posts) But the entire page must be refreshed to achieve dynamic behavior. The next step is to try to avoid the need to refreshing the entire page by using ajax to refresh just the widget that has changed. This is halfway done now, since this functionality is available for some particular widgets. it is a matter of generalizing the mechanism.

Tuesday, June 18, 2013

Caching Web pages with TCache. Translation of a java example that uses JCache

I just read this introduction to JCache because I was curious about the similarities with my package TCache. While JCache is an standard interface for distributed HashMaps, like memcached or Resin, TCache is an implementation of a transactional cache that is not yet distributed -but I plan it to be.

But the latter has a richer semantic, since It has not only search by key, but also support the STM semantic of updates and retrievals. It also has a query language using Haskell field names and various kinds of indexations (and it is more type safe).

Java is extraordinarily verbose, and the Java people enjoy adding even more verbosity to their frameworks and standards (except perhaps the engineers at Google). 

I translated the same example in the refered article to TCache and MFlow. I will use seconds instead of milliseconds

module Main where

import MFlow.Wai.Blaze.Html.All
import Data.TCache.Memoization
import System.Time
import Control.Concurrent  -- for the console example

seconds :: IO String
seconds= do
         TOD t _ <- liftIO getClockTime
         return $ show t

-- generates the page in Text.Blaze.Html format
page :: IO Html
page= do
   t <-  seconds 
   return $ p << ("Hello World " ++ t)

-- caches the Html code
cachedPage:: IO Html
cachedPage = cachedByKey "hello message" 10 page

helloServlet=  do
      msg <- liftIO $  cachedPage
      msg ++>  noWidget

That's all the code of the Java example. cachedByKey stores the value of the computation in the cache for ten second with the key "hello message".  When the value is requested after ten seconds, the computation is re-executed again.

The operator << is a convenience operator defined in MFlow to avoid the overloaded strings extension, but what is cached in cachedPage is pure blaze-html markup. So cachedByKey can be used in any other Haskell web framework to cache Html pages.

helloServlet can also be written using wcached or wfreeze, which is specific for caching MFlow widgets:

helloServlet'= wfreeze  "hello message Widget" 10 $ messageWidget 

messageWidget ::  View Html IO ()
messageWidget= liftIO page >>= \msg -> msg ++> noWidget 

noWidget is a dumb widget that has no rendering.

To execute both servlet in the port 80:

main= do

   addMessageFlows[("noscript",wstateless helloServlet)
                   ,("alternative", wstateless helloServlet')]

   wait $ run 80 waiMessageFlow

The procedure associated to "noscript" is invoked when no path is in the URL.

A similar console program, which polls the cache every second:

main= do
      msg <-  cachedByKey "hello message text" 10 messageText
      print msg
      threadDelay 1000000

   t <- seconds 
   return $ p <<("Hello World " ++ t)

Monday, June 10, 2013

Callbacks: Dynamic Web widgets and dynamic forms without JavaScript

A callback is an action that is executed when a widget receives valid input. MFlow has 'waction's  They execute a sequence of pages when invoked. When the flow action is finished the display return to the original page, to execute further actions or to return the result of the page form. A waction takes complete control of the navigation.

But it would be nice to execute a flow in each widget in the page simultaneously. Each widget in the page can have dynamic behaviors without using JavaScript. Seaside is an incredible web framework developed in a very nice language: Smalltalk. It has such functionality.

This seaside widget counter is replicated five times in the same page:

There you can see the beautiful and short implementation and how nice Smalltalk is.

I tried hard, and finally I developed this functionality in MFlow. The same counter widget can be defined in a similarly short way in  MFlow as such:

counterWidget n= do
  (h1 << show n
   ++> wlink "i" << b << " ++ "
   <|> wlink "d" << b << " -- ")
  `wcallback` \op -> case op of
                      "i" -> counterWidget (n + 1)
                      "d" -> counterWidget (n - 1)

Unlike the Seaside one, this is a recursive definition. The look and the behavior is the same than in the case of the Seaside counter (link above).
A page with a counter can be defined as such:

conterPage= ask $ counterWidget 0

And a page with five counters separated by horizontal lines can be defined as such:

 multicounterPage= ask $ firstOf(replicate 5 counter)
  counter= counterWidget 0 <++ hr

As in the case of the Seaside example, the five independent counters can be increased and decreased independently. Moreover in both cases they behave well with the back button.

wcallback replaces a widget with other widget when the first is validated (or does whatever possible in a View monad, including the return of a result). various chained callbacks can create a local flow. Actually,  wcallback is implemented as  a bind operation:

  :: Monad m =>
     View view m a -> (a -> View view m b) -> View view m b

The seaside callbacks works in a different way. they modify the same object, that is rendered in the next continuation.

The Haskell implementation and the use of RESTful URLs recently developed  permits a pure RESTful version of the multicounter example, while in the Seaside case, the counters state in each page is stored in a continuation that is deleted after a timeout, so when you press again the same URL, the counters will appear zeroed. In the MFlow application, the GET requests created by the increment and decrement links produce URLs that are side effect free. If you bookmarck one of these URLs and send it by email, the receiver will see the same counter values when he press the link. That is very very nice for a stateful web framework.

I said that  wcallback is a bind operations, but the real bind in the View monad is defined to perform a slightly different thing. While the former substitute the widget by other when the first is validated, bind add the new widget after the original one. This permits the creation of very interesting behaviours. For example, monadic forms instead of applicative ones that present input fields incrementally. Unlike in the case of Applicative forms, different dialogs can be presented depending on the user responses.

Here below is the code of a dynamic widget that interact with the server. It perform a monadic interaction with various steps and use a callback.

It is a functional logging widget. If the user is not anonymous, it simply display that the user is logged. If the user is not logged, it display a login box to enter the user name. once the name is entered, it display a password field below the user name. If the user is validated then the user is logged, the form dissapears and display the logged user name (in the callback). If the validation is erroneous, it displays a message below:

wlogin= do
    username <- getCurrentUser
    if username /= anonymous 
     then return username
     else do
      name <- getString (Just $ "Enter username") <++ br
      pass <- getPassword <++ br
      val  <- userValidate (name,pass)
      case val of
        Just msg -> notValid msg 
        Nothing -> login name >> return name

   `wcallback`  \name -> p << ("logged as " ++ name) ++> noWidget

You can see how the widget interact nicely with the server.

You can see all of this in the following screencast. Excuse my dizziness. To my bad English -not used for quite a while- I add the tireness of many hours of programming. I recorded the video right after I solved the last great problem before making sure that all of this is possible in MFlow. Now there remain only bugs.

This version of MFlow is at the head branch:

The video will appear after Youtube end the processing:

Friday, June 07, 2013

RESTful URLs and navigation in MFlow

This screencast shows some new features that I´m developing just now  (The session is interrupted by a failure ;) .  This is probably the first stateful web framework with restful URLs.

I show how to create  navigation routes/navigation menu threes and I show, with the help of the debugger, how the application goes back and forth in the execution three to match the URL entered.

Any (GET) page in the flow can be addressed by a restful URL.

This last version of MFlow is at the HEAD branch:

This video is the continuation after fixing the error. It shows how the state is managed and how it rollback when the user press the back button. (to avoid rollback, take a look at previous posts about state management)