How can I get JSF 2.0 to include JS as 'application/javascript' instead of 'text/javascript'
In our JSF 2.0 application at work, we include several javascript files via <h:outputscript>
.
<h:outputScript library="javascript" name="DoStuff.js"/>
The resulting html references them as 'text/javascript'.
<script type="text/javascript" src="/mycontext/javax.faces.resource/DoStuff.js.jsf?ln=javascript"></script>
According to this question, "text/javascript" is obsolete, what's more, htmlunit complains about the type rather verbosely. O开发者_开发百科f course, everything works just fine and I could shut off htmlunit's logging, but I'd rather have JSF generate the correct type.
Is there a way to override the type chosen by <h:outputscript>
?
This is hardcoded in the default renderer of the <h:outputScript>
. Assuming that you're using Mojarra, it's the com.sun.faces.renderkit.html_basic.ScriptRenderer
. According to the source, the type
attribute is been set in the startElement
method. You could just override it:
public class ExtendedScriptRenderer extends ScriptRenderer {
@Override
protected void startElement(ResponseWriter writer, UIComponent component) throws IOException {
writer.startElement("script", component);
writer.writeAttribute("type", "application/javascript", "type");
}
}
Or if you want to provide the enduser the possibility to specify the type
attribute itself and default to application/javascript
when unspecified:
public class ExtendedScriptRenderer extends ScriptRenderer {
@Override
protected void startElement(ResponseWriter writer, UIComponent component) throws IOException {
writer.startElement("script", component);
String type = (String) component.getAttributes().get("type");
if (type == null) type = "application/javascript";
writer.writeAttribute("type", type, "type");
}
}
To get it to run, register it as follows in faces-config.xml
:
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>javax.faces.resource.Script</renderer-type>
<renderer-class>com.example.ExtendedScriptRenderer</renderer-class>
</renderer>
</render-kit>
There's by the way also the nice @FacesRenderer
annotation which should work as follows
@FacesRenderer(componentFamily="javax.faces.Output", rendererType="javax.faces.resource.Script")
public class ExtendedScriptRenderer extends ScriptRenderer {
// ...
}
However, when it's already been definied by a standard renderer (the ScriptRenderer
!), then the custom one will fail to override it by a @FacesRenderer
. See also issue 1748.
精彩评论