jsr344-experts@javaserverfaces-spec-public.java.net

[jsr344-experts] Re: [jsr344-experts mirror] [1089-HTML5-data-*attributes] 20120525 REVISED PROPOSAL

From: Frank Caputo <frank_at_frankcaputo.de>
Date: Sat, 26 May 2012 15:23:13 +0200

On 26.05.2012, at 05:00, Edward Burns <edward.burns_at_oracle.com> wrote:

> This email is broken down into sections prefixed with SECTION:. If you
> want to cut to the chase, look for SECTION: Revised proposal, at the
> end.
>
> ACTION: Please reply by 23:59 EDT (GMT - 0400) Tuesday 29 May.
>
> SECTION: Current specification
>
> * Generic passthru attributes are not supported.
>
> * HTML5 data* attributes are supported by means of <f:dataAttribute>, like
> this:
>
> <h:inputText value="#{bean.postalCode}">
> <f:dataAttribute name="hover-style" value="fancy" />
> <f:dataAttribute name="echo-values" value="always" />
> </h:inputText>
>
> This would cause the rendering of something like this
>
> <input type="text" id="j_id34" value="23252"
> data-hover-style="fancy" data-echo-values="always" ></input>
>
> There is no means for handling arbitrary passthru attributes, just
> arbitrary data-* attributes.
>
> SECTION: EG list discussion summary
>
> Frank also had significant content about a new feature which he called
> "a generic dynamic element". Let's tackle that as a separate thread.
> This thread will continue to talk only about passthru attributes.

+1

>
> I'm not satisfied with the current specification. It doesn't satisfy
> the key use-case of the reporter: pass arbitrary data-* attributes using
> a single tag in the page. Several EG members agree that more needs to
> be done. Imre Osswald and Frank Caputo noted that we should not limit
> the discussion just to data-* attributes but should see data-*
> attributes as a special case of passthru attribute.
>
> PW> If pass-though attributes do become part of the spec they should
> PW> probably be opt-in. There may be existing code currently using
> PW> additional attributes for their own ends. I believe that
> PW> UIComponent.getValueExpression() can be used to get any attribute,
> PW> so some developers may have attributes in their XHTML that they use
> PW> currently but they absolutely do not want exposed to the browser.
>
> AS> Yep. I have the same concern. Currently Facelets dumps unspecified
> AS> attributes into the UIComponent's attributes map. Existing apps are
> AS> using this for their own purposes and would be negatively impacted
> AS> if we simply started passing all of these through to the client.
>
> Limiting the passthru attribute feature to <f:attributes> implicitly
> forces an opt-in, so that's good. Later in the thread, Phill Webb
> suggested using XML namespaced attributes as another way to opt-in.
>
> Ed proposed <f:dataAttribute json="{ foo : bar}" /> but Andy quickly
> pointed out the inappropriateness of this approach with several usage
> examples, stating "We need to abstract away the literal type info from
> the attribute name." Really, the point of the feature is to allow the
> creation of a Map<String,Object> that renderers can use for attributes.
>
> Then, Andy asked, "I don't quite get this - ie. I don't understand how
> jQuery comes into the picture when EL binding to a Java managed bean."
>
> MM> I guess the following is true: a JSF component renders a tag which
> MM> is dynamically used by a JQuery widget. Additional configuration
> MM> data (which jQuery needs to configure this widget) can be passed in
> MM> with the data params.
>
> IO> Why limit this to "data" attributes?
>
> IO> I suggest we add a more general <f:attributes> or <f:attribute
> IO> values=""> (I prefer the extra one), which should be able to set
> IO> any attribute-value(s) on its parent tag.
>
> Let's not even entertain overloading the existing <f:attribute>. Let's
> consider <f:attributes >.
>
> IO> <f:attributes name="data" value="#{el.to.map}" /> would be like the
> IO> proposed <f:dataAttributes value="#{el.to.map}" />
>
> Let's call this aspect "the attribute name decoration problem", and we
> need a good solution for it. Phill Webb's namespaced attribute proposal
> is a good solution for it.
>
> IO> If used with json, it should be possible to also add the "value" as
> IO> the [body] content of the tag.
>
> Yes, I like that idea, but I'll ammend Imre's suggestion to be
>
> <f:attributes prefix="data">
> {
> 'toggle': true,
> 'duration': #{my.animationSettings.toggleDuration}
> 'object': '{"one":"A", "two": "B", "three": "C"}'
> }
> </f:attributes>
>
> <f:attributes>
> {
> 'role': 'banner',
> }
> </f:attributes>
>
> instead of what he proposed.
>
> IO> This should probably get some counterpart in the interface section.
>
> Yes, I agree, and it would employ the same solution to the attribute
> name decoration problem as <f:attributes>. Let's solve the
> non-composite case first. In any case, we'll stay away from "targets"
> because that concept was upsetting to some EG members.
>
> FC> 1) All attributes not handled by a component should be simply
> FC> rendered out as they are. Eg. h:inputText doesn't know the attribute
> FC> placeholder.
>
> I kinda say this already when it comes to the dataHostingElement concept
> in my new "General notes regarding HTML5 support" in the Standard
> HTML_BASIC RenderKit specification.
>
> FC> If the value of an unknown attribute is null or "", don't render it.
>
> Sure.
>
> FC> Maybe we could override attributes. Eg. h:inputText doesn't have the
> FC> attribute type, but the renderer renders it.
>
> FC> <h:inputText value="#{foo.bar}" type="email"/> would be rendered as
> FC> <input type="email" value=""/> because the unknown attribute
> FC> overrides it.
>
> FC> The type attribute is just a hint for the client (eg. to change the
> FC> keyboard layout) while it doesn't change anything on the server.
>
> AS> I also like Frank's suggestion that we allow this to be used to
> AS> override attributes that are rendered by the Renderer:
>
> No, I don't like that at all. If there is a conflict between a passthru
> attribute and something the Renderer is required to render, the passthru
> attribute loses. This is what composite components are for.

