| rev | 
   line source | 
| 
jbe/bsw@0
 | 
     1 --[[--
 | 
| 
jbe/bsw@0
 | 
     2 ui.form{
 | 
| 
jbe/bsw@0
 | 
     3   record    = record,     -- optional record to be used 
 | 
| 
jbe/bsw@0
 | 
     4   read_only = read_only,  -- set to true, if form should be read-only (no submit button)
 | 
| 
jbe/bsw@0
 | 
     5   external  = external,   -- external URL to be used as HTML form action
 | 
| 
jbe/bsw@0
 | 
     6   module    = module,     -- module name to be used for HTML form action
 | 
| 
jbe/bsw@0
 | 
     7   view      = view,       -- view name   to be used for HTML form action
 | 
| 
jbe/bsw@0
 | 
     8   action    = action,     -- action name to be used for HTML form action
 | 
| 
jbe/bsw@0
 | 
     9   routing = {
 | 
| 
jbe/bsw@0
 | 
    10     default = {           -- default routing for called action
 | 
| 
jbe/bsw@0
 | 
    11       mode   = mode,      -- "forward" or "redirect"
 | 
| 
jbe/bsw@0
 | 
    12       module = module,    -- optional module name, defaults to current module
 | 
| 
jbe/bsw@0
 | 
    13       view   = view,      -- view name
 | 
| 
jbe/bsw@0
 | 
    14       id     = id,        -- optional id to be passed to the view
 | 
| 
jbe/bsw@0
 | 
    15       params = params     -- optional params to be passed to the view
 | 
| 
jbe/bsw@0
 | 
    16     },
 | 
| 
jbe/bsw@0
 | 
    17     ok    = { ... },      -- routing when "ok"    is returned by the called action
 | 
| 
jbe/bsw@0
 | 
    18     error = { ... },      -- routing when "error" is returned by the called action
 | 
| 
jbe/bsw@0
 | 
    19     ...   = { ... }       -- routing when "..."   is returned by the called action
 | 
| 
jbe@12
 | 
    20   },
 | 
| 
jbe@12
 | 
    21   partial   = {           -- parameters for partial loading, see below
 | 
| 
jbe@12
 | 
    22     module = module,
 | 
| 
jbe@12
 | 
    23     view   = view,
 | 
| 
jbe@12
 | 
    24     id     = id,
 | 
| 
jbe@12
 | 
    25     params = params,
 | 
| 
jbe@12
 | 
    26     target = target
 | 
| 
jbe@12
 | 
    27   },
 | 
| 
jbe/bsw@0
 | 
    28   content = function()
 | 
| 
jbe/bsw@0
 | 
    29     ...                   -- code creating the contents of the form
 | 
| 
jbe/bsw@0
 | 
    30   end
 | 
| 
jbe/bsw@0
 | 
    31 }
 | 
| 
jbe/bsw@0
 | 
    32 
 | 
| 
jbe/bsw@0
 | 
    33 This functions creates a web form, which encloses the content created by the given 'content' function. When a 'record' is given, ui.field.* helper functions will be able to automatically determine field values by using the given record. If 'read_only' is set to true, then a call of ui.submit{...} will be ignored, and ui.field.* helper functions will behave differently.
 | 
| 
jbe/bsw@0
 | 
    34 
 | 
| 
jbe@12
 | 
    35 When passing a table as "partial" argument, AND if partial loading has been enabled by calling ui.enable_partial_loading(), then ui._partial_load_js is
 | 
| 
jbe@12
 | 
    36 used to create an onsubmit event. The "partial" setting table is passed to ui._partial_load_js as first argument. See ui._partial_load_js(...) for
 | 
| 
jbe@12
 | 
    37 further documentation.
 | 
| 
jbe@12
 | 
    38 
 | 
| 
jbe/bsw@0
 | 
    39 --]]--
 | 
| 
jbe/bsw@0
 | 
    40 
 | 
| 
jbe/bsw@11
 | 
    41 local function prepare_routing_params(params, routing, default_module)
 | 
| 
jbe/bsw@11
 | 
    42   local routing_default_given = false
 | 
| 
jbe/bsw@11
 | 
    43   if routing then
 | 
| 
jbe/bsw@11
 | 
    44     for status, settings in pairs(routing) do
 | 
| 
jbe/bsw@11
 | 
    45       if status == "default" then
 | 
| 
jbe/bsw@11
 | 
    46         routing_default_given = true
 | 
| 
jbe/bsw@11
 | 
    47       end
 | 
| 
jbe/bsw@11
 | 
    48       local module = settings.module or default_module or request.get_module()
 | 
| 
jbe/bsw@11
 | 
    49       assert(settings.mode, "No mode specified in routing entry.")
 | 
