[Snippet] T5: A mixin to rewrite the markup of element

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[Snippet] T5: A mixin to rewrite the markup of element

nillehammer
Tapestry's Submit component renders out as <input type="submit">. Since
HTML 4.0 a submit button can be written as <button type="submit">. I
prefer this approach, because it makes it easier to distinguish between
real input elements (especially textfields) and buttons. I have created
a JIRA request for this: https://issues.apache.org/jira/browse/TAP5-1545
Hopefully it will get implemented in future Tapestry versions.

In the meanwhile I have helped myself out with a mixin that is able to
change the markup of the element (element name and attributes) it is
attached to. In case someone else finds this usefull this is the code:

import java.util.Collection;
import java.util.List;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.BeforeRenderTemplate;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.dom.Attribute;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.dom.Node;

/**
  * Mixin that changes the markup of an element to desired values.
  */
public final class MarkupChanger {

     /**
      * The desired new name for the element.
      */
     @Parameter(required = true, allowNull = false, defaultPrefix =
BindingConstants.LITERAL)
     private String newElemName;

     /**
      * A string containing pairs of attribute names and values
separated by ",".
      */
     @Parameter(allowNull = false, defaultPrefix = BindingConstants.LITERAL)
     private String newAttribs;

     /**
      * The {@link Element} to change the markup.
      */
     private Element originalElem;

     /**
      * In this render phase we can easily get the element that this
mixin is
      * placed into by calling writer.getElement.
      *
      * @param writer
      *          {@link MarkupWriter} injected by Tapestry.
      */
     @BeforeRenderTemplate
     final void determineOriginalElem(final MarkupWriter writer ) {

         this.originalElem = writer.getElement();
     }

     /**
      * We do all the rewriting of markup in the final phase not to
interfere with
      * the render phases of the original element.
      *
      * @param writer
      *          {@link MarkupWriter} injected by Tapestry.
      */
     @AfterRender
     final void changeMarkup(final MarkupWriter writer ) {

         // Create a new element with the desired new name.
         final Element newElem = writer.element(this.newElemName);

         // Add all original attributes to the newly created element.
         final Collection<Attribute> attribs =
this.originalElem.getAttributes();

         for (final Attribute attrib : attribs) {

             newElem.attribute(attrib.getName(), attrib.getValue());
         }

         // Add new attributes to the new element, possibly overwriting
original ones.
         if (this.newAttribs != null && !this.newAttribs.isEmpty()) {

             final String[] attribArr = this.newAttribs.split(",");

             // parse null-String to null.
             for (int i = 0; i < attribArr.length; i++) {

                 if ("null".equals(attribArr[i])) {

                     attribArr[i] = null;
                 }
             }

             newElem.forceAttributes(attribArr);
         }

         // Get children from the original element and add them to the
new one.
         final List<Node> children = this.originalElem.getChildren();

         for (final Node node : children) {

             node.moveToBottom(newElem);
         }

         // End tag for new element.
         writer.end();

         // Remove the original element from DOM.
         this.originalElem.remove();
     }
}

Cheers nillehammer

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [Snippet] T5: A mixin to rewrite the markup of element

Michael Gentry-2
In the past, I had trouble with IE6 and multiple buttons in a FORM.  You
couldn't distinguish which button was clicked on.  I don't know if this
issue still exists in IE7+ because I just stopped using BUTTON.  Just
something you may want to keep in mind if you have to support older versions
of IE and have multiple buttons.

mrg


On Sat, Jun 11, 2011 at 3:05 PM, Nillehammer <
[hidden email]> wrote:

> Tapestry's Submit component renders out as <input type="submit">. Since
> HTML 4.0 a submit button can be written as <button type="submit">. I prefer
> this approach, because it makes it easier to distinguish between real input
> elements (especially textfields) and buttons. I have created a JIRA request
> for this: https://issues.apache.org/jira/browse/TAP5-1545
> Hopefully it will get implemented in future Tapestry versions.
>
> In the meanwhile I have helped myself out with a mixin that is able to
> change the markup of the element (element name and attributes) it is
> attached to. In case someone else finds this usefull this is the code:
>
> import java.util.Collection;
> import java.util.List;
>
> import org.apache.tapestry5.BindingConstants;
> import org.apache.tapestry5.MarkupWriter;
> import org.apache.tapestry5.annotations.AfterRender;
> import org.apache.tapestry5.annotations.BeforeRenderTemplate;
> import org.apache.tapestry5.annotations.Parameter;
> import org.apache.tapestry5.dom.Attribute;
> import org.apache.tapestry5.dom.Element;
> import org.apache.tapestry5.dom.Node;
>
> /**
>  * Mixin that changes the markup of an element to desired values.
>  */
> public final class MarkupChanger {
>
>    /**
>     * The desired new name for the element.
>     */
>    @Parameter(required = true, allowNull = false, defaultPrefix =
> BindingConstants.LITERAL)
>    private String newElemName;
>
>    /**
>     * A string containing pairs of attribute names and values separated by
> ",".
>     */
>    @Parameter(allowNull = false, defaultPrefix = BindingConstants.LITERAL)
>    private String newAttribs;
>
>    /**
>     * The {@link Element} to change the markup.
>     */
>    private Element originalElem;
>
>    /**
>     * In this render phase we can easily get the element that this mixin is
>     * placed into by calling writer.getElement.
>     *
>     * @param writer
>     *          {@link MarkupWriter} injected by Tapestry.
>     */
>    @BeforeRenderTemplate
>    final void determineOriginalElem(final MarkupWriter writer ) {
>
>        this.originalElem = writer.getElement();
>    }
>
>    /**
>     * We do all the rewriting of markup in the final phase not to interfere
> with
>     * the render phases of the original element.
>     *
>     * @param writer
>     *          {@link MarkupWriter} injected by Tapestry.
>     */
>    @AfterRender
>    final void changeMarkup(final MarkupWriter writer ) {
>
>        // Create a new element with the desired new name.
>        final Element newElem = writer.element(this.newElemName);
>
>        // Add all original attributes to the newly created element.
>        final Collection<Attribute> attribs =
> this.originalElem.getAttributes();
>
>        for (final Attribute attrib : attribs) {
>
>            newElem.attribute(attrib.getName(), attrib.getValue());
>        }
>
>        // Add new attributes to the new element, possibly overwriting
> original ones.
>        if (this.newAttribs != null && !this.newAttribs.isEmpty()) {
>
>            final String[] attribArr = this.newAttribs.split(",");
>
>            // parse null-String to null.
>            for (int i = 0; i < attribArr.length; i++) {
>
>                if ("null".equals(attribArr[i])) {
>
>                    attribArr[i] = null;
>                }
>            }
>
>            newElem.forceAttributes(attribArr);
>        }
>
>        // Get children from the original element and add them to the new
> one.
>        final List<Node> children = this.originalElem.getChildren();
>
>        for (final Node node : children) {
>
>            node.moveToBottom(newElem);
>        }
>
>        // End tag for new element.
>        writer.end();
>
>        // Remove the original element from DOM.
>        this.originalElem.remove();
>    }
> }
>
> Cheers nillehammer
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>