Jason,
I wanted to add onclick, onmouseover and onmouseout to the rows in my
grid, and due to some timing issues with JavaScript enhancement (it
could take 3-4 seconds before the JS was loaded after the browser
displayed the HTML), I went with DOM rewriting. Here's a sample of my
code. You can probably do the same, by adding tr elements to the DOM tree.
First, I wrote a little utility class that should be enhanced to
something similar to the $$() Prototype method. My version just finds
the first matching node.
package org.jonathan.t5web;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.dom.Node;
import org.apache.tapestry5.ioc.internal.util.Defense;
public class ElementFinder
{
private static interface Finder {
Node search(Node root);
}
private static class IdFinder implements Finder {
private String id;
public IdFinder(String id) {
this.id = id;
}
public Element search(Node root) {
return ((Element)root).getElementById( id );
}
}
private static class IndexFinder implements Finder {
private int index;
public IndexFinder(int index) {
this.index = index;
}
public Node search(Node root) {
return root.getChildren().get( index );
}
}
private static class TagFinder implements Finder {
private String tag;
public TagFinder(String tag) {
this.tag = tag;
}
public Element search(Node root) {
return ((Element)root).find( tag );
}
}
public Node find(String selector, Node rootElement) {
Defense.notBlank(selector, selector);
Defense.notNull( rootElement, rootElement );
String[] selectors = selector.split( );
Node search = rootElement;
for (String s : selectors) {
Finder finder = parseSelector( s );
search = finder.search( search );
if (search == null) {
return null;
}
}
return search;
}
/**
* Returns true if the selector is an id, e.g. #customerSearch
* @param selector
*/
private boolean isIdSelector( String selector ) {
return selector.startsWith( # );
}
IdFinder buildIdFinder( String idSelector ) {
return new IdFinder(idSelector.substring( 1 ));
}
/**
* Returns true if the selector is an id, e.g. #customerSearch
* @param selector
*/
private boolean isIndexSelector( String selector ) {
return selector.startsWith( [ ) selector.endsWith( ] );
}
IndexFinder buildIndexFinder(String indexSelector) {
return new IndexFinder(Integer.parseInt(
indexSelector.substring( 1, indexSelector.length() - 1 ) ));
}
Finder parseSelector(String selector) {
if (isIdSelector( selector )) {
return buildIdFinder( selector );
}
if (isIndexSelector( selector )) {
return buildIndexFinder( selector );
}
if (isTagSelector( selector )) {
return buildTagFinder( selector );
}
throw new IllegalArgumentException(selector + is not an id,
tag or index);
}
Finder buildTagFinder( String selector )
{
return new TagFinder( selector );
}
private boolean isTagSelector( String selector )
{
return !selector.startsWith( # ) !selector.startsWith( [
) !selector.endsWith( ] );
}
}
Now, you need to provide an afterRender method to do the DOM rewriting:
void afterRender(MarkupWriter writer) {
Document doc = writer.getDocument();
if (doc == null) {
_logger.info( writer.getDocument( ) is null );
return;
}
ElementFinder finder = new ElementFinder();
Node tbody = finder.find( #customerTable tbody,
doc.getRootElement() );
if (tbody == null) {
_logger.info( writer.getDocument(
).getElementById(customerTable).find(tbody) is null );
return;
}
String prefixUrl = generateCustomerRowLinkEventUrlPrefix();
_rowIndex = 0;
for (Node node : tbody.getChildren()) {
Element tr = (Element)node;
Node custId = finder.find( [1] [0], tr );
tr.attribute( onclick, doCustomerTableRowClick(' +
prefixUrl + custId.toString() + '); );
tr.attribute( onmouseover, this.className =
'DataTableEntryMouseOver'; );
tr.attribute( onmouseout, this.className = ' +
getRowClass() + ';);
_rowIndex++;
}
}
Hope this helps,
Jonathan
On 24/02/2009 01:40, Jason Tan wrote:
Hi,
I'd like to render multipletr elements within the same grid row.
Searching this mailing list seems to come up with a combination of
subclassing Grid and GridRows (i.e.