You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2014/03/27 16:12:56 UTC

svn commit: r1582342 - in /myfaces/core/trunk/impl/src: main/java/org/apache/myfaces/view/facelets/tag/ main/java/org/apache/myfaces/view/facelets/tag/jsf/html/ test/java/org/apache/myfaces/view/facelets/tag/jsf/html/ test/resources/org/apache/myfaces/...

Author: lu4242
Date: Thu Mar 27 15:12:55 2014
New Revision: 1582342

URL: http://svn.apache.org/r1582342
Log:
MYFACES-3876 - Clarify requeriments and behavior of HTML friendly markup feature 

Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultTagDecorator.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultHtmlDecoratorTestCase.java
    myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/html/testConvertTagAttributes1.xhtml

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java?rev=1582342&r1=1582341&r2=1582342&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/MetaRulesetImpl.java Thu Mar 27 15:12:55 2014
@@ -30,6 +30,7 @@ import javax.faces.view.facelets.Tag;
 import javax.faces.view.facelets.TagAttribute;
 import javax.faces.view.facelets.TagException;
 import java.beans.IntrospectionException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -37,6 +38,7 @@ import java.util.Map;
 import java.util.WeakHashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.faces.render.Renderer;
 import org.apache.myfaces.view.facelets.PassthroughRule;
 import org.apache.myfaces.view.facelets.tag.jsf.PassThroughLibrary;
 
@@ -118,6 +120,12 @@ public final class MetaRulesetImpl exten
     private final Class<?> _type;
     
     private final List<MetaRule> _passthroughRules;
+    
+    /**
+     * Indicates when a tag comes from html markup.
+     * 
+     */
+    private final boolean _htmlMarkupTag;
 
     public MetaRulesetImpl(Tag tag, Class<?> type)
     {
@@ -143,6 +151,7 @@ public final class MetaRulesetImpl exten
             PassThroughLibrary.NAMESPACE);
         TagAttribute[] passthroughAttributeAlias = _tag.getAttributes().getAll(
             PassThroughLibrary.ALIAS_NAMESPACE);
+        boolean htmlMarkupTag = false;
         
         if (passthroughAttribute.length > 0 ||
             passthroughAttributeAlias.length > 0)
@@ -160,6 +169,10 @@ public final class MetaRulesetImpl exten
                 {
                     _passthroughAttributes[i] = attribute;
                     i++;
+                    if (Renderer.PASSTHROUGH_RENDERER_LOCALNAME_KEY.equals(attribute.getLocalName()))
+                    {
+                        htmlMarkupTag = true;
+                    }
                 }
                 else
                 {
@@ -176,6 +189,8 @@ public final class MetaRulesetImpl exten
                 _attributes.put(attribute.getLocalName(), attribute);
             }
         }
+        
+        _htmlMarkupTag = htmlMarkupTag;
 
         // add default rules
         _rules.add(BeanPropertyTagRule.INSTANCE);
@@ -229,40 +244,100 @@ public final class MetaRulesetImpl exten
         
         assert !_rules.isEmpty();
         
