You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2009/03/21 11:51:08 UTC

svn commit: r756912 - in /incubator/click/trunk/click/framework/src/org/apache/click: ./ element/

Author: sabob
Date: Sat Mar 21 10:51:07 2009
New Revision: 756912

URL: http://svn.apache.org/viewvc?rev=756912&view=rev
Log:
javadoc

Added:
    incubator/click/trunk/click/framework/src/org/apache/click/element/package.html
Modified:
    incubator/click/trunk/click/framework/src/org/apache/click/Control.java
    incubator/click/trunk/click/framework/src/org/apache/click/Page.java
    incubator/click/trunk/click/framework/src/org/apache/click/element/CssImport.java
    incubator/click/trunk/click/framework/src/org/apache/click/element/CssStyle.java
    incubator/click/trunk/click/framework/src/org/apache/click/element/Element.java
    incubator/click/trunk/click/framework/src/org/apache/click/element/JsImport.java
    incubator/click/trunk/click/framework/src/org/apache/click/element/JsScript.java
    incubator/click/trunk/click/framework/src/org/apache/click/element/ResourceElement.java

Modified: incubator/click/trunk/click/framework/src/org/apache/click/Control.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/Control.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/Control.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/Control.java Sat Mar 21 10:51:07 2009
@@ -215,7 +215,7 @@
      *     }
      * } </pre>
      *
-     * Alternative one can add the HEAD elements in the Control's constructor:
+     * Alternatively one can add the HEAD elements in the Control's constructor:
      *
      * <pre class="prettyprint">
      * public MyControl extends AbstractControl {

Modified: incubator/click/trunk/click/framework/src/org/apache/click/Page.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/Page.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/Page.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/Page.java Sat Mar 21 10:51:07 2009
@@ -694,7 +694,7 @@
      *     }
      * } </pre>
      *
