You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by dg...@apache.org on 2006/02/09 08:45:44 UTC

svn commit: r376215 - in /struts/shale/trunk: clay-plugin/src/java/org/apache/shale/clay/component/ use-cases/src/java/org/apache/shale/usecases/symbols/ use-cases/src/web/ajax/ use-cases/src/web/symbols/ xdocs/ xdocs/images/

Author: dgeary
Date: Wed Feb  8 23:45:42 2006
New Revision: 376215

URL: http://svn.apache.org/viewcvs?rev=376215&view=rev
Log:
Added an introduction to Clay and a segment on HTML Views in addition to minor tweaks to Clay.java and the Ajax use case.

Added:
    struts/shale/trunk/xdocs/images/login-clay-red.jpg   (with props)
    struts/shale/trunk/xdocs/images/login-clay.jpg   (with props)
    struts/shale/trunk/xdocs/images/login-html-red.jpg   (with props)
    struts/shale/trunk/xdocs/images/login-html.jpg   (with props)
    struts/shale/trunk/xdocs/images/login.jpg   (with props)
Modified:
    struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/component/Clay.java
    struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/symbols/RegistrationForm.java
    struts/shale/trunk/use-cases/src/web/ajax/zipCode.jsp
    struts/shale/trunk/use-cases/src/web/symbols/home.jsp
    struts/shale/trunk/use-cases/src/web/symbols/nameReuse.jsp
    struts/shale/trunk/xdocs/features-reusable-views.xml
    struts/shale/trunk/xdocs/index.xml
    struts/shale/trunk/xdocs/navigation.xml

Modified: struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/component/Clay.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/component/Clay.java?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/component/Clay.java (original)
+++ struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/component/Clay.java Wed Feb  8 23:45:42 2006
@@ -45,6 +45,10 @@
 import org.apache.shale.clay.config.beans.ConfigBeanFactory;
 import org.apache.shale.util.Messages;
 
+/**
+ * This component grafts a subview onto the current JSF view.
+ * 
+ */
 public class Clay extends UINamingContainer {
     
     /**
@@ -326,7 +330,7 @@
         }
         
         // Recursively build the subtree and fixup references. The root
-        // of the subview will be assinged to the child private property.
+        // of the subview will be assigned to the child private property.
         
         ClayContext clayContext = new ClayContext();
         clayContext.setChild(null);
@@ -337,8 +341,7 @@
         Map symbolTable = new TreeMap();
         symbolTable.putAll(getDisplayElementRoot().getSymbols());
         symbolTable.putAll(getSymbols());
-		clayContext.setSymbols(symbolTable);
-		
+        clayContext.setSymbols(symbolTable);
         
         clayContext.setRootElement(getDisplayElementRoot());
         clayContext.setParent(this);
@@ -393,7 +396,7 @@
     
     /**
      * <p>
-     * Calls to super and adds some trace logging.
+     * Called by JSF, this method delegates to {@link recursiveRenderChildren}.
      * </p>
      */
     public void encodeChildren(FacesContext context) throws IOException {
@@ -407,8 +410,8 @@
     
     /**
      * <p>
-     * Calls to super and invokes the rendering of the sub component tree if the
-     * parent component doesn't render it's children.
+     * Called by JSF, this method simply emits a logging statement
+	  * if tracing is enabled.
      * </p>
      */
     public void encodeEnd(FacesContext context) throws IOException {
@@ -416,7 +419,7 @@
         if (log.isTraceEnabled())
             log.trace("encodeEnd(FacesContext)");
         
-        }
+    }
     
     /**
      * <p>
@@ -478,10 +481,8 @@
     
     /**
      * <p>Returns <code>true</code> indicating that this
-     * component will render it's children.  This will 
-     * indicate to a parent component that renders children 
-     * not to recursively render Clay's children -
-     * simply invoke encodeChildren(FacesContext).</p>
+     * component renders it's children. That means JSF will
+	  * invoke <code>encodeChildren()</code> method.
      */
     public boolean getRendersChildren() {
         return true;

Modified: struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/symbols/RegistrationForm.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/symbols/RegistrationForm.java?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/symbols/RegistrationForm.java (original)
+++ struts/shale/trunk/use-cases/src/java/org/apache/shale/usecases/symbols/RegistrationForm.java Wed Feb  8 23:45:42 2006
@@ -30,10 +30,10 @@
 public class RegistrationForm extends AbstractViewController {
     
     /**
-     * <p>This view controller is scoped in the request.  The init method
-     * is invoked each request and the page's state is handle using 
-     * session scoped backing beans.  The dialog for these session scoped
-     * backing beans are managed through this stateless controller. 
+     * <p>This view controller is scoped in the request. The init method
+     * is invoked for each request and the page's state is stored in
+     * session scoped beans. The dialog for these session scoped
+     * beans are managed through this stateless controller.
      * This separation of view model data and action controller is similar 
      * to Struts Action 1.x.</p> 
      */

Modified: struts/shale/trunk/use-cases/src/web/ajax/zipCode.jsp
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/ajax/zipCode.jsp?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/web/ajax/zipCode.jsp (original)
+++ struts/shale/trunk/use-cases/src/web/ajax/zipCode.jsp Wed Feb  8 23:45:42 2006
@@ -29,13 +29,13 @@
             <!--
             var req; // XMLHttpRequest
 
-            // zipChanged(zip) is called when a selection is made 
+            // zipChanged(zip) is called when a selection is made
             // from the zip code menu.
 
             function zipChanged(zip) {
-               sendRequest("http://localhost:8080/struts-shale-usecases/" +
+               sendRequest(<%= request.getContextPath() %> +
                            "dynamic/remoting$business/cityAndStateForZip.faces" +
-                           "?zip=" + escape(zip), 
+                           "?zip=" + escape(zip),
                             processZipCodeSelection);
             }
 
@@ -84,9 +84,9 @@
                              var stateElement = window.document
                                                       .getElementById("ajaxZipForm:state");
                              cityElement.value = city;
-                             stateElement.value = therest.substring(stateStartIndex, 
+                             stateElement.value = therest.substring(stateStartIndex,
                                                                     stateEndIndex);
-                           }   
+                           }
                         }
                      }
                   }

Modified: struts/shale/trunk/use-cases/src/web/symbols/home.jsp
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/symbols/home.jsp?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/web/symbols/home.jsp (original)
+++ struts/shale/trunk/use-cases/src/web/symbols/home.jsp Wed Feb  8 23:45:42 2006
@@ -50,7 +50,922 @@
          <f:param name="url" value="/symbols/layout.html"/></h:outputLink> that defines 
       sections of a typical page having a header, 
       footer, left navbar and body sections.  The layout is defined as an HTML template, 
