The goal
---------------------
To create a mixin that will attach a client-side javascript object to
the mixing component. This mixin should not know anything about the
component and remain completely genereic, needing only a DOM id to
provide to the JS object.


Requirements
---------------------
To attach JS behavior, you need a DOM id. Therefore the mixin must be
able to obtain this value from the component.


Problems
---------------------
Not all components generate DOM ids, in which case you have to provide
one informally.
For a mixin to be able to attach a JS object to an element generated by
a component, it has to be able to obtain that id.

Digging through api I have found 2 possible ways to obtain the DOM id.
1) If the component implements ClientElement, then
ClientElement#getClientId is the correct way.
2) If the component has used the MarkupWriter
(http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/MarkupWriter.html)
to create the exact element from which we need the DOM id, then we can
use MarkupWriter#getElement to get that element before it is closed.
With that Element
(http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/dom/Element.html)
we can see if a DOM id has been set by using Element#getAttribute (and
passing "id" as the argument).


Last notes
---------------------
Perhaps I'm a bit delusional on this issue. At first I thought that the
DOM id was so important that there should be a more intimate handling of
it, perhaps moving the getClientId from ClientElement to
ComponentResourcesCommon, so that _every_ component has one. The problem
is that a component can be arbitrarily complex, generating markup of an
unknown hierachical depth of elements. In addition, the component body
may be constructed primarily by it's template.

I'm still thinking on this, but it seems like attaching a mixin to a
component's dom id will require explicitly telling it what that is.

Input still welcome :-)

chris

-- 
http://thegodcode.net



Josh Canfield wrote:
> Ah, id with no t: is just a parameter like any other. Try this mixin:
>
> import org.apache.tapestry.MarkupWriter;
> import org.apache.tapestry.annotations.Parameter;
>
> public class Title {
>
>     @Parameter(defaultPrefix="literal")
>     private String _id;
>       
>     void beginRender(MarkupWriter writer)
>     {
>         writer.attributes("title", "You're id is " + _id);
>     }
> }
>
>
> The downside is if the component you are mixing into already has the
> id parameter define, your mixin gets null. I'm not sure why they can't
> share... the docs say
>
> "If the component and a mix both define a parameter with the same
> name, then the component wins: the component's parameter will be
> bound, and the mixin's parameter will be unbound."
>
> but I'm not clear why that is the case.
>
> Does that help?
> Josh
>
> On Thu, Apr 10, 2008 at 9:57 PM, Chris Lewis <[EMAIL PROTECTED]> wrote:
>   
>> Hi Josh,
>>
>> Indeed t:id does work, but apart from the fact that I'm not entirely
>> sure what T5 does with that value as opposed to the un-namespaced
>> version (id), it doesn't fully work. The reason is because the Any
>> component, like many in the core lib, do not explicitly write a DOM id
>> in the HTML of the resulting element. So while this allows me to get
>> some id in java code (which I need), it doesn't address the problem of
>> their not being a DOM id, so of course my JS fails. The only ways around
>> this that I know are:
>>
>> 1) Explicitly provide the id as the normal 'id' attribute in the
>> template as an informal parameter and provide another one in the t:
>> namespace, to be passed to the component. The problem with this is I
>> have to provide it twice, which aside from being annoying is error-prone.
>>
>> 2) Have the mixin explicitly write a HTML id attribute to the tag of the
>> containing component. This would be horrible in my opinion, because
>> without intimate knowledge of the component using the mixin, or any
>> other mixins coordinating behavior, you can't know be sure you won't
>> damage something (overwriting an id attribute already created, writing a
>> second id attribute (which would be wrong), etc). And of course if the
>> mixin requires intimate knowledge then it's not a good mixin.
>>
>> Thanks - any other ideas? :-)
>>
>> chris
>>
>>
>> Josh Canfield wrote:
>>     
>>> Hey Chris,
>>>
>>> t:id="my_div" seems to do what you want. I haven't looked closely at
>>> un-namespaced id works in Tapestry, I've just always used the t:id
>>> variety...
>>>
>>> Josh
>>>
>>> On Thu, Apr 10, 2008 at 5:36 AM, Chris Lewis <[EMAIL PROTECTED]> wrote:
>>>
>>>       
>>>> Dear list,
>>>>
>>>> I decided to throw together an app detailing how JS works with T5 (how
>>>> to connect behavior from a component or mixin, the important inner
>>>> workings, etc). I created a mixin that attaches behavior (mouse overs)
>>>> to an HTML element (and doing this requires the DOM id of that element).
>>>> For a simple demo I just wanted to attach it to a styled <div
>>>> id="my_div">, so I had to use a <div t:type="any" id="my_div">. No
>>>> problem. Now I need that DOM id in my java code (mixin) so I can pass it
>>>> to the instantiation string of my JS object. Here's what I tried:
>>>>
>>>>    @Parameter(value = "prop:componentResources.id", defaultPrefix =
>>>> TapestryConstants.LITERAL_BINDING_PREFIX)
>>>>    private String clientId;
>>>>
>>>> This is the 'usual' way of getting the client side id of the component,
>>>> at least when that component outputs it in the html element body. Since
>>>> Any does not, it appears to interpret (or rather ignore) the id
>>>> attribute and treat it as an informal. The problem with that is there is
>>>> no way, at least that I know of, to get my hands on that value in java
>>>> code. So what I'm having to do in my template code is explicitly declare
>>>> the t:clientId parameter:
>>>>
>>>> <div t:type="any" t:mixins="hoverhighlight" id="my_box" 
>>>> t:clientId="my_box">
>>>>
>>>> This works, but it's annoying that T5 can't know what the client side id
>>>> will be. Components that actually produce a T5-generated client side id
>>>> generally implement ClientElement#getClientId and explicitly insert the
>>>> html id attribute with that as a value. I realize that it wouldn't make
>>>> sense for _every_ component to do this, but IMO there should be a way to
>>>> get at this id in the situations where it's been provided. Perhaps I've
>>>> missed something, but unless I've missed something there's no current
>>>> way to do this and get the dom id in code:
>>>>
>>>> <div t:type="any" t:mixins="hoverhighlight" id="my_box">
>>>>
>>>> Thanks for any input you can offer.
>>>>
>>>> chris
>>>>
>>>> --
>>>> http://thegodcode.net
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [EMAIL PROTECTED]
>>>> For additional commands, e-mail: [EMAIL PROTECTED]
>>>>
>>>>
>>>>
>>>>         
>>>
>>>
>>>       
>> --
>> http://thegodcode.net
>>
>>
>>     
>
>
>
>   

-- 
http://thegodcode.net

Reply via email to