« Return to Thread: page modification, not just decoration

Re: page modification, not just decoration

by Joe Walnes-2 :: Rate this Message:

Reply to Author | View in Thread



On 5/8/07, Alexandru Popescu ☀ <the.mindstorm.mailinglist@...> wrote:
On 5/4/07, kawczynski <sitemesh-users@...> wrote:
> I need to implement a solution to 60+ websites to account for new reporting requirements.  The solution needs to be able to perform the following:
>
> - add onclick event handlers to <a href> tags that are external to the current site
> - include different <meta> tags based on the URI (using database-driven configuration)
> - include <script src> tags if they didn't already exist on the page.
>
> I read that SiteMesh does decoration, but I have yet to find documentation on it being able to perform low-level body element insertion or modification.  Can someone tell me it this is possible, and point me in the direction of a howto?
>

Sitemesh is a decoration tool and not an HTML parser, so some of the
things you need to accomplish are not possible.

Well actually it *is* an extensible HTML parser :)


1/  add onclick event handlers to <a href> tags that are external to
the current site

To do this, you can extend SiteMesh's HTML parser and add a new tag rule for processing <a> tags.

public class MyParser extends HTMLPageParser {

  // override default rulest
  protected void addUserDefinedRules(State html, PageBuilder page) {
    super.addUserDefinedRules(html, page);

    // Add a rule.
    // Rules allow the parser to do custom things when encountering HTML tags.
    html.addRule(new LinkRewritingRule()); // see below
  }
}

class LinkRewritingRule extends BasicRule {

      public LinkRewritingRule() {
        super("a"); // Handles all <a> tags.
      }

      public void process(Tag tag) { // Called when parser encounters <a>
        CustomTag newTag = new CustomTag(tag); // Allows tag modification
       
        // modify href attribute
        boolean caseSensitive = false; // allow HREF or href or HrEf
        String oldHref = newTag.getAttributeValue("href", caseSensitive);
        if (oldHref != null) {
          String newHref = // do something;
          newTag.setAttributeValue("href", caseSensitive, newHref);
        }
       
        // write the new tag bag to the page
        newTag.writeTo (currentBuffer());
      }
    }
}

To enable this, edit sitemesh.xml and update the <page-parser> tag to point to your new parser class.


2/ include different <meta> tags based on the URI (using
database-driven configuration)

Your decorator is a standard executable page (probably a JSP or Velocity page), so you can include code to output the necessary meta tags there (which can look at the URI).


3/ include <script src> tags if they didn't already exist on the page.

You could create another tag rule, that looks out for <script src> tags and adds them to the page properties. (If you've ever accessed the meta tag properties from a SiteMesh page this works the same way):

class ScriptSrcExtractingRule extends BasicRule {
      private PageBuilder page;

      public ScriptSrcExtractingRule(PageBuilder page) {
        super("script"); // Handles all <script> tags.
        this.page = page;
      }

      public void process(Tag tag) { // Called when parser encounters <script>
        String src = newTag.getAttributeValue("src", caseSensitive);
        if (src != null) {
          // we found a <script src>. Make it available as a page property.
          page.addProperty("script." + src);
        }
        tag.writeTo(currentBuffer()); // ensure original <script> tag is still written out.
      }
    }
}

Add this to your parser class (above).

Then from decorators, you can do:

<decorator:usePage id="myPage" />
<% if (!myPage.hasProperty("script.something.js")) { %>
<script src="something.js"></script>
<% } %>

cheers
-Joe

 « Return to Thread: page modification, not just decoration