• You do not have permissions to view this page - please try logging in.
Tabla de contenidos
No hay encabezados

 

// 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:
//@himikel mod 2010-11-09: Using local image resources 
var tablesorter_uri      = "/skins/local/tstable/tstable.tablesorter.min.js";
var tablesorter_bg_uri   = "/skins/local/tstable/tablesorter_bg.gif";
var tablesorter_asc_uri  = "/skins/local/tstable/tablesorter_asc.gif";
var tablesorter_desc_uri = "/skins/local/tstable/tablesorter_desc.gif"; 
var pager_uri            = "/skins/local/tstable/jquery.tablesorter.pager.js";
var pager_first_uri      = "/skins/local/tstable/pager_first.png";
var pager_prev_uri       = "/skins/local/tstable/pager_prev.png";
var pager_next_uri       = "/skins/local/tstable/pager_next.png";
var pager_last_uri       = "/skins/local/tstable/pager_last.png";
/*
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("&nbsp;");
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\"); 
            //@himikel #rem 2010-11-04: Skip error message using with SecionUI
            //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*(\\&nbsp;)*(\\<br ?\\/?\\>)*)*/,'');
        html = html.replace( /(\\s*(\\&nbsp;)*(\\<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>;
Etiquetas (Edit tags)
  • No tags
Debe inicie sesión para enviar un comentario.