-        if (!_attributes.isEmpty())
+        if (_htmlMarkupTag)
         {
-            target = this._getMetadataTarget();
-            int ruleEnd = _rules.size() - 1;
-
-            // now iterate over attributes
-            for (Map.Entry<String, TagAttribute> entry : _attributes.entrySet())
+            // HTML markup component
+            if (!_attributes.isEmpty())
             {
-                Metadata data = null;
-
-                int i = ruleEnd;
+                target = this._getMetadataTarget();
+                int ruleEnd = _rules.size() - 1;
+                int ptRuleEnd = _passthroughRules.size() - 1;
 
-                // First loop is always safe
-                do
+                // now iterate over attributes
+                for (Map.Entry<String, TagAttribute> entry : _attributes.entrySet())
                 {
-                    MetaRule rule = _rules.get(i);
-                    data = rule.applyRule(entry.getKey(), entry.getValue(), target);
-                    i--;
-                } while (data == null && i >= 0);
+                    Metadata data = null;
 
-                if (data == null)
-                {
-                    if (log.isLoggable(Level.SEVERE))
+                    Method m = target.getWriteMethod(entry.getKey());
+
+                    // if the property is writable
+                    if (m != null)
+                    {
+                        int i = ruleEnd;
+                    
+                        // Apply as a normal attribute
+                        // First loop is always safe
+                        do
+                        {
+                            MetaRule rule = _rules.get(i);
+                            data = rule.applyRule(entry.getKey(), entry.getValue(), target);
+                            i--;
+                        } while (data == null && i >= 0);
+                    }
+                    else if (ptRuleEnd >= 0)
+                    {
+                        // Apply as passthrough attribute
+                        int i = ptRuleEnd;
+                        
+                        do
+                        {
+                            MetaRule rule = _passthroughRules.get(i);
+                            data = rule.applyRule(entry.getKey(), entry.getValue(), target);
+                            i--;
+                        } while (data == null && i >= 0);
+                    }
+                    
+                    if (data == null)
+                    {
+                        if (log.isLoggable(Level.SEVERE))
+                        {
+                            log.severe(entry.getValue() + " Unhandled by MetaTagHandler for type " + _type.getName());
+                        }
+                    }
+                    else
                     {
-                        log.severe(entry.getValue() + " Unhandled by MetaTagHandler for type " + _type.getName());
+                        _mappers.add(data);
                     }
                 }
-                else
+            }
+        }
+        else
+        {
+            if (!_attributes.isEmpty())
+            {
+                target = this._getMetadataTarget();
+                int ruleEnd = _rules.size() - 1;
+
+                // now iterate over attributes
+                for (Map.Entry<String, TagAttribute> entry : _attributes.entrySet())
                 {
-                    _mappers.add(data);
+                    Metadata data = null;
+
+                    int i = ruleEnd;
+
+                    // First loop is always safe
+                    do
+                    {
+                        MetaRule rule = _rules.get(i);
+                        data = rule.applyRule(entry.getKey(), entry.getValue(), target);
+                        i--;
+                    } while (data == null && i >= 0);
+
+                    if (data == null)
+                    {
+                        if (log.isLoggable(Level.SEVERE))
+                        {
+                            log.severe(entry.getValue() + " Unhandled by MetaTagHandler for type " + _type.getName());
+                        }
+                    }
+                    else
+                    {
+                        _mappers.add(data);
+                    }
                 }
             }
         }
-        
+
         if (_passthroughAttributes.length > 0 &&
             _passthroughRules.size() > 0)
         {
@@ -302,7 +377,7 @@ public final class MetaRulesetImpl exten
                 }
             }
         }
