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. Of 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>
?
In JSF 2.0, you can use <h:outputScript /> tag to render a HTML “script” element, and link it to a js file.
The h:outputScript tag renders an HTML element of the type "script" with type "text/javascript". This tag is used to add an external javascript file to JSF page.
You need to do a few things for jQuery to work with JSF 2.0. Assign ID for all relevant UI components and their parents. Only then can you be sure about the DOM element ID of the component you are trying to manipulate.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With