Thursday, January 22, 2009

Thoughts on XPages hijacking the id-attribute

I don't think I'm alone in thinking that the XPages hijacking of the id-attribute on fields/etc is a bad design choice. Matt White is amongst the people that have struggled with/found a way to work around the problem.

I don't think there has been much public debate around the problem. Hopefully enough people will read this post, to get a debate started, and maybe get IBM to change it's implementation in the nearby future.

With Dojo as the base framework, there is no reason for IBM to use the ID-attribute to reference elements. There is a speedy CSS selector engine available to them that enables them to use any attribute they want to, to get a pointer to an element. There is also a CSS selector API in the works, which when implemented (soon, in FF 3.1, others will follow) will allow even faster lookups.

In the still not finished HTML 5 specification by W3C/WHATWG, a data-attribute is proposed to use for storing custom values in. Since XPages is something that will last for a good while, and IBM want to play with the cool kids and follow web standards. Why not use data-attributes to add pointers for the XPages engine, and leave the id-attribute to us developers?

9 comments:

NotesSensei said...

Hi Tommy,

the use of the ID is according to specification. Just keep in mind, that you can have a custom control more than once already at design time or you can use a repeat control to decide how often a control appears at runtime. Following html spec an id must be unique, so jsf will control the ids. With a little sprinkle of server JS (think ${stuff} ) it is not too painful. We just need to keep an eye on that.
:-) stw

Tommy Valand said...

I'm not sure which specification you're refering to, but regardless of specification, I still think it's a bad design choice.

The id is the most used attribute to get a hold of an element in the DOM. The choice to "steal" this attribute from the developers/designers is ignorant at best.

I would think most Domino developers don't follow the blogosphere, and will waste a lot of time (=money) looking for ways to work around this needless problem.

NotesSensei said...

Hi Tommy,
I hear you. What I try to say:
1) ID attributes according to the HTML specification need to be unique.
2) A XPages control (even a whole XPage) can be rendered more than once, therefore the ID can't be defined static without violating the HTML specifications. There are multiple scenarios:
2a) a custom control is statically added twice or more to one XPage
2b) a (custom) control is used inside a repeat control more than once (determined at runtime depending on data)
2c) a XPage is rendered in a portal container with other XPages (or another copy of itself).
-- In all cases the renderer needs to ensure that the IDs are unique --
You could argue the renderer needs to exhibit two behaviors: don't touch the ID if it is unique, update it if not. However that makes coding a matter of chance. The current behavior is at least consistent across all scenarios.
I do agree that keeping this knowledge in blogs only is a bad idea. We do discuss that in our XPages training material (Tim Clark and I have written). Why don't you start a LDD Wiki entry and we collaborate on that entry to make it clear to all interested parties?

Tommy Valand said...

What I mean is that XPages shouldn't touch the id-attribute at all.

Dojo has a browser-independent method (dojo.query) to get elements based on any attribute, e.g.
<input
data-xpage-id="view1:random_nonsense">

To get the element: dojo.query( 'input[data-xpage-id=view1:random_nonsense]' )[0]

Let XPages use the "hard way" to get the element, and let the developers use the easiest way.

Nate said...

Tommy, if the developer had the ability to set the ID attribute, how could the Xpages renderer ensure it's uniqueness?

The whole point of the flexibility of the Xpages engine is that anything can be a custom control, and that you can put any custom control inside a repeat. If you repeat a custom control where the developer has set an ID value, how do you ensure it's uniqueness?

Tommy Valand said...

@Nate: If the XPage uses data-attributes or some other attribute as points of reference, it doesn't matter to the XPage if the ids set by the developer aren't unique.

It makes it harder for the developer to get the elements, but that is the developer's fault.

By using computed id's in a repeat control, it should be easy to generate unique id's. Having "everything" computable is one of the things that are so great with the XPage technology.

Tony McGuckin said...

Lets step back a little... does dojo give you server-side JS power also?? Answer... No.

So to give some perspective on the way XPages uses the ID attribute: Not only does XPages ensure uniqueness for client-side elements, but it also maintains this rule on the server-side. You can therefore leverage this power using client- and server-side API.

On the client-side, use the #{id:} resolution preprocessor to resolve ids, and on the server-side use the getComponent("foo"), and getClientId("foo") global methods:

1. Client-side example:

In the rendered HTML exists:

<input id="view1:id2:foo">...

So in my client-side JS I can do:

var x = document.getElementById("#{id:foo}");

2. Server-side example:

In my server-side JS I can grab the control with the id of foo like this:

var x = getComponent("foo");

I can go deeper... say I need to know the full name-spaced client-side ID... no problem...

var cid = getClientId("foo");

IMHO: I believe XPages provides flexible, easy-to-use ways to still work with IDs... client-side and server-side! ;-)

dr. Theory said...

Can someone please explain why in some cases the Id doesn't get calculated.
This for instance -->
var rId = '#{javascript:getClientId("fieldContainer")}';

-->
returns string '#{javascript:getClientId("fieldContainer")}'

Tommy Valand said...

Is the snippet you posted inside the XPage? It won't work if it's inside a client-side javascript library.