-      but the entry point can be a full XML or full HTML template.  There is a central 
+      but the entry point can be a full XML or full HTML teIndex: src/java/org/apache/shale/faces/ValidatorRenderKit.java
+===================================================================
+--- src/java/org/apache/shale/faces/ValidatorRenderKit.java	(revision 0)
++++ src/java/org/apache/shale/faces/ValidatorRenderKit.java	(revision 0)
+@@ -0,0 +1,68 @@
++/*
++ * Copyright 2006 The Apache Software Foundation.
++ *
++ * Licensed 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.
++ *
++ */
++
++package org.apache.shale.faces;
++
++import java.io.OutputStream;
++import java.io.Writer;
++
++import javax.faces.context.ResponseStream;
++import javax.faces.context.ResponseWriter;
++import javax.faces.render.RenderKit;
++import javax.faces.render.Renderer;
++import javax.faces.render.ResponseStateManager;
++
++import org.apache.shale.renderer.ValidatorCommandRenderer;
++
++public class ValidatorRenderKit extends RenderKit {
++
++    private RenderKit defaultRenderKit = null;
++    public ValidatorRenderKit(RenderKit defaultRenderKit) {
++       this.defaultRenderKit = defaultRenderKit;
++    }
++
++    public void addRenderer(String componentFamily, String rendererType, Renderer renderer) {
++       this.defaultRenderKit.addRenderer(componentFamily, rendererType, renderer);
++    }
++
++    public Renderer getRenderer(String componentFamily, String rendererType) {
++        Renderer target = defaultRenderKit.getRenderer(componentFamily, rendererType);
++        if (componentFamily.equals("javax.faces.Command")) {
++           if (!(target instanceof ValidatorCommandRenderer)) {
++               target = new ValidatorCommandRenderer(target);
++               addRenderer(componentFamily, rendererType, target);
++           }
++        }
++
++        return target;
++    }
++
++    public ResponseStateManager getResponseStateManager() {
++        return defaultRenderKit.getResponseStateManager();
++    }
++
++    public ResponseWriter createResponseWriter(Writer writer,
++            String contentTypeList,
++            String characterEncoding){
++        return defaultRenderKit.createResponseWriter(writer, contentTypeList, characterEncoding);
++    }
++
++    public ResponseStream createResponseStream(OutputStream outputStream) {
++        return defaultRenderKit.createResponseStream(outputStream);
++    }
++
++}
+Index: src/java/org/apache/shale/validator/Globals.java
+===================================================================
+--- src/java/org/apache/shale/validator/Globals.java	(revision 367478)
++++ src/java/org/apache/shale/validator/Globals.java	(working copy)
+@@ -19,7 +19,7 @@
+ /**
+  * <p>Manifest constants that are global to the validator implementation.</p>
+  *
+- * $Id:$
++ * $Id$
+  */
+
+ public class Globals {
+Index: src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java
+===================================================================
+--- src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java	(revision 0)
++++ src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java	(revision 0)
+@@ -0,0 +1,168 @@
++/*
++ * Copyright 2006 The Apache Software Foundation.
++ *
++ * Licensed 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.
++ *
++ */
++
++package org.apache.shale.renderer;
++
++import java.io.IOException;
++import java.io.StringWriter;
++
++import javax.faces.component.UICommand;
++import javax.faces.component.UIComponent;
++import javax.faces.context.FacesContext;
++import javax.faces.context.ResponseWriter;
++import javax.faces.render.Renderer;
++
++public class ValidatorCommandRenderer extends Renderer {
++
++    private Renderer defaultRenderer = null;
++    public ValidatorCommandRenderer(Renderer defaultRenderer) {
++       this.defaultRenderer = defaultRenderer;
++    }
++
++
++
++    /**
++     * <p>
++     * Attribute name used to override the default behavior of how the immediate
++     * attribute effects the execution of client side javascript validation.
++     * </p>
++     */
++    public static final String OVERRIDE_IMMEDIATE = "org.apache.shale.validator.immediate";
++
++    private static final int ENCODE_BEGIN = 0;
++
++    private static final int ENCODE_CHILDREN = 1;
++
++    private static final int ENCODE_END = 2;
++
++    /**
++     * <b>Interrogates the component's immediate property and the component's
++     * immediate override attribute to determine if client side validation is
++     * invoked. If either the property or attribute override is false, client
++     * side validation is invoked. Otherwise, the response writer is hijacked
++     * and the original render is invoked. The result is buffered and a
++     * statement of javascript is injected into the onclick event which cancels
++     * client side validation. The original response writer is restored and the
++     * modified markup is written to the response writer. The
++     * <code>encodeSwitch</code> determines if the encodeBegin, encodeChildren
++     * or encodeEnd methods should be invoked on the decorated renderer.</b>
++     */
++    protected void encode(FacesContext context, UIComponent component,
++            int encodeSwitch) throws IOException {
++
++        UICommand command = (UICommand) component;
++
++        // look for a override to the default
++        boolean immediateOverride = true;
++        String attr = (String) component.getAttributes()
++                .get(OVERRIDE_IMMEDIATE);
++        if (attr != null) {
++            immediateOverride = Boolean.valueOf(attr).booleanValue();
++        }
++
++        if (command.isImmediate() && immediateOverride) {
++
++            ResponseWriter hijackedWriter = context.getResponseWriter();
++            // builds a buffer to write the page to
++            StringWriter writer = new StringWriter();
++            // create a buffered response writer
++            ResponseWriter buffResponsewriter = context.getRenderKit()
++                    .createResponseWriter(writer, null,
++                            hijackedWriter.getCharacterEncoding());
++            // push buffered writer to the faces context
++            context.setResponseWriter(buffResponsewriter);
++
++            if (encodeSwitch == ENCODE_BEGIN)
++                defaultRenderer.encodeBegin(context, component);
++            else if (encodeSwitch == ENCODE_CHILDREN)
++                defaultRenderer.encodeChildren(context, component);
++            else
++                defaultRenderer.encodeEnd(context, component);
++
++            StringBuffer buff = writer.getBuffer();
++            int i = buff.indexOf("onclick=\"");
++            if (i > 0) {
++                buff.insert(i + "onclick=\"".length(), "bCancel=true;");
++            }
++
++            hijackedWriter.write(buff.toString());
++            context.setResponseWriter(hijackedWriter);
++
++        } else {
++            if (encodeSwitch == ENCODE_BEGIN)
++                defaultRenderer.encodeBegin(context, component);
++            else if (encodeSwitch == ENCODE_CHILDREN)
++                defaultRenderer.encodeChildren(context, component);
++            else
++                defaultRenderer.encodeEnd(context, component);
++        }
++    }
++
++
++
++    /**
++     * <p>
++     * Decorates the original component renderer invoking its decode method.
++     * <p>
++     */
++    public void decode(FacesContext context, UIComponent component) {
++        defaultRenderer.decode(context, component);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing
++     * <code>ENCODE_BEGIN</code> for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeBegin(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_BEGIN);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing
++     * <code>ENCODE_CHILDREN</code> for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeChildren(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_CHILDREN);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing <code>ENCODE_END</code>
++     * for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeEnd(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_END);
++    }
++
++    /**
++     * <p>
++     * This method is hard-coded to return <code>true</code>. The other
++     * overriden methods invoke the decorated original render.
++     */
++    public boolean getRendersChildren() {
++        return defaultRenderer.getRendersChildren();
++    }
++
++}
+Index: src/java/org/apache/shale/view/faces/ViewViewHandler.java
+===================================================================
+--- src/java/org/apache/shale/view/faces/ViewViewHandler.java	(revision 367478)
++++ src/java/org/apache/shale/view/faces/ViewViewHandler.java	(working copy)
+@@ -23,15 +23,18 @@
+ import java.util.Map;
+
+ import javax.faces.FacesException;
++import javax.faces.FactoryFinder;
+ import javax.faces.application.ViewHandler;
+ import javax.faces.component.UIViewRoot;
+ import javax.faces.context.FacesContext;
+ import javax.faces.el.EvaluationException;
+-import javax.faces.el.ValueBinding;
+ import javax.faces.el.VariableResolver;
++import javax.faces.render.RenderKit;
++import javax.faces.render.RenderKitFactory;
+
+ import org.apache.commons.logging.Log;
+ import org.apache.commons.logging.LogFactory;
++import org.apache.shale.faces.ValidatorRenderKit;
+ import org.apache.shale.util.Messages;
+ import org.apache.shale.view.Constants;
+ import org.apache.shale.view.ViewController;
+@@ -124,6 +127,7 @@
+     public UIViewRoot createView(FacesContext context, String viewId) {
+         UIViewRoot view = original.createView(context, viewId);
+         setupViewController(context, view, viewId, false);
++        setupRenderKit(context, view);
+         return view;
+     }
+
+@@ -263,5 +267,13 @@
+
+     }
+
++
++    private void setupRenderKit(FacesContext context, UIViewRoot view) {
++        RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
++        RenderKit defaultRenderKit = factory.getRenderKit(context, view.getRenderKitId());
++        if (!(defaultRenderKit instanceof ValidatorRenderKit))
++           factory.addRenderKit(view.getRenderKitId(), new ValidatorRenderKit(defaultRenderKit));
++     }
+
++
+ }
+Index: src/java/org/apache/shale/faces/ValidatorRenderKit.java
+===================================================================
+--- src/java/org/apache/shale/faces/ValidatorRenderKit.java	(revision 0)
++++ src/java/org/apache/shale/faces/ValidatorRenderKit.java	(revision 0)
+@@ -0,0 +1,68 @@
++/*
++ * Copyright 2006 The Apache Software Foundation.
++ *
++ * Licensed 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.
++ *
++ */
++
++package org.apache.shale.faces;
++
++import java.io.OutputStream;
++import java.io.Writer;
++
++import javax.faces.context.ResponseStream;
++import javax.faces.context.ResponseWriter;
++import javax.faces.render.RenderKit;
++import javax.faces.render.Renderer;
++import javax.faces.render.ResponseStateManager;
++
++import org.apache.shale.renderer.ValidatorCommandRenderer;
++
++public class ValidatorRenderKit extends RenderKit {
++
++    private RenderKit defaultRenderKit = null;
++    public ValidatorRenderKit(RenderKit defaultRenderKit) {
++       this.defaultRenderKit = defaultRenderKit;
++    }
++
++    public void addRenderer(String componentFamily, String rendererType, Renderer renderer) {
++       this.defaultRenderKit.addRenderer(componentFamily, rendererType, renderer);
++    }
++
++    public Renderer getRenderer(String componentFamily, String rendererType) {
++        Renderer target = defaultRenderKit.getRenderer(componentFamily, rendererType);
++        if (componentFamily.equals("javax.faces.Command")) {
++           if (!(target instanceof ValidatorCommandRenderer)) {
++               target = new ValidatorCommandRenderer(target);
++               addRenderer(componentFamily, rendererType, target);
++           }
++        }
++
++        return target;
++    }
++
++    public ResponseStateManager getResponseStateManager() {
++        return defaultRenderKit.getResponseStateManager();
++    }
++
++    public ResponseWriter createResponseWriter(Writer writer,
++            String contentTypeList,
++            String characterEncoding){
++        return defaultRenderKit.createResponseWriter(writer, contentTypeList, characterEncoding);
++    }
++
++    public ResponseStream createResponseStream(OutputStream outputStream) {
++        return defaultRenderKit.createResponseStream(outputStream);
++    }
++
++}
+Index: src/java/org/apache/shale/validator/Globals.java
+===================================================================
+--- src/java/org/apache/shale/validator/Globals.java	(revision 367478)
++++ src/java/org/apache/shale/validator/Globals.java	(working copy)
+@@ -19,7 +19,7 @@
+ /**
+  * <p>Manifest constants that are global to the validator implementation.</p>
+  *
+- * $Id:$
++ * $Id$
+  */
+
+ public class Globals {
+Index: src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java
+===================================================================
+--- src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java	(revision 0)
++++ src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java	(revision 0)
+@@ -0,0 +1,168 @@
++/*
++ * Copyright 2006 The Apache Software Foundation.
++ *
++ * Licensed 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.
++ *
++ */
++
++package org.apache.shale.renderer;
++
++import java.io.IOException;
++import java.io.StringWriter;
++
++import javax.faces.component.UICommand;
++import javax.faces.component.UIComponent;
++import javax.faces.context.FacesContext;
++import javax.faces.context.ResponseWriter;
++import javax.faces.render.Renderer;
++
++public class ValidatorCommandRenderer extends Renderer {
++
++    private Renderer defaultRenderer = null;
++    public ValidatorCommandRenderer(Renderer defaultRenderer) {
++       this.defaultRenderer = defaultRenderer;
++    }
++
++
++
++    /**
++     * <p>
++     * Attribute name used to override the default behavior of how the immediate
++     * attribute effects the execution of client side javascript validation.
++     * </p>
++     */
++    public static final String OVERRIDE_IMMEDIATE = "org.apache.shale.validator.immediate";
++
++    private static final int ENCODE_BEGIN = 0;
++
++    private static final int ENCODE_CHILDREN = 1;
++
++    private static final int ENCODE_END = 2;
++
++    /**
++     * <b>Interrogates the component's immediate property and the component's
++     * immediate override attribute to determine if client side validation is
++     * invoked. If either the property or attribute override is false, client
++     * side validation is invoked. Otherwise, the response writer is hijacked
++     * and the original render is invoked. The result is buffered and a
++     * statement of javascript is injected into the onclick event which cancels
++     * client side validation. The original response writer is restored and the
++     * modified markup is written to the response writer. The
++     * <code>encodeSwitch</code> determines if the encodeBegin, encodeChildren
++     * or encodeEnd methods should be invoked on the decorated renderer.</b>
++     */
++    protected void encode(FacesContext context, UIComponent component,
++            int encodeSwitch) throws IOException {
++
++        UICommand command = (UICommand) component;
++
++        // look for a override to the default
++        boolean immediateOverride = true;
++        String attr = (String) component.getAttributes()
++                .get(OVERRIDE_IMMEDIATE);
++        if (attr != null) {
++            immediateOverride = Boolean.valueOf(attr).booleanValue();
++        }
++
++        if (command.isImmediate() && immediateOverride) {
++
++            ResponseWriter hijackedWriter = context.getResponseWriter();
++            // builds a buffer to write the page to
++            StringWriter writer = new StringWriter();
++            // create a buffered response writer
++            ResponseWriter buffResponsewriter = context.getRenderKit()
++                    .createResponseWriter(writer, null,
++                            hijackedWriter.getCharacterEncoding());
++            // push buffered writer to the faces context
++            context.setResponseWriter(buffResponsewriter);
++
++            if (encodeSwitch == ENCODE_BEGIN)
++                defaultRenderer.encodeBegin(context, component);
++            else if (encodeSwitch == ENCODE_CHILDREN)
++                defaultRenderer.encodeChildren(context, component);
++            else
++                defaultRenderer.encodeEnd(context, component);
++
++            StringBuffer buff = writer.getBuffer();
++            int i = buff.indexOf("onclick=\"");
++            if (i > 0) {
++                buff.insert(i + "onclick=\"".length(), "bCancel=true;");
++            }
++
++            hijackedWriter.write(buff.toString());
++            context.setResponseWriter(hijackedWriter);
++
++        } else {
++            if (encodeSwitch == ENCODE_BEGIN)
++                defaultRenderer.encodeBegin(context, component);
++            else if (encodeSwitch == ENCODE_CHILDREN)
++                defaultRenderer.encodeChildren(context, component);
++            else
++                defaultRenderer.encodeEnd(context, component);
++        }
++    }
++
++
++
++    /**
++     * <p>
++     * Decorates the original component renderer invoking its decode method.
++     * <p>
++     */
++    public void decode(FacesContext context, UIComponent component) {
++        defaultRenderer.decode(context, component);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing
++     * <code>ENCODE_BEGIN</code> for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeBegin(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_BEGIN);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing
++     * <code>ENCODE_CHILDREN</code> for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeChildren(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_CHILDREN);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing <code>ENCODE_END</code>
++     * for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeEnd(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_END);
++    }
++
++    /**
++     * <p>
++     * This method is hard-coded to return <code>true</code>. The other
++     * overriden methods invoke the decorated original render.
++     */
++    public boolean getRendersChildren() {
++        return defaultRenderer.getRendersChildren();
++    }
++
++}
+Index: src/java/org/apache/shale/view/faces/ViewViewHandler.java
+===================================================================
+--- src/java/org/apache/shale/view/faces/ViewViewHandler.java	(revision 367478)
++++ src/java/org/apache/shale/view/faces/ViewViewHandler.java	(working copy)
+@@ -23,15 +23,18 @@
+ import java.util.Map;
+
+ import javax.faces.FacesException;
++import javax.faces.FactoryFinder;
+ import javax.faces.application.ViewHandler;
+ import javax.faces.component.UIViewRoot;
+ import javax.faces.context.FacesContext;
+ import javax.faces.el.EvaluationException;
+-import javax.faces.el.ValueBinding;
+ import javax.faces.el.VariableResolver;
++import javax.faces.render.RenderKit;
++import javax.faces.render.RenderKitFactory;
+
+ import org.apache.commons.logging.Log;
+ import org.apache.commons.logging.LogFactory;
++import org.apache.shale.faces.ValidatorRenderKit;
+ import org.apache.shale.util.Messages;
+ import org.apache.shale.view.Constants;
+ import org.apache.shale.view.ViewController;
+@@ -124,6 +127,7 @@
+     public UIViewRoot createView(FacesContext context, String viewId) {
+         UIViewRoot view = original.createView(context, viewId);
+         setupViewController(context, view, viewId, false);
++        setupRenderKit(context, view);
+         return view;
+     }
+
+@@ -263,5 +267,13 @@
+
+     }
+
++
++    private void setupRenderKit(FacesContext context, UIViewRoot view) {
++        RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
++        RenderKit defaultRenderKit = factory.getRenderKit(context, view.getRenderKitId());
++        if (!(defaultRenderKit instanceof ValidatorRenderKit))
++           factory.addRenderKit(view.getRenderKitId(), new ValidatorRenderKit(defaultRenderKit));
++     }
+
++
+ }
+Index: src/java/org/apache/shale/faces/ValidatorRenderKit.java
+===================================================================
+--- src/java/org/apache/shale/faces/ValidatorRenderKit.java	(revision 0)
++++ src/java/org/apache/shale/faces/ValidatorRenderKit.java	(revision 0)
+@@ -0,0 +1,68 @@
++/*
++ * Copyright 2006 The Apache Software Foundation.
++ *
++ * Licensed 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.
++ *
++ */
++
++package org.apache.shale.faces;
++
++import java.io.OutputStream;
++import java.io.Writer;
++
++import javax.faces.context.ResponseStream;
++import javax.faces.context.ResponseWriter;
++import javax.faces.render.RenderKit;
++import javax.faces.render.Renderer;
++import javax.faces.render.ResponseStateManager;
++
++import org.apache.shale.renderer.ValidatorCommandRenderer;
++
++public class ValidatorRenderKit extends RenderKit {
++
++    private RenderKit defaultRenderKit = null;
++    public ValidatorRenderKit(RenderKit defaultRenderKit) {
++       this.defaultRenderKit = defaultRenderKit;
++    }
++
++    public void addRenderer(String componentFamily, String rendererType, Renderer renderer) {
++       this.defaultRenderKit.addRenderer(componentFamily, rendererType, renderer);
++    }
++
++    public Renderer getRenderer(String componentFamily, String rendererType) {
++        Renderer target = defaultRenderKit.getRenderer(componentFamily, rendererType);
++        if (componentFamily.equals("javax.faces.Command")) {
++           if (!(target instanceof ValidatorCommandRenderer)) {
++               target = new ValidatorCommandRenderer(target);
++               addRenderer(componentFamily, rendererType, target);
++           }
++        }
++
++        return target;
++    }
++
++    public ResponseStateManager getResponseStateManager() {
++        return defaultRenderKit.getResponseStateManager();
++    }
++
++    public ResponseWriter createResponseWriter(Writer writer,
++            String contentTypeList,
++            String characterEncoding){
++        return defaultRenderKit.createResponseWriter(writer, contentTypeList, characterEncoding);
++    }
++
++    public ResponseStream createResponseStream(OutputStream outputStream) {
++        return defaultRenderKit.createResponseStream(outputStream);
++    }
++
++}
+Index: src/java/org/apache/shale/validator/Globals.java
+===================================================================
+--- src/java/org/apache/shale/validator/Globals.java	(revision 367478)
++++ src/java/org/apache/shale/validator/Globals.java	(working copy)
+@@ -19,7 +19,7 @@
+ /**
+  * <p>Manifest constants that are global to the validator implementation.</p>
+  *
+- * $Id:$
++ * $Id$
+  */
+
+ public class Globals {
+Index: src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java
+===================================================================
+--- src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java	(revision 0)
++++ src/java/org/apache/shale/renderer/ValidatorCommandRenderer.java	(revision 0)
+@@ -0,0 +1,168 @@
++/*
++ * Copyright 2006 The Apache Software Foundation.
++ *
++ * Licensed 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.
++ *
++ */
++
++package org.apache.shale.renderer;
++
++import java.io.IOException;
++import java.io.StringWriter;
++
++import javax.faces.component.UICommand;
++import javax.faces.component.UIComponent;
++import javax.faces.context.FacesContext;
++import javax.faces.context.ResponseWriter;
++import javax.faces.render.Renderer;
++
++public class ValidatorCommandRenderer extends Renderer {
++
++    private Renderer defaultRenderer = null;
++    public ValidatorCommandRenderer(Renderer defaultRenderer) {
++       this.defaultRenderer = defaultRenderer;
++    }
++
++
++
++    /**
++     * <p>
++     * Attribute name used to override the default behavior of how the immediate
++     * attribute effects the execution of client side javascript validation.
++     * </p>
++     */
++    public static final String OVERRIDE_IMMEDIATE = "org.apache.shale.validator.immediate";
++
++    private static final int ENCODE_BEGIN = 0;
++
++    private static final int ENCODE_CHILDREN = 1;
++
++    private static final int ENCODE_END = 2;
++
++    /**
++     * <b>Interrogates the component's immediate property and the component's
++     * immediate override attribute to determine if client side validation is
++     * invoked. If either the property or attribute override is false, client
++     * side validation is invoked. Otherwise, the response writer is hijacked
++     * and the original render is invoked. The result is buffered and a
++     * statement of javascript is injected into the onclick event which cancels
++     * client side validation. The original response writer is restored and the
++     * modified markup is written to the response writer. The
++     * <code>encodeSwitch</code> determines if the encodeBegin, encodeChildren
++     * or encodeEnd methods should be invoked on the decorated renderer.</b>
++     */
++    protected void encode(FacesContext context, UIComponent component,
++            int encodeSwitch) throws IOException {
++
++        UICommand command = (UICommand) component;
++
++        // look for a override to the default
++        boolean immediateOverride = true;
++        String attr = (String) component.getAttributes()
++                .get(OVERRIDE_IMMEDIATE);
++        if (attr != null) {
++            immediateOverride = Boolean.valueOf(attr).booleanValue();
++        }
++
++        if (command.isImmediate() && immediateOverride) {
++
++            ResponseWriter hijackedWriter = context.getResponseWriter();
++            // builds a buffer to write the page to
++            StringWriter writer = new StringWriter();
++            // create a buffered response writer
++            ResponseWriter buffResponsewriter = context.getRenderKit()
++                    .createResponseWriter(writer, null,
++                            hijackedWriter.getCharacterEncoding());
++            // push buffered writer to the faces context
++            context.setResponseWriter(buffResponsewriter);
++
++            if (encodeSwitch == ENCODE_BEGIN)
++                defaultRenderer.encodeBegin(context, component);
++            else if (encodeSwitch == ENCODE_CHILDREN)
++                defaultRenderer.encodeChildren(context, component);
++            else
++                defaultRenderer.encodeEnd(context, component);
++
++            StringBuffer buff = writer.getBuffer();
++            int i = buff.indexOf("onclick=\"");
++            if (i > 0) {
++                buff.insert(i + "onclick=\"".length(), "bCancel=true;");
++            }
++
++            hijackedWriter.write(buff.toString());
++            context.setResponseWriter(hijackedWriter);
++
++        } else {
++            if (encodeSwitch == ENCODE_BEGIN)
++                defaultRenderer.encodeBegin(context, component);
++            else if (encodeSwitch == ENCODE_CHILDREN)
++                defaultRenderer.encodeChildren(context, component);
++            else
++                defaultRenderer.encodeEnd(context, component);
++        }
++    }
++
++
++
++    /**
++     * <p>
++     * Decorates the original component renderer invoking its decode method.
++     * <p>
++     */
++    public void decode(FacesContext context, UIComponent component) {
++        defaultRenderer.decode(context, component);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing
++     * <code>ENCODE_BEGIN</code> for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeBegin(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_BEGIN);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing
++     * <code>ENCODE_CHILDREN</code> for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeChildren(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_CHILDREN);
++    }
++
++    /**
++     * <p>
++     * Invokes the <code>encode</code> method passing <code>ENCODE_END</code>
++     * for the encodeSwitch parameter.
++     * </p>
++     */
++    public void encodeEnd(FacesContext context, UIComponent component)
++            throws IOException {
++        encode(context, component, ENCODE_END);
++    }
++
++    /**
++     * <p>
++     * This method is hard-coded to return <code>true</code>. The other
++     * overriden methods invoke the decorated original render.
++     */
++    public boolean getRendersChildren() {
++        return defaultRenderer.getRendersChildren();
++    }
++
++}
+Index: src/java/org/apache/shale/view/faces/ViewViewHandler.java
+===================================================================
+--- src/java/org/apache/shale/view/faces/ViewViewHandler.java	(revision 367478)
++++ src/java/org/apache/shale/view/faces/ViewViewHandler.java	(working copy)
+@@ -23,15 +23,18 @@
+ import java.util.Map;
+
+ import javax.faces.FacesException;
++import javax.faces.FactoryFinder;
+ import javax.faces.application.ViewHandler;
+ import javax.faces.component.UIViewRoot;
+ import javax.faces.context.FacesContext;
+ import javax.faces.el.EvaluationException;
+-import javax.faces.el.ValueBinding;
+ import javax.faces.el.VariableResolver;
++import javax.faces.render.RenderKit;
++import javax.faces.render.RenderKitFactory;
+
+ import org.apache.commons.logging.Log;
+ import org.apache.commons.logging.LogFactory;
++import org.apache.shale.faces.ValidatorRenderKit;
+ import org.apache.shale.util.Messages;
+ import org.apache.shale.view.Constants;
+ import org.apache.shale.view.ViewController;
+@@ -124,6 +127,7 @@
+     public UIViewRoot createView(FacesContext context, String viewId) {
+         UIViewRoot view = original.createView(context, viewId);
+         setupViewController(context, view, viewId, false);
++        setupRenderKit(context, view);
+         return view;
+     }
+
+@@ -263,5 +267,13 @@
+
+     }
+
++
++    private void setupRenderKit(FacesContext context, UIViewRoot view) {
++        RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
++        RenderKit defaultRenderKit = factory.getRenderKit(context, view.getRenderKitId());
++        if (!(defaultRenderKit instanceof ValidatorRenderKit))
++           factory.addRenderKit(view.getRenderKitId(), new ValidatorRenderKit(defaultRenderKit));
++     }
+
++
+ }
+mplate.  There is a central
       Clay configuration that is dedicated to full XML views and a base component definition 
       in the common clay configuration file.  
       <br/><br/>

