making_forms.anubis 11 KB

 *Project*                             The Anubis Project
   
 *Title*                                Making Web Forms. 
   
 *Copyright*                     Copyright (c) Alain Prouté 2005. 


 *Author*       Alain Prouté
   
  
   
read web/making_a_web_site.anubis   
   
   
 *Overview*
   This  file   contains  tools  for   helping  making  forms   for  a  web   site,  using
   'making_a_web_site.anubis'.
   
   
   *** (1) General principles. 
   
   A  form allows  a client  to  send a  lot of  informations  within a  web page.   These
   informations are entered by the client in so-called 'input fields'. The server must:
   
     - check the content of  the form, and eventually return the form  to the client (with
   already entered values) for modifications with a warning message. This is 'phase 1'. 
   
     - when the form is OK, save  the informations (maybe after some transformations) into
   a data base, and send a confirmation page to the client. This is 'phase 2'. 
   
   Below is the flowchart of the behavior of the form: 
   
   
                                              :
                                      phase 1 : phase 2
                                              :
            +-------------+                   :            +-------------------+
            |    form     |<------+           :            | confirmation page |
            +-------------+       |           :            +-------------------+
           submit|                |           :                          ^
                 |                |           :         client side      |
        ......................................:..........................................
                 |                |           :         server side      |
                 |                |           :                          |
                 |                |no         :                          |
                 |           ---------        :                          |
                 |          /         \       :                          |
                 |         /  is form  \   yes:       +-------------+    |
                 +------->|   correctly |------------>| save or     |----+
                           \  filled   /      :       | update data |
                            \ in ?    /       :       +-------------+
                             ---------        :             |
                                              :             |
                                              :             V
                                              :       +-----------+
                                              :       | data base |
                                              :       +-----------+
   
   
   Actually, the confirmation  page may be an infirmation page if  some problem arose with
   the data base. 
   
   
   This file contains tools for automating most of this process. 
   
   Recall   that   pages  are   actually   computed   from   'states'  as   explained   in
   'web/making_a_web_site.anubis', so  that we are  mainly concerned by states  instead of
   pages. The type of states is represented below by the parameter $State. 
   
   You must distinguish two kinds of data:
   
      - intermediary data which  are those needed in  phase 1. These data are  made of the
   current values of the  fields of the form. They are needed, because  if the form is not
   correctly filled in, the form must be  sent back to the client with most fields already
   filled in with previous values so that the client does not have to enter correct values
   again. Intermediary  data have an  initial value. This  initial value may be  a general
   default value if the form is for  getting new informations from the client. It may also
   be the case  that the client just wants  to update already existing data.  In this case
   the initial  intermediary data are computed  from the informations  already stored into
   the data base.
   
      - definitive data, which may be constructed from intermediary data when the form has
   been correctly filled  in. These definitive data  are saved into the data  base in some
   new record, or an existing record is updated.
   
   So, we also have to distinguish between two sorts of forms: 
   
      - forms for getting new data,
      - forms for updating existing data. 

   Actually, the  above flowchart is not complete,  because in the case  of updating data,
   the  data may have  changed between  the moment  the old  data are  sent to  the client
   (within the initial  form) and the moment  updating must take place. In  this case, you
   have to  decide is you  update the  data or sent  the form back  to the client  with an
   appropriate message.
   

   
   *** (2) Carrying on. 

   For each form, you have to define the following types:
   
      - the type of messages (represented below by the parameter $Msg),
      - the type of  definitive data (represented below by the parameter  $Row, as used by
          'tools/sdbms.anubis')
   
   The tools  defined below perform  all the stuff  which is possible without  knowing the
   actual types represented by our parameters.
   
   Now, the main tool 'make_form' (a  schema of definition using the parameters), produces
   a result of the following type:
   
public type MakeFormResult($State):
   result($State -> HTML_Off_Form    the_form,      // to be used in the 'compute_page' function
          Web_Action($State)         the_action).   // action of submitting the form
   
   
   The form, as  filled up by the client,  may be either incorrect or  correct. Hence, the
   following type:
  
