webmcp
annotate framework/env/ui/list.lua @ 6:5cba83b3f411
Version 1.0.6
Bugfix: class_prototype:add_reference{...} uses now qualified names in SQL queries to allow JOINs
Fixes in the documentation of slot.put_into and trace.debug
Bugfix: class_prototype:add_reference{...} uses now qualified names in SQL queries to allow JOINs
Fixes in the documentation of slot.put_into and trace.debug
| author | jbe/bsw | 
|---|---|
| date | Fri Jan 22 12:00:00 2010 +0100 (2010-01-22) | 
| parents | 9fdfb27f8e67 | 
| children | 10275e753a22 | 
| rev | line source | 
|---|---|
| jbe/bsw@0 | 1 --[[-- | 
| jbe/bsw@0 | 2 ui.list{ | 
| jbe/bsw@0 | 3 label = list_label, -- optional label for the whole list | 
| jbe/bsw@0 | 4 style = style, -- "table", "ulli" or "div" | 
| jbe/bsw@0 | 5 prefix = prefix, -- prefix for HTML field names | 
| jbe/bsw@0 | 6 records = records, -- array of records to be displayed as rows in the list | 
| jbe/bsw@0 | 7 columns = { | 
| jbe/bsw@0 | 8 { | 
| jbe/bsw@0 | 9 label = column_label, -- label for the column | 
| jbe/bsw@0 | 10 label_attr = label_attr, -- table with HTML attributes for the heading cell or div | 
| jbe/bsw@0 | 11 field_attr = field_attr, -- table with HTML attributes for the data cell or div | 
| jbe/bsw@0 | 12 name = name, -- name of the field in each record | 
| jbe/bsw@0 | 13 html_name = html_name, -- optional html-name for writable fields (defaults to name) | 
| jbe/bsw@0 | 14 ui_field_type = ui_field_type, -- name of the ui.field.* function to use | 
| jbe/bsw@0 | 15 ...., -- other options for the given ui.field.* functions | 
| jbe/bsw@0 | 16 format = format, -- name of the format function to be used (if not using ui_field_type) | 
| jbe/bsw@0 | 17 format_options = format_options, -- options to be passed to the format function | 
| jbe/bsw@0 | 18 content = content -- function to output field data per record (ignoring name, format, ...) | 
| jbe/bsw@0 | 19 }, | 
| jbe/bsw@0 | 20 { ... }, | 
| jbe/bsw@0 | 21 ... | 
| jbe/bsw@0 | 22 } | 
| jbe/bsw@0 | 23 } | 
| jbe/bsw@0 | 24 | 
| jbe/bsw@0 | 25 This function takes an array of records to be displayed in a list. The whole list may have a label. The style's "table" (for <table>), "ulli" (for <ul><li>) and "div" (just using <div> tags) are supported. For each column several options must be specified. | 
| jbe/bsw@0 | 26 | 
| jbe/bsw@0 | 27 --]]-- | 
| jbe/bsw@0 | 28 | 
| jbe/bsw@0 | 29 -- TODO: documentation of the prefix option | 
| jbe/bsw@0 | 30 -- TODO: check short descriptions of fields in documentation | 
| jbe/bsw@0 | 31 -- TODO: field_attr is used for the OUTER html tag's attributes, while attr is used for the INNER html tag's attributes (produced by ui.field.*), is that okay? | 
| jbe/bsw@0 | 32 -- TODO: use field information of record class, if no columns are given | 
| jbe/bsw@0 | 33 -- TODO: callback to set row attr's for a specific row | 
| jbe/bsw@0 | 34 | 
| jbe/bsw@0 | 35 function ui.list(args) | 
| jbe/bsw@0 | 36 local args = args or {} | 
| jbe/bsw@0 | 37 local label = args.label | 
| jbe/bsw@0 | 38 local list_type = args.style or "table" | 
| jbe/bsw@0 | 39 local prefix = args.prefix | 
| jbe/bsw@0 | 40 local records = assert(args.records, "ui.list{...} needs records.") | 
| jbe/bsw@0 | 41 local columns = assert(args.columns, "ui.list{...} needs column definitions.") | 
| jbe/bsw@0 | 42 local outer_attr = table.new(args.attr) | 
| jbe/bsw@0 | 43 local header_existent = false | 
| jbe/bsw@0 | 44 for idx, column in ipairs(columns) do | 
| jbe/bsw@0 | 45 if column.label then | 
| jbe/bsw@0 | 46 header_existent = true | 
| jbe/bsw@0 | 47 break | 
| jbe/bsw@0 | 48 end | 
| jbe/bsw@0 | 49 end | 
| jbe/bsw@0 | 50 local slot_state = slot.get_state_table() | 
| jbe/bsw@0 | 51 local outer_tag, head_tag, head_tag2, label_tag, body_tag, row_tag | 
| jbe/bsw@0 | 52 if list_type == "table" then | 
| jbe/bsw@0 | 53 outer_tag = "table" | 
| jbe/bsw@0 | 54 head_tag = "thead" | 
| jbe/bsw@0 | 55 head_tag2 = "tr" | 
| jbe/bsw@0 | 56 label_tag = "th" | 
| jbe/bsw@0 | 57 body_tag = "tbody" | 
| jbe/bsw@0 | 58 row_tag = "tr" | 
| jbe/bsw@0 | 59 field_tag = "td" | 
| jbe/bsw@0 | 60 elseif list_type == "ulli" then | 
| jbe/bsw@0 | 61 outer_tag = "div" | 
| jbe/bsw@0 | 62 head_tag = "div" | 
| jbe/bsw@0 | 63 label_tag = "div" | 
| jbe/bsw@0 | 64 body_tag = "ul" | 
| jbe/bsw@0 | 65 row_tag = "li" | 
| jbe/bsw@0 | 66 field_tag = "td" | 
| jbe/bsw@0 | 67 elseif list_type == "div" then | 
| jbe/bsw@0 | 68 outer_tag = "div" | 
| jbe/bsw@0 | 69 head_tag = "div" | 
| jbe/bsw@0 | 70 label_tag = "div" | 
| jbe/bsw@0 | 71 body_tag = "div" | 
| jbe/bsw@0 | 72 row_tag = "div" | 
| jbe/bsw@0 | 73 field_tag = "div" | 
| jbe/bsw@0 | 74 else | 
| jbe/bsw@0 | 75 error("Unknown list type specified for ui.list{...}.") | 
| jbe/bsw@0 | 76 end | 
| jbe/bsw@0 | 77 outer_attr.class = outer_attr.class or "ui_list" | 
| jbe/bsw@0 | 78 ui.container{ | 
| jbe/bsw@0 | 79 auto_args = args, | 
| jbe/bsw@0 | 80 content = function() | 
| jbe/bsw@0 | 81 ui.tag{ | 
| jbe/bsw@0 | 82 tag = outer_tag, | 
| jbe/bsw@0 | 83 attr = outer_attr, | 
| jbe/bsw@0 | 84 content = function() | 
| jbe/bsw@0 | 85 if header_existent then | 
| jbe/bsw@0 | 86 ui.tag{ | 
| jbe/bsw@0 | 87 tag = head_tag, | 
| jbe/bsw@0 | 88 attr = { class = "ui_list_head" }, | 
| jbe/bsw@0 | 89 content = function() | 
| jbe/bsw@0 | 90 local function header_content() | 
| jbe/bsw@0 | 91 for idx, column in ipairs(columns) do | 
| jbe/bsw@0 | 92 if column.ui_field_type ~= "hidden" then | 
| jbe/bsw@0 | 93 local label_attr = table.new(column.label_attr) | 
| jbe/bsw@0 | 94 label_attr.class = | 
| jbe/bsw@0 | 95 label_attr.class or { class = "ui_list_label" } | 
| jbe/bsw@0 | 96 ui.tag{ | 
| jbe/bsw@0 | 97 tag = label_tag, | 
| jbe/bsw@0 | 98 attr = label_attr, | 
| jbe/bsw@0 | 99 content = column.label or "" | 
| jbe/bsw@0 | 100 } | 
| jbe/bsw@0 | 101 end | 
| jbe/bsw@0 | 102 end | 
| jbe/bsw@0 | 103 end | 
| jbe/bsw@0 | 104 if head_tag2 then | 
| jbe/bsw@0 | 105 ui.tag{ tag = head_tag2, content = header_content } | 
| jbe/bsw@0 | 106 else | 
| jbe/bsw@0 | 107 header_content() | 
| jbe/bsw@0 | 108 end | 
| jbe/bsw@0 | 109 end | 
| jbe/bsw@0 | 110 } | 
| jbe/bsw@0 | 111 end | 
| jbe/bsw@0 | 112 ui.tag{ | 
| jbe/bsw@0 | 113 tag = body_tag, | 
| jbe/bsw@0 | 114 attr = { class = "ui_list_body" }, | 
| jbe/bsw@0 | 115 content = function() | 
| jbe/bsw@0 | 116 for record_idx, record in ipairs(records) do | 
| jbe/bsw@0 | 117 local row_class | 
| jbe/bsw@0 | 118 if record_idx % 2 == 0 then | 
| jbe/bsw@0 | 119 row_class = "ui_list_row ui_list_even" | 
| jbe/bsw@0 | 120 else | 
| jbe/bsw@0 | 121 row_class = "ui_list_row ui_list_odd" | 
| jbe/bsw@0 | 122 end | 
| jbe/bsw@0 | 123 ui.tag{ | 
| jbe/bsw@0 | 124 tag = row_tag, | 
| jbe/bsw@0 | 125 attr = { class = row_class }, | 
| jbe/bsw@0 | 126 content = function() | 
| jbe/bsw@0 | 127 local old_html_name_prefix, old_form_record | 
| jbe/bsw@0 | 128 if prefix then | 
| jbe/bsw@0 | 129 old_html_name_prefix = slot_state.html_name_prefix | 
| jbe/bsw@0 | 130 old_form_record = slot_state.form_record | 
| jbe/bsw@0 | 131 slot_state.html_name_prefix = prefix .. "[" .. record_idx .. "]" | 
| jbe/bsw@0 | 132 slot_state.form_record = record | 
| jbe/bsw@0 | 133 end | 
| jbe/bsw@0 | 134 local first_column = true | 
| jbe/bsw@0 | 135 for column_idx, column in ipairs(columns) do | 
| jbe/bsw@0 | 136 if column.ui_field_type ~= "hidden" then | 
| jbe/bsw@0 | 137 local field_attr = table.new(column.field_attr) | 
| jbe/bsw@0 | 138 field_attr.class = | 
| jbe/bsw@0 | 139 field_attr.class or { class = "ui_list_field" } | 
| jbe/bsw@0 | 140 local field_content | 
| jbe/bsw@0 | 141 if column.content then | 
| jbe/bsw@0 | 142 field_content = function() | 
| jbe/bsw@0 | 143 return column.content(record) | 
| jbe/bsw@0 | 144 end | 
| jbe/bsw@0 | 145 elseif column.name then | 
| jbe/bsw@0 | 146 if column.ui_field_type then | 
| jbe/bsw@0 | 147 local ui_field_func = ui.field[column.ui_field_type] | 
| jbe/bsw@0 | 148 if not ui_field_func then | 
| jbe/bsw@0 | 149 error('Unknown ui_field_type "' .. column.ui_field_type .. '".') | 
| jbe/bsw@0 | 150 end | 
| jbe/bsw@0 | 151 local ui_field_options = table.new(column) | 
| jbe/bsw@0 | 152 ui_field_options.record = record | 
| jbe/bsw@0 | 153 ui_field_options.label = nil | 
| jbe/bsw@0 | 154 if not prefix and ui_field_options.readonly == nil then | 
| jbe/bsw@0 | 155 ui_field_options.readonly = true | 
| jbe/bsw@0 | 156 end | 
| jbe/bsw@0 | 157 field_content = function() | 
| jbe/bsw@0 | 158 return ui.field[column.ui_field_type](ui_field_options) | 
| jbe/bsw@0 | 159 end | 
| jbe/bsw@0 | 160 elseif column.format then | 
| jbe/bsw@0 | 161 local formatter = format[column.format] | 
| jbe/bsw@0 | 162 if not formatter then | 
| jbe/bsw@0 | 163 error('Unknown format "' .. column.format .. '".') | 
| jbe/bsw@0 | 164 end | 
| jbe/bsw@0 | 165 field_content = formatter( | 
| jbe/bsw@0 | 166 record[column.name], column.format_options | 
| jbe/bsw@0 | 167 ) | 
| jbe/bsw@0 | 168 else | 
| jbe/bsw@0 | 169 field_content = function() | 
| jbe/bsw@0 | 170 return ui.autofield{ | 
| jbe/bsw@0 | 171 record = record, | 
| jbe/bsw@0 | 172 name = column.name, | 
| jbe/bsw@0 | 173 html_name = column.html_name | 
| jbe/bsw@0 | 174 } | 
| jbe/bsw@0 | 175 end | 
| jbe/bsw@0 | 176 end | 
| jbe/bsw@0 | 177 else | 
| jbe/bsw@0 | 178 error("Each column needs either a 'content' or a 'name'.") | 
| jbe/bsw@0 | 179 end | 
| jbe/bsw@0 | 180 local extended_field_content | 
| jbe/bsw@0 | 181 if first_column then | 
| jbe/bsw@0 | 182 first_column = false | 
| jbe/bsw@0 | 183 extended_field_content = function() | 
| jbe/bsw@0 | 184 for column_idx, column in ipairs(columns) do | 
| jbe/bsw@0 | 185 if column.ui_field_type == "hidden" then | 
| jbe/bsw@0 | 186 local ui_field_options = table.new(column) | 
| jbe/bsw@0 | 187 ui_field_options.record = record | 
| jbe/bsw@0 | 188 ui_field_options.label = nil | 
| jbe/bsw@0 | 189 if not prefix and ui_field_options.readonly == nil then | 
| jbe/bsw@0 | 190 ui_field_options.readonly = true | 
| jbe/bsw@0 | 191 end | 
| jbe/bsw@0 | 192 ui.field.hidden(ui_field_options) | 
| jbe/bsw@0 | 193 end | 
| jbe/bsw@0 | 194 end | 
| jbe/bsw@0 | 195 field_content() | 
| jbe/bsw@0 | 196 end | 
| jbe/bsw@0 | 197 else | 
| jbe/bsw@0 | 198 extended_field_content = field_content | 
| jbe/bsw@0 | 199 end | 
| jbe/bsw@0 | 200 ui.tag{ | 
| jbe/bsw@0 | 201 tag = field_tag, | 
| jbe/bsw@0 | 202 attr = field_attr, | 
| jbe/bsw@0 | 203 content = extended_field_content | 
| jbe/bsw@0 | 204 } | 
| jbe/bsw@0 | 205 end | 
| jbe/bsw@0 | 206 end | 
| jbe/bsw@0 | 207 if prefix then | 
| jbe/bsw@0 | 208 slot_state.html_name_prefix = old_html_name_prefix | 
| jbe/bsw@0 | 209 slot_state.form_record = old_form_record | 
| jbe/bsw@0 | 210 end | 
| jbe/bsw@0 | 211 end | 
| jbe/bsw@0 | 212 } | 
| jbe/bsw@0 | 213 end | 
| jbe/bsw@0 | 214 end | 
| jbe/bsw@0 | 215 } | 
| jbe/bsw@0 | 216 end | 
| jbe/bsw@0 | 217 } | 
| jbe/bsw@0 | 218 end | 
| jbe/bsw@0 | 219 } | 
| jbe/bsw@0 | 220 if prefix then | 
| jbe/bsw@0 | 221 -- ui.field.hidden is used instead of ui.hidden_field to suppress output in case of read-only mode. | 
| jbe/bsw@0 | 222 ui.field.hidden{ | 
| jbe/bsw@0 | 223 html_name = prefix .. "[len]", | 
| jbe/bsw@0 | 224 value = #records | 
| jbe/bsw@0 | 225 } | 
| jbe/bsw@0 | 226 end | 
| jbe/bsw@0 | 227 end |