Modified: struts/shale/trunk/use-cases/src/web/symbols/nameReuse.jsp
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/web/symbols/nameReuse.jsp?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/use-cases/src/web/symbols/nameReuse.jsp (original)
+++ struts/shale/trunk/use-cases/src/web/symbols/nameReuse.jsp Wed Feb  8 23:45:42 2006
@@ -43,7 +43,7 @@
    <hr>
    <clay:clay id="businessPerson" jsfid="businessPersonNamePanel" managedBeanName="businessPerson"/>
    <br>
-   <h:commandButton action="#{symbols$nameReuse.save}" value="Save"/> <h:commandButton action="home" value="Home" immediate="true"/>
+   <h:commandButton action="#{symbols$nameReuse.save}" value="Save"/><h:commandButton action="home" value="Home" immediate="true"/>
  </h:form>        
 </body>
 

Modified: struts/shale/trunk/xdocs/features-reusable-views.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/features-reusable-views.xml?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/xdocs/features-reusable-views.xml (original)
+++ struts/shale/trunk/xdocs/features-reusable-views.xml Wed Feb  8 23:45:42 2006
@@ -2,25 +2,290 @@
 <document>
 
   <properties>
-    <title>Shale Reusable Views</title>
+    <title>Shale Clay</title>
   </properties>
 
   <body>
     
