Please discuss this template in this forum discussion.
Table of Contents |
This template creates sortable, filterable tables using the jQuery "Tablesorter" extension plus a whole pile of additional Dekiscript and Javascript. Key to this template are:
In general, this template has different virtues from BlakeH's version using Datatables. I encourage you to look at both. As for me, I use this all the time on my wiki, and hope it works for you.
This template requires Lyons (9.02.x).
| Version | Date | Author | Description |
| 1.24 | 11/22/2010 | neilw | Added "nodata" option |
| 1.23 | 8/13/2010 | neilw | Cleaned up the stylesheet a bit to remove redundant and inefficient selectors |
| 1.22 | 7/26/2010 | neilw | Updated sort:false operation; now applies table styling when sorting is disabled. Still no filter or pager for the moment. |
| 1.21 | 7/19/2010 | neilw | Updated tablesorter script to properly recognize "0" as a number. The tablesorter javascript file has been renamed to tstable.tablesorter.min.js, and the URL in the template has been updated accordingly. |
| 1.20 | 7/14/2010 | neilw |
|
| 1.18 | 2/23/2010 | neilw | Added UNSAFECONTENT permissions self-check |
| 1.17 | 2/12/2010 | neilw | Improved table header HTML for improved reliability |
| 1.16 | 10/16/2009 | neilw | One more CSS tweak to make IE7 happy. Good grief! |
| 1.15 | 10/12/2009 | neilw | Cleaned up CSS and table header spacing to work more consistently in all browsers (esp. IE) |
| 1.14 | 10/9/2009 | neilw | Fixed a bug in 1.13 (sigh) |
| 1.13 | 10/8/2009 | neilw | Put in a spacer for blank cells, to improve display on some browsers |
| 1.12 | 09/25/2009 | neilw | Added support for data as list of lists to enable CSV example |
| 1.11 | 08/25/2009 | neilw | Fixed bug with pager and fewer than 10 rows in table |
| 1.10 | 07/29/2009 | neilw | Added pager support (doesn't yet work with filters) |
| 1.00 | 07/27/2009 | neilw | First published version |
NOTE: You must have UNSAFECONTENT permissions to install this template successfully.
These instructions will help you install the template'TSTable' on your wiki quickly and correctly.
Perform the following steps:
HTML Source for Template:TSTable
For all the examples on this page, the code is shown before the working example. The code is shown with the syntax extension, and looks like this:
TSTable()
This means that the actual code on the page should be enclosed in a Dekiscript block. If you want to copy the code from this page, then use the same procedure as described in steps 2-4 above.
Let's get this out of the way right now: this template is a bit of a beast. It has a zillion options, some of which are complex, and can take some time to figure out. However, I have tried very hard to adhere to the following principle:
Simple things should be simple, and complex things should be possible
This means that, if I've done my job correctly, you'll be able to get up and running with it quickly and easily, and can ease your way into the more esoteric stuff at your own pace. So don't be put off by the long and gruesome argument specifications; that's needed as reference but you don't need to try to absorb it all at once. Peruse it briefly, and then head down to the tutorial to step through the functionality.
Before we delve into the gory details, let's just have a few quick examples to show what kinds of things we can do, and how simple it is to do simple things.
First, we have "apply" mode. This means we have an existing table on the page (maybe hand-edited, maybe generated by another template), and want to make it sortable. Just call TSTable() right before the table in question:
TSTable()
| text | numbers | dates |
| this | 9 | July 22, 2009 |
| is | -1 | August 6, 2009 |
| text | 11 | April 1, 2010 |
which then becomes:
| text | numbers | dates |
| this | 9 | July 22, 2009 |
| is | -1 | August 6, 2009 |
| text | 11 | April 1, 2010 |
Clicking in the header of each column sorts that column, just like you'd expect. Click again and the sort order is reversed. Hold shift and click multiple columns to sort on multiple columns. Also note that the sorter correctly handles numbers in the middle column, and dates in the third column (data format support is limited, more on that later). It also cleans up leading space from some of the entries.
Next, let's try a very simple example of "generate" mode, where we'll create a sortable table from data we'll supply to the template, in this case a wiki data structure. While we're at it, we'll enable the pager:
TSTable {
options: { pager:true },
columns: ["Title", "Viewcount"],
data: wiki.getpage("en/docs/DekiScript/Reference").subpages
}
This produces:
| Title | Viewcount |
|---|---|
| DekiScript Syntax | 178 |
| DekiScript Operators | 124 |
| Wiki Functions and Variables | 506 |
| DekiScript Remote Function Calls | 122 |
| DekiScript Statements | 156 |
| DekiScript Literals | 211 |
| HTML Page Composition Model | 170 |
| DekiScript HTML/XML Statements | 240 |
| DekiScript Functions and Variables | 543 |
| JavaScript Events & Messages (JEM) | 590 |
| XPath | 97 |
![]() ![]() ![]() ![]() | |
Finally, a more fancy table generation, using more options and a filter:
TSTable {
options: { zebra:true, width:"100%", rowstyle:"(#$.comments ? 'font-weight:bold' : '')" },
columns: [
{ key:"Title", width:"20%" },
{ key:"Path", sorter:false },
{ key:"ViewCount", width:"10%", initial:1 },
{ key:"(#$.comments)", title:"#Comments", width:10% },
{ key:"(var c=$.comments; #c ? c[#c-1].author.name .. ' (' .. date.format(c[#c-1].date,'MM/dd/yyyy') .. ')' : '')",
title:"Last comment", width:"15%" }
],
data: wiki.getpage("en/docs/DekiScript/Reference").subpages,
filter: [ [ "all items", "1" ], [ "items with comments", "#$.comments>0" ], [ "items without comments", "#$.comments==0" ] ]
}
Becomes:
Show:
| Title | Path | ViewCount | #Comments | Last comment |
|---|---|---|---|---|
| DekiScript Syntax | en/docs/DekiScript/Reference/DekiScript_Syntax | 178 | 0 | |
| DekiScript Operators | en/docs/DekiScript/Reference/DekiScript_Operators | 124 | 2 | klumsy (06/11/2010) |
| Wiki Functions and Variables | en/docs/DekiScript/Reference/Wiki_Functions_and_Variables | 506 | 2 | SteveB (04/28/2010) |
| DekiScript Remote Function Calls | en/docs/DekiScript/Reference/DekiScript_Remote_Function_Calls | 122 | 0 | |
| DekiScript Statements | en/docs/DekiScript/Reference/DekiScript_Statements | 156 | 0 | |
| DekiScript Literals | en/docs/DekiScript/Reference/DekiScript_Literals | 211 | 0 | |
| HTML Page Composition Model | en/docs/DekiScript/Reference/HTML_Page_Composition_Model | 170 | 0 | |
| DekiScript HTML/XML Statements | en/docs/DekiScript/Reference/DekiScript_HTML//XML_Statements | 240 | 3 | wovenlander (09/12/2010) |
| DekiScript Functions and Variables | en/docs/DekiScript/Reference/DekiScript_Functions_and_Variables | 543 | 0 | |
| JavaScript Events & Messages (JEM) | en/docs/DekiScript/Reference/JEM | 590 | 2 | SteveB (10/19/2009) |
| XPath | en/docs/DekiScript/Reference/XPath | 97 | 1 | muddyboots (04/29/2010) |
So that's what we can do. If this looks interesting to you, then read on.
TSTable takes four optional arguments, but each one is a world unto itself, and will be described separately below.
| Name | Type | Default | Description |
| options | map? | various defaults; see docs | This argument specifies options that apply to the entire table. See below for more details. |
| columns | list? | use "apply" mode (see docs) | This argument specifies the characteristics of the table columns. It only applies to "Generate mode" (see docs below). Each list element may be either a map, allowing for more complex specification, or a string, for quick and dirty tables. Examples of each form are provided below. |
| data | list of maps? or map of maps? or list of lists? | use "apply" mode (see docs) | Data to use when generating the table. If data is not specified, then "apply" mode will be used, and the template will find the next table on the page and convert it to sortable. If data is specified, then TSTable will generate a newe table using this data. Normally, this will be a list of maps, with each map containing the data for one table row. If a map is provided, though, TSTable will take map.values() of the provided map and therefore convert it into a list. This makes it convenient to provide certain wiki data structures which are implemented as maps but can work well here (e.g., page.subpages). See the examples! If data is a list of lists, then each element of each list will be used in order. See the "CSV Splitting example". |
| filter | list of lists? | no filter | This arg allows you to specify a custom filter for the table. The filter is implemented as a pull-down, with user-defined options. The first option is always the default, and will be enabled when the page is first displayed. |
This is a map containing global options for the table. Here are available elements in the map:
| Name | Type | Mode | Default | Description |
| id | str? | apply | find next table | Find the table with specified ID attribute and apply. If not specified, find the next table on the page after the TSTable() call. |
| generate | generate ID | Apply the given ID to the generated table. If not specified, TSTable() will generate a unique ID | ||
| width | str? | generate | none | specify width of generated table. If not specified, browser will auto-size the table. |
| zebra | bool? | either | false | Apply zebra-striping to the table. Color of the zebra stripe is customizable in the script in the "zebra_color" variable. |
| rowstyle | str? | generate | no styling | This arg allows you to specify a style to apply to each data row of the table. If the string is surrounded by parentheses, it will be evaluated as a Dekiscript expression for each row (see docs below) |
| initial | list of lists? | either | no initial sorting | This specifies the "sortlist" argument to the tablesorter extension, and overrides "initial" elements specified in the "columns" argument. Use this to specify a list of columns on which to sort the table when first displaying the page. |
| pager | bool? | generate | false | Enables the pager, which is useful for large tables. Initially, the table will display 10 records per page. If there are fewer than 10 items in the table, the pager will not appear. At present, the pager cannot be used with the filter. |
| sort | bool? | either | true | This globally enables or disables sorting on the whole table. If sort=false, you can just use TSTable as a table generator. |
| nodata | str? | generate | "(no data)" | Text to display if there are no data rows in the table |
This argument is only used in "generate" mode.
This is a list containing specifications for the table columns. Each element of the list may be either a map or a string. If it's a string, then TSTable() assumes the string is actually the "key" element. The table below specifies the available elements for each column map:
| Name | Type | Default | Description |
| key | str | This is the sole required element, and specifies the element of the row map in the data argument containing the cell contents. If the string is surrounded by parentheses, then it will instead be evaluated as a Dekiscript expression applied to the row data (see docs below). | |
| title | str? | key | Title of the column. If not specified, the value of "key" will be used instead. Note that "key" is not case-sensitive, so you can capitalize it as desired to produce a good-looking title. |
| width | str? | none | Specify width of the column. If not specified, browser will auto-size the column. |
| style | str? | no styling | This arg allows you to specify a style to apply to this column of the table. If the string is surrounded by parentheses, it will be evaluated as a Dekiscript expression for each row (see docs below) |
| initial | num? | column not initially selected as sort column | Sort on this column when first displaying the table: 0 = ascending order |
| sorter | bool? or str? | true | By default, each column is sortable. TSTable figures out how to sort based on analyzing the first row of data. Usually it does a good enough job, but not always. Using the "sorter" option, you can force the type of sort to use, or else disable sorting for the column altogether. Note string values are not case sensitive.
|
This argument is only used in "generate" mode.
This is a list of maps containing the data for the table. If a map is provided, TSTable will automatically convert it to a list by applying map.values() to it. This makes it convenient to pass wiki data structures, which are frequently maps of maps (e.g., page.subpages). We'll show this in the tutorial.
Each list element contains a map of data for one row of the table. The values for each column are extracted according to the "key" element of the corresponding "columns" argument (see above). For instance, if the first column specifies key:"uri", then the first column of row n of the table will be equal to data[n].uri. This all will become much more clear in the examples.
Normally, cell styles will be applied according to the "style" elements in the "columns" argument. However, if you want to you can pre-calculate the style for any particular column by putting it in the data with the key stylec, where c = the column number, starting from zero. In other words, if the row data has the element style1:"background-color:#FF0000", then the second column of that row (remember, we count from zero) will have a red background.
This argument is only used in "generate" mode, and will not work if the pager is enabled.
If specified, this defines a filter that can be used to show only desired table rows. The argument is a list of lists, each corresponding to an option on the filter pull-down control. The first is always the default. Each list has two elements:
| Name | Type | Description |
| Option name | str | This is the name of the option that will be displayed in the pull-down |
| Expression | str | This is a Dekiscript expression that will be applied to each row of the table. If it evaluates to "true", then that row will be displayed when this option is selected. Because this string is always evaluated as Dekiscript, it need not be enclosed in parentheses, but it won't hurt if it is. |
Evaluated Dekiscript expressions are described more below. In the meantime, here's a simple example of a filter:
[ [ "show all items", "true" ], [ "show nothing", "false" ] ]
In this example, the Dekiscript expressions are as simple as they can get. The first element is commonly used as the default, "show all" option. The second is not very useful!
Please see the TsTable() tutorial to really learn and understand how this all works. This is the same tutorial that used to be right here, just moved to its own page.
// UNSAFECONTENT PERMISSION CHECK
// This code checks if the template is properly installed for unsafe content execution,
// and may be removed if this check is not desired. If you leave this here, add your new code
// in a new DekiScript block below this one.
var chkunsafe = wiki.inclusions()[-1];
if (!wiki.pagepermissions(chkunsafe.id, chkunsafe.author.id).unsafecontent)
<div style="color:red; width:75%; padding:5px; border:1px solid red;">
"WARNING: The page '"..chkunsafe.path.."' must be re-saved by a user with UNSAFECONTENT permission in order to work correctly. ";
<a href="http://developer.mindtouch.com/en/kb/Using_templates_which_require_UNSAFECONTENT_permission"> "See this" </a>;
" for more info.";
</div>;
// TsTable template, by neilw, 2009
// Versions
// 1.00 7/27/2009 neilw First published version
// 1.10 7/29/2009 neilw Added pagination support (doesn't work with filter yet)
// 1.11 8/25/2009 neilw Fixed bug with pager and fewer than 10 rows
// 1.12 9/25/2009 neilw Added support for data as list of lists
// 1.13 10/8/2009 neilw Put in a spacer for empty table cells
// 1.14 10/9/2009 neilw Fixed a bug introduced in 1.13 (sigh)
// 1.15 10/12/2009 neilw Cleaned up CSS, especially for IE
// 1.16 10/13/2009 neilw Added default filter option, reduced spurious error alerts
// 1.17 2/12/2010 neilw Improved table header HTML for improved reliability
// 1.18 2/23/2010 neilw Added UNSAFECONTENT permission check
// 1.20 7/14/2010 neilw Added full support for "sorter" option in columns
// Added "nosort" option for table
// 1.21 7/19/2010 neilw Now properly recognize "0" as a number (new tablesorter script, new name!!!)
// 1.22 7/26/2010 neilw Improved "sort:false" option
// 1.23 8/13/2010 neilw Cleaned up stylesheet a *little*
// 1.24 11/22/2010 neilw Added "nodata" option
// LOCAL SETTINGS
//This template requires the following files to be installed as specified below:
var tablesorter_uri = "http://developer.mindtouch.com/@api/deki/files/6272/=tstable.tablesorter.min.js";
var tablesorter_bg_uri = "http://developer.mindtouch.com/@api/deki/files/4627/=tablesorter_bg.gif";
var tablesorter_asc_uri = "http://developer.mindtouch.com/@api/deki/files/4626/=tablesorter_asc.gif";
var tablesorter_desc_uri = "http://developer.mindtouch.com/@api/deki/files/4624/=tablesorter_desc.gif";
var pager_uri = "http://developer.mindtouch.com/@api/deki/files/4651/=jquery.tablesorter.pager.js";
var pager_first_uri = "http://developer.mindtouch.com/@api/deki/files/4648/=pager_first.png";
var pager_prev_uri = "http://developer.mindtouch.com/@api/deki/files/4647/=pager_prev.png";
var pager_next_uri = "http://developer.mindtouch.com/@api/deki/files/4650/=pager_next.png";
var pager_last_uri = "http://developer.mindtouch.com/@api/deki/files/4649/=pager_last.png";
// The following variables define important styles for this template:
var thead_unsel_color = "#D0E0E0"; // Color of unselected header cell
var thead_sel_color = "#8DBDD8"; // Color of selected header cell
var zebra_color = "#ECECF0"; // Color of odd rows when "zebra" is specified
// USAGE: template.TsTable(options, columns, data)
// "columns": Optional array of column specifications, one for each table column. Each column spec can be either a
// simple string or a map. This argument only applies if "data" is also specified (GENERATE mode). If it's a
// string, then it specifies the key and title for the column data. If it's a map, then the possible fields are:
// key: keyname for the map element containing the cell data. THIS IS THE ONE AND ONLY FIELD THAT IS
// REQUIRED. If surrounded by parentheses, will be evaluated as a Dekiscript expression to provided
// the cell value (see docs).
// title: Title for the column. If not specified, will use "key".
// width: width of column
// style: style to apply to this cell. If surrounded by parentheses, will be evalauted as a Dekiscript
// expression (see docs)
// initial: set this column as initial sort column; 0 ==> ascending, 1 ==> descending
// sorter: control sortability on this column (this is case sensitive!):
// false ==> disable sorting on this column
// "text" ==> sort column as text
// "digit" ==> sort column as numbers
// "currency" ==> sort column as currency values (ignore leading currency symbol)
// "ipAddress" ==> sort as IP addresses
// "url" ==> sort as URL; ignore protocol prefix
// "isoDate" ==> sort as ISO formatted date (yyyy-M-d; separator may be "-" or "/")
// "percent" ==> sort as percentage (ignore trailing "%")
// "usLongDate" ==> sort as date (MMM dd, (yyyy | 'yy) [hh:mm:ss (AM|PM))
// "usShortDate" ==> sort as date (MM-dd-(yyyy|yy)
// "time" ==> sort as time (hh:mm (am|pm))
// date: TBD
// "options": Optional map containing an assortment of options that apply to the whole table:
// id: ID attribute of the table element. If we're applying tablesorter to an existing table, the template
// will look for a table with this name. If we're generating a table, its ID will be set to this value
// width: width of the entire table
// initial: initial sort order for the table. This is the "sortlist" parameter for the tablesorter extension.
// rowstyle: style applied to each row. If surrounded by parentheses, will be evaluated as a Dekiscript
// expression (see docs)
// zebra: set to true to enable zebra-striping of the table row
// pager: enable the table pager (doesn't work with filters yet!)
// sort: enable or disable sorting on the entire table (default:true)
// nodata: message to be printed when there is no data (default: "(no data)")
// "data": array of maps or lists containing data for each row of the table. The "columns" argument specified in the "key"
// element which element of the map will be used to supply data for this cell. Additional elements may be
// present in the map for purposes of style or content evaluation (see docs), or it will be ignored. If a data row is
// a list, then the elements will be used in order.
// "filter": array of 2-element arrays, each specifying optional filters that may be applied to the table.
// The first sub-array element specifies the name of the filter, which will be displayed in the
// <select> widget. The second element is Dekiscript code which is applied to each row in the table;
// if the code evaluates to "true" then the row will be displayed when that option is selected.
// The first selection, and the default, is always "show all items", so you don't need to specify
// that one. See docs for more details.
/**** Misc "globals" ****/
var options_arg = $1 ?? $options ?? {};
var columns_arg = $0 ?? $columns;
var data_arg = $2 ?? $data;
if (data_arg is map)
let data_arg = map.values(data_arg);
var filter_arg = $3 ?? $filter;
var apply = (data_arg == nil); // if no data, modify existing table (APPLY mode)
var eval_re = "(^\\((.*)\\)$)"; // regular expression to detect "eval"
var errors = []; // list of error messages
/**** Argument Processing ****/
//
// "columns" arg
//
var c_series = [];
var columns = []; // processed list of column specifications
var headers = {}; // "headers" arg for tablesorter
var sortlist = []; // "sortlist" arg for tablesorter
if (columns_arg == nil) {
if (!apply) let errors ..= [ "must specify COLUMNS when DATA is also specified ('generate' mode)" ];
}
else {
let c_series = num.series(0, #columns_arg - 1);
if (apply) let errors ..= [ "WARNING: ignoring COLUMNS in 'apply' mode" ];
else if (columns_arg is not list) let errors ..= [ 'COLUMNS: must be a list' ];
else foreach (var i in c_series) {
var c = columns_arg[i];
if (c is str)
let c = { key:c };
// check for bogus extra fields
foreach (var k in map.keys(c))
if (!list.contains([ "title","key","width","sorter","initial","style" ], //"date","type","hide" ]
string.tolower(k))) let errors ..= [ "COLUMNS["..i.."]: unknown field: '"..k.."'" ];
// "key" field
if (c.key == nil) {
let errors ..= [ "COLUMNS["..i.."]: no KEY supplied" ];
let c ..= { key:"xxx" };
}
else if (string.match(c.key, eval_re)) let c ..= { eval_key:true };
// "title" field
if (c.title == nil) let c ..= { title:c.key };
// "sorter" field
if (c.sorter is bool || c.sorter is str) {
var sorterOptions = [ "text", "digit", "currency", "ipAddress", "url", "isoDate",
"percent", "usLongDate", "shortDate", "time", "metadata" ];
if (c.sorter is str && !list.contains(sorterOptions, c.sorter))
let errors ..= [ "COLUMNS["..i.."]: invalid SORTER option '"..c.sorter.."'" ];
else
let headers ..= { (i):{ sorter:c.sorter } };
}
// "initial" field
if (c.initial != nil) {
if (!string.match(c.initial, "(^[01]$)")) let errors ..= [ "COLUMNS["..i.."]: INITIAL must be 0 or 1" ];
else let sortlist ..= [ [i,c.initial] ];
}
// "style" field
if (c.style != nil && string.match(c.style, eval_re)) let c ..= { eval_style:true };
// Build columns
let columns ..= [ c ];
}
}
//
// "options" arg
//
// check for bogus extra fields
foreach (var k in map.keys(options_arg))
if (!list.contains(["id","width","zebra","initial","rowstyle","pager","sort","nodata" ], string.tolower(k)))
let errors ..= [ 'OPTIONS: unknown option: ' .. k ];
// simple fields
var tname = options_arg.id?? (apply ? nil : @tname);
var find = (tname == nil);
if (find) let tname = @tname;
var width = options_arg.width;
var widgets = options_arg.zebra == true ? [ 'zebra' ] : [];
let sortlist = options_arg.initial ?? sortlist;
var pager = options_arg.pager ?? false;
var perpage = [ 10, 25, 50, 100, 250, 500 ];
var enableSorting = options_arg.sort ?? true;
var noData = options_arg.nodata;
if (noData is not str) let noData = "(no data)";
// "rowstyle" field
if (options_arg.rowstyle != nil && string.match(options_arg.rowstyle, eval_re))
let options_arg ..= { eval_rowstyle:true };
//
// "data" and "filter" arg
//
var filter = [];
var filter_default = -1;
var filter_code = [];
if (filter_arg) {
if (filter_arg is not list) let errors ..= [ "expected FILTER arg to be a list" ];
else if (pager) let errors ..= [ "filter won't work when pager is enabled (disabling filter)" ];
else {
let filter = [ ];
let filter_default = 0;
let filter_code = [ ];
foreach (var i in num.series(0,#filter_arg-1)) {
var f = filter_arg[i];
if (f is not list)
let errors ..= [ "FILTER: option "..i.." is not a list" ];
else {
if (#f != 2 && !(#f == 3 && f[2] is bool))
let errors ..= [ "FILTER: option "..i.." is not a list of two elementsvalid" ];
else {
let filter ..= [ f[0] ];
let filter_code ..= [ f[1] ];
if (f[2]) let filter_default = i;
}
}
}
}
}
var space = web.html(" ");
var data = []; // processed data array
if (!apply) {
foreach (var r in data_arg) {
if (r is list) let r = { (i):r[i] foreach var i in num.series(0,#r-1) };
if (r is map) {
let class = [];
let r ..= { rowstyle:(options_arg.eval_rowstyle ?
list.apply([r],options_arg.rowstyle)[0] : options_arg.rowstyle) };
foreach (var i in c_series) {
var c = columns[i];
if (c.eval_key || r[c.key] != nil)
let r ..= { (i): (c.eval_key ? list.apply([r],c.key)[0] : r[c.key]) };
}
foreach (var i in c_series) {
var c = columns[i];
if (c.style) let r ..= { ("style"..i): (c.eval_style ? list.apply([r],c.style)[0] : c.style ) };
}
if (#filter_code)
foreach (var i in num.series(0,#filter_code-1))
if (list.apply([r],filter_code[i])[0])
let class ..= [ "tsf"..i ];
let data ..= [ r..{ class:string.join(class," ") } ];
}
else
let errors ..= [ "DATA: item ".. __index .. " is not a map or list" ];
}
}
else if (filter_arg)
let errors ..= [ "WARNING: ignoring FILTER arg in 'apply' mode" ];
//
// Output XML
//
<html>
// Scripts and stylesheets go in the head
<head>
<script type="text/javascript" src=(tablesorter_uri)></script>;
<script type="text/javascript"> var garbage = 0; </script>;
<script type="text/javascript" src=(pager_uri)></script>;
<script type="text/javascript">"
// Call main tablesorter function
DekiWiki.$(document).ready(function($) {
tstableApply($, "..json.emit(apply)..","..json.emit(find)..","..json.emit(@id)..","..
json.emit(tname)..","..json.emit(headers)..","..json.emit(sortlist)..","..
json.emit(widgets)..","..json.emit(filter_default)..","..json.emit(pager)..","..json.emit(enableSorting)..");
});
"</script>;
<script type="text/javascript">"
// Apply tablesorter to table
function tstableApply($, apply, find, id, name, headers, sortlist, widgets, filter, pager, enable) {
// Find the table
var $table;
if (!find)
$table = $('table#'+name);
else {
var pid = 'p#' + id;
var $nodes = $(pid).nextAll();
for (var i = 0; i < $nodes.length; i++) {
$table = $nodes.eq(i);
if ($table.is('table')) break;
$table = $table.find('table:first');
if ($table.length) break;
}
if (!$table.length) {
alert(\"ERROR: TsTable: can't find table\");
return;
}
$table.attr({'id':name, 'border':'0', 'cellspacing':'0px', 'cellpadding':'3px'});
}
// set 'tablesorter' class if necessary
if (!$table.hasClass('tablesorter')) $table.addClass('tablesorter');
// Copy header row to 'thead' element if necessary
var $header = $table.find('thead tr');
if (!$header.length) {
var $ohr = $table.find('tr:eq(0)');
if (!$ohr.length) return; // table is empty, bail out
$table.prepend('<thead><tr>'+$ohr.html()+'</tr></thead>');
$ohr.remove();
$header = $table.find('thead tr');
}
// Convert header <td> to <th> if necessary
if (apply) {
var hdrhtml = '';
$header.children().each(function() { hdrhtml += '<th>'+$(this).html()+'</th>'; });
$header.html(hdrhtml);
}
// Convert format of each header element to reserve room for arrow
$header.children().each(function() {
$(this).css('padding-right','20px');
});
// Clean up leading and trailing space
$table.find('td,th').each(function() {
$(this).find('p:first-child').css({'margin-top':'0px','padding-top':'0px'});
$(this).find('p:last-child').css({'margin-bottom':'0px','padding-bottom':'0px'});
var html = $(this).html();
html = html.replace(/^(\\s*(\\ )*(\\<br ?\\/?\\>)*)*/,'');
html = html.replace( /(\\s*(\\ )*(\\<br ?\\/?\\>)*)*$/,'');
$(this).html(html);
});
// If we're not going to enable sorting, get out
if (!enable) return;
// Install filter
if (filter >= 0) {
var selectid = 'select#tsf' + id;
$(selectid).change(function() {
var $options = $(this).find('option:selected');
$table.find('tbody.tsf > tr').each(function() {
var show = false;
var $row = $(this);
$options.each(function() { show |= $row.hasClass($(this).attr('value')); } );
if (show) $row.show();
else $row.hide();
});
$table.trigger('applyWidgets');
return(false);
});
$(selectid).find('option').each(function(i) { $(this).attr('selected',i==filter?'selected':''); });
$(selectid).change();
}
// Now activate tablesorter
$table.tablesorter({
headers: headers, sortList: sortlist, widgets: widgets,
cssHeader: 'tsHeader', cssAsc: 'tsHeaderSortUp', cssDesc: 'tsHeaderSortDown'
});
if (pager) {
var pagerid = '#'+id+'pager';
$(pagerid).find('option').each(function(i) { $(this).attr('selected',i==0?'selected':''); });
$table.tablesorterPager({container: $('#'+id+'pager'), positionFixed:false});
}
}
"</script>;
// Styles
var tid = "table.tablesorter#"..tname;
<style type="text/css">"
.tablesorter {
border-collapse: separate;
border-left: solid #808080 1px;
border-top: solid #808080 1px;
}
.tablesorter > thead > tr > th, .tablesorter > tbody > tr > td, .tablesorter > tfoot > tr > td {
border-right: solid #808080 1px;
border-bottom: solid #808080 1px;
}
.tablesorter > thead > tr > th, .tablesorter > tfoot > tr > th {
background-color: "..thead_unsel_color..";
font-weight: bold;
}
.tsHeader {
background-image: url("..tablesorter_bg_uri..");
background-repeat: no-repeat;
background-position: center right;
cursor: pointer;
}
.tablesorter > tbody tr.odd { background-color:"..zebra_color.."; }
.tsHeader.tsHeaderSortUp {
background-image: url("..tablesorter_asc_uri..");
background-color: "..thead_sel_color..";
}
.tsHeader.tsHeaderSortDown {
background-image: url("..tablesorter_desc_uri..");
background-color: "..thead_sel_color..";
}
"</style>;
</head>
// Generate table HTML in the body
<body>
// Error messages
if (#errors)
<div style="color:red; font-weight:bold;"> "TSTABLE ERRORS:";
<ul> foreach (var e in errors) <li> e </li>; </ul>
</div>;
// Insert marker if applying
if (apply) { <p id=(@id) style="display:none;" /><div />; }
// Else generate table
else {
if (#filter) {
<p><span>"Show: "</span><select id=("tsf"..@id)>
foreach (var i in num.series(0,#filter-1))
<option value=("tsf"..i) selected=(i==0?"selected":"")> filter[i] </option>;
</select></p>;
}
<table class="tablesorter" id=(tname) width=(width) cellpadding="3px" cellspacing="0px">
// Header
<thead><tr> foreach (var c in columns) <th width=(c.width)>c.title</th>; </tr></thead>
// Body
<tbody class="tsf">
foreach (var r in data) <tr style=(r.rowstyle) class=(r.class)>
foreach (var i in c_series) <td style=(r["style"..i])> (r[i]==nil || r[i]=="") ? space : r[i] </td>;
</tr>;
if (!#data) <tr><td colspan=(#columns)> noData </td></tr>;
</tbody>
if (pager) {
<tfoot style=(#data > perpage[0] ? "" : "display:none")>
<tr bgcolor=(thead_unsel_color)><td id=(@id .. "pager") colspan=(#columns) align="center">
<img class="first" style="cursor:pointer" src=(pager_first_uri) />
<img class="prev" style="cursor:pointer" src=(pager_prev_uri) />
<img src="/skins/common/icons/icon-trans.gif" width="8" height="8" />
<span class="pagedisplay"> " " </span>
<img src="/skins/common/icons/icon-trans.gif" width="8" height="8" />
<img class="next" style="cursor:pointer" src=(pager_next_uri) />
<img class="last" style="cursor:pointer" src=(pager_last_uri) />
<select class="pagesize" style="float:right">
foreach (var pp in perpage) {
<option value=(pp) selected=(__index == 0 ? "selected" : "")> (pp>#data ? "all":pp) </option>;
if (pp > #data) break;
}
</select>
</td></tr></tfoot>;
}
</table>;
}
</body>
</html>;
| File | Version | Size | Modified | |
|---|---|---|---|---|
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
Copyright © 2011 MindTouch, Inc. Powered by
{ key:'(<input type="button" value="Details" />)', title:"Last comment" }
Thanks.
Any thoughts?
Use wiki.getsearch("type:wiki", 10000) to get the list of pages (replace 10000 with whatever is the maximum you want to allow). You may want to pre-sort the list before giving it to TsTable, which you can do either inside wiki.getsearch() or with a list.sort() afterwards. Keep in mind that if the number of pages is very large this could take a while!
Update: After trying to fix the mess manually, I recopied the code from here, pasted it into a text editor (Notepad++), selected all and copied it from there, and then successfully pasted it into the dekiscript section of my template page. Live and learn... FYI, even after doing this, I still ended up with some extra pre tags that needed to be cleaned out. edited 00:04, 6 Feb 2010
I've answered your question (once :)) on the forums; please continue the discussion there.
Seems to be a problem with the javascript files on developer.mindtocuh.com.
Please make a exclusion if you don't have a internet connection. So you can edit pages in intranet.
Ty