-     * An alternative is to add the HEAD elements in the Page constructor:
+     * Alternatively one can add the HEAD elements in the Page constructor:
      *
      * <pre class="prettyprint">
      * public MyPage extends Page {

Modified: incubator/click/trunk/click/framework/src/org/apache/click/element/CssImport.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/element/CssImport.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/element/CssImport.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/element/CssImport.java Sat Mar 21 10:51:07 2009
@@ -19,10 +19,36 @@
 package org.apache.click.element;
 
 import org.apache.click.Context;
+import org.apache.click.util.ClickUtils;
 import org.apache.click.util.HtmlStringBuffer;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 
 /**
+ * Provides a Css HEAD element for importing <tt>external</tt> Cascading
+ * Stylesheet files using the &lt;link&gt; tag.
+ * <p/>
+ * Example usage:
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the CSS import is only added the
+ *         // first time this method is called.
+ *         if (headElements == null) {
+ *             // Get the head elements from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             CssImport cssImport = new CssImport("/css/style.css");
+ *             headElements.add(cssImport);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * The <tt>cssImport</tt> instance will be rendered as follows (assuming the
+ * context path is <tt>myApp</tt>):
+ * <pre class="prettyprint">
+ * &lt;link type="text/css" rel="stylesheet" href="/myApp/css/style.css"/&gt; </pre>
  *
  * @author Bob Schellink
  */
@@ -31,20 +57,21 @@
     // ----------------------------------------------------------- Constructors
 
     /**
-     * Constructs a new CssImport link.
+     * Constructs a new Css import element.
      */
     public CssImport() {
         this(null);
     }
 
     /**
-     * Construct a new CssImport link with the specified <tt>href</tt> attribute.
+     * Construct a new Css import element with the specified <tt>href</tt>
+     * attribute.
      * <p/>
-     * <b>Please note</b> if the given <tt>href</tt> begins with a <tt class="wr">"/"</tt>
-     * character the href will be prefixed with the web application
-     * <tt>context path</tt>.
+     * <b>Please note</b> if the given <tt>href</tt> begins with a
+     * <tt class="wr">"/"</tt> character the href will be prefixed with the web
+     * application <tt>context path</tt>.
      *
-     * @param href the CSS link href attribute
+     * @param href the Css import href attribute
      */
     public CssImport(String href) {
         setHref(href);
@@ -64,13 +91,13 @@
     }
 
     /**
-     * This method always return true because CSS import must be unique based on
+     * This method always return true because Css import must be unique based on
      * its <tt>href</tt> attribute. In other words the Page HEAD should only
      * contain a single CSS import for the specific <tt>href</tt>.
      *
-     * @see HtmlHeader#isUnique()
+     * @see ResourceElement#isUnique()
      *
-     * @return true because CSS import must unique based on its <tt>href</tt>
+     * @return true because Css import must unique based on its <tt>href</tt>
      * attribute
      */
     public boolean isUnique() {
@@ -120,7 +147,8 @@
     // --------------------------------------------------------- Public Methods
 
     /**
-     * Render the HTML representation of the CSS import to the specified buffer.
+     * Render the HTML representation of the CssImport element to the specified
+     * buffer.
      *
      * @param buffer the buffer to render output to
      */
@@ -173,19 +201,4 @@
     public int hashCode() {
         return new HashCodeBuilder(17, 37).append(getHref()).toHashCode();
     }
-
-    // ------------------------------------------------ Package Private Methods
-
-    /**
-     * This operation is not supported because CSS imports is always unique
-     * based on their <tt>href</tt> attribute.
-     *
-     * @see HtmlHeader#setUnique(boolean)
-     *
-     * @param unique sets whether the Css import should be unique or not
-     */
-    void setUnique(boolean unique) {
-        throw new UnsupportedOperationException("CssImport is always"
-            + " unique based on the 'href' attribute");
-    }
 }

Modified: incubator/click/trunk/click/framework/src/org/apache/click/element/CssStyle.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/element/CssStyle.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/element/CssStyle.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/element/CssStyle.java Sat Mar 21 10:51:07 2009
@@ -19,10 +19,129 @@
 package org.apache.click.element;
 
 import org.apache.click.util.HtmlStringBuffer;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 
 /**
+ * Provides a Css HEAD element for including <tt>inline</tt> Cascading
+ * Stylesheets using the &lt;style&gt; tag.
+ * <p/>
+ * Example usage:
+ *
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the CSS import is only added the
+ *         // first time this method is called.
+ *         if (headElements == null) {
+ *             // Get the header entries from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             CssStyle cssStyle = new CssStyle("body { font: 12px arial; }");
+ *             headElements.add(cssStyle);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * The <tt>cssStyle</tt> instance will render as follows:
+ *
+ * <pre class="prettyprint">
+ * &lt;style type="text/css" rel="stylesheet"&gt;
+ * body { font: 12px arial; }
+ * &lt;/style&gt;
+ * </pre>
+ *
+ * Below is an example showing how to render inline CSS from a Velocity
+ * template.
+ * <p/>
+ * First we create a Velocity template <tt>(/css/style-template.css)</tt> which
+ * contains the variable <tt>$context</tt> that must be replaced at runtime with
+ * the application <tt>context path</tt>:
+ *
+ * <pre class="prettyprint">
+ * .blue {
+ *     background: #00ff00 url('$context/css/blue.png') no-repeat fixed center;
+ * } </pre>
+ *
+ * Next is the Page implementation:
+ *
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the CSS is only added the first time
+ *         // this method is called.
+ *         if (headElements == null) {
+ *             // Get the head elements from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             Context context = getContext();
+ *
+ *             // Create a default template model to pass to the template
+ *             Map model = ClickUtils.createTemplateModel(this, context);
+ *
+ *             // Specify the path to CSS Velocity template
+ *             String cssTemplate = "/css/style-template.css";
+ *
+ *             // Render the template using the model above
+ *             String content = context.renderTemplate(cssTemplate, model);
+ *
+ *             // Create the inline Css for the given template
+ *             CssStyle cssStyle = new CssStyle(content);
+ *             headElements.add(cssStyle);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * The <tt>Css</tt> above will render as follows (assuming the context path is
+ * <tt>myApp</tt>):
+ *
+ * <pre class="prettyprint">
+ * &lt;style type="text/css" rel="stylesheet"&gt;
+ * .blue {
+ *     background: #00ff00 url('/myApp/css/blue.png') no-repeat fixed center;
+ * }
+ * &lt;/style&gt;
+ * </pre>
+ *
+ * <h3>Character data (CDATA) support</h3>
+ *
+ * Sometimes it is necessary to wrap <tt>inline</tt> {link Css} in CDATA tags.
+ * Two use cases are common for doing this:
+ * <ul>
+ * <li>For XML parsing: When using Ajax one often send back partial
+ * XML snippets to the browser, which is parsed as valid XML. However the XML
+ * parser will throw an error if the script contains reserved XML characters
+ * such as '&amp;', '&lt;' and '&gt;'. For these situations it is recommended
+ * to wrap the script content inside CDATA tags.
+ * </li>
+ * <li>XHTML validation: if you want to validate your site using an XHTML
+ * validator e.g: <a target="_blank" href="http://validator.w3.org/">http://validator.w3.org/</a>.</li>
+ * </ul>
+ *
+ * To wrap the CSS Style content in CDATA tags, set
+ * {@link #setCharacterData(boolean)} to true. Below is how a CSS content would
+ * be rendered:
+ *
+ * <pre class="prettyprint">
+ * &lt;style type="text/css"&gt;
+ *  /&lowast;&lt;![CDATA[&lowast;/
+ *
+ *  div &gt; p {
+ *    border: 1px solid black;
+ *  }
+ *
+ *  /&lowast;]]&gt;&lowast;/
+ * &lt;/style&gt; </pre>
+ *
+ * Notice the CDATA tags are commented out which ensures older browsers that
+ * don't understand the CDATA tag, will ignore it and only process the actual
+ * content.
+ * <p/>
+ * For an overview of XHTML validation and CDATA tags please see
+ * <a target="_blank" href="http://javascript.about.com/library/blxhtml.htm">http://javascript.about.com/library/blxhtml.htm</a>.
  *
  * @author Bob Schellink
  */
@@ -30,29 +149,27 @@
 
      // -------------------------------------------------------------- Variables
 
-    /** A buffer holding the inline CSS content. */
+    /** A buffer holding the inline Css content. */
     private HtmlStringBuffer content = new HtmlStringBuffer();
 
     /**
-     * Indicates if the HtmlHeader's content should be wrapped in a CDATA tag.
-     * <b>Note:</b> this property only applies to HtmlHeader imports which contain
-     * <tt>inline</tt> content.
+     * Indicates if the HeadElement's content should be wrapped in a CDATA tag.
      */
     private boolean characterData = false;
 
     // ------------------------------------------------------------ Constructor
 
     /**
-     * Construct a new CSS Style element.
+     * Construct a new Css style element.
      */
     public CssStyle() {
         this(null);
     }
 
     /**
-     * Construct a new CSS Style element with the given content.
+     * Construct a new Css style element with the given content.
      *
-     * @param content the CSS content
+     * @param content the Css content
      */
     public CssStyle(String content) {
         if (content != null) {
@@ -74,16 +191,16 @@
     }
 
     /**
-     * Return the CSS content buffer.
+     * Return the Css content buffer.
      *
-     * @return the CSS content buffer
+     * @return the Css content buffer
      */
     public HtmlStringBuffer getContent() {
         return content;
     }
 
     /**
-     * Set the CSS content buffer.
+     * Set the Css content buffer.
      *
      * @param content the new content buffer
      */
@@ -92,10 +209,10 @@
     }
 
     /**
-     * Return true if the HtmlHeader's content should be wrapped in CDATA tags,
+     * Return true if the CssStyle's content should be wrapped in CDATA tags,
      * false otherwise.
      *
-     * @return true if the HtmlHeader's content should be wrapped in CDATA tags,
+     * @return true if the CssStyle's content should be wrapped in CDATA tags,
      * false otherwise
      */
     public boolean isCharacterData() {
@@ -103,9 +220,10 @@
     }
 
     /**
-     * Sets whether the HtmlHeader's content should be wrapped in CDATA tags or not.
+     * Sets whether the CssStyle's content should be wrapped in CDATA tags or
+     * not.
      *
-     * @param characterData true indicates that the HtmlHeader's content should be
+     * @param characterData true indicates that the CssStyle's content should be
      * wrapped in CDATA tags, false otherwise
      */
     public void setCharacterData(boolean characterData) {
@@ -115,16 +233,18 @@
     // --------------------------------------------------------- Public Methods
 
     /**
-     * Append the given CSS string to the content buffer.
+     * Append the given Css string to the content buffer.
      *
      * @param content the CSS string to append to the content buffer
+     * @return the Css content buffer
      */
-    public void append(String content) {
-        this.content.append(content);
+    public HtmlStringBuffer append(String content) {
+        return this.content.append(content);
     }
 
     /**
-     * Render the HTML representation of the CSS to the specified buffer.
+     * Render the HTML representation of the CssStyle element to the specified
+     * buffer.
      *
      * @param buffer the buffer to render output to
      */
@@ -143,7 +263,7 @@
         // Render CDATA tag if necessary
         renderCharacterDataPrefix(buffer);
 
-        buffer.append(getContent());
+        renderContent(buffer);
 
         renderCharacterDataSuffix(buffer);
 
@@ -193,6 +313,17 @@
         return new HashCodeBuilder(17, 37).append(getId()).toHashCode();
     }
 
+    // ------------------------------------------------------ Protected Methods
+
+    /**
+     * Render this CssStyle content to the specified buffer.
+     *
+     * @param buffer the buffer to append the output to
+     */
+    protected void renderContent(HtmlStringBuffer buffer) {
+        buffer.append(getContent());
+    }
+
     // ------------------------------------------------ Package Private Methods
 
     /**
@@ -221,21 +352,4 @@
             buffer.append(" /*]]>*/");
         }
     }
