| rev | 
   line source | 
| 
jbe/bsw@0
 | 
     1 --[[--
 | 
| 
jbe/bsw@0
 | 
     2 ui.multiselect{
 | 
| 
jbe/bsw@0
 | 
     3   name               = name,                -- HTML name ('html_name' is NOT a valid argument for this function)
 | 
| 
jbe/bsw@0
 | 
     4   container_attr     = container_attr,      -- extra HTML attributes for the container (div) enclosing field and label
 | 
| 
jbe/bsw@0
 | 
     5   attr               = attr,                -- extra HTML attributes for the field
 | 
| 
jbe/bsw@0
 | 
     6   label              = label,               -- text to be used as label for the input field
 | 
| 
jbe/bsw@0
 | 
     7   label_attr         = label_attr,          -- extra HTML attributes for the label
 | 
| 
jbe/bsw@0
 | 
     8   readonly           = readonly_flag        -- set to true, to force read-only mode
 | 
| 
jbe/bsw@0
 | 
     9   foreign_records    = foreign_records,     -- list of records to be chosen from, or function returning such a list
 | 
| 
jbe/bsw@0
 | 
    10   foreign_id         = foreign_id,          -- name of id field in foreign records
 | 
| 
jbe/bsw@0
 | 
    11   foreign_name       = foreign_name,        -- name of field to be used as name in foreign records
 | 
| 
jbe/bsw@0
 | 
    12   selected_ids       = selected_ids,        -- list of ids of currently selected foreign records
 | 
| 
jbe/bsw@0
 | 
    13   connecting_records = connecting_records,  -- list of connection entries, determining which foreign records are currently selected
 | 
| 
jbe/bsw@0
 | 
    14   own_id             = own_id,              -- TODO documentation needed
 | 
| 
jbe/bsw@0
 | 
    15   own_reference      = own_reference,       -- name of foreign key field in connecting records, which references the main record
 | 
| 
jbe/bsw@0
 | 
    16   foreign_reference  = foreign_reference,   -- name of foreign key field in connecting records, which references foreign records
 | 
| 
jbe/bsw@0
 | 
    17   format_options     = format_options       -- format options for format.string
 | 
| 
jbe/bsw@0
 | 
    18 }
 | 
| 
jbe/bsw@0
 | 
    19 
 | 
| 
jbe/bsw@0
 | 
    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{...}.
 | 
| 
jbe/bsw@0
 | 
    21 
 | 
| 
jbe/bsw@0
 | 
    22 --]]--
 | 
| 
jbe/bsw@0
 | 
    23 
 | 
| 
jbe/bsw@0
 | 
    24 function ui.multiselect(args)
 | 
| 
jbe/bsw@0
 | 
    25   local style = args.style or "checkbox"
 | 
| 
jbe/bsw@0
 | 
    26   local extra_args = { fetch_record = true }
 | 
| 
jbe/bsw@0
 | 
    27   if not args.readonly and args.style == "checkbox" then
 | 
| 
jbe/bsw@0
 | 
    28     extra_args.disable_label_for_id = true
 | 
| 
jbe/bsw@0
 | 
    29   end
 | 