-
+            
         if (_mappers.isEmpty())
         {
             return NONE;

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultTagDecorator.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultTagDecorator.java?rev=1582342&r1=1582341&r2=1582342&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultTagDecorator.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultTagDecorator.java Thu Mar 27 15:12:55 2014
@@ -261,10 +261,24 @@ public class DefaultTagDecorator impleme
     
     private TagAttributes convertTagAttributes(Tag tag)
     {
+        TagAttribute[] sourceTagAttributes = tag.getAttributes().getAll();
+        
+        String elementNameTagLocalName = tag.getLocalName();
+        if ("element".equals(tag.getLocalName()) &&
+            JSF_NAMESPACE.equals(tag.getNamespace()) || JSF_ALIAS_NAMESPACE.equals(tag.getNamespace()))
+        {
+            // In jsf:element tag, the attribute elementName is required, so from this point we can
+            // assume that elementName has been set. But we need to enable the special treatement
+            // for attribute in jsf:element, so the way to do it is 
+            TagAttribute elemNameAttr = tag.getAttributes().get(Renderer.PASSTHROUGH_RENDERER_LOCALNAME_KEY);
+            if (elemNameAttr != null)
+            {
+                elementNameTagLocalName = elemNameAttr.getValue();
+            }
+        }        
         TagAttribute elementNameTagAttribute = new TagAttributeImpl(
             tag.getLocation(), PASS_THROUGH_NAMESPACE , Renderer.PASSTHROUGH_RENDERER_LOCALNAME_KEY,
-            P_ELEMENTNAME, tag.getLocalName() );
-        TagAttribute[] sourceTagAttributes = tag.getAttributes().getAll();
+            P_ELEMENTNAME, elementNameTagLocalName );
         
         // FIXME: Doing a black box test over Mojarra it was found that passthrough
         // attributes are added to both passthrough map and normal attribute map. It seems
@@ -275,6 +289,7 @@ public class DefaultTagDecorator impleme
         
         // 1. Count how many attributes requires to be duplicated
         int duplicateCount = 0;
+        /*
         for (int i = 0; i < sourceTagAttributes.length; i++)
         {
             TagAttribute tagAttribute = sourceTagAttributes[i];
@@ -295,12 +310,13 @@ public class DefaultTagDecorator impleme
             {
                 duplicateCount++;
             }
-        }
+        }*/
         
         TagAttribute[] convertedTagAttributes = new TagAttribute[
             sourceTagAttributes.length+1+duplicateCount];
         boolean elementNameTagAttributeSet = false;
         int j = 0;
+
         for (int i = 0; i < sourceTagAttributes.length; i++)
         {
             TagAttribute tagAttribute = sourceTagAttributes[i];
@@ -319,35 +335,54 @@ public class DefaultTagDecorator impleme
                 convertedTagAttributes[j] = new TagAttributeImpl(tagAttribute.getLocation(), 
                     convertedNamespace, tagAttribute.getLocalName(), qname, tagAttribute.getValue());
                 
+                /*
                 if (!isReservedJSFAttribute(qname))
                 {
                     j++;
                     // Duplicate passthrough
+                    // -= Leonardo Uribe =- After discussion with Ed Burns and Frank Caputo, the reason is jsf 
+                    // namespace in an attribute is used to convert the tag into jsf:element, so there are cases
+                    // where you want the attribute to be passed into the passthrough attribute map instead the
+                    // normal attribute map. It is not expected to override jsf:element because this is a 
+                    // special component used to output markup, so it has been defined the attribute names that
+                    // does not require this duplication. It was also found that for the remaining cases, copy
+                    // the passthrough attribute does not have any effect, because by effect of the renderer
+                    // associated to the component these attribute are passed through by the renderer code and
+                    // time later when the passthrough attributes are rendered, there is a check that indicates
+                    // that the attribute has been already rendered.
                     convertedTagAttributes[j] = new TagAttributeImpl(tagAttribute.getLocation(), 
                         PASS_THROUGH_NAMESPACE, tagAttribute.getLocalName(), 
                         "p:"+tagAttribute.getLocalName(), tagAttribute.getValue());
-                }
+                }*/
             }
             else if (namespace == null)
             {
                 // should not happen, but let it because org.xml.sax.Attributes considers it
+                // -= Leonardo Uribe =- after conversation with Frank Caputo, who was the main contributor for
+                // this feature in JSF 2.2, he said that if the namespace is empty the intention is pass the
+                // attribute to the passthrough attribute map, so there is an error in the spec documentation.
                 convertedTagAttributes[j] = tagAttribute;
+                /*
                 j++;
                 // Duplicate passthrough
                 convertedTagAttributes[j] = new TagAttributeImpl(tagAttribute.getLocation(), 
                     PASS_THROUGH_NAMESPACE, tagAttribute.getLocalName(), 
-                    "p:"+tagAttribute.getLocalName(), tagAttribute.getValue());
+                    "p:"+tagAttribute.getLocalName(), tagAttribute.getValue());*/
             }
             else if (tagAttribute.getNamespace().length() == 0)
             {
                 // "... If the current attribute's namespace is empty 
                 // let the current attribute be convertedTagAttribute. ..."
+                // -= Leonardo Uribe =- after conversation with Frank Caputo, who was the main contributor for
+                // this feature in JSF 2.2, he said that if the namespace is empty the intention is pass the
+                // attribute to the passthrough attribute map, so there is an error in the spec documentation.
                 convertedTagAttributes[j] = tagAttribute;
+                /*
                 j++;
                 // Duplicate passthrough
                 convertedTagAttributes[j] = new TagAttributeImpl(tagAttribute.getLocation(), 
                     PASS_THROUGH_NAMESPACE, tagAttribute.getLocalName(), 
-                    "p:"+tagAttribute.getLocalName(), tagAttribute.getValue());
+                    "p:"+tagAttribute.getLocalName(), tagAttribute.getValue());*/
             }
             else if (!tag.getNamespace().equals(tagAttribute.getNamespace()))
             {

Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultHtmlDecoratorTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultHtmlDecoratorTestCase.java?rev=1582342&r1=1582341&r2=1582342&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultHtmlDecoratorTestCase.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/tag/jsf/html/DefaultHtmlDecoratorTestCase.java Thu Mar 27 15:12:55 2014
@@ -336,13 +336,21 @@ public class DefaultHtmlDecoratorTestCas
         UIViewRoot root = facesContext.getViewRoot();
         vdl.buildView(facesContext, root, "testConvertTagAttributes1.xhtml");
 
+        //<input jsf:id="box1" type="text"
+        //       jsf:value="#{test.value}" jsf:customAttr="SomeValue"
+        //       onclick="alert('hello')"
+        //       placeholder="Enter text" 
+        //       pt:data_up="Going Up"/>
         UIInput input1 = (UIInput) root.findComponent("myForm:box1");
         Assert.assertNotNull(input1);
         
         Assert.assertEquals(input1.getPassThroughAttributes().get("placeholder"), "Enter text");
-        Assert.assertEquals(input1.getAttributes().get("placeholder"), "Enter text");
+        //Assert.assertEquals(input1.getAttributes().get("placeholder"), "Enter text");
+        Assert.assertNull(input1.getAttributes().get("placeholder"));
         
-        Assert.assertEquals(input1.getAttributes().get("customAttr"), "SomeValue");
+        
+        //Assert.assertEquals(input1.getAttributes().get("customAttr"), "SomeValue");
+        Assert.assertNull(input1.getAttributes().get("customAttr"));
         // Attributes outside "id", "binding", "rendered" or "transient" can be 
         // copied on passthrough attribute map.
         Assert.assertEquals(input1.getPassThroughAttributes().get("customAttr"), "SomeValue");
@@ -351,60 +359,92 @@ public class DefaultHtmlDecoratorTestCas
         Assert.assertNull(input1.getAttributes().get("data_up"));
         
         Assert.assertNotNull(input1.getValueExpression("value"));
-        Assert.assertNotNull(input1.getPassThroughAttributes().get("value"));
+        //Assert.assertNotNull(input1.getPassThroughAttributes().get("value"));
+        Assert.assertNull(input1.getPassThroughAttributes().get("value"));
         Assert.assertEquals(input1.getValue(), "value1");
         Assert.assertEquals(input1.getAttributes().get("value"), "value1");
         
+        //<input jsf:id="box2" pt:elementName="meter"
+        //       jsf:value="#{test.value}" jsf:customAttr="SomeValue"
+        //       onclick="alert('hello')"
+        //       placeholder="Enter text" 
+        //       pt:data_up="Going Up">Hello World!</input>
         UIComponent input2 = root.findComponent("myForm:box2");
         Assert.assertFalse(input2 instanceof UIInput);
         Assert.assertEquals(input2.getRendererType(), "javax.faces.passthrough.Element");
         
         Assert.assertEquals(input2.getPassThroughAttributes().get("placeholder"), "Enter text");
-        Assert.assertEquals(input2.getAttributes().get("placeholder"), "Enter text");
+        //Assert.assertEquals(input2.getAttributes().get("placeholder"), "Enter text");
+        Assert.assertNull(input2.getAttributes().get("placeholder"));
         
-        Assert.assertEquals(input2.getAttributes().get("customAttr"), "SomeValue");
+        //Assert.assertEquals(input2.getAttributes().get("customAttr"), "SomeValue");
+        Assert.assertNull(input2.getAttributes().get("customAttr"));
         Assert.assertEquals(input2.getPassThroughAttributes().get("customAttr"), "SomeValue");
         
         Assert.assertEquals(input2.getPassThroughAttributes().get("data_up"), "Going Up");
         Assert.assertNull(input2.getAttributes().get("data_up"));
         
-        Assert.assertNotNull(input2.getValueExpression("value"));
+        // note there is no type attribute, so it is translated into a jsf:element, and in that
+        // component, "value" is not defined, so it is set as passthrough
+        Assert.assertNull(input2.getValueExpression("value"));
         Assert.assertNotNull(input2.getPassThroughAttributes().get("value"));
-        Assert.assertEquals(input2.getAttributes().get("value"), "value1");
+        Assert.assertNull(input2.getAttributes().get("value"));
         
+        //<jsf:element id="box3" elementName="meter" 
+        //       value="#{test.value}" jsf:customAttr="SomeValue"
+        //       onclick="alert('hello')"
+        //       placeholder="Enter text" 
+        //       pt:data_up="Going Up">
+        //       Hello Element!
+        //</jsf:element>
         UIComponent input3 = root.findComponent("myForm:box3");
         Assert.assertFalse(input3 instanceof UIInput);
         Assert.assertEquals(input3.getRendererType(), "javax.faces.passthrough.Element");     
         
         Assert.assertEquals(input3.getPassThroughAttributes().get("placeholder"), "Enter text");
-        Assert.assertEquals(input3.getAttributes().get("placeholder"), "Enter text");
+        Assert.assertNull(input3.getAttributes().get("placeholder"));
         
-        Assert.assertEquals(input2.getAttributes().get("customAttr"), "SomeValue");
-        Assert.assertEquals(input2.getPassThroughAttributes().get("customAttr"), "SomeValue");
+        Assert.assertNull(input3.getAttributes().get("customAttr"));
+        Assert.assertEquals(input3.getPassThroughAttributes().get("customAttr"), "SomeValue");
         
         Assert.assertEquals(input3.getPassThroughAttributes().get("data_up"), "Going Up");
         Assert.assertNull(input3.getAttributes().get("data_up"));
         
-        Assert.assertNotNull(input3.getValueExpression("value"));
+        Assert.assertNull(input3.getValueExpression("value"));
         Assert.assertNotNull(input3.getPassThroughAttributes().get("value"));
-        Assert.assertEquals(input3.getAttributes().get("value"), "value1");
+        Assert.assertNull(input3.getAttributes().get("value"));
         
         //Assert.assertEquals(input2.getPassThroughAttributes().get("elementName"), "meter");
         
+        //<h:panelGroup id="box4">
+        //<div jsf:class="noprint">
+        //    MYBOX4
+        //</div>
+        //</h:panelGroup>
         UIComponent box4 = root.findComponent("myForm:box4");
         Assert.assertNotNull(box4);
         UIComponent boxDiv4 = box4.getChildren().get(0);
         Assert.assertNotNull(boxDiv4);
         Assert.assertEquals(boxDiv4.getAttributes().get("styleClass"), "noprint");
-        Assert.assertEquals(boxDiv4.getPassThroughAttributes().get("class"), "noprint");
+        //Assert.assertEquals(boxDiv4.getPassThroughAttributes().get("class"), "noprint");
+        Assert.assertNull(boxDiv4.getPassThroughAttributes().get("class"));
         
+        //<h:panelGroup id="box5">
+        //<div jsf:style="noprint">
+        //    MYBOX5
+        //</div>
+        //</h:panelGroup>
         UIComponent box5 = root.findComponent("myForm:box5");
         Assert.assertNotNull(box5);
         UIComponent boxDiv5 = box5.getChildren().get(0);
         Assert.assertNotNull(boxDiv5);
-        Assert.assertEquals(boxDiv5.getAttributes().get("style"), "noprint");
+        Assert.assertNull(boxDiv5.getAttributes().get("style"));
         Assert.assertEquals(boxDiv5.getPassThroughAttributes().get("style"), "noprint");
         
+        UIComponent box6 = root.findComponent("myForm:box6");
+        Assert.assertNotNull(box6);
+        Assert.assertEquals(box6.getAttributes().get("onclick"), "alert('hello')");
+        
         StringWriter sw = new StringWriter();
         
         ResponseWriter mrw = new HtmlResponseWriterImpl(sw, "text/html", "UTF-8");
@@ -518,5 +558,45 @@ public class DefaultHtmlDecoratorTestCas
         Assert.assertTrue(sw.toString().contains("MYBOX5"));
         Assert.assertTrue(sw.toString().contains("<div "));
         Assert.assertTrue(sw.toString().contains("</div>"));
+        
+        // TEST 6
+        
+        sw = new StringWriter();
+        mrw = new HtmlResponseWriterImpl(sw, "text/html", "UTF-8");
+        facesContext.setResponseWriter(mrw);
+        
+        box6.encodeAll(facesContext);
+        
+        sw.flush();
+
+        //<div jsf:id="box6" onclick="alert('hello')">
+        //    <f:ajax event="click" render="box5"/>
+        //    MYBOX6
+        //</div>
+        // Try second time, to avoid the script section by f:ajax effect
+        sw = new StringWriter();
+        mrw = new HtmlResponseWriterImpl(sw, "text/html", "UTF-8");
+        facesContext.setResponseWriter(mrw);
+        
+        box6.encodeAll(facesContext);
+        
+        sw.flush();        
+        attrs = new HtmlRenderedAttr[]{
+            new HtmlRenderedAttr("onclick", 
+                    "jsf.util.chain(document.getElementById('myForm:box6'), event,'alert(\\'hello\\')', "
+                    + "'jsf.ajax.request(\\'myForm:box6\\',event,{render:\\'myForm:box5 \\',"
+                            + "\\'javax.faces.behavior.event\\':\\'click\\'})');"),
+        };
+        
+        
+        
+        HtmlCheckAttributesUtil.checkRenderedAttributes(attrs, sw.toString());
+        if(HtmlCheckAttributesUtil.hasFailedAttrRender(attrs))
+        {
+            Assert.fail(HtmlCheckAttributesUtil.constructErrorMessage(attrs, sw.toString()));
+        }
+        Assert.assertTrue(sw.toString().contains("MYBOX6"));
+        Assert.assertTrue(sw.toString().contains("<div "));
+        Assert.assertTrue(sw.toString().contains("</div>"));
     }  
 }

Modified: myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/html/testConvertTagAttributes1.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/html/testConvertTagAttributes1.xhtml?rev=1582342&r1=1582341&r2=1582342&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/html/testConvertTagAttributes1.xhtml (original)
+++ myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/jsf/html/testConvertTagAttributes1.xhtml Thu Mar 27 15:12:55 2014
@@ -54,6 +54,11 @@
             MYBOX5
         </div>
         </h:panelGroup>
+        
+        <div jsf:id="box6" onclick="alert('hello')">
+            <f:ajax event="click" render="box5"/>
+            MYBOX6
+        </div>
     </form>
 </body>
 </html>
\ No newline at end of file