Re: [xwiki-devs] [xwiki-notifications] r19209 - in platform: core/trunk/xwiki-core/src/main/resources web/trunk/standard/src/main/webapp/resources/js/xwiki/table web/trunk/standard/src/main/webapp/templates
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 [email protected] http://lists.xwiki.org/mailman/listinfo/notifications
Hi Vincent, Note the livetable is an empty table everywhere you don't have JavaScript. Inserting the select in JavaScript sounds a bad idea to me. It would be a hack to hide form controls (button, select, etc) to renderers for which they do not have sense. But those form controls are meaningful in the macro, to me a form is something that by itself justify the use of the HTML macro. (and actually I'm not sure you can do that trick that easily, since the select values are generated server side from velocity). I'm completely convinced we have to use standard wiki syntax as much as possible, but we should also keep in mind that some macros will not make any kind of sense anywhere but in a browser. Can renderers that do not support HTML fragments just drop them (eventually outputting a message to say a part of the original document is missing) ? Thanks, Jerome. Vincent Massol wrote:
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 [email protected] http://lists.xwiki.org/mailman/listinfo/notifications
_______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
On Apr 30, 2009, at 10:14 AM, Jerome Velociter wrote:
Hi Vincent,
Note the livetable is an empty table everywhere you don't have JavaScript. Inserting the select in JavaScript sounds a bad idea to me. It would be a hack to hide form controls (button, select, etc) to renderers for which they do not have sense. But those form controls are meaningful in the macro, to me a form is something that by itself justify the use of the HTML macro. (and actually I'm not sure you can do that trick that easily, since the select values are generated server side from velocity).
I'm completely convinced we have to use standard wiki syntax as much as possible, but we should also keep in mind that some macros will not make any kind of sense anywhere but in a browser. Can renderers that do not support HTML fragments just drop them (eventually outputting a message to say a part of the original document is missing) ?
Yes that's the problem: they'll be dropped. So instead of a table with data it'll be an empty space. That said we need to think how we'd want a livetable to be displayed in other renderers. As I said that's not a problem we have now but we need to be aware of it since it'll crop up again one day. -Vincent
Thanks, Jerome.
Vincent Massol wrote:
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
Vincent Massol wrote:
On Apr 30, 2009, at 10:14 AM, Jerome Velociter wrote:
Hi Vincent,
Note the livetable is an empty table everywhere you don't have JavaScript. Inserting the select in JavaScript sounds a bad idea to me. It would be a hack to hide form controls (button, select, etc) to renderers for which they do not have sense. But those form controls are meaningful in the macro, to me a form is something that by itself justify the use of the HTML macro. (and actually I'm not sure you can do that trick that easily, since the select values are generated server side from velocity).
I'm completely convinced we have to use standard wiki syntax as much as possible, but we should also keep in mind that some macros will not make any kind of sense anywhere but in a browser. Can renderers that do not support HTML fragments just drop them (eventually outputting a message to say a part of the original document is missing) ?
Yes that's the problem: they'll be dropped. So instead of a table with data it'll be an empty space. That said we need to think how we'd want a livetable to be displayed in other renderers.
For me, we should display a message that explain "this part of the document cannot be represented in this format". Could this be a parameter of the HTML macro, the "I'm sorry I can not be rendered with this renderer, etc." message ? Again, even if we make the macro use only wiki syntax, it will be an empty table, which is IMHO worse than an empty space (users will be wondering that is supposed to be). Of course we can think of an alternative to be displayed (which I believe is not an easy task for a live table, since you'll never want to display a table with 30.000 entries, so displaying the whole table is... out of the table), but we'll have the case anyway with potentially lot of other things. (How do you render a canvas element ? a flash object ? an applet ? etc.) I really think we'll need a way to display an "excuse message". Jerome.
As I said that's not a problem we have now but we need to be aware of it since it'll crop up again one day.
-Vincent
Thanks, Jerome.
Vincent Massol wrote:
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
devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
On Apr 30, 2009, at 11:28 AM, Jerome Velociter wrote:
Vincent Massol wrote:
On Apr 30, 2009, at 10:14 AM, Jerome Velociter wrote:
Hi Vincent,
Note the livetable is an empty table everywhere you don't have JavaScript. Inserting the select in JavaScript sounds a bad idea to me. It would be a hack to hide form controls (button, select, etc) to renderers for which they do not have sense. But those form controls are meaningful in the macro, to me a form is something that by itself justify the use of the HTML macro. (and actually I'm not sure you can do that trick that easily, since the select values are generated server side from velocity).
I'm completely convinced we have to use standard wiki syntax as much as possible, but we should also keep in mind that some macros will not make any kind of sense anywhere but in a browser. Can renderers that do not support HTML fragments just drop them (eventually outputting a message to say a part of the original document is missing) ?
Yes that's the problem: they'll be dropped. So instead of a table with data it'll be an empty space. That said we need to think how we'd want a livetable to be displayed in other renderers.
For me, we should display a message that explain "this part of the document cannot be represented in this format". Could this be a parameter of the HTML macro, the "I'm sorry I can not be rendered with this renderer, etc." message ? Again, even if we make the macro use only wiki syntax, it will be an empty table, which is IMHO worse than an empty space (users will be wondering that is supposed to be). Of course we can think of an alternative to be displayed (which I believe is not an easy task for a live table, since you'll never want to display a table with 30.000 entries, so displaying the whole table is... out of the table), but we'll have the case anyway with potentially lot of other things. (How do you render a canvas element ? a flash object ? an applet ? etc.) I really think we'll need a way to display an "excuse message".
Yes that would be easy to do. -Vincent
Jerome.
As I said that's not a problem we have now but we need to be aware of it since it'll crop up again one day.
-Vincent
Thanks, Jerome.
Vincent Massol wrote:
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
devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
_______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs
participants (2)
-
Jerome Velociter -
Vincent Massol