| 
jbe/bsw@0
 | 
    30   ui.form_element(args, extra_args, function(args)
 | 
| 
jbe/bsw@0
 | 
    31     local foreign_records = args.foreign_records
 | 
| 
jbe/bsw@0
 | 
    32     if type(foreign_records) == "function" then
 | 
| 
jbe/bsw@0
 | 
    33       foreign_records = foreign_records(args.record)
 | 
| 
jbe/bsw@0
 | 
    34     end
 | 
| 
jbe/bsw@0
 | 
    35     local connecting_records = args.connecting_records
 | 
| 
jbe/bsw@0
 | 
    36     if type(connecting_records) == "function" then
 | 
| 
jbe/bsw@0
 | 
    37       connecting_records = connecting_records(args.record)
 | 
| 
jbe/bsw@0
 | 
    38     end
 | 
| 
jbe/bsw@0
 | 
    39     local select_hash = {}
 | 
| 
jbe/bsw@0
 | 
    40     if args.selected_ids then
 | 
| 
jbe/bsw@0
 | 
    41       for idx, selected_id in ipairs(args.selected_ids) do
 | 
| 
jbe/bsw@0
 | 
    42         select_hash[selected_id] = true
 | 
| 
jbe/bsw@0
 | 
    43       end
 | 
| 
jbe/bsw@0
 | 
    44     elseif args.own_reference then
 | 
| 
jbe/bsw@0
 | 
    45       for idx, connecting_record in ipairs(args.connecting_records) do
 | 
| 
jbe/bsw@0
 | 
    46         if connecting_record[args.own_reference] == args.record[args.own_id] then
 | 
| 
jbe/bsw@0
 | 
    47           select_hash[connecting_record[args.foreign_reference]] = true
 | 
| 
jbe/bsw@0
 | 
    48         end
 | 
| 
jbe/bsw@0
 | 
    49       end
 | 
| 
jbe/bsw@0
 | 
    50     else
 | 
| 
jbe/bsw@0
 | 
    51       for idx, connecting_record in ipairs(args.connecting_records) do
 | 
| 
jbe/bsw@0
 | 
    52         select_hash[connecting_record[args.foreign_reference]] = true
 | 
| 
jbe/bsw@0
 | 
    53       end
 | 
| 
jbe/bsw@0
 | 
    54     end
 | 
| 
jbe/bsw@0
 | 
    55     local attr = table.new(args.attr)
 | 
| 
jbe/bsw@0
 | 
    56     if not attr.class then
 | 
| 
jbe/bsw@0
 | 
    57       attr.class = "ui_multi_selection"
 | 
| 
jbe/bsw@0
 | 
    58     end
 | 
| 
jbe/bsw@0
 | 
    59     if args.readonly then
 | 
| 
jbe/bsw@0
 | 
    60       ui.tag{
 | 
| 
jbe/bsw@0
 | 
    61         tag     = "ul",
 | 
| 
jbe/bsw@0
 | 
    62         attr    = attr,
 | 
| 
jbe/bsw@0
 | 
    63         content = function()
 | 
| 
jbe/bsw@0
 | 
    64           for idx, record in ipairs(foreign_records) do
 | 
| 
jbe/bsw@0
 | 
    65             if select_hash[record[args.foreign_id]] then
 | 
| 
jbe/bsw@0
 | 
    66               ui.tag{
 | 
| 
jbe/bsw@0
 | 
    67                 tag     = "li",
 | 
| 
jbe/bsw@0
 | 
    68                 content = format.string(
 | 
| 
jbe/bsw@0
 | 
    69                   record[args.foreign_name],
 | 
| 
jbe/bsw@0
 | 
    70                   args.format_options
 | 
| 
jbe/bsw@0
 | 
    71                 )
 | 
| 
jbe/bsw@0
 | 
    72               }
 | 
| 
jbe/bsw@0
 | 
    73             end
 | 
| 
jbe/bsw@0
 | 
    74           end
 | 
| 
jbe/bsw@0
 | 
    75         end
 | 
| 
jbe/bsw@0
 | 
    76       }
 | 
| 
jbe/bsw@0
 | 
    77     elseif style == "select" then
 | 
| 
jbe/bsw@0
 | 
    78       attr.name     = args.name
 | 
| 
jbe/bsw@0
 | 
    79       attr.multiple = "multiple"
 | 
| 
jbe/bsw@0
 | 
    80       ui.tag{
 | 
| 
jbe/bsw@0
 | 
    81         tag     = "select",
 | 
| 
jbe/bsw@0
 | 
    82         attr    = attr,
 | 
| 
jbe/bsw@0
 | 
    83         content = function()
 | 
| 
jbe/bsw@0
 | 
    84           if args.nil_as then
 | 
| 
jbe/bsw@0
 | 
    85             ui.tag{
 | 
| 
jbe/bsw@0
 | 
    86               tag     = "option",
 | 
| 
jbe/bsw@0
 | 
    87               attr    = { value = "" },
 | 
| 
jbe/bsw@0
 | 
    88               content = format.string(
 | 
| 
jbe/bsw@0
 | 
    89                 args.nil_as,
 | 
| 
jbe/bsw@0
 | 
    90                 args.format_options
 | 
| 
jbe/bsw@0
 | 
    91               )
 | 
| 
jbe/bsw@0
 | 
    92             }
 | 
| 
jbe/bsw@0
 | 
    93           end
 | 
| 
jbe/bsw@0
 | 
    94           for idx, record in ipairs(foreign_records) do
 | 
| 
jbe/bsw@0
 | 
    95             local key = record[args.foreign_id]
 | 
| 
jbe/bsw@0
 | 
    96             local selected = select_hash[key]
 | 
| 
jbe/bsw@0
 | 
    97             ui.tag{
 | 
| 
jbe/bsw@0
 | 
    98               tag     = "option",
 | 
| 
jbe/bsw@0
 | 
    99               attr    = {
 | 
| 
jbe/bsw@0
 | 
   100                 value    = key,
 | 
| 
jbe/bsw@0
 | 
   101                 selected = (selected and "selected" or nil)
 | 
| 
jbe/bsw@0
 | 
   102               },
 | 
| 
jbe/bsw@0
 | 
   103               content = format.string(
 | 
| 
jbe/bsw@0
 | 
   104                 record[args.foreign_name],
 | 
| 
jbe/bsw@0
 | 
   105                 args.format_options
 | 
| 
jbe/bsw@0
 | 
   106               )
 | 
| 
jbe/bsw@0
 | 
   107             }
 | 
| 
jbe/bsw@0
 | 
   108           end
 | 
| 
jbe/bsw@0
 | 
   109         end
 | 
| 
jbe/bsw@0
 | 
   110       }
 | 
| 
jbe/bsw@0
 | 
   111     elseif style == "checkbox" then
 | 
| 
jbe/bsw@0
 | 
   112       attr.type = "checkbox"
 | 
| 
jbe/bsw@0
 | 
   113       attr.name = args.name
 | 
| 
jbe/bsw@0
 | 
   114       for idx, record in ipairs(foreign_records) do
 | 
| 
jbe/bsw@0
 | 
   115         local key = record[args.foreign_id]
 | 
| 
jbe/bsw@0
 | 
   116         local selected = select_hash[key]
 | 
| 
jbe/bsw@0
 | 
   117         attr.id   = ui.create_unique_id()
 | 
| 
jbe/bsw@0
 | 
   118         attr.value = key
 | 
| 
jbe/bsw@0
 | 
   119         attr.checked = selected and "checked" or nil
 | 
| 
jbe/bsw@0
 | 
   120         ui.container{
 | 
| 
jbe/bsw@0
 | 
   121           label = format.string(
 | 
| 
jbe/bsw@0
 | 
   122             record[args.foreign_name],
 | 
| 
jbe/bsw@0
 | 
   123             args.format_options
 | 
| 
jbe/bsw@0
 | 
   124           ),
 | 
| 
jbe/bsw@0
 | 
   125           attr          = { class = "ui_checkbox_div" },
 | 
| 
jbe/bsw@0
 | 
   126           label_for     = attr.id,
 | 
| 
jbe/bsw@0
 | 
   127           label_attr    = { class = "ui_checkbox_label" },
 | 
| 
jbe/bsw@0
 | 
   128           content_first = true,
 | 
| 
jbe/bsw@0
 | 
   129           content       = function()
 | 
| 
jbe/bsw@0
 | 
   130             ui.tag{ tag  = "input", attr = attr }
 | 
| 
jbe/bsw@0
 | 
   131           end
 | 
| 
jbe/bsw@0
 | 
   132         }
 | 
| 
jbe/bsw@0
 | 
   133       end
 | 
| 
jbe/bsw@0
 | 
   134     else
 | 
| 
jbe/bsw@0
 | 
   135       error("'style' attribute for ui.multiselect{...} must be set to \"select\", \"checkbox\" or nil.")
 | 
| 
jbe/bsw@0
 | 
   136     end
 | 
| 
jbe/bsw@0
 | 
   137   end)
 | 
| 
jbe/bsw@0
 | 
   138 end
 |