Sorry, I don't get it. How can I simply add support for input type="email" with a composite component without any Java code?

>
> BL> The problem with this being that facelet files are not DTD-less
> BL> (shema-less), and so this would be a more complex solution. IMO
> BL> however, it would be an effort worth pursuing, as the arbitrary
> BL> attribute support would be intrinsic to JSF, and not "bolted on".
>
> Doch, in facelets, you can have any arbitrary attributes and it's not at
> all constrained by any XML schema.
>
> FC> UIComponentBase should provide a Map of all unknown attributes to the renderer.
>
> See what I say in the UIComponent.DATA_ATTRIBUTES_KEY javadoc.
>
> AS> One case that does not seem to be covered by the pass-through attribute
> AS> approach is the original case that Paul raised - ie. the ability to
> AS> specify an arbitrary # of possibly dynamically determined bonus
> AS> attributes. If we want to tackle this case, seems like we would still
> AS> be stuck with adding some Map<String, Object>-based attribute, eg:
>
> Doch, this case is covered and is the whole point of Imre's
> <f:attributes> with some solution to the attribute name decoration
> problem.
>
> AS> Getting back to data-* and generic attribute pass through...
> AS>
> AS> For this case I actually prefer Phil's suggestion of using a namepsace
> AS> prefix:
>
> PW> Perhaps a prefix should also be used for unknown attributes to allow
> PW> tooling some hints that breaking the facelet schema in this case is
> PW> permitted.
>
> Again, this is not needed because there is no facelet schema. It's just
> XML. You can put whatever you want in there as long as it is valid XML.
>
> AS> In any case, if we start by adding:
>
> AS> - p:foo="bar" for pass-through attributes on existing (rendering)
> AS> component tags.
> AS> - passThruAttributes="#{foo.mapOfPassThroughAttributes}"
>
> FC> +1, my proposal was just to ease life of HTML developers, who don't
> FC> want to put their attributes into a backing bean, because often they
> FC> don't have the skills to do so. And the more complex the clients get
> FC> the more specialized the frontend developers will be and the less
> FC> they know Java.
>
> Rather than put a new attribute everywhere, which also doesn't help
> composite custom component authors either, I like Imre's idea of
> <f:attributes> and its <cc:attributes> cousin for this case. This also
> gives us a self-contained place to support inline JSON.

My +1 was not for the namespaced attributes, just for the map. Namespaced attributes won't help the HTML developer. Without the namespace using the jsfc syntax you have completion, validation and whatever the IDE supports out of the box for all those HTML attributes. Using the namespace you lose IDE support.

Maybe we could do it both. By default only the namespaced are passed through.

If one uses custom attributes for whatever, there must me some Java code which evaluates it. This Java code could simply remove that attribute from the pass through map, if the developer changes the default behavior to pass through all unknown attributes. So new applications can simply enable pass through by default and old applications won't break.

