Note that since you've used the HTML macro using
renderers may not
 output the live grid (only renderers that support HTML will be able to
 output some result).
 I've checked the html and all of it could be replaced by wiki syntax
 except for the select part. We could use wiki syntax everywhere and
 use some JS to inject the select in the HTML DOM afterwards. This
 would allow to output it easily.
 We currently have only 2 renderers that we use: xwiki syntax and xhtml
 and both support Raw events when the syntax is HTML. We can imagine
 that PDF, RTF renderers would also support it (it'll depend on how we
 implement it, if we use FOP it's fine but there's also a very simple
 way to implement a PDF renderer using itext but then I don't think if
 it can support HMTL fragments). We have a LaTex renderer that we
 currently don't use and this one won't work for example.
 This is just a thought for now. We just need to be aware of it for the
 future. We need to remember that using the HTML macro bypasses the
 rendering mechanism and thus generate non standard stuff.
 Thanks
 -Vincent
 On Apr 30, 2009, at 8:08 AM, jvelociter (SVN) wrote:
  Author: jvelociter
 Date: 2009-04-30 08:08:53 +0200 (Thu, 30 Apr 2009)
 New Revision: 19209
 Modified:
   platform/core/trunk/xwiki-core/src/main/resources/
 ApplicationResources.properties
   platform/web/trunk/standard/src/main/webapp/resources/js/xwiki/
 table/livetable.css
   platform/web/trunk/standard/src/main/webapp/resources/js/xwiki/
 table/livetable.js
   platform/web/trunk/standard/src/main/webapp/templates/macros.vm
 Log:
 XWIKI-3705 Clean and enhance the javascript Live Table component
 XWIKI-3706 Provide a velocity macro to automate the creation of live
 tables
 * Added support for multiple pagination nodes (for example one on
 top, and one under the table). Formatting of livetable.js
 * Added the #livetable macro in macros.vm, that supports syntax 1.0
 and 2.0
 Modified: platform/core/trunk/xwiki-core/src/main/resources/
 ApplicationResources.properties
 ===================================================================
 --- platform/core/trunk/xwiki-core/src/main/resources/
 ApplicationResources.properties        2009-04-30 01:14:08 UTC (rev 19208)
 +++ platform/core/trunk/xwiki-core/src/main/resources/
 ApplicationResources.properties        2009-04-30 06:08:53 UTC (rev 19209)
 @@ -1612,14 +1612,26 @@
 xe.pagination.results=Results
 xe.pagination.results.of=out of
 xe.pagination.page=Page
 +xe.pagination.page.next.title=Next Page
 +xe.pagination.page.prev.title=Previous Page
 -xe.attachments.all.filename=Filename
 -xe.attachments.all.page=Page
 -xe.attachments.all.space=Space
 -xe.attachments.all.date=Date
 -xe.attachments.all.author=Author
 -xe.attachments.all.type=Type
 +xe.grid.loading=Loading...
 +xe.index.doc.name=Page
 +xe.index.doc.space=Space
 +xe.index.doc.date=Date
 +xe.index.doc.author=Last Author
 +xe.index.actions=Actions
 +xe.index.emptyvalue=
 +
 +xe.index.attachments.filename=Filename
 +xe.index.attachments.title=Page
 +xe.index.attachments.space=Space
 +xe.index.attachments.date=Date
 +xe.index.attachments.author=Author
 +xe.index.attachments.type=Type
 +xe.index.attachments.emptyvalue=
 +
 xe.document.copy=Copy a document
 xe.document.copying=Copying document
 xe.document.copy.source=Source Document:
 Modified: platform/web/trunk/standard/src/main/webapp/resources/js/
 xwiki/table/livetable.css
 ===================================================================
 --- platform/web/trunk/standard/src/main/webapp/resources/js/xwiki/
 table/livetable.css    2009-04-30 01:14:08 UTC (rev 19208)
 +++ platform/web/trunk/standard/src/main/webapp/resources/js/xwiki/
 table/livetable.css    2009-04-30 06:08:53 UTC (rev 19209)
 @@ -46,7 +46,7 @@
        padding:0!important;
        float: right;
 }
 -.controlPagination a{
 +.controlPagination div{
        position:absolute;
        top:0;
        left:0;
 @@ -55,22 +55,25 @@
        overflow:hidden;
        border:none;
 }
 -.controlPagination a.prevPagination , .controlPagination
 a.noPrevPagination, .controlPagination
 a.nextPagination, .controlPagination a.noNextPagination {
 -      background-image:url("$xwiki.getSkinFile('js/xwiki/table/img/
 navigation.png')");
 +.controlPagination div.prevPagination , .controlPagination
 div.noPrevPagination, .controlPagination
 div.nextPagination, .controlPagination div.noNextPagination {
 +      background-image:url("$xwiki.getSkinFile('icons/xwiki/pagination-
 controls.png')");
        width: 21px;
        height: 22px;
 }
 -.controlPagination a.prevPagination {
 +.controlPagination div.prevPagination:hover, .controlPagination
 div.nextPagination:hover {
 +    cursor:pointer;
 +}
 +.controlPagination div.prevPagination {
        background-position:left top;
 }
 -.controlPagination a.noPrevPagination{
 +.controlPagination div.noPrevPagination{
        background-position:left bottom;
 }
 -.controlPagination a.nextPagination {
 +.controlPagination div.nextPagination {
        background-position:right top;
        left: 21px;
 }
 -.controlPagination a.noNextPagination {
 +.controlPagination div.noNextPagination {
        background-position:right bottom;
        left: 21px;
 }
 @@ -126,7 +129,7 @@
        background:#dddddd url("$xwiki.getSkinFile('icons/silk/
 bullet_arrow_down.gif')") no-repeat scroll right center;
 }
 thead.xwiki-grid-display-header th.asc {
 -      background:#dddddd url("$xwiki.getSkinFile('icons/silk/
 bullet_arrow_up.png')") no-repeat scroll right center;
 +      background:#dddddd url("$xwiki.getSkinFile('icons/silk/
 bullet_arrow_up.gif')") no-repeat scroll right center;
 }
 thead.xwiki-grid-display-header th.selected {
        color:#4D4D4D;
 Modified: platform/web/trunk/standard/src/main/webapp/resources/js/
 xwiki/table/livetable.js
 ===================================================================
 --- platform/web/trunk/standard/src/main/webapp/resources/js/xwiki/
 table/livetable.js     2009-04-30 01:14:08 UTC (rev 19208)
 +++ platform/web/trunk/standard/src/main/webapp/resources/js/xwiki/
 table/livetable.js     2009-04-30 06:08:53 UTC (rev 19209)
 @@ -4,14 +4,14 @@
  * XWiki namespace
  */
 if (typeof XWiki == "undefined") {
 -      XWiki = new Object();
 +    XWiki = new Object();
 }
 /**
  * widgets namespace
  */
 if (typeof XWiki.widgets == "undefined") {
 -      XWiki.widgets = new Object();
 +    XWiki.widgets = new Object();
 }
 /**
 @@ -35,7 +35,7 @@
     * @todo Make this a valid ARIA grid: 
http://www.w3.org/TR/aria-role/#structural
     */
   initialize: function(url, domNodeName, handler, options)
 -  {
 +  {
     // id of the root element that encloses this livetable
     this.domNodeName = domNodeName;
 @@ -45,21 +45,23 @@
     this.displayNode = $(domNodeName + "-display") || $('display1');
     if (typeof options == "undefined") {
 -         options = {};
 +       options = {};
     }
     this.limit = options.limit || 10;
     this.action = options.action || "view"; // FIXME check if this
 can be removed safely.
 -    if ($(domNodeName + '-pagination')) {
 -       this.paginator = new GridPagination(this, domNodeName + "-
 pagination", options.maxPages || 10);
 +    // pagination
 +    var paginationNodes = $(this.domNodeName).select(".xwiki-grid-
 pagination");
 +    if (typeof paginationNodes != "undefined") {
 +       this.paginator = new GridPagination(this, paginationNodes,
 options.maxPages || 10);
     }
     if ($(domNodeName + '-filters')) {
 -              // Ideally we should pass domNodeName + "-filters" as the filter
 node instead of the whole display table,
 -              // so that the filters elements (input/selects) are retrieved
 down this filter node
 -              // But right now this would break the RMUI since the checkbox to
 switch from group view to user view
 -              // in the rights UI is outside this element.
 -              // FIXME
 +      // Ideally we should pass domNodeName + "-filters" as the
 filter node instead of the whole display table,
 +      // so that the filters elements (input/selects) are retrieved
 down this filter node
 +      // But right now this would break the RMUI since the checkbox
 to switch from group view to user view
 +      // in the rights UI is outside this element.
 +      // FIXME
       this.filter = new GridFilter(this,
 this.displayNode.up("table"));
     }
     if ($(domNodeName + "-tagcloud"))
 @@ -174,27 +176,27 @@
     * @param limit Maximum number of rows to display.
     */
   displayRows: function(offset, limit)
 -  {
 +  {
     var f = offset + limit - 1;
     if (f > this.totalRows) f = this.totalRows;
     var off = (this.totalRows > 0) ? offset : 0;
     var msg = "<strong>" + off + "</strong> -
<strong>" + f + "</
 strong> $msg.get('xe.pagination.results.of') <strong>" +
 this.totalRows + "</strong>";
     var msg = msg.toLowerCase();
 -
 +
     this.limitsDisplay.innerHTML =
 "$msg.get('xe.pagination.results') " + msg;
     this.clearDisplay();
     for (var i = off; i <= f; i++) {
       if (this.fetchedRows[i]) {
 -              var elem = this.handler(this.fetchedRows[i], i, this);
 +        var elem = this.handler(this.fetchedRows[i], i, this);
         this.displayNode.appendChild(elem);
         document.fire("xwiki:livetable:newrow", {
 -            "row":elem,
 -            "table":this
 -      });
 +          "row":elem,
 +          "table":this
 +    });
       }
     }
 -    if (this.paginator) this.paginator.refreshPaginator();
 +    if (this.paginator) this.paginator.refreshPagination();
   },
   /**
 @@ -239,7 +241,7 @@
       this.getRows(min, max - min + 1, offset, limit);
     }
 -    if(this.paginator) this.paginator.refreshPaginator();
 +    if(this.paginator) this.paginator.refreshPagination();
     return buff;
   },
 @@ -291,7 +293,7 @@
       this.showRows(newoffset, this.limit);
     }
 -    if (this.paginator) this.paginator.refreshPaginator();
 +    if (this.paginator) this.paginator.refreshPagination();
   },
   /**
 @@ -346,47 +348,63 @@
  * Helper class to display pagination
  */
 var GridPagination = Class.create({
 -    initialize: function(table, domNode, max)
 +    initialize: function(table, domNodes, max)
     {
       this.table = table;
 -      this.domNode = $(domNode);
 +      var self = this;
 +      this.pagesNodes = [];
 +      domNodes.each(function(elem){
 +         self.pagesNodes.push(elem.down(".xwiki-grid-pagination-
 content"));
 +      });
       this.max = max;
 +      $
 (this
 .table.domNodeName).select("div.prevPagination").invoke("observe",
 "click", this.gotoPrevPage.bind(this));
 +      $
 (this
 .table.domNodeName).select("div.nextPagination").invoke("observe",
 "click", this.gotoNextPage.bind(this));
     },
 -    refreshPaginator: function()
 +    refreshPagination: function()
     {
 -      this.domNode.innerHTML = "";
 +      var self = this;
 +      this.pagesNodes.each(function(elem){
 +         elem.innerHTML = "";
 +      });
       var pages = Math.ceil(this.table.totalRows / this.table.limit);
       var currentMax = (!this.max) ? pages : this.max;
       var currentPage = Math.floor( this.table.lastoffset /
 this.table.limit) + 1;
       var startPage = Math.floor(currentPage / currentMax) *
 currentMax - 1;
       // always display the first page
       if (startPage>1) {
 -           this.domNode.appendChild(this.createPageLink(1, false));
 -           if (startPage>2) {
 -                  this.domNode.appendChild(document.createTextNode(" ... "));
 +         this.pagesNodes.each(function(elem){
 +             elem.insert(self.createPageLink(1, false));
 +         });
 +         if (startPage>2) {
 +            this.pagesNodes.invoke("insert", " ... ");
          }
       }
       // display pages
 -        var i;
 +      var i;
       for (i=(startPage<=0) ? 1 : startPage;i<=Math.min(startPage +
 currentMax + 1, pages);i++) {
          var selected = (currentPage == i) ? true : false
 -         this.domNode.appendChild(this.createPageLink(i, selected));
 -         this.domNode.appendChild(document.createTextNode(" "));
 +         this.pagesNodes.each(function(elem){
 +             elem.insert(self.createPageLink(i, selected));
 +         });
 +         this.pagesNodes.invoke("insert", " ");
       }
       // alwyas display the last page.
       if (i<pages) {
 -          if (i+1 < pages) {
 -                this.domNode.appendChild(document.createTextNode(" ... "));
 +        if (i+1 < pages) {
 +          this.pagesNodes.invoke("insert", " ... ");
         }
 -        this.domNode.appendChild(this.createPageLink(pages, false));
 +        //this.pagesNodes.invoke("insert", pageSpan.clone());
 +        this.pagesNodes.each(function(elem){
 +             elem.insert(self.createPageLink(pages, false));
 +        });
       }
     },
     createPageLink:function(page, selected) {
 -          var pageSpan = new Element("span",
 {'class':'pagenumber'}).update(page);
 -          if (selected) {
 -                 pageSpan.addClassName("selected");
 +        var pageSpan = new Element("span",
 {'class':'pagenumber'}).update(page);
 +        if (selected) {
 +           pageSpan.addClassName("selected");
         }
 -          var self = this;
 +        var self = this;
         pageSpan.observe("click", function(ev){
             self.gotoPage(ev.element().innerHTML);
         });
 @@ -400,16 +418,16 @@
       var currentPage = Math.floor( this.table.lastoffset /
 this.table.limit) + 1;
       var prevPage = currentPage - 1;
       if (prevPage > 0) {
 -              this.table.showRows(((parseInt(prevPage) - 1) *
 this.table.limit) + 1, this.table.limit);
 -        }
 +        this.table.showRows(((parseInt(prevPage) - 1) *
 this.table.limit) + 1, this.table.limit);
 +      }
     },
     gotoNextPage: function() {
       var currentPage = Math.floor( this.table.lastoffset /
 this.table.limit) + 1;
       var pages = Math.ceil(this.table.totalRows / this.table.limit);
       var nextPage = currentPage + 1;
       if (nextPage <= pages) {
 -              this.table.showRows(((parseInt(nextPage) - 1) *
 this.table.limit) + 1, this.table.limit);
 -        }
 +        this.table.showRows(((parseInt(nextPage) - 1) *
 this.table.limit) + 1, this.table.limit);
 +      }
     }
 });
 Modified: platform/web/trunk/standard/src/main/webapp/templates/
 macros.vm
 ===================================================================
 --- platform/web/trunk/standard/src/main/webapp/templates/macros.vm
 2009-04-30 01:14:08 UTC (rev 19208)
 +++ platform/web/trunk/standard/src/main/webapp/templates/macros.vm
 2009-04-30 06:08:53 UTC (rev 19209)
 @@ -1369,4 +1369,248 @@
  *#
 #macro(editActionButton $action $resourceIdentifier)
 #submitButton("action_${action}", $msg.get("core.shortcuts.edit.$
 {resourceIdentifier}"), $msg.get($resourceIdentifier))
 +#end
 +
 +#**
 + * AJAX Live table that displays XWiki data.
 + *
 + * Example of usage, in syntax 2.0:
 + * <code>
 + * {{velocity}}
 + * #set($columns = [ "_avatar", "first_name", "last_name",
"email"])
 + * #set($columnsProperties = {
 + *                  "first_name" : { "type" : "text" ,
"size" : 10,
 "link" : "view"},
 + *                  "last_name" : { "type" : "text" ,
"size" : 10,
 "link" : "view"},
 + *                  "email" : { "type" : "text" ,
"size" : 20,
 "link" : "editor"},
 + *                  "_avatar" : { "type" : "none" ,
"size" : 20,
 "link" : "none", "html" : "true",
"sortable":false }
 + *                })
 + * #set($options = { "className":"XWiki.XWikiUsers",
 + *                    "translationPrefix" : "xe.index.users.",
 + *                    "tagCloud" : true,
 + *                    "rowCount": 15 })
 + * #livetable("userstable" $columns $columnsProperties $options)
 + * {{/velocity}}
 + * </code>
 + *
 + * @param divid the id of the table div
 + * @param collist the column list
 + * @param colprops the columns properties
 + * @param options the livetable options.
 + *#
 +#macro(livetable $divid $collist $colprops $options)
 +  ##
 +  ## SX deps.
 +  ##
 +  #set($ok = $xwiki.jsfx.use("js/xwiki/table/livetable.js", true))
 +  #set($ok = $xwiki.ssfx.use("js/xwiki/table/livetable.css", true))
 +  ##
 +  ## Options / defaults
 +  ##
 +  #if("$!options.translationPrefix" != "") #set($transprefix =
 $options.translationPrefix) #else #set($transprefix = "") #end
 +  #if("$!options.selectedColumn" != "")  #set($selectedColumn =
 $options.selectedColumn) #end
 +  #if("$!options.defaultOrder" == "desc") #set($defaultOrder =
 "desc") #else #set($defaultOrder = "asc") #end
 +  #if("$!options.rowCount" != "") #set($count = $options.rowCount)
 #else #set($count = 15) #end
 +  #if("$!options.maxPages" != "") #set($maxPages =
 $options.maxPages) #else #set($maxPages = 10) #end
 +  #if("$!options.selectedColumn" != "") #set($selectedColumn =
 $options.selectedColumn) #end
 +  #if("$!options.callback" != "") #set($callback =
 $options.callback) #end
 +  #if("$!options.tagCloud" == "" || $options.tagCloud == false)
 #set($tagcloud=false) #else #set($tagcloud = true) #end
 +  #set($classname = "$!options.className")
 +  ##
 +  ## Columns informations
 +  ##
 +  #set($collist2 = "")
 +  #set($classparams = "")
 +  #foreach($colname in $collist)
 +    #if("$!selectedColumn" == "" &&
!$colname.startsWith("_"))
 +      #set($selectedColumn = $colname)
 +    #end
 +    #set($collist2 = "${collist2},${colname}")
 +    #set($propClassName = "")
 +    #set($propClassName = $colprops.get($colname).get("class"))
 +    #if($propClassName!="")
 +      #set($classparams = "${classparams}&${colname}_class=$
 {propClassName}")
 +    #end
 +  #end
 +  #set($collist2 = $collist2.substring(1))
 +  #if("$!options.url" != "")
 +    #set($dataurl = $options.url)
 +  #elseif("$!options.resultPage" != "")
 +    #set($dataurl =
 $xwiki.getURL($options.resultPage,"view","xpage=plain&transprefix=$
 {transprefix}&classname=${className}&collist=${collist2}$
 {classparams}") )
 +  #else
 +    #set($dataurl =
 $
 xwiki
.getURL("XWiki.LiveTableResults","view","xpage=plain&transprefix=$
 {transprefix}&classname=${classname}&collist=${collist2}$
 {classparams}"))
 +  #end
 +  ##
 +  ## HTML Table
 +  ##
 +  #if($doc.syntaxId == "xwiki/2.0")
 +{{html}}
 +  #end
 +  #if($tagcloud)
 +    #set($ok = $xwiki.ssx.use("XWiki.TagCloud"))
 +    <div id="${divid}-tagcloud">
 +      <div class="xwiki-grid-tagcloud"></div>
 +    </div>
 +  #end
 +  <table id="${divid}" class="xwiki-grid">
 +    <tr>
 +      <td class="xwiki-grid-pagination" colspan="2">
 +        <span id="${divid}-limits"
class="xwiki-grid-limits"></span>
 +        <span id="${divid}-ajax-loader" class="xwiki-grid-
 loader"><img src="$xwiki.getSkinFile('icons/xwiki/ajax-loader-
 large.gif')" alt="$msg.get('xe.grid.loading')"
title="" />
 $msg.get("xe.grid.loading")</span>
 +        <span class="controlPagination">
 +          <div title="$msg.get('xe.pagination.page.prev.title')"
 class="prevPagination"></div>
 +          <div title="$msg.get('xe.pagination.page.next.title')"
 class="nextPagination"></div>
 +        </span>
 +        <span class="pagination">
 +          <span id="${divid}-pagination-text" class="xwiki-grid-
 pagination-text">$msg.get("xe.pagination.page")</span>
 +          <span id="${divid}-pagination" class="xwiki-grid-
 pagination-content" ></span>
 +        </span>
 +      </td>
 +    </tr>
 +    <tr>
 +      <td class="xwiki-grid-display-container">
 +        <table class="xwiki-grid-display">
 +          <thead class="xwiki-grid-display-header">
 +            <tr>
 +            #foreach($colname in $collist)
 +              #set($colprop = $colprops.get($colname))
 +              #if("$!colprop.sortable" == "" || $colprop.sortable !
 = false)
 +                #set($isSortable = true)
 +              #else
 +                #set($isSortable = false)
 +              #end
 +              <th class="xwiki-grid-display-header-text
 #if($isSortable)sortable#end #if($colname == $selectedColumn)
 selected $defaultOrder #elseif($isSortable) asc #end"
 #if($isSortable)rel="${colname}"#end
#if("$!colprop.type"=="hidden")
 style="display: none"
#end>$msg.get("${transprefix}${colname}")</th>
 +            #end
 +            </tr>
 +            <tr class="xwiki-grid-display-filters">
 +            #foreach($colname in $collist)
 +              #set($colprop = $colprops.get($colname))
 +              #if("$!colprop.filterable" == "" ||
 $colprop.filterable != false)
 +                #set($isFilterable = true)
 +              #else
 +                #set($isFilterable = false)
 +              #end
 +              #if("$!colprop.type"=="list" && $isFilterable)
 +                <td class="xwiki-grid-display-header-filter">
 +                #if($colprop.get("class"))
 +                  #set($propClassName = $colprop.get("class"))
 +                #else
 +                  #set($propClassName = $className)
 +                #end
 +                #set($class =
 $xwiki.getDocument($propClassName).getxWikiClass())
 +                #set($list = "")
 +                #set($list = $class.get($colname).getListValues())
 +                <select name='${colname}'><option
value=''>none</
 option>
 +                #set($map = $class.get($colname).getMapValues())
 +                #foreach($listitem in $list)
 +                  <option value="$listitem">
 $map.get($listitem).getValue()</option>
 +                #end
 +                </select>
 +              </td>
 +              #elseif( ("$!colprop.type"=="text"||"$!
 colprop.type"=="number") && $isFilterable)
 +                <td class="xwiki-grid-display-header-filter"><input
 name="${colname}" type="text" #if($colprop.size!="")
size="$
 {colprop.size}" #end  title='$msg.get("xe.search.filters.title")
 $msg.get("${transprefix}${colname}")' /></td>
 +              #elseif("$!colprop.type"=="hidden")
 +              #else
 +              <td class="xwiki-grid-display-header-filter"></td>
 +              #end
 +            #end
 +            </tr>
 +          </thead>
 +          <tbody id="${divid}-display" class="xwiki-grid-display-
 body"><tr><td> </td></tr></tbody>
 +        </table>
 +      </td>
 +    </tr>
 +    <tr>
 +      <td class="xwiki-grid-pagination" colspan="2">
 +        <span class="controlPagination">
 +          <div title="$msg.get('xe.pagination.page.prev.title')"
 class="prevPagination"></div>
 +          <div title="$msg.get('xe.pagination.page.next.title')"
 class="nextPagination"></div>
 +        </span>
 +        <span class="pagination">
 +          <span id="${divid}-pagination-text" class="xwiki-grid-
 pagination-text">$msg.get("xe.pagination.page")</span>
 +          <span id="${divid}-pagination" class="xwiki-grid-
 pagination-content" ></span>
 +        </span>
 +      </td>
 +    </tr>
 +  </table>
 +  <script type="text/javascript">
 +  //<![CDATA[
 +  #if($callback)
 +    var ta = new XWiki.widgets.LiveTable("$dataurl", "${divid}",
 $callback ,{"maxPages":$maxPages});
 +  #else
 +    var ta = new XWiki.widgets.LiveTable("$dataurl", "${divid}",
 #livetablecallback($collist $colprops) ,{"maxPages":$maxPages});
 +  #end
 +   //]]>
 +  </script>
 +  #if($doc.syntaxId == "xwiki/2.0")
 +{{/html}}
 +  #end
 +#end
 +
 +#**
 + * Internal macro - Used by the livetable macro to generate a
 JavaScript annonymous function
 + * that is passed to the LiveTable object constructor. This is
 function is dynamically written
 + * according to columns properties passed to the livetable macro.
 + *
 + * @param collist the list of columns
 + * @param colprops the columns properties
 + *
 + * @internal
 + *#
 +#macro(livetablecallback $collist $colprops)
 +function (row, i, table)
 +{
 +  // This callback method code has been generated from velocity.
 +  var tr = new Element("tr");
 +  #foreach($colname in $collist)
 +    // $colname
 +    #set($colprop = $colprops.get($colname))
 +    #if("$!colprop.type"!="hidden")
 +      #if($colname.indexOf("doc.")==0)
 +        #set($jscolname = $colname.replaceAll("doc.", "doc_"))
 +      #else
 +        #set($jscolname = $colname)
 +      #end
 +
#if("$!colprop.link"=="view"||"$!colprop.link"=="field"||"$!
 colprop.link"=="auto"||"$!colprop.link"=="editor")
 +        var a = new Element("a");
 +        #if("$!colprop.link"=="auto")
 +          a.href = (row.${jscolname}_url=="") ? row.doc_url : row.$
 {jscolname}_url;
 +        #elseif($colprop.link=="field")
 +          a.href = (row.${jscolname}_url=="") ?
 "javascript:void(0)" : row.${jscolname}_url;
 +        #elseif($colprop.link=="editor")
 +          #if($colprop.get("class"))
 +            #set($propClassName = $colprop.get("class"))
 +          #else
 +            #set($propClassName = $className)
 +          #end
 +          a.href = "javascript:void()";
 +        #else
 +          a.href = row.doc_url;
 +        #end
 +        #if($colprop.html && $colprop.html==true)
 +          a.innerHTML = row.${jscolname};
 +        #else
 +          a.update(row.${jscolname});
 +        #end
 +        var fieldel = new Element("td");
 +        fieldel.observe("click", function(event){
 +          var tag = event.element().down("a");
 +          editProperty(row.page, "${propClassName}", "${colname}",
 function(value) { tag.innerHTML = value});
 +        });
 +        fieldel.className = "${jscolname} link${colprop.link} type$!
 {colprop.type}";
 +        fieldel.appendChild(a);
 +        tr.appendChild(fieldel);
 +      #else
 +        var fieldel = document.createElement('td');
 +        fieldel.className = "${jscolname} link${colprop.link} type$!
 {colprop.type}";
 +        #if($colprop.html && $colprop.html==true)
 +          fieldel.innerHTML = row.${jscolname};
 +        #else
 +          fieldel.update(row.${jscolname});
 +        #end
 +        tr.appendChild(fieldel);
 +      #end
 +    #end
 +  #end
 +  return tr;
 +}
 #end
 \ No newline at end of file
 _______________________________________________
 notifications mailing list
 notifications(a)xwiki.org
 
http://lists.xwiki.org/mailman/listinfo/notifications 
 _______________________________________________
 devs mailing list
 devs(a)xwiki.org