Java Drinker
Java Drinker

Reputation: 3167

Facelet components layouts and javascript

I have a question regarding the placement of javascript within facelet components. This is more regarding best practice/style than a programming issue, but I feel like all the solutions I have thought of have been hacks at best. Ok here is my scenario:

I have a facelet template like so (my faces, and apache Trinidad)...

<ui:composition>
<f:view locale="#{myLocale}">
    <ui:insert name="messageBundles" /><!--Here we add load bundle tags-->

    <tr:document mode="strict" styleClass="coolStyleDoc">

        <f:facet name="metaContainer">
            <!--This trinidad defined facet is added to HTML head-->
            <tr:group> <!-- blah bal my own styles and js common to all  -->
                <ui:insert name="metaData" />
            </tr:group>
        </f:facet>
        <tr:form usesUpload="#{empty usesUpload ? 'false' : usesUpload}">
            <div id="formTemplateHeader">
                <ui:insert name="contentHeader" />
            </div>
            <div id="formTemplateContentContainer">
                <div id="formTemplateContent">
                    <ui:insert name="contentBody" />
                </div>
            </div>
            <div id="formTemplateFooter">
                <ui:insert name="contentFooter">
                </ui:insert>
            </div>
        </tr:form>
<!-- etc...--->

Now, a facelet that wants to use this template would look like the following:

<ui:composition template="/path/to/my/template.jspx">

    <ui:define name="bundles">
        <custom:loadBundle basename="messagesStuff" var="bundle" />
    </ui:define>

    <ui:define name="metaData">
        <script>
        <!-- cool javascript stuff goes here-->
        </script>
    </ui:define>

    <ui:define name="contentHeader">
        <!-- MY HEADING!-->
    </ui:define>

    <ui:define name="contentBody">
        <!-- MY Body!-->
    </ui:define>

    <ui:define name="contentFooter">
        <!-- Copyright/footer stuff!-->
    </ui:define>
</ui:composition>

All this works quite well, but the problem I have is when I want to use a facelet component inside this page. If the facelet component has its own javascript code (jQuery stuff etc), how can I make it so that that javascript code is included in the header section of the generated html? Any help would be appreciated. Please let me know if this is not clear or something... thanks in advance

Upvotes: 1

Views: 5676

Answers (3)

Bozho
Bozho

Reputation: 597362

You can include the script by either:

  • <script type="text/javascript" src="externalScript.js"></script>
  • or

    <script type="text/javascript">
    //<![CDATA[
    ....
    //]]>
    </script>
    

Upvotes: 0

Java Drinker
Java Drinker

Reputation: 3167

Hey everyone, just in case anyone was also wondering, and stuck like me with the old jsf, or couldn't use the method proposed by McDowell for some reason, here is how i ended up doing it. It's sort of a lazy man's way, enforced only by convention, not code.

So here is my page that uses the template for it's layout. You can see that it embeds the customFacelet component twice.

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:tr="http://myfaces.apache.org/trinidad"
xmlns:custom="http://mycompany.com/jsf/custom">

<ui:composition template="/path/to/template.jspx">

    <ui:define name="bundles">
        <custom:loadBundle basename="bundleName" var="msgs" />
    </ui:define>

    <ui:define name="metaData">
      <!-- Custom facelet javascript part only -->
        <custom:faceletComponent type="metaData" />
    </ui:define>

    <ui:define name="contentHeader">
        <!-- Fixed header stuff -->
    </ui:define>

    <ui:define name="contentBody">
      <!-- Lots of tables and graphs and awesome content first .... -->

      <!-- Custom facelet again, this time with content only  -->
        <custom:faceletComponent type="content" data="#{bean.data}"/>
    </ui:define>

    <ui:define name="contentFooter">
        <!-- Fixed footer stuff -->
    </ui:define>

</ui:composition>

And here is the facelet, that defines separately rendered areas for js and content...

<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>

<!-- This facelet requires the metaData sections to be placed in the header

    Required Attributes:

    NAME            TYPE                        DESCRIPTION
    =====           =====                       ============
    type            String                  One of ['metaData', 'content']. Determines which section to render
    data      MyBeanType      Get all the facelet data              

-->
<ui:composition>

    <tr:group rendered="#{type eq 'metaData'}">
      <!-- All of this should go in the header-->
        <script type="text/javascript">
            Event.observe(document, 'dom:loaded', function(e) {
      //Funky jQuery stuff here that does tranitions and animations etc
    });
        </script>
    </tr:group>

    <tr:group rendered="#{type eq 'content'}">
      <!-- Here is the facelet content, shared widget html etc
    This part relies on the javascript above
  -->
    </tr:group>
</ui:composition>

Upvotes: 1

McDowell
McDowell

Reputation: 108969

Assuming JSF2 Facelets, you should be able to do something with the h:head/h:outputScript tags.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>JSF2</title>
    </h:head>
    <h:body>
        Hello from Facelets
        <h:outputScript target="head">
        <![CDATA[
          document.write("<!-- this will render in the head tag -->");
        ]]>
        </h:outputScript>
    </h:body>
</html>

Upvotes: 4

Related Questions