-
-    /**
-     * @see HtmlHeader#setUnique(boolean)
-     *
-     * @deprecated use {@link #setId(java.lang.String)} instead
-     *
-     * @param unique sets whether the HtmlHeader import should be unique or not
-     */
-    void setUnique(boolean unique) {
-        super.setUnique(unique);
-
-        // If CSS is unique and ID is not defined, derive the ID from the content
-        if (unique && StringUtils.isBlank(getId()) && getContent().length() > 0) {
-            int hash = getContent().toString().hashCode();
-            setId(Integer.toString(hash));
-        }
-    }
 }

Modified: incubator/click/trunk/click/framework/src/org/apache/click/element/Element.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/element/Element.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/element/Element.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/element/Element.java Sat Mar 21 10:51:07 2009
@@ -24,6 +24,11 @@
 import org.apache.click.util.HtmlStringBuffer;
 
 /**
+ * Provides a base class for rendering HTML elements, for example
+ * JavaScript (&lt;script&gt;) and Cascading Stylesheets
+ * (&lt;link&gt;/&lt;style&gt;).
+ * <p/>
+ * Subclasses should override {@link #getTag()} to return a specific HTML tag.
  *
  * @author Bob Schellink
  */
@@ -31,7 +36,7 @@
 
     // -------------------------------------------------------------- Variables
 