-    <section name="Shale Reusable Views">
+    <section name="Clay">
     <a name="clay"/>
 
       <a name="clay-introduction"/>
-      <subsection name="Clay Introduction">
+      <subsection name="Introduction">
 
-        <p>The <strong>Clay</strong> component is a complex JavaServer Faces
-        component that features a way to build more reusable view fragments.
-        As its name implies, the Clay component can be shaped and molded into
-        a subtree of JSF components acting as a &quot;stand-in&quot;
-        for the JSP tags normally required to add components 
-        to the view's component tree.</p>
+		  <p>Every JavaServer Faces (JSF) view is represented on the server as a 
+		  tree of components. Shale's <strong>Clay</strong> lets you graft a 
+		  component subtree onto an existing component tree.</p>
 
+		  <p>At first blush, this may not seem like much; after all, you
+		  can accomplish the same thing with JSF's standard <code>f:subview</code>
+		  tag. However, Clay builds upon this fundamental feature to give you 
+		  the following killer capabilities:</p>
+		  <ul>
+		    <li><i>HTML Views</i></li>
+			 <p> 
+			 Similar to <a href="">Tapestry</a> and 
+			 <a href="https://facelets.dev.java.net">Facelets</a>, you define your
+			 views in HTML. For dynamic content, you tie HTML elements to JSF components
+			 with a <code>jsfid</code> attribute--when Clay renders your view, it
+			 replaces static HTML elements that have <code>jsfid</code> attributes with their
+			 component counterpart. When Clay creates the components, it transmits HTML style 
+			 attributes from the HTML tag to the component; therefore, graphic designers can implement
+			 a look and feel with mockup HTML and that look and feel is absorbed by the component
+			 that replaces the mockup HTML.
+			 </p>
+
+			 <li><i>Meta-data Inheritance and Tiles-like Composition</i></li>
+			 <p>
+			 You can define a component as an extension of an existing component and 
+			 then override or add attributes. This mechamism is similar to the inheritance
+			 mechanism built into the popular <a href="">Tiles</a> framework for composing
+			 web pages from discrete JSP fragments, known as tiles. In fact, Clay's features
+			 are sophisticated enough that Clay can give you much of the same benefits that
+			 Tiles users enjoy.
+			 </p>
+
+			 <li><i>Symbols</i></li>
+			 <p>
+			 You can map managed beans to symbols, which you can use as though they were 
+			 the actual managed bean. This aliasing facility, much like 
+			 <a href="http://myfaces.apache.org">MyFaces</a>
+			 <a href="http://wiki.apache.org/myfaces/AliasBean"><code>t:aliasBean</code></a> 
+			 tag--lets you reuse a view for many different managed beans.
+			 </p>
+		  </ul>
+
+		  <p>The most prominent Clay feature is HTML Views. In this document, we will cover
+		  that feature in some detail. For more information on composition and symbols,
+		  see the Shale javadoc.<i>  Todo: add sections on composition and symbols</i></p>
       </subsection>
