Thanks for the example, Thiago.
I modified your code it to make it work with my example.
Now, to make my tml[1] work I edit the mixin[2] to render the foot-block
and then move it to the right place.
I had to use two less beautifull workarounds. The first one was that
marker tag. Although the documentation sais the "MarkupWriter is more
like a cursor into the DOM tree" I didn't find out how to get the
cursor's position. So that's why there is a marker tag. Now I can find
the previously rendered tfoot-block and grid-table, which are relative
positioned to the marker.
Then comes my second workaround. Initially I wanted to call
tfoot.moveToBottom(gridTable); but that causes a stack overflow because
this move-method does not delete Node#nextSibling, only the previous
lastChild's nextSibling - which was null. The nextSibling of the Element
"tfoot" in my code points to the grid-div! So this causes some
endless-loop. Is this worth a Jira?
Anyway, as my code is not perfect, yet, I'd appreciate any suggestions
for improvement :)
[1] example.tml snippet
<t:grid source="source" t:mixins="GridFooter">
<p:foot>
<tfoot>
<tr>
<td colspan="3">
Some Footer
</td>
</tr>
</tfoot>
</p:foot>
</t:grid>
[2] GridFooter.java
@MixinAfter
public class GridFooter {
@Parameter(name = "foot", defaultPrefix = BindingConstants.LITERAL)
private Block foot;
Object beginRender(MarkupWriter writer) {
return foot;
}
@AfterRender
void rewriteDOM(MarkupWriter writer) {
// first workaround caused by the lack of xpath knowledge
Element marker = writer.element("marker");
writer.end();
final Element tfoot = findNextElementByTag("tfoot",
childElements(marker.getContainer()), 0);
final Element gridDiv = firstSibling("div", tfoot);
final Element gridTable = firstChild("table", gridDiv);
// 2dn workaround: copy tfoot because moving it directly causes
a stack overflow
Element e = writer.element("tfoot");
e.raw(tfoot.toString().replace("<tfoot>",
"").replace("</tfoot>", ""));
writer.end();
e.moveToBottom(gridTable);
tfoot.remove();
marker.remove();
}
private List<Element> childElements(Element element) {
List<Element> elements = new ArrayList<Element>();
for (Node node : element.getChildren()) {
if (node instanceof Element) {
elements.add((Element) node);
}
}
return elements;
}
private Element firstChild(String tag, Element element) {
Element firstChild = null;
List<Element> children = childElements(element);
for (Element child : children) {
if (child.getName().equals(tag)) {
firstChild = child;
} else {
firstChild = firstChild(tag, child);
}
if (firstChild != null) {
break;
}
}
return firstChild;
}
private Element firstSibling(String tag, Element element) {
Element firstSibling = null;
List<Element> siblings = childElements(element.getContainer());
Element sibling = null;
for (int i = 0; i < siblings.size(); i++) {
sibling = siblings.get(i);
if (sibling.equals(element)) {
firstSibling = findNextElementByTag(tag, siblings, i++);
break;
}
}
return firstSibling;
}
private Element findNextElementByTag(String tag, List<Element>
siblings, int start) {
if(siblings.size() <= start) return null;
Element e = siblings.get(start);
if(e.getName().equals(tag)) return e;
return findNextElementByTag(tag, siblings, ++start);
}
}
Howard Lewis Ship schrieb:
Remember that the Grid can sometimes only take you so far; if you look
at its implementation, you'll see that much of it is driven by
reusable sub-components.
I expect, in 5.2, to create an AbstractGrid that will be easier to
subclass and extend.
I know, but there is so much nice functionality in the Grid that I don't
want have copy-pasted into some custom component. I rather write some
Frankenstein-Mixin than copy-paste your work ;)
An AbstractGrid would be nice!
Christian
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org