public type CheckFormResult($Msg): 
   incorrect ($Msg), 
   correct.
  
   
   
   The form must be described. Actually, the form is made of the following components:
   
     - a title,
     - an text for explaining what the form is used for,
     - all fields of the form, each field contains:
         - a explanation, 
         - a tag for the input field, 
         - the input field itself,
     - a submit button. 
   
   
   We have selected  the following sorts of  inputs for our forms. All  the components are
   functions which will be applied to the current state when the form is generated.
   
public type FieldCheck($Msg):
   failure($Msg),
   ok. 
   
public type FormInput($State,$Msg):
   text       ($State -> String             initial_value,
               $State -> FieldCheck($Msg)     check_field),
   password,
   check_box, 
   selector   ($State -> List(String)       items,
               $State -> Maybe(String)      selected),
   upload. 
   
   
public type FormField($State,$Msg):
   field(String                    name,         // symbolic name of field
         $State -> String          explanation,  
         $State -> String          tag, 
         FormInput($State,$Msg)    input). 
 
   
public type FormDescription($State,$Msg):
   form(String                          form_name, 
        $State -> String                title, 
        $State -> String                explain, 
        List(FormField($State,$Msg))    fields, 
        $State -> String                submit_button_text). 
   
   
   Now,  for making a  form, you  must provide  the content  of the  form, a  function for
   checking the form and a function for saving or updating the informations.

   
   Choose how to transmit the form:
   
public type FormTransmission:
   http,                               // HTTP only
   https,                              // HTTPS only
   http_https.                         // both
   
public define MakeFormResult($State)
   make_form
     (
       FormTransmission                        form_transmission,
       FormDescription($State,$Msg)            form_description,    
       $State -> $IData                        initial_values, 
       $State -> CheckFormResult($Msg)         check_form,
       $IData -> $State                        save_or_update
     ).
   
   The above  function is executed  only once  for each form  when the server  starts. The
   result is  used to feed up  the arguments for  the function 'make_web_site_description'
   defined in 'web/making_a_web_site.anubis'.
   
   
  
   --- That's all form the public part ! -------------------------------------------------
   

   
   
public define MakeFormResult($State)
   make_form
     (
       FormDescription($Sate,$Msg)            form_description, 
   
       $State -> $IData                        initial_idata, 
   
       ($IData   intermediate_data,  
        $State   previous_state) -> 
              CheckFormResult($Msg,$IData)     check_form,
   
       ($IData) -> $State                      save_or_update,
       FormTransmission                        ftrans
     ) =
   if form_description is form(form_name,title,explain,fields,button_text) then 
   with action_name = form_name+"_submit", 
   result(
     ($State s) |-> form(form_name,
        table([nude],flat[
          row(cell([h_center,columns(3)],text([size(16)],title(s)))),
          row(cell([left,columns(3),width(400)],paragraph([justified,size(10)],explain(s)))), 
          map((FormField($State,$Msg) f) |-> if f is field(name,expl,tag,input) then 
                    [
                      row(cell([h_center,columns(3)],paragraph([justified,size(10)],expl(s)))),
                      row[cell([right],text([size(10)],tag(s))),
                          cell([width(10)],text([],"")),
                          cell([left],if input is 
                            {
                              text(init)     then text_input      (name,init,55) 
                              password       then password_input  (name,55)
                              check_box(c)   then check_box       (name,c)
                              selector(i,s)  then if s is 
                                                    {
                                                      failure    then selector(name,1,i(s))
                                                      success(k) then selector(name,1,i(s),k)
                                                    }
                              upload         then file_upload     (name,55)
                            })]
                    ]
               ,fields),
          row(cell([h_center,columns(3)],
                    actioner(if ftrans is 
                               {
                                 http         then http, 
                                 https        then https, 
                                 http_https   then same
                               },
                             same,
                             link([size(14)],button_text(s)),
                             action_name,
                             [])))])),
          
     (if ftrans is 
        {
           http        then http_action
           https       then https_action
           http_https  then http_https_action
        })(action_name,
           allow,
           (List(Web_arg) lwa,
            $State        s) |-> if check_form(s) is 
              {
                incorrect(msg,idata) then 
                correct              then 
              }
         )
       ).