webmcp
annotate framework/env/ui/list.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 | 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 |