| 
jbe/bsw@11
 | 
    50       assert(settings.view, "No view specified in routing entry.")
 | 
| 
jbe/bsw@11
 | 
    51       params["_webmcp_routing." .. status .. ".mode"]   = settings.mode
 | 
| 
jbe/bsw@11
 | 
    52       params["_webmcp_routing." .. status .. ".module"] = module
 | 
| 
jbe/bsw@11
 | 
    53       params["_webmcp_routing." .. status .. ".view"]   = settings.view
 | 
| 
jbe/bsw@11
 | 
    54       params["_webmcp_routing." .. status .. ".id"]     = settings.id
 | 
| 
jbe/bsw@11
 | 
    55       if settings.params then
 | 
| 
jbe/bsw@11
 | 
    56         for key, value in pairs(settings.params) do
 | 
| 
jbe/bsw@11
 | 
    57           params["_webmcp_routing." .. status .. ".params." .. key] = value
 | 
| 
jbe/bsw@11
 | 
    58         end
 | 
| 
jbe/bsw@11
 | 
    59       end
 | 
| 
jbe/bsw@11
 | 
    60     end
 | 
| 
jbe/bsw@11
 | 
    61   end
 | 
| 
jbe/bsw@11
 | 
    62   if not routing_default_given then
 | 
| 
jbe/bsw@11
 | 
    63     params["_webmcp_routing.default.mode"]   = "forward"
 | 
| 
jbe/bsw@11
 | 
    64     params["_webmcp_routing.default.module"] = request.get_module()
 | 
| 
jbe/bsw@11
 | 
    65     params["_webmcp_routing.default.view"]   = request.get_view()
 | 
| 
jbe/bsw@11
 | 
    66   end
 | 
| 
jbe/bsw@11
 | 
    67   return params
 | 
| 
jbe/bsw@11
 | 
    68 end
 | 
| 
jbe/bsw@11
 | 
    69 
 | 
| 
jbe/bsw@0
 | 
    70 function ui.form(args)
 | 
| 
jbe/bsw@0
 | 
    71   local args = args or {}
 | 
| 
jbe/bsw@0
 | 
    72   local slot_state = slot.get_state_table()
 | 
| 
jbe/bsw@0
 | 
    73   local old_record   = slot_state.form_record
 | 
| 
jbe/bsw@0
 | 
    74   local old_readonly = slot_state.form_readonly
 | 
| 
jbe/bsw@0
 | 
    75   slot_state.form_record = args.record
 | 
| 
jbe/bsw@0
 | 
    76   if args.readonly then
 | 
| 
jbe/bsw@0
 | 
    77     slot_state.form_readonly = true
 | 
| 
jbe/bsw@0
 | 
    78     ui.container{ attr = args.attr, content = args.content }
 | 
| 
jbe/bsw@0
 | 
    79   else
 | 
| 
jbe/bsw@0
 | 
    80     slot_state.form_readonly = false
 | 
| 
jbe/bsw@0
 | 
    81     local params = table.new(args.params)
 | 
| 
jbe/bsw@11
 | 
    82     prepare_routing_params(params, args.routing, args.module)
 | 
| 
jbe/bsw@0
 | 
    83     params._webmcp_csrf_secret = request.get_csrf_secret()
 | 
| 
jbe/bsw@0
 | 
    84     local attr = table.new(args.attr)
 | 
| 
jbe/bsw@0
 | 
    85     attr.action = encode.url{
 | 
| 
jbe/bsw@0
 | 
    86       external  = args.external,
 | 
| 
jbe/bsw@0
 | 
    87       module    = args.module or request.get_module(),
 | 
| 
jbe/bsw@0
 | 
    88       view      = args.view,
 | 
| 
jbe/bsw@0
 | 
    89       action    = args.action,
 | 
| 
jbe/bsw@0
 | 
    90     }
 | 
| 
jbe/bsw@0
 | 
    91     attr.method = args.method and string.upper(args.method) or "POST"
 | 
| 
jbe/bsw@11
 | 
    92     if ui.is_partial_loading_enabled() and args.partial then
 | 
