Allowing Tapestry components to contribute CSS

It has always been easy to contribute javascript from a component to a page in Tapestry. The Body component included in Tapestry framework is responsible for gathering all contributed javascript and placing it either in body’s onLoad or exactly after the body tag.

However, instructing Tapestry to add a CSS, either from within a custom component or while in the middle of a page has always been an issue. I even remember that there was a patched Tapestry version which allowed such functionality.

Well, after reading Using JavaScript to dynamically add Portlet CSS stylesheets by Mark McLaren, a simpler solution can be implemented.

So, I just created a new Style component (included in TapFX v0.30 library) and here’s the code:
style.js

 function tapfx_addStyleSheet(styleUrl)
 {
 	if(document.createStyleSheet) 
 	{
 		document.createStyleSheet(styleUrl);
 	}
 	else 
 	{	
 		var styles = "@import url('" + styleUrl + "');";
 		var newSS=document.createElement('link');
 		newSS.rel='stylesheet';
 		newSS.href='data:text/css,'+escape(styles);
 		document.getElementsByTagName("head")[0].appendChild(newSS);
 	}
 }

Style.script

 <?xml version="1.0"?>
 
 <script>
     <include-script resource-path="style.js"/>
     <input-symbol required="yes" key="css" class="java.lang.String" />
     <body>
        <![CDATA[
         tapfx_addStyleSheet('${css}');
           ]]>
     </body>    
 </script>
 

Style.jwc

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE component-specification PUBLIC
   "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
   "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
 <component-specification allow-informal-parameters="no" allow-body="no">
     <description>Adds a css to the page</description>
     
     <parameter name="css" type="org.apache.tapestry.IAsset" direction="in" required="yes">
         <description>The css asset to add.</description>
     </parameter>    
 
 </component-specification>
 

Script.html

 <span jwcid="@Script" script="/net/sf/tapfx/components/style/Style.script"
 	css="ognl:page.requestCycle.requestContext.getAbsoluteURL(css.buildURL(page.requestCycle))"/>
 

I should just mention that all these work for Tapestry v3.01-3.03 for the moment.

andyhot