>
> ECTION: precedence questions
>
> AS> If we go with two tags:
> AS>
> AS> <f:dataAttributes value="#{foo.bonusDataAttrs}">
> AS> <f:dataAttribute name="foo" value="bar"/>
> AS>
> AS> I would think that we would spec this such that <f:dataAttribute> would
> AS> win over the equivalent value in the EL-bound map.
>
> AS> Would the above tags result in a Map<String, Object> that contains all
> AS> of the values specified in the EL-bound map + all of the explicitly
> AS> specified <f:dataAttribute> values?
>
> Yes, a union of the two different kinds of sources of values.
>
> MM> I would throw an exception if both are there (just like in Facelets:
> MM> you can't specify the same attribute twice, right?)
>
> IO> (I guess with f:attribute you can?)
>
> I haven't confirmed this, but I agree with Imre that you probably can
> without complaint.
>
> AS> Would we support multiple <f:dataAttributes> tags for a single
> AS> component? For example, in this case:
> AS>
> AS> <f:dataAttributes value="#{foo.bonusDataAttrs}">
> AS> <f:dataAttributes value="#{bar.morebonusDataAttrs}">
> AS>
> AS> Do we merge the maps? Last one wins? Unsupported?
>
> IO> +1 for merge (Last one wins)
>
> Yes, we merge them and take the union where the last one wins.
>
> AS> Is our Map<String, Object> mutable?
>
> Sure it is, it's just a data structure in the component attributes map.
>
> MM> If we merge, I guess no.
>
> Why not? Once the tag is applied and the Map is populated, there's no
> need to make it immutable.

+1 for the precedence section.

>
> In any case, this SECTION is moot if we go with the namespaced attribute
> solution.
>
> SECTION: Revised proposal.
>
> 1. Drop <f:dataAttribute> [1]

+1

> 2. Keep the text in the standard HTML_BASIC renderkit spec that talks
> about what to do with the UIComponent.DATA_ATTRIBUTES_KEY
> attribute. [2] Change the name of the key to
> PASS_THROUGH_ATTRIBUTES_KEY and amend all textual references to
> remove the "data-" ness because the data-ness (if any) will now be
> baked into the keys where it should have been all along.
> Linguistically, data-ness can be replaced with pass through-ness.
> Specify that the map must be Map<String, Object>. The text already
> allows EL for the values, but also allows EL for the keys. We will
> no longer be able to have EL for the keys with this design.
>
> QUESTION: do we want to have a proper JavaBeans getter on UIComponent
> instead of UIComponent.PASS_THROUGH_ATTRIBUTES_KEY that is to be used as
> a key in UIComponents.getAttributes().get()?

I like the JavaBeans getter, because this enables code completion.

> 3. Introduce a new facelet XMLNS
> http://java.sun.com/jsf/passThroughAttribute and modify the spec PDF
> section 10.3.2 to require that all tag handlers process any
> attributes with that namespace such that they get pushed into the Map<String, Object>.

+1, if we also add the ability to pass through all unknown attributes.

> 4. Add <f:attributes>. This element has a "value" attribute that is a
> ValueExpression that points to Map<String,Object>. The spec for this
> element states that all entries in such a map are copied to the
> PASS_THROUGH_ATTRIBUTES_KEY map.

+1

> 5. Allow <f:attributes> to have body content that, if present, is
> interpreted as JSON. It is not valid to have both body content and a
> "value" attribute. If you want to do that sort of thing, have
> multiple <f:attributes>. In the case of multiple <f:attributes>
> elements, since each one will be copying its entries to the
> PASS_THROUGH_ATTRIBUTES_KEY map, each successive one will blindly
> overwrite any duplicate entries.

+1

Cheers,
Frank

>
> If I missed anything PERTAINING ONLY TO PASS THRU ATTRIBUTES (not pass
> through elements), please reply and say so.
>
> Notes: look for the green text to see what was added so far.
>
> [1] https://maven.java.net/service/local/repositories/snapshots/archive/javax/faces/javax.faces-api/2.2-SNAPSHOT/javax.faces-api-2.2-g. 20120525.150835-110-javadoc.jar/!/vdldocs/facelets/f/dataAttribute.html
>
> [2] https://maven.java.net/service/local/repositories/snapshots/archive/javax/faces/javax.faces-api/2.2-SNAPSHOT/javax.faces-api-2.2-20120525.150835-110-javadoc.jar/!/renderkitdocs/HTML_BASIC/renderkit-summary.html
>
> --
> | edward.burns_at_oracle.com | office: +1 407 458 0017
> | homepage: | http://ridingthecrest.com/
>