ad_table { -Torder_target_url {} -Torderby {} -Tmissing_text "<em>No data found.</em>" -Tsuffix {} -Tcolumns {} -Taudit {} -Trows_per_band 1 -Tband_colors {{} {\"\#ececec\"}} -Trows_per_page 0 -Tmax_rows 0 -Ttable_extra_html {} -Theader_row_extra {bgcolor=\"\#f8f8f8\"} -Ttable_break_html "<p>" -Tpre_row_code {} -Trow_code {\[subst \$Trow_default\]} -Tpost_data_ns_sets {} -Textra_vars {} } Tdb selection TdatadefWhat it does:
Note: all the variables in this function are named Tblah (except selection for the obvious reasons) since otherwise we cannot safely call set_variables_from_query since we could potentially have namespace collisionsbuild and return an html fragment given an active query and a data definition.
Datadef structure :
- Tdb and selection -- variables for an active query
- Tdatadef -- the table declaration.
{ {column_id "Column_Heading" order_clause display_info} ... }
- column_id -- what to set as orderby for sorting and also is the default variable for the table cell.
- the text for the heading to be wrapped in <
> and </th> tags. I am not entirely happy that things are wrapped automatically since you might not want plain old th tags but I also don;t want to add another field in the structure. - order_clause -- the order clause for the field. If null it defaults to "column_id $order". It is also interpolated, with orderby and order defined as variables so that:
{upper(last_name) $order, upper(first_names) $order}would do the right thing.the value "no_sort" should be used for columns which should not allow sorting.
- display_info. If this is a null string you just default to generating <td>column_id</td>. If it is a string in the lookup list then special formatting is applied; this is l r c tf 01 for align=left right center, Yes/No (from tf), Yes/No from 0/1.
if the display stuff is not any of the above then it is interpolated and the results returned (w/o any <td> tags put in). An example:
set table_def { {ffn "Full Name" {upper(last_name) $order, upper(first_names) $order} {<td><a href="/admin/users/one.tcl?user_id=$user_id">$first_names $last_name</a></td>}} {email "e-Mail" {} {<td><a href="mailto:$email">$email</a>}} {email_bouncing_p "e-Bouncing?" {} tf} {user_state "State" {} {}} {last_visit "Last Visit" {} r} {actions "Actions" no_sort {<td> <a href="/admin/users/basic-info-update.tcl?user_id=$user_id">Edit Info</a> | <a href="/admin/users/password-update.tcl?user_id=$user_id">New Password</a> | [ad_registration_finite_state_machine_admin_links $user_state $user_id]}} }Defined in: /web/philip/packages/acs-core/table-display-procs.tclSource code:
arg_parser_for_ad_table $args set Tcount 0 set Tband_count 0 set Tpage_count 0 set Tband_color 0 set Tn_bands [llength $Tband_colors] set Tform [ns_conn form] # export variables from calling environment if {![empty_string_p $Textra_vars]} { foreach Tvar $Textra_vars { upvar $Tvar $Tvar } } # get the current ordering information set Torderbykey {::not_sorted::} set Treverse {} regexp {^([^*,]+)([*])?} $Torderby match Torderbykey Treverse if {$Treverse == "*"} { set Torder desc } else { set Torder asc } # set up the target url for new sorts if {[empty_string_p $Torder_target_url]} { set Torder_target_url [ns_conn url] } set Texport "[uplevel [list export_ns_set_vars url [list orderby$Tsuffix]]]&" if {$Texport == "&"} { set Texport {} } set Tsort_url "$Torder_target_url?${Texport}orderby$Tsuffix=" set Thtml {} set Theader {} # build the list of columns to display... set Tcolumn_list [ad_table_column_list $Tdatadef $Tcolumns] # generate the header code # append Theader "<table $Ttable_extra_html>\n" if {[empty_string_p $Theader_row_extra]} { append Theader "<tr>\n" } else { append Theader "<tr $Theader_row_extra>\n" } foreach Ti $Tcolumn_list { set Tcol [lindex $Tdatadef $Ti] if { ( [ns_set find $selection [lindex $Tcol 0]] < 0 && [empty_string_p [lindex $Tcol 2]] ) || [string compare [lindex $Tcol 2] no_sort] == 0 } { # not either a column in the select or has sort code # then just a plain text header so do not do sorty things append Theader " <th>[lindex $Tcol 1]</th>\n" } else { if {[string compare [lindex $Tcol 0] $Torderbykey] == 0} { if {$Torder == "desc"} { set Tasord "^" } else { set Tasord "v" } } else { set Tasord {} } append Theader " <th><a href=\"$Tsort_url[ns_urlencode [ad_new_sort_by [lindex $Tcol 0] $Torderby]]\">\n" append Theader "[lindex $Tcol 1]</a> $Tasord</th>\n" } } append Theader "</tr>\n" # # This has gotten kind of ugly. Here we are looping over the # rows returned and then potentially a list of ns_sets which can # be passed in (grrr. Richard Li needs for general protections stuff # for "fake" public record which does not exist in DB). # set Tpost_data 0 while { 1 } { if {!$Tpost_data && [ns_db getrow $Tdb $selection]} { # in all its evil majesty set_variables_after_query } else { # move on to fake rows... incr Tpost_data } if { $Tpost_data && $Tpost_data <= [llength $Tpost_data_ns_sets] } { # bind the Tpost_data_ns_sets row of the passed in data set_variables_after_query_not_selection [lindex $Tpost_data_ns_sets [expr $Tpost_data - 1]] } elseif { $Tpost_data } { # past the end of the fake data drop out. break } if { $Tmax_rows && $Tcount >= $Tmax_rows } { if { ! $Tpost_data } { # we hit max count and had rows left to read... ns_db flush $Tdb } break } # deal with putting in the header if need if { $Tcount == 0 } { append Thtml "$Theader" } elseif { $Tpage_count == 0 } { append Thtml "</table>\n$Ttable_break_html\n$Theader" } # first check if we are in audit mode and if the audit columns have changed set Tdisplay_changes_only 0 if {![empty_string_p $Taudit] && $Tcount > 0} { # check if the audit key columns changed foreach Taudit_key $Taudit { if {[string compare [set $Taudit_key] [set P$Taudit_key]] == 0} { set Tdisplay_changes_only 1 } } } # this is for breaking on sorted field etc. append Thtml [subst $Tpre_row_code] if { ! $Tdisplay_changes_only } { # in audit mode a record spans multiple rows. incr Tcount incr Tband_count } incr Tpage_count if { $Trows_per_page && $Tpage_count >= $Trows_per_page } { set Tband_color 0 set Tband_count 0 set Tpage_count 0 } # generate the row band color if { $Tn_bands } { if { $Tband_count >= $Trows_per_band } { set Tband_count 0 set Tband_color [expr ($Tband_color + 1) % $Tn_bands ] } # do this check since we would like the ability to band with # page background as well if {[empty_string_p [lindex $Tband_colors $Tband_color]]} { set Trow_default "<tr>\n" } else { set Trow_default "<tr bgcolor=[lindex $Tband_colors $Tband_color]>\n" } } else { set Trow_default "<tr>\n" } append Thtml [subst $Trow_code] foreach Ti $Tcolumn_list { set Tcol [lindex $Tdatadef $Ti] # If we got some special formatting code we handle it # single characters r l c are special for alignment set Tformat [lindex $Tcol 3] set Tcolumn [lindex $Tcol 0] switch $Tformat { "" {set Tdisplay_field " <td>[set $Tcolumn]</td>\n"} r {set Tdisplay_field " <td align=right>[set $Tcolumn]</td>\n"} l {set Tdisplay_field " <td align=left>[set $Tcolumn]</td>\n"} c {set Tdisplay_field " <td align=center>[set $Tcolumn]</td>\n"} tf {set Tdisplay_field " <td align=center>[util_PrettyBoolean [set $Tcolumn]]</td>\n"} 01 {set Tdisplay_field " <td align=center>[util_PrettyTclBoolean [set $Tcolumn]]</td>\n"} bz {set Tdisplay_field " <td align=right> [blank_zero [set $Tcolumn]]</td>\n"} default {set Tdisplay_field " [subst $Tformat]\n"} } if { $Tdisplay_changes_only && [string compare $Tdisplay_field $Tlast_display($Ti)] == 0} { set Tdisplay_field {<td> </td>} } else { set Tlast_display($Ti) $Tdisplay_field } append Thtml $Tdisplay_field } append Thtml "</tr>\n" # keep the last row around so we can do fancy things. # so on next row we can say things like if $Pvar != $var not blank if { $Tpost_data && $Tpost_data <= [llength $Tpost_data_ns_sets] } { # bind the Tpost_data_ns_sets row of the passed in data set_variables_after_query_not_selection [lindex $Tpost_data_ns_sets [expr $Tpost_data - 1]] P } else { set_variables_after_query_not_selection $selection P } } if { $Tcount > 0} { append Thtml "</table>\n" } else { append Thtml $Tmissing_text } return $Thtml
philg@mit.edu