webmcp
view framework/env/ui/multiselect.lua @ 2:72860d232f32
Version 1.0.2
Fixed bug with explicit garbage collection (requests > 256kB caused an error)
Views prefixed with an underscore can't be called externally
ui.paginate now displays the last page, if the selected page number is too high.
Fixed bug with explicit garbage collection (requests > 256kB caused an error)
Views prefixed with an underscore can't be called externally
ui.paginate now displays the last page, if the selected page number is too high.
| author | jbe/bsw | 
|---|---|
| date | Thu Dec 10 12:00:00 2009 +0100 (2009-12-10) | 
| parents | 9fdfb27f8e67 | 
| children | 81dfcfd960ed | 
 line source
     1 --[[--
     2 ui.multiselect{
     3   name               = name,                -- HTML name ('html_name' is NOT a valid argument for this function)
     4   container_attr     = container_attr,      -- extra HTML attributes for the container (div) enclosing field and label
     5   attr               = attr,                -- extra HTML attributes for the field
     6   label              = label,               -- text to be used as label for the input field
     7   label_attr         = label_attr,          -- extra HTML attributes for the label
     8   readonly           = readonly_flag        -- set to true, to force read-only mode
     9   foreign_records    = foreign_records,     -- list of records to be chosen from, or function returning such a list
    10   foreign_id         = foreign_id,          -- name of id field in foreign records
    11   foreign_name       = foreign_name,        -- name of field to be used as name in foreign records
    12   selected_ids       = selected_ids,        -- list of ids of currently selected foreign records
    13   connecting_records = connecting_records,  -- list of connection entries, determining which foreign records are currently selected
    14   own_id             = own_id,              -- TODO documentation needed
    15   own_reference      = own_reference,       -- name of foreign key field in connecting records, which references the main record
    16   foreign_reference  = foreign_reference,   -- name of foreign key field in connecting records, which references foreign records
    17   format_options     = format_options       -- format options for format.string
    18 }
    20 This function inserts a select field with possibility of multiple selections in the active slot. This function does not reside within ui.field.*, because multiple selections are not stored within a field of a record, but within a different SQL table. Note that 'html_name' is NOT a valid argument to this function. For description of the generic field helper arguments, see help for ui.autofield{...}.
    22 --]]--
    24 function ui.multiselect(args)
    25   local style = args.style or "checkbox"
    26   local extra_args = { fetch_record = true }
    27   if not args.readonly and args.style == "checkbox" then
    28     extra_args.disable_label_for_id = true
    29   end
    30   ui.form_element(args, extra_args, function(args)
    31     local foreign_records = args.foreign_records
    32     if type(foreign_records) == "function" then
    33       foreign_records = foreign_records(args.record)
    34     end
    35     local connecting_records = args.connecting_records
    36     if type(connecting_records) == "function" then
    37       connecting_records = connecting_records(args.record)
    38     end
    39     local select_hash = {}
    40     if args.selected_ids then
    41       for idx, selected_id in ipairs(args.selected_ids) do
    42         select_hash[selected_id] = true
    43       end
    44     elseif args.own_reference then
    45       for idx, connecting_record in ipairs(args.connecting_records) do
    46         if connecting_record[args.own_reference] == args.record[args.own_id] then
    47           select_hash[connecting_record[args.foreign_reference]] = true
    48         end
    49       end
    50     else
    51       for idx, connecting_record in ipairs(args.connecting_records) do
    52         select_hash[connecting_record[args.foreign_reference]] = true
    53       end
    54     end
    55     local attr = table.new(args.attr)
    56     if not attr.class then
    57       attr.class = "ui_multi_selection"
    58     end
    59     if args.readonly then
    60       ui.tag{
    61         tag     = "ul",
    62         attr    = attr,
    63         content = function()
    64           for idx, record in ipairs(foreign_records) do
    65             if select_hash[record[args.foreign_id]] then
    66               ui.tag{
    67                 tag     = "li",
    68                 content = format.string(
    69                   record[args.foreign_name],
    70                   args.format_options
    71                 )
    72               }
    73             end
    74           end
    75         end
    76       }
    77     elseif style == "select" then
    78       attr.name     = args.name
    79       attr.multiple = "multiple"
    80       ui.tag{
    81         tag     = "select",
    82         attr    = attr,
    83         content = function()
    84           if args.nil_as then
    85             ui.tag{
    86               tag     = "option",
    87               attr    = { value = "" },
    88               content = format.string(
    89                 args.nil_as,
    90                 args.format_options
    91               )
    92             }
    93           end
    94           for idx, record in ipairs(foreign_records) do
    95             local key = record[args.foreign_id]
    96             local selected = select_hash[key]
    97             ui.tag{
    98               tag     = "option",
    99               attr    = {
   100                 value    = key,
   101                 selected = (selected and "selected" or nil)
   102               },
   103               content = format.string(
   104                 record[args.foreign_name],
   105                 args.format_options
   106               )
   107             }
   108           end
   109         end
   110       }
   111     elseif style == "checkbox" then
   112       attr.type = "checkbox"
   113       attr.name = args.name
   114       for idx, record in ipairs(foreign_records) do
   115         local key = record[args.foreign_id]
   116         local selected = select_hash[key]
   117         attr.id   = ui.create_unique_id()
   118         attr.value = key
   119         attr.checked = selected and "checked" or nil
   120         ui.container{
   121           label = format.string(
   122             record[args.foreign_name],
   123             args.format_options
   124           ),
   125           attr          = { class = "ui_checkbox_div" },
   126           label_for     = attr.id,
   127           label_attr    = { class = "ui_checkbox_label" },
   128           content_first = true,
   129           content       = function()
   130             ui.tag{ tag  = "input", attr = attr }
   131           end
   132         }
   133       end
   134     else
   135       error("'style' attribute for ui.multiselect{...} must be set to \"select\", \"checkbox\" or nil.")
   136     end
   137   end)
   138 end
