[% # Internal documentation for the DYNATABLE block # The block generates a table, originally designed to move over all # report generating code to a common framework; deduplicating the # HTML/txt/csv/pdf table generation code as it was all over the place # Note that the block is designed to be used both as a regular output # table as well as an input table. As a result it can be used with/as # part of a form. When used with a form, the following auto-generated # fields (not specified as input) are included in the submitted data: # - rowcount_: total number of rows in body and footer # - row_ : the row_id belonging to row # Other fields are mapped to their fieldnames: # []_ # Note that URLs computed from href_base and XX_href_suffix as well as # order_url will be URL encoded by this block # The block takes the following arguments: # - attributes : a hash of attributes (specified below) # - columns : an array of hashes specifying per-column attributes # - hide_header : a boolean, used to suppress
...
# - tbody : a hash of values to be used for the body (see below) # - tfoot : a hash of values to be used for
...
# the 'attributes' hash supports the following attributes: # - id : the value for the table's "id" attribute # - class : the (additional) css classes to be applied to the table # - width : the value to be used for the table's "width" attribute # - order_url : URL to be used to change the column sort order # - input_prefix : Prefix to be applied to all inputs on the table, # allowing multiple tables in a single # the elements in the 'columns' array support these attributes: # - type : can be any of 'input_text', 'href', 'hidden', 'checkbox' # 'radio', 'text', 'boolean_checkmark', 'select' # - col_id : the internal identifier for the column # - class : the (additional) css classes to be applied to the column # - data_dojo_type : Dojo type for the inputs in the column # - name : the value presented in the table header for this column # - toggle : a boolean indicating that the header is to be a button # changing state of the checkboxes in its column # - href_base : the URL base to use for 'href' typed columns # - href_target : value for the 'target' attribute of the 'a' tag # - options : items to be selected from in case of SELECT type # - default_blank: (boolean) indicates a blank drop down item should be added # the elements in the 'tbody' hash support these attributes: # - rows : an array of hashes with the values for each column # - NOINPUT : boolean suppressing inputs on this row for input columns # - html_class : the (additional) css classes to be applied to the row # - row_id : value identifying the row (usually the primary key) # - ${col_id} : value to be used for column with 'col_id' eq ${col_id} # - ${col_id}_href_suffix : the URL fragment to be appended to the # href_base value specified by ${col_id} # when that's an 'href' typed column # - ${col_id}_NOHREF : boolean suppressing 'href'; using 'text' # - ${col_id}_ROWSPAN : integer number of rows to span # - ${col_id}_ROWSPANNED : boolean indicating cell is spanned by a prior row # the elements in the 'tfoot' hash support these attributes: # - rows : an array of hashes with the values for each column # - col_types : a hash of ${col_id} values, overriding the column's # type, including 'spacer' as a supported type # - dojo_type : overrides the column's ${data_dojo_type} -%] [% BLOCK dynatable %]

[%- IF !hide_header %]
[% FOREACH COL IN columns; IF COL.type == 'hidden'; %] | [% ELSE %] | [% IF attributes.order_url and not COL.toggle ; # the order url is already to be URL encoded -- Report.pm takes care of that %][% COL.name %][% ELSIF COL.toggle ; query = "input[name^=\\'" _ PFX _ COL.col_id _ "_\\']"; %] [% ELSE; COL.name; END; %] [%- END; END; %]
--- | --- | ---
[% END -%]
[% ROWCOUNT = 0; PFX = attributes.input_prefix; FOREACH ROW IN tbody.rows; ROWCOUNT = ROWCOUNT + 1 -%]
[% PROCESS input element_data = { type="hidden" name=PFX _ "row_" _ ROWCOUNT value=ROW.row_id }; %] [% FOREACH COL IN columns; ROWSPANNED = COL.col_id _ "_ROWSPANNED"; IF ROW.$ROWSPANNED; NEXT; END; ROWSPAN = COL.col_id _ "_ROWSPAN"; IF ROW.$ROWSPAN; ROWSPAN=" rowspan=\"" _ ROW.$ROWSPAN _ "\""; ELSE; ROWSPAN=""; END; TYPE = COL.type; NOHREF = COL.col_id _ "_NOHREF"; IF (ROW.NOINPUT AND TYPE != 'href' AND TYPE != 'hidden') OR (ROW.$NOHREF AND TYPE == 'href'); TYPE = 'text'; END; IF TYPE == 'hidden'; NAME = PFX _ COL.col_id _ '_' _ ROW.row_id; %] | [% PROCESS input element_data = { type = "hidden" name = NAME value = ROW.${COL.col_id} }; %] [% ELSE; -%] | [% IF TYPE == 'text'; ROW.${COL.col_id}; ELSIF TYPE == 'input_text'; PROCESS input element_data = { id=PFX _ COL.col_id _ '-' _ ROWCOUNT type="text" "data-dojo-type" = COL.data_dojo_type class=COL.class name=PFX _ COL.col_id _ '_' _ ROW.row_id value=ROW.${COL.col_id} }; ELSIF TYPE == 'password'; PROCESS input element_data = { id=PFX _ COL.col_id _ '-' _ ROWCOUNT type="password" "data-dojo-type" = COL.data_dojo_type class=COL.class name=PFX _ COL.col_id _ '_' _ ROW.row_id value=ROW.${COL.col_id} }; ELSIF TYPE == 'checkbox'; IF ROW.row_id.defined; PROCESS input element_data = { id=PFX _ COL.col_id _ '-' _ ROWCOUNT type="checkbox" name=PFX _ COL.col_id _ '_' _ ROWCOUNT class=COL.class value=ROW.row_id checked=(ROW.${COL.col_id} ? "checked" : '') }; END; ELSIF TYPE == 'boolean_checkmark'; IF ROW.${COL.col_id}; '✓'; END; ELSIF TYPE == 'radio'; PROCESS input element_data = { id=PFX _ COL.col_id _ '-' _ ROWCOUNT type="radio" name=PFX _ COL.col_id class=COL.class value=ROW.row_id checked=(ROW.${COL.col_id} ? "checked" : '') }; ELSIF TYPE == 'select'; # ROW is passed as an argument if COL.options is a callback # function, which allows dropdown options to be dynamically # customised to each row. The ROW argument is harmlessly # ignored by Template Toolkit if COL.options is a static # arrayref common to every row. OPTION_LIST = COL.options(ROW); PROCESS select element_data = { text_attr='text' value_attr='value' id=PFX _ COL.col_id _ '-' _ ROWCOUNT name=PFX _ COL.col_id _ '_' _ ROW.row_id class=COL.class options=OPTION_LIST default_blank=COL.default_blank default_values=[ROW.${COL.col_id}] }; ELSIF TYPE == 'href'; HREF_SFX = COL.col_id _ "_href_suffix"; IF ROW.$HREF_SFX; ESCAPED_HREF = COL.href_base _ ROW.$HREF_SFX | url; ELSE; ESCAPED_BASE = COL.href_base | url; ESCAPED_PARAM = UNESCAPE(ROW.row_id) | uri; ESCAPED_HREF = ESCAPED_BASE _ ESCAPED_PARAM; END; IF COL.href_target; HREF_TGT = ' target="' _ COL.href_target _ '"'; END; "" _ ROW.${COL.col_id} _ ""; ELSE; ROW.${COL.col_id}; END; # enumeration TYPE %] [% END; # IF hidden ELSE END; # FOREACH -%]
[% END -%]
[% IF tfoot -%]
[%- FOREACH ROW IN tfoot.rows; SPACECOUNT = 0; ROWCOUNT = ROWCOUNT + 1; -%]
[%- FOREACH COL IN columns; COL_ID = COL.col_id; IF tfoot.coltypes.$COL_ID; TYPE = tfoot.coltypes.$COL_ID; ELSE; TYPE = COL.type; END; # Used both by 'checkbox' and 'radio' types! IF ROW.${COL.name}; CHECKED = "checked"; ELSE; CHECKED = ''; END; DOJO = tfoot.dojo_type.$COL_ID; DOJO_PROPS = tfoot.dojo_props.$COL_ID; IF tfoot.coltypes.${COL.col_id} == 'spacer'; SPACECOUNT = SPACECOUNT + 1; ELSE; IF SPACECOUNT > 0 %] [% END; IF TYPE == 'hidden'; NAME = PFX _ COL.col_id _ '_' _ '_tfoot_' _ ROWCOUNT; -%] | [% PROCESS input element_data = { type="hidden" name=NAME value=ROW.${COL.col_id} } %] [%- ELSE %] | [% IF TYPE == 'input_text' -%] [% PROCESS input element_data = { id=PFX _ COL.col_id _ '-' _ ROWCOUNT type="text" class=COL.class "data-dojo-type"=DOJO "data-dojo-props"=DOJO_PROPS name=PFX _ COL.col_id _ '_tfoot_' _ ROWCOUNT value=ROW.${COL.col_id} } %] [%- ELSIF TYPE == 'checkbox'; %] [% PROCESS input element_data = { id=PFX _ COL.col_id _ '-' _ ROWCOUNT type="checkbox" name=PFX _ COL.col_id _ '_' _ ROWCOUNT class=COL.class value=ROW.row_id checked=CHECKED } %] [%- ELSIF TYPE == 'radio' %] [% PROCESS input element_data = { id=PFX _ COL.col_id _ '-' _ ROWCOUNT type="radio" name=PFX _ COL.col_id class=COL.class value=ROW.row_id checked=CHECKED } %] [%- ELSIF TYPE == 'href'; HREF_SFX = COL.col_id _ "_href_suffix"; IF row.$HREF_SFX; HREF = COL.href_base _ ROW.$HREF_SFX; ELSE; HREF = COL.href_base _ ROW.row_id; END %][% ROW.${COL.col_id} %] [%- ELSE -%] [% ROW.${COL.col_id} %] [%- END -%] [%- END; END #ifs -%] [%- END -%]
[%- END -%]
[% END; -%]

[% PROCESS input element_data = { type="hidden" name="rowcount_" _ attributes.id value=ROWCOUNT } %] [% END #block %]