I have an XPage that allows the selection of a query-document. The full-text query that's inside it searches documents from the database, does some calculations and displays them as a view on the screen. There is also a button on the screen that sets requestScope.showExcel=true and does a full reload, in order to download the data directly into Excel (using .setHeader("Content-disposition", "inline; myfile.xls"). It is no more than a simple table with its tr and td tags. So far so good.
Column properties (height, width, colour) can be set per column, these are stored inside the query-document (which is a separate document, not part of the search results). Those properties are put into a style-tag element created using an xp:text control set to create html output.
It all works, except for one thing: Excel and OpenOffice or LibreOffice Calc don't like the style section in the body. When I save the output and move the styles to the head section the file loads okay in Excel.
So I went out to put our computed styling in the head section. I found the styleSheet resource, with its computed content parameter. It does generate some of the CSS I put in, but not all. As it turns out, the content is computed on load, and not dynamically. The button mentioned above does a full refresh of the page, which made me assume that styles would also be updated.
Alas, no. The stylesheet content seems to be fixed.
My questions:
Is there a way that inline CSS can be put in a style section in the head section in a dynamic way, so that it is recomputed when the page is reloaded (full update)?
Is there maybe some control somewhere that lets me add arbitrary content to the head section?
Or is there a way in Java to dynamically adapt the head section??
Thanks for your help!
Just create your own renderer for your header resource:
package ch.hasselba.xpages.renderkit;
import com.ibm.commons.util.StringUtil;
import com.ibm.xsp.complex.Parameter;
import com.ibm.xsp.render.ResourceRenderer;
import com.ibm.xsp.resource.GenericHeadResource;
import com.ibm.xsp.resource.Resource;
import com.ibm.xsp.util.JSUtil;
import java.io.IOException;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
public class GenericHeadResourceRenderer extends ResourceRenderer {
public void encodeResource(FacesContext fc, UIComponent uiComponent,
Resource res) throws IOException {
GenericHeadResource headRes = (GenericHeadResource) res;
ResponseWriter rw = fc.getResponseWriter();
String tagName = headRes.getTagName();
if (StringUtil.isNotEmpty(tagName)) {
rw.startElement(tagName, uiComponent);
List<Parameter> params = headRes.getAttributes();
if (params != null) {
for (Parameter param : params) {
String name = param.getName();
if (StringUtil.isNotEmpty(name)) {
String value = param.getValue();
if (value == null) {
value = "";
}
if( "content".equals( name ) ){
rw.write( value );
}else{
rw.writeAttribute(name, value, name);
}
}
}
}
rw.endElement(tagName);
JSUtil.writeln(rw);
}
}
}
To activate the renderer, you have to overwrite the existing one in the faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<render-kit>
<renderer>
<component-family>com.ibm.xsp.resource.Resource</component-family>
<renderer-type>com.ibm.xsp.resource.GenericHead</renderer-type>
<renderer-class>ch.hasselba.xpages.renderkit.GenericHeadResourceRenderer</renderer-class>
</renderer>
</render-kit>
</faces-config>
Then, add the dynamic content you want in a parameter with the name "content":
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:headTag tagName="style">
<xp:this.attributes>
<xp:parameter name="type" value="text/css" />
<xp:parameter name="content"
value="#{javascript:java.lang.System.currentTimeMillis()}" />
</xp:this.attributes>
</xp:headTag>
</xp:this.resources>
</xp:view>