+
+      <a name="clay-view-options"/>
+      <subsection name="HTML Views">
+		  <p>Back in the early days of J2EE, when people wrote applications that
+		  were mostly collections of servlets, everybody implemented their views in HTML.
+		  But because implementing user interfaces with print statements that originate
+		  from the bowels of a servlet is just marginally better than a trip to the dentist, 
+		  Sun quickly followed servlets with JSP. Now, we could mix Java code with HTML 
+		  instead of the other way around, which as everybody knows may have seemed like a 
+		  step in the right direction, but was, and still is, fraught with perils of its own.</p>
+
+		  <p>Anyway, the point is that we moved away from HTML with JSP tags, and later on,
+		  custom tags. Of course nowadays, with the advent of JavaServer Faces, it's fashionable
+		  to construct your user interface almost entirely with JSF tags. For the software
+		  developer who is also a graphic designer, that's a pretty sweet deal. JSF tags are
+		  much more concise than the HTML that they replace and developers can control all 
+		  manner of things look and feel. But what if the software developer and graphic designer
+		  are different people? What then?</p>
+
+		  <p>If you'd like your graphic designers to implement your look and feel while your
+		  software developers work on components, then JSP is a terrible solution. I can see
+		  those of you in the back of the room nodding your heads, so I won't preach to the choir.
+		  The Apache <a href="">Tapestry</a> framework was the first Java web framework that not 
+		  only acknowledged that fact, but, more importantly, did something about it.</p>
+
+		  <p>Tapestry maintains a strict separation between graphic designers and software
+		  developers through an innovative design. Graphic designers mockup HTML to implement 
+		  a look and feel. Software developers take that HTML and add an innocuous <code>jwcid</code>
+		  attribute to the HTML tags that represent dynamic content. That attribute's value
+		  references a Tapestry component defined in an XML file. When the HTML is viewed as
+		  an HTML page, the graphic designer sees the mockup HTML, but when the same HTML file
+		  is run through Tapestry, the mockup HTML is replaced by Tapestry components. And here's
+		  the clincher: <i>when the components replace the mockup HTML, they soak up the mockup HTML's
+		  look and feel</i>. This lets graphic designers concentrate on the look and feel and lets
+		  developers work on components. Whoa.</p>
+
+		  <p>Clay unabashedly copies Tapestry's innovations. In fact, if you replace <i>Tapestry</i>
+		  with <i>Clay</i> and <i>jwcid</i> with <i>jsfid</i> in the preceeding paragraph, you'd have 
+		  an accurate description of Clay's HTML Views. But enough talk; let's see how it works.</p>
+
+		  <p>Here's yet another incarnation of a simple login and registration application: 
+		  (hey, it's better than Hello World!).</p>
+        <p><img src="images/login.jpg" alt="Shale Use Cases - Clay Login Example"/></p>
+		  <p>This application uses Tiles, so its JSP pages are pretty well carved up. We're
+		  going to look at the JSP page that implements the login form. (Don't sweat the
+		  deatils)</p>
+<pre>
+&lt;%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %&gt;
+&lt;%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %&gt;
+&lt;%@ taglib prefix="s" uri="http://struts.apache.org/shale/core" %&gt;
+
+&lt;s:token id="token"/&gt;
+
+&lt;h:panelGrid columns="1" styleClass="loginPanel"&gt;
+  &lt;h:panelGrid styleClass="summaryHeadingPanel"&gt;
+    &lt;h:outputText value="#{msgs.loginHeading}" styleClass="loginHeading"/&gt;
+  &lt;/h:panelGrid&gt;
+
+  &lt;h:message for="token" styleClass="errors"/&gt;
+
+  &lt;h:panelGrid columns="2" styleClass="loginFields"&gt;
+    &lt;%-- NAME FIELD --%&gt;
+    &lt;h:outputLabel for="name" value="#{msgs.namePrompt}"/&gt;
+    &lt;h:panelGroup&gt;
+      &lt;h:inputText size="15" id="name" onfocus="activatefield(this);"
+                onblur="deactivatefield(this);" styleClass="input" 
+					 validator="#{loginPage.validate}" required="true" 
+                value="#{userContext.name}"/&gt; 
+      &lt;h:message for="name" styleClass="errors"/&gt;
+    &lt;/h:panelGroup&gt;
+
+	 &lt;%-- PASSWORD FIELD --%&gt;
+    &lt;h:outputLabel for="pwd" value="#{msgs.passwordPrompt}"/&gt;
+    &lt;h:panelGroup&gt;
+      &lt;h:inputSecret size="6" id="pwd" value="#{userContext.password}"
+          onfocus="activatefield(this);" onblur="deactivatefield(this);"
+          styleClass="input"/&gt; 
+      &lt;h:message for="pwd" styleClass="errors"/&gt;
+    &lt;/h:panelGroup&gt;
+    &lt;h:outputText value=" "/&gt;&lt;h:outputText value=" "/&gt;
+    &lt;h:commandButton value="#{msgs.loginButtonPrompt}"
+	                 action="#{loginPage.submit}"/&gt;
+	 &lt;/h:panelGrid&gt;
+  &lt;/h:panelGrid&gt;
+</pre>
+		  <p>Quick! Turn away! Let's replace that JSP with mockup HTML tied to JSF components:</p>
+<pre>
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;title&gt;Clay&lt;/title&gt;
+    &lt;link href="/shale/styles/site.css"
+          rel="stylesheet" type="text/css"/&gt;
+  &lt;/head&gt;
+  &lt;body class="loginPage"&gt;
+    &lt;table style="vertical-align: top; text-align: center; width: 100%; height: 100%"&gt;
+      &lt;tr style="vertical-align: top;"&gt;
+        &lt;td colspan="2" class="header"&gt;
+          &lt;img src="/shale/graphics/powered-by-tiles.jpg" align="top"/&gt;
+          &lt;img src="/shale/graphics/spacer.gif" width="6px" height="1px"/&gt;
+          &lt;img src="/shale/graphics/shaleClay.jpg"/&gt;
+          &lt;img src="/shale/graphics/spacer.gif" width="6px" height="1px"/&gt;
+          &lt;img src="/shale/graphics/powered-by-javaserver-faces.jpg" align="top"/&gt;
+        &lt;/td&gt;
+    &lt;/tr&gt;
+    &lt;/tr&gt;
+    &lt;form id="menuContentForm" onsubmit="return validateForm(this);"&gt;
+      &lt;tr style="vertical-align: top; height: 100%;"&gt;
+        &lt;td class="menu"&gt;
+          &lt;table&gt;
+            &lt;tr&gt;&lt;td&gt;
+              &lt;img src="/shale/graphics/china-flag-animated.gif" border="0px"/&gt;
+              &lt;img src="/shale/graphics/us-flag-animated.gif"    border="0px"/&gt;
+            &lt;/td&gt;&lt;/tr&gt;
+            &lt;tr&gt;&lt;td&gt;
+              &lt;a href="#" jsfid="dialogLink"&gt;Create an account&lt;/a&gt;
+            &lt;/td&gt;&lt;/tr&gt;
+          &lt;/table&gt;
+		  &lt;/td&gt;
+		&lt;/tr&gt;
+		...
+</pre>
+		  <p>The HTML is considerably longer than the JSP, so we've only shown the top of the
+		  HTML file. You don't need to see it all--all that's pertinent is the mockup HTML and
+		  the <code>jsfid</code> attributes that point to JSF components. Remember that we can 
+		  access the preceeding HTML either directly (as a graphic designer) 
+		  or through Clay (as a developer or end user). Here's what it looks like when we access the 
+		  HTML directly: </p>
+        <p><img src="images/login-html.jpg" alt="Clay Login Example - Login with HTML"/></p>
+
+		  <p>And here's what it looks like through Clay:</p>
+        <p><img src="images/login-clay.jpg" alt="Clay Login Example - Login with Clay"/></p>
+
+		  <p>Did you notice the differences? First, the URL in the address bars: one ends in <code>.html</code>
+		  and the other ends in <code>.faces</code>. Second, the error messages: mockups for the HTML and
+		  real error messages for Clay. In the second snapshot, I attempted to login without a username, which
+		  triggered JSF validation, resulting in the ensuing error message. Remember, when we run this seemingly
+		  begnign HTML through Clay's transducer, we get a full blown login page, just like the
+		  original page that we saw at the beginning of this section. We changed the images a bit to reflect
+		  the fact that now we're using Clay, but that's a fully capable login page you're looking at. Of
+		  course, that fully capable login page is populated, at runtime, by Clay with JSF components
+		  that replace the HTML mockup. Cool, eh?</p>
+
+		  <p>So, you wonder, where do the components come from? Well, we define them in an XML file, silly.
+		  Shame on you for asking. In fact, here's the XML definition of the username <code>h:inputText</code>, 
+		  which is an input component:</p>
+<p>
+<pre>
+&lt;!-- username textfield --&gt;
+&lt;component jsfid="username" 
+         extends="inputText" 
+         id="username"&gt;
+  &lt;attributes&gt;
+    &lt;set name="required"  value="true"/&gt;
+    &lt;set name="value"     value="#{userContext.username}"/&gt;
+    &lt;set name="validator" value="#{managed-bean-name.validate}"/&gt;
+  &lt;/attributes&gt;
+&lt;/component&gt;
+</pre>
+</p>
+		  <p>Now, pretend you are a graphic designer and you decide to change error messages to red. Let's
+		  keep it simple and just change the error message for the username field. So, you go into
+		  <code>clay-login.html</code> and add a <code>style</code> attribute to the error message mockup:</p>
+<p>
+<pre>
+...
+&lt;td&gt;
+  &lt;input jsfid="username" type="text" size="15"/&gt;
+&lt;/td&gt;
+&lt;td&gt;
+  &lt;span jsfid="usernameMessage" style="color: red;"&gt;
+    username error message
+  &lt;/span&gt;
+&lt;/td&gt;
+...
+</pre>
+</p>
+        <p>You save that file, refresh the browser, and, as expected, you see this: (check the address bar - that's the HTML file)</p>
+
+        <p><img src="images/login-clay-red.jpg" alt="Clay Login Example - Login with Clay"/></p>
+
+		  <p>Later that day, a developer runs the application through Clay and
+		  Clay replaces the mockup error message with a real error message component 
+		  and <i>transmits the style for the mockup to the
+		  component</i>. So, when an end-user runs the application and stubbornly refuses to
+		  supply a username, he endures the following shame:</p>
+
+        <p><img src="images/login-html-red.jpg" alt="Shale Use Cases - Clay Login Example"/></p>
+		  <p><i>Hot damn!</i> Our runtime error message is also red. Clay has transmitted the 
+		  <code>style</code> attribute of the mockup HTML for
+		  the username error message to the component that replaces it at runtime. Now graphic
+		  designers and software developers can truly lead independent lives.</p>
+
+		  <p>One more thing before we conclude this section. You may wonder how Clay replaces
+		  mockup HTML with components; how does Clay know to do that to our HTML page? The 
+		  answer is that Clay is implemented as a JSF component, and, along with our HTML
+		  page, we have a JSP page that uses that component to process the HTML. That component
+		  is accessed through a custom tag, like this:</p>
+<pre>
+&lt;%@ taglib prefix="sh" uri="http://struts.apache.org/shale/clay-plugin" %&gt;
+...
+&lt;sh:clay id="loginTemplate" jsfid="/pages/clay-login.html" 
+    managedBeanName="loginPage"/&gt;
+</pre>
+
+      <p>In the preceeding code, we give the clay tag a <code>jsfid</code> that points, not to a
+		component, but to our HTML page instead. Notice we also specify a managed bean that's used 
+		by the component definitions; for example, here's the definition of the login page's 
+		submit button:</p>
+<pre>
+&lt;!-- login submit button --&gt;
+&lt;component jsfid="login" extends="commandButton" id="login"&gt;
+  &lt;attributes&gt;
+    &lt;set name="action" value="#{managed-bean-name.submit}"/&gt;
+    &lt;set name="value"  value="Log In" /&gt;
+  &lt;/attributes&gt;
+&lt;/component&gt;
+</pre>
+      <p>The expression <code>#{managed-bean-name.submit}</code> references the managed bean we
+		specified with the <code>clay</code> tag above with the <code>managedBeanName</code>
+		attribute. You can alias managed beans for any component, which allows a single component
+		definition to be used for any managed bean that has corresponding method signatures.</p>
+
+		<p>As you might suspect, implementing Clay with a custom component gives you a great deal
+		of flexibility. Although HTML views are Clay's most visible feature, they
+		are by no means its only feature. Clay also sports Tiles-like composition and more
+		sophisticated symbol replacement than the managed bean example discussed above.</p>
+		</subsection>
 
       <a name="clay-view-options"/>
       <subsection name="Clay View Composition Options">

Added: struts/shale/trunk/xdocs/images/login-clay-red.jpg
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/images/login-clay-red.jpg?rev=376215&view=auto
==============================================================================
Binary file - no diff available.

Propchange: struts/shale/trunk/xdocs/images/login-clay-red.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: struts/shale/trunk/xdocs/images/login-clay.jpg
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/images/login-clay.jpg?rev=376215&view=auto
==============================================================================
Binary file - no diff available.

Propchange: struts/shale/trunk/xdocs/images/login-clay.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: struts/shale/trunk/xdocs/images/login-html-red.jpg
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/images/login-html-red.jpg?rev=376215&view=auto
==============================================================================
Binary file - no diff available.

Propchange: struts/shale/trunk/xdocs/images/login-html-red.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: struts/shale/trunk/xdocs/images/login-html.jpg
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/images/login-html.jpg?rev=376215&view=auto
==============================================================================
Binary file - no diff available.

Propchange: struts/shale/trunk/xdocs/images/login-html.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: struts/shale/trunk/xdocs/images/login.jpg
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/images/login.jpg?rev=376215&view=auto
==============================================================================
Binary file - no diff available.

Propchange: struts/shale/trunk/xdocs/images/login.jpg
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: struts/shale/trunk/xdocs/index.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/index.xml?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/xdocs/index.xml (original)
+++ struts/shale/trunk/xdocs/index.xml Wed Feb  8 23:45:42 2006
@@ -171,7 +171,10 @@
             with the <a href="http://www.springframework.org">Spring Framework</a>,
             allowing the use of Spring's dependency injection framework to create
             JavaServer Faces managed beans.</li>
-        <li><a href="features-reusable-views.html">Reusable Views</a> - An innovative
+        <li><a href="features-reusable-views.html">Clay</a> - An alternative to JSP where
+		      you define views in pure HTML, in a fashion similar to <a href="http://jakarta.apache.org/tapestry/index.html">Tapestry</a>
+				and <a href="https://facelets.dev.java.net/">Facelets</a>.
+		  An innovative
             sub-framework for supporting the configuration of reusable subtrees
             of JavaServer Faces components for customizable reuse.</li>
         <li><a href="features-test-framework.html">Test Framework</a> - Set of mock objects

Modified: struts/shale/trunk/xdocs/navigation.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/xdocs/navigation.xml?rev=376215&r1=376214&r2=376215&view=diff
==============================================================================
--- struts/shale/trunk/xdocs/navigation.xml (original)
+++ struts/shale/trunk/xdocs/navigation.xml Wed Feb  8 23:45:42 2006
@@ -26,7 +26,7 @@
         <item name="JNDI Integration"   href="/features-jndi-integration.html"/>
         <item name="Spring Integration" href="/features-spring-integration.html"/>
         <item name="Tiles Integration"  href="/features-tiles-integration.html"/>
-        <item name="Reusable Views"     href="/features-reusable-views.html"/>
+        <item name="Clay"               href="/features-reusable-views.html"/>
         <item name="Test Framework"     href="/features-test-framework.html"/>
         <item name="Tiger Extensions"   href="/features-tiger-extensions.html"/>
     </menu>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org