| 
jbe/bsw@11
 | 
    93       attr.onsubmit = slot.use_temporary(function()
 | 
| 
jbe/bsw@11
 | 
    94         local partial_mode = "form_normal"
 | 
| 
jbe/bsw@11
 | 
    95         if args.action then
 | 
| 
jbe/bsw@11
 | 
    96           partial_mode = "form_action"
 | 
| 
jbe/bsw@11
 | 
    97           slot.put(
 | 
| 
jbe/bsw@11
 | 
    98             'var element; ',
 | 
| 
jbe/bsw@11
 | 
    99             'var formElements = []; ',
 | 
| 
jbe/bsw@11
 | 
   100             'for (var i=0; i<this.elements.length; i++) { ',
 | 
| 
jbe/bsw@11
 | 
   101               'formElements[formElements.length] = this.elements[i]; ',
 | 
| 
jbe/bsw@11
 | 
   102             '} ',
 | 
| 
jbe/bsw@11
 | 
   103             'for (i=0; i<formElements.length; i++) { ',
 | 
| 
jbe/bsw@11
 | 
   104               'element = formElements[i]; ',
 | 
| 
jbe/bsw@11
 | 
   105               'if (element.name.search(/^_webmcp_routing\\./) >= 0) { ',
 | 
| 
jbe/bsw@11
 | 
   106                 'element.parentNode.removeChild(element); ',
 | 
| 
jbe/bsw@11
 | 
   107               '} ',
 | 
| 
jbe/bsw@11
 | 
   108             '}'
 | 
| 
jbe/bsw@11
 | 
   109           )
 | 
| 
jbe/bsw@11
 | 
   110           local routing_params = {}
 | 
| 
jbe/bsw@11
 | 
   111           prepare_routing_params(
 | 
| 
jbe/bsw@11
 | 
   112             routing_params,
 | 
| 
jbe/bsw@11
 | 
   113             args.partial.routing,
 | 
| 
jbe/bsw@11
 | 
   114             args.partial.module
 | 
| 
jbe/bsw@11
 | 
   115           )
 | 
| 
jbe/bsw@11
 | 
   116           for key, value in pairs(routing_params) do
 | 
| 
jbe/bsw@11
 | 
   117             slot.put(
 | 
| 
jbe/bsw@11
 | 
   118               ' ',
 | 
| 
jbe/bsw@11
 | 
   119               'element = document.createElement("input"); ',
 | 
| 
jbe/bsw@11
 | 
   120               'element.setAttribute("type", "hidden"); ',
 | 
| 
jbe/bsw@11
 | 
   121               'element.setAttribute("name", ', encode.json(key), '); ',
 | 
| 
jbe/bsw@11
 | 
   122               'element.setAttribute("value", ', encode.json(value), '); ',
 | 
| 
jbe/bsw@11
 | 
   123               'this.appendChild(element);'
 | 
| 
jbe/bsw@11
 | 
   124             )
 | 
| 
jbe/bsw@11
 | 
   125           end
 | 
| 
jbe/bsw@11
 | 
   126           slot.put(' ')
 | 
| 
jbe/bsw@11
 | 
   127         end
 | 
| 
jbe/bsw@11
 | 
   128         slot.put(ui._partial_load_js(args.partial, partial_mode))
 | 
| 
jbe/bsw@11
 | 
   129       end)
 | 
| 
jbe/bsw@11
 | 
   130     end
 | 
| 
jbe/bsw@0
 | 
   131     if slot_state.form_opened then
 | 
| 
jbe/bsw@0
 | 
   132       error("Cannot open a non-readonly form inside a non-readonly form.")
 | 
| 
jbe/bsw@0
 | 
   133     end
 | 
| 
jbe/bsw@0
 | 
   134     slot_state.form_opened = true
 | 
| 
jbe/bsw@0
 | 
   135     ui.tag {
 | 
| 
jbe/bsw@0
 | 
   136       tag     = "form",
 | 
| 
jbe/bsw@0
 | 
   137       attr    = attr,
 | 
| 
jbe/bsw@0
 | 
   138       content = function()
 | 
| 
jbe/bsw@0
 | 
   139         if args.id then
 | 
| 
jbe/bsw@0
 | 
   140           ui.hidden_field{ name = "_webmcp_id", value = args.id }
 | 
| 
jbe/bsw@0
 | 
   141         end
 | 
| 
jbe/bsw@0
 | 
   142         for key, value in pairs(params) do
 | 
| 
jbe/bsw@0
 | 
   143           ui.hidden_field{ name = key, value = value }
 | 
| 
jbe/bsw@0
 | 
   144         end
 | 
| 
jbe/bsw@0
 | 
   145         if args.content then
 | 
| 
jbe/bsw@0
 | 
   146           args.content()
 | 
| 
jbe/bsw@0
 | 
   147         end
 | 
| 
jbe/bsw@0
 | 
   148       end
 | 
| 
jbe/bsw@0
 | 
   149     }
 | 
| 
jbe/bsw@0
 | 
   150     slot_state.form_opened = false
 | 
| 
jbe/bsw@0
 | 
   151   end
 | 
| 
jbe/bsw@0
 | 
   152   slot_state.form_readonly = old_readonly
 | 
| 
jbe/bsw@0
 | 
   153   slot_state.form_record   = old_record
 | 
| 
jbe/bsw@0
 | 
   154 end
 |