-    /** The HtmlHeader attributes Map. */
+    /** The Element attributes Map. */
     private Map attributes;
 
     // ------------------------------------------------------ Public properties

Modified: incubator/click/trunk/click/framework/src/org/apache/click/element/JsImport.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/element/JsImport.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/element/JsImport.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/element/JsImport.java Sat Mar 21 10:51:07 2009
@@ -19,10 +19,37 @@
 package org.apache.click.element;
 
 import org.apache.click.Context;
+import org.apache.click.util.ClickUtils;
 import org.apache.click.util.HtmlStringBuffer;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 
 /**
+ * Provides a JavaScript HEAD element for importing <tt>external</tt> JavaScript
+ * files using the &lt;script&gt; tag.
+ * <p/>
+ * Example usage:
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the JS import is only added the
+ *         // first time this method is called.
+ *         if (headElements == null) {
+ *             // Get the head elements from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             JsImport jsImport = new JsImport("/js/js-library.js");
+ *             headElements.add(jsImport);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * The <tt>jsImport</tt> instance will be rendered as follows (assuming the context
+ * path is <tt>myApp</tt>):
+ * <pre class="prettyprint">
+ * &lt;script type="text/javascript" href="/myApp/js/js-library.js"&gt;&lt;/script&gt; </pre>
+ *
  * @author Bob Schellink
  */
 public class JsImport extends ResourceElement {
@@ -30,20 +57,21 @@
     // ----------------------------------------------------------- Constructors
 
     /**
-     * Constructs a new JavascriptImport.
+     * Constructs a new JavaScript import element.
      */
     public JsImport() {
         this(null);
     }
 
     /**
-     * Construct a new JavascriptImport with the specified <tt>src</tt> attribute.
+     * Construct a new JavaScript import element with the specified
+     * <tt>src</tt> attribute.
      * <p/>
-     * <b>Please note</b> if the given <tt>src</tt> begins with a <tt class="wr">"/"</tt>
-     * character the src will be prefixed with the web application
-     * <tt>context path</tt>.
+     * <b>Please note</b> if the given <tt>src</tt> begins with a
+     * <tt class="wr">"/"</tt> character the src will be prefixed with the web
+     * application <tt>context path</tt>.
      *
-     * @param src the Javascript src attribute
+     * @param src the JavaScript import src attribute
      */
     public JsImport(String src) {
         setSrc(src);
@@ -53,20 +81,20 @@
     // ------------------------------------------------------ Public properties
 
     /**
-     * Returns the Css import HTML tag: &lt;script&gt;.
+     * Returns the JavaScript import HTML tag: &lt;script&gt;.
      *
-     * @return the Css import HTML tag: &lt;script&gt;
+     * @return the JavaScript import HTML tag: &lt;script&gt;
      */
     public String getTag() {
         return "script";
     }
 
     /**
-     * This method always return true because JavaScript import must be unique
+     * This method always return true because a JavaScript import must be unique
      * based on its <tt>src</tt> attribute. In other words the Page HEAD should
      * only contain a single JavaScript import for the specific <tt>src</tt>.
      *
-     * @see HtmlHeader#isUnique()
+     * @see ResourceElement#isUnique()
      *
      * @return true because JavaScript import must unique based on its
      * <tt>src</tt> attribute
@@ -118,7 +146,7 @@
     // ------------------------------------------------ Package Private Methods
 
     /**
-     * Render the HTML representation of the JavaScript import to the specified
+     * Render the HTML representation of the JsImport element to the specified
      * buffer.
      *
      * @param buffer the buffer to render output to
@@ -170,19 +198,4 @@
     public int hashCode() {
         return new HashCodeBuilder(17, 37).append(getSrc()).toHashCode();
     }
-
-    // ------------------------------------------------ Package Private Methods
-
-    /**
-     * This operation is not supported because JavaScript imports is always
-     * unique based on their <tt>src</tt> attribute.
-     *
-     * @see HtmlHeader#setUnique(boolean)
-     *
-     * @param unique sets whether the JavaScript import should be unique or not
-     */
-    void setUnique(boolean unique) {
-        throw new UnsupportedOperationException("JavascriptImport is always"
-            + " unique based on the 'src' attribute");
-    }
 }

Modified: incubator/click/trunk/click/framework/src/org/apache/click/element/JsScript.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/element/JsScript.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/element/JsScript.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/element/JsScript.java Sat Mar 21 10:51:07 2009
@@ -19,10 +19,131 @@
 package org.apache.click.element;
 
 import org.apache.click.util.HtmlStringBuffer;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.builder.HashCodeBuilder;
 
 /**
+ * Provides a HEAD element for including <tt>inline</tt> JavaScript using the
+ * &lt;script&gt; tag.
+ * <p/>
+ * Example usage:
+ *
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the JS is only added the
+ *         // first time this method is called.
+ *         if (headElements == null) {
+ *             // Get the head elements from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             JsScript jsScript = new JsScript("alert('Hello World!);");
+ *             headElements.add(jsScript);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * The <tt>jsScript</tt> instance will be rendered as follows:
+ *
+ * <pre class="prettyprint">
+ * &lt;script type="text/javascript"&gt;
+ * alert('Hello World');
+ * &lt;/script&gt;
+ * </pre>
+ *
+ * Below is an example showing how to render inline Javascript from a
+ * Velocity template.
+ * <p/>
+ * First we create a Velocity template <tt>(/js/mycorp-template.js)</tt> which
+ * contains the variable <tt>$divId</tt> that must be replaced at runtime with
+ * the real Div ID attribute:
+ *
+ * <pre class="prettyprint">
+ * hide = function() {
+ *     var div = document.getElementById('$divId');
+ *     div.style.display = "none";
+ * }
+ * </pre>
+ *
+ * Next is the Page implementation:
+ *
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the JS is only added the
+ *         // first time this method is called.
+ *         if (headElements == null) {
+ *             // Get the head elements from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             // Create a default template model to pass to the template
+ *             Map model = ClickUtils.createTemplateModel(this, getContext());
+ *
+ *             // Add the id of the div to hide
+ *             model.put("divId", "myDiv");
+ *
+ *             // Specify the path to the JavaScript Velocity template
+ *             String jsTemplate = "/js/mycorp-template.js";
+ *
+ *             // Render the template providing it with the model
+ *             String template = getContext().renderTemplate(jsTemplate, model);
+ *
+ *             // Create the inline JavaScript for the given template
+ *             JsScript jsScript = new JsScript(template);
+ *             headElements.add(jsScript);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * The <tt>jsScript</tt> instance will render as follows (assuming the context
+ * path is <tt>myApp</tt>):
+ *
+ * <pre class="prettyprint">
+ * &lt;script type="text/javascript"&gt;
+ *     hide = function() {
+ *         var div = document.getElementById('myDiv');
+ *         div.style.display = "none";
+ *     }
+ * &lt;/style&gt;
+ * </pre>
+ *
+ * <h3>Character data (CDATA) support</h3>
+ *
+ * Sometimes it is necessary to wrap <tt>inline</tt> {@link JsScript} in CDATA
+ * tags. Two use cases are common for doing this:
+ * <ul>
+ * <li>For XML parsing: When using Ajax one often send back partial
+ * XML snippets to the browser, which is parsed as valid XML. However the XML
+ * parser will throw an error if the script contains reserved XML characters
+ * such as '&amp;', '&lt;' and '&gt;'. For these situations it is recommended
+ * to wrap the script content inside CDATA tags.
+ * </li>
+ * <li>XHTML validation: if you want to validate your site using an XHTML
+ * validator e.g: <a target="_blank" href="http://validator.w3.org/">http://validator.w3.org/</a>.</li>
+ * </ul>
+ *
+ * To wrap the JavaScript content in CDATA tags, set
+ * {@link #setCharacterData(boolean)} to true. Below is how the JavaScript
+ * content would be rendered:
+ *
+ * <pre class="prettyprint">
+ * &lt;script type="text/javascript"&gt;
+ *  /&lowast;&lt;![CDATA[&lowast;/
+ *
+ *  if(x &lt; y) alert('Hello');
+ *
+ *  /&lowast;]]&gt;&lowast;/
+ * &lt;/script&gt; </pre>
+ *
+ * Notice the CDATA tags are commented out which ensures older browsers that
+ * don't understand the CDATA tag, will ignore it and only process the actual
+ * content.
+ * <p/>
+ * For an overview of XHTML validation and CDATA tags please see
+ * <a target="_blank" href="http://javascript.about.com/library/blxhtml.htm">http://javascript.about.com/library/blxhtml.htm</a>.
  *
  * @author Bob Schellink
  */
@@ -30,29 +151,27 @@
 
     // -------------------------------------------------------------- Variables
 
-    /** A buffer holding the inline CSS content. */
+    /** A buffer holding the inline JavaScript content. */
     private HtmlStringBuffer content = new HtmlStringBuffer();
 
     /**
-     * Indicates if the HtmlHeader's content should be wrapped in a CDATA tag.
-     * <b>Note:</b> this property only applies to HtmlHeader imports which contain
-     * <tt>inline</tt> content.
+     * Indicates if the JsScript's content should be wrapped in a CDATA tag.
      */
     private boolean characterData = false;
 
     // ----------------------------------------------------------- Constructors
 
     /**
-     * Construct a new inline Javascript element.
+     * Construct a new inline JavaScript element.
      */
     public JsScript() {
         this(null);
     }
 
     /**
-     * Construct a new inline Javascript element with the given content.
+     * Construct a new inline JavaScript element with the given content.
      *
-     * @param content the Javascript content
+     * @param content the JavaScript content
      */
     public JsScript(String content) {
         if (content != null) {
@@ -64,25 +183,25 @@
     // ------------------------------------------------------ Public Properties
 
     /**
-     * Returns the Javascript HTML tag: &lt;script&gt;.
+     * Returns the JavaScript HTML tag: &lt;script&gt;.
      *
-     * @return the Javascript HTML tag: &lt;script&gt;
+     * @return the JavaScript HTML tag: &lt;script&gt;
      */
     public String getTag() {
         return "script";
     }
 
     /**
-     * Return the Javascript content buffer.
+     * Return the JavaScript content buffer.
      *
-     * @return the Javascript content buffer
+     * @return the JavaScript content buffer
      */
     public HtmlStringBuffer getContent() {
         return content;
     }
 
     /**
-     * Set the Javascript content buffer.
+     * Set the JavaScript content buffer.
      *
      * @param content the new content buffer
      */
@@ -91,10 +210,10 @@
     }
 
     /**
-     * Return true if the HtmlHeader's content should be wrapped in CDATA tags,
+     * Return true if the JsScript's content should be wrapped in CDATA tags,
      * false otherwise.
      *
-     * @return true if the HtmlHeader's content should be wrapped in CDATA tags,
+     * @return true if the JsScript's content should be wrapped in CDATA tags,
      * false otherwise
      */
     public boolean isCharacterData() {
@@ -102,9 +221,9 @@
     }
 
     /**
-     * Sets whether the HtmlHeader's content should be wrapped in CDATA tags or not.
+     * Sets whether the JsScript's content should be wrapped in CDATA tags or not.
      *
-     * @param characterData true indicates that the HtmlHeader's content should be
+     * @param characterData true indicates that the JsScript's content should be
      * wrapped in CDATA tags, false otherwise
      */
     public void setCharacterData(boolean characterData) {
@@ -114,17 +233,18 @@
     // --------------------------------------------------------- Public Methods
 
     /**
-     * Append the given Javascript string to the content buffer.
+     * Append the given JavaScript string to the content buffer.
      *
-     * @param content the Javascript string to append to the content
+     * @param content the JavaScript string to append to the content
      * buffer
+     * @return the JavaScript content buffer
      */
-    public void append(String content) {
-        this.content.append(content);
+    public HtmlStringBuffer append(String content) {
+        return this.content.append(content);
     }
 
     /**
-     * Render the HTML representation of the JavaScript to the specified
+     * Render the HTML representation of the JsScript element to the specified
      * buffer.
      *
      * @param buffer the buffer to render output to
@@ -144,7 +264,7 @@
         // Render CDATA tag if necessary
         renderCharacterDataPrefix(buffer);
 
-        buffer.append(getContent());
+        renderContent(buffer);
 
         renderCharacterDataSuffix(buffer);
 
@@ -194,6 +314,17 @@
         return new HashCodeBuilder(17, 37).append(getId()).toHashCode();
     }
 
+    // ------------------------------------------------------ Protected Methods
+
+    /**
+     * Render this JsScript content to the specified buffer.
+     *
+     * @param buffer the buffer to append the output to
+     */
+    protected void renderContent(HtmlStringBuffer buffer) {
+        buffer.append(getContent());
+    }
+
     // ------------------------------------------------ Package Private Methods
 
     /**
@@ -222,21 +353,4 @@
             buffer.append(" /*]]>*/");
         }
     }
-
-    /**
-     * @see HtmlHeader#setUnique(boolean)
-     *
-     * @deprecated use {@link #setId(java.lang.String)} instead
-     *
-     * @param unique sets whether the HtmlHeader import should be unique or not
-     */
-    void setUnique(boolean unique) {
-        super.setUnique(unique);
-
-        // If CSS is unique and ID is not defined, derive the ID from the content
-        if (unique && StringUtils.isBlank(getId()) && getContent().length() > 0) {
-            int hash = Math.abs(getContent().toString().hashCode());
-            setId(Integer.toString(hash));
-        }
-    }
 }

Modified: incubator/click/trunk/click/framework/src/org/apache/click/element/ResourceElement.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/element/ResourceElement.java?rev=756912&r1=756911&r2=756912&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/element/ResourceElement.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/element/ResourceElement.java Sat Mar 21 10:51:07 2009
@@ -22,6 +22,122 @@
 import org.apache.commons.lang.StringUtils;
 
 /**
+ * Provides a base class for rendering HEAD resources of an HTML page, for
+ * example JavaScript (&lt;script&gt;) and Cascading Stylesheets
+ * (&lt;link&gt;/&lt;style&gt;).
+ * <p/>
+ * Subclasses should override {@link #getTag()} to return a specific HTML tag.
+ * <p/>
+ * Below are some example Resource elements:
+ * <ul>
+ * <li>{@link JsImport}, for importing <tt>external</tt> JavaScript using the
+ * &lt;script&gt; element.</li>
+ * <li>{@link JsScript}, for including <tt>inline</tt> JavaScript using the
+ * &lt;script&gt; element.</li>
+ * <li>{@link CssImport}, for importing <tt>external</tt> Cascading Stylesheets
+ * using the &lt;link&gt; element.</li>
+ * <li>{@link CssStyle}, for including <tt>inline</tt> Cascading Stylesheets
+ * using the &lt;style&gt; element.</li>
+ * </ul>
+ *
+ * <h3>Remove duplicates</h3>
+ * Click will ensure that duplicate Resource elements are removed by checking
+ * the {@link #isUnique()} property. No matter how many Controls or Pages
+ * import the same Resource, only one will be rendered if {@link #isUnique()}
+ * returns <tt>true</tt>.
+ * <p/>
+ * The rules for defining a unique Resource is as follows:
+ * <ul>
+ * <li>{@link JsImport} and {@link CssImport} is unique based on the
+ * attributes {@link JsImport#getSrc()} and {@link CssImport#getHref()}
+ * respectively.</li>
+ * <li>{@link JsScript} and {@link CssStyle} is unique if their HTML
+ * {@link #setId(java.lang.String) ID} attribute is set. The HTML
+ * spec defines that an element's HTML ID must be unique per page.</li>
+ * </ul>
+ * For example:
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the JavaScript and Css is only added
+ *         // the first time this method is called.
+ *         if (headElements == null) {
+ *             // Get the head elements from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             JsImport jsImport = new JsImport("/js/mylib.js");
+ *             // Click will ensure the library "/js/mylib.js" is only included
+ *             // once in the Page
+ *             headElements.add(jsImport);
+ *
+ *             JsScript jsScript = new JsScript("alert('Hello!');");
+ *             // Click won't ensure the script is unique because its ID
+ *             // attribute is not defined
+ *             headElements.add(jsScript);
+ *
+ *             jsScript = new JsScript("alert('Hello!');");
+ *             jsScript.setId("my-unique-script-id");
+ *             // Click will ensure the script is unique because its ID attribute
+ *             // is defined. Click will remove other scripts with the same ID
+ *             headElements.add(jsScript);
+ *
+ *             CssImport cssImport = new CssImport("/css/style.css");
+ *             // Click will ensure the library "/css/style.css" is only
+ *             // included once in the Page
+ *             headElements.add(cssImport);
+ *
+ *             CssScript cssScript = new CssScript("body { font-weight: bold; }");
+ *             cssScript.setId("my-unique-style-id");
+ *             // Click will ensure the css is unique because its ID attribute
+ *             // is defined. Click will remove other css styles with the same ID
+ *             headElements.add(cssScript);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * <h3>Conditional comment support for Internet Explorer</h3>
+ *
+ * Sometimes it is necessary to provide additional JavaScript and Css for
+ * Internet Explorer because it deviates quite often from the standards.
+ * <p/>
+ * Conditional comments allows you to wrap the resource in a special comment
+ * which only IE understands, meaning other browsers won't process the resource.
+ * <p/>
+ * You can read more about conditional comments
+ * <a target="_blank" href="http://msdn.microsoft.com/en-us/library/ms537512(VS.85).aspx#syntax">here</a>
+ * and <a target="_blank" href="http://www.quirksmode.org/css/condcom.html">here</a>
+ * <p/>
+ * It has to be said that IE7 and up has much better support for Css, thus
+ * conditional comments are mostly used for IE6 and below.
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *     public List getHeadElements() {
+ *         // We use lazy loading to ensure the JavaScript and Css is only added
+ *         // the first time this method is called.
+ *         if (headElements == null) {
+ *             // Get the head elements from the super implementation
+ *             headElements = super.getHeadElements();
+ *
+ *             CssImport cssImport = new CssImport("/css/ie-style.css");
+ *             // Use one of the predefined conditional comments to target IE6
+ *             // and below
+ *             cssImport.setConditionalComment(IE_LESS_THAN_IE7);
+ *             headElements.add(cssImport);
+ *
+ *             cssImport = new CssImport("/css/ie-style2.css");
+ *             // Use a custom predefined conditional comments to target only IE6
+ *             cssImport.setConditionalComment("[if IE 6]");
+ *             headElements.add(cssImport);
+ *         }
+ *         return headElements;
+ *     }
+ * } </pre>
+ *
+ * ResourceElement contains some predefined Conditional Comments namely
+ * {@link #IF_IE}, {@link #IF_LESS_THAN_IE7} and {@link #IF_IE7}.
  *
  * @author Bob Schellink
  */
@@ -49,24 +165,25 @@
 
     // -------------------------------------------------------------- Variables
 
-    /** The Internet Explorer conditional comment to wrap the HtmlHeader import with. */
+    /**
+     * The Internet Explorer conditional comment to wrap the Resource with.
+     */
     private String conditionalComment;
 
     /**
      * Indicates if Click should ensure the import is unique, default value is
-     * <tt>false</tt>. <b>Note:</b> subclasses of HtmlHeader have different rules to
-     * determine if unique should be true or false.
+     * <tt>false</tt>.
      */
     private boolean unique = false;
 
     // ------------------------------------------------------ Public properties
 
     /**
-     * Return true if the HtmlHeader should be unique, false otherwise. The default
+     * Return true if the Resource should be unique, false otherwise. The default
      * value is <tt>true</tt> if the {@link #getId() ID} attribute is defined,
      * false otherwise.
      *
-     * @return true if the HtmlHeader should be unique, false otherwise.
+     * @return true if the Resource should be unique, false otherwise.
      */
     public boolean isUnique() {
         String id = getId();
@@ -80,21 +197,20 @@
     }
 
     /**
-     * Return Internal Explorer's <tt>conditional comment</tt> to wrap the HtmlHeader
-     * import with.
+     * Return Internal Explorer's <tt>conditional comment</tt> to wrap the
+     * Resource with.
      *
-     * @return Internal Explorer's conditional comment to wrap the HtmlHeader import
-     * with.
+     * @return Internal Explorer's conditional comment to wrap the Resource with.
      */
     public String getConditionalComment() {
         return conditionalComment;
     }
 
     /**
-     * Set Internet Explorer's conditional comment to wrap the HtmlHeader import with.
+     * Set Internet Explorer's conditional comment to wrap the Resource with.
      *
      * @param conditionalComment Internet Explorer's conditional comment to wrap
-     * the HtmlHeader import with
+     * the Resource with
      */
     public void setConditionalComment(String conditionalComment) {
         this.conditionalComment = conditionalComment;
@@ -102,6 +218,16 @@
 
     // --------------------------------------------------------- Public methods
 
+    /**
+     * Render the HTML representation of the Resource element to the specified
+     * buffer.
+     * <p/>
+     * If {@link #getTag()} returns null, this method will return an empty
+     * string.
+     *
+     * @param buffer the specified buffer to render the Resource element output
+     * to
+     */
     public void render(HtmlStringBuffer buffer) {
         renderConditionalCommentPrefix(buffer);
 
@@ -147,29 +273,4 @@
             buffer.append("\n<![endif]-->");
         }
     }
-
-    /**
-     * This method provides backwards compatibility with the String based
-     * HTML imports, to indicate whether Javascript and CSS must be unique
-     * or not. The replacement functionality is provided by the html
-     * {@link #setId(java.lang.String) ID} attribute.
-     * <p/>
-     * This property is *not* for public use and will be removed in a future
-     * release. This property is only set from PageImports.
-     *
-     * @deprecated use {@link #setId(java.lang.String)} instead
-     *
-     * @param unique sets whether the HtmlHeader import should be unique or not
-     */
-    void setUnique(boolean unique) {
-        String id = getId();
-
-        // If id is defined, unique property cannot be set to false
-        if (StringUtils.isNotBlank(id) && !unique) {
-            throw new IllegalArgumentException("Cannot set unique property"
-                + " to 'false' because an 'ID' attribute has been defined"
-                + " which indicates the import should be unique.");
-        }
-        this.unique = unique;
-    }
 }

Added: incubator/click/trunk/click/framework/src/org/apache/click/element/package.html
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/element/package.html?rev=756912&view=auto
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/element/package.html (added)
+++ incubator/click/trunk/click/framework/src/org/apache/click/element/package.html Sat Mar 21 10:51:07 2009
@@ -0,0 +1,28 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.
+-->
+
+<body>
+Provides basic HTML elements including:
+<ul>
+    <li>{@link org.apache.click.element.JsImport JsImport} - for importing external JavaScript files</li>
+    <li>{@link org.apache.click.element.JsScript JsScript} - for embedding JavaScript content in the page</li>
+    <li>{@link org.apache.click.element.CssImport CssImport} - for importing external Css files</li>
+    <li>{@link org.apache.click.element.CssStyle CssStyle} - for embedding Css content in the page</li>
+</ul>
+</body>
\ No newline at end of file