dev@javaserverfaces.java.net

<h:commandLink> - 'onclick' encoding

From: Stanimir Stamenkov <stanio_at_yahoo.com>
Date: Thu, 6 May 2010 04:28:17 -0700 (PDT)

I've initially posted this to the JavaServer Faces forum:

http://forums.sun.com/thread.jspa?threadID=5437994


and was suggested posting it here:

I've noticed a deficiency in the JSF specification regarding the
encoding of the 'onclick' attribute of the <h:commandLink>
component:

http://java.sun.com/javaee/javaserverfaces/1.2/docs/tlddocs/h/commandLink.html
http://java.sun.com/javaee/javaserverfaces/2.0/docs/pdldocs/jsp/h/commandLink.html
http://java.sun.com/javaee/javaserverfaces/2.0/docs/pdldocs/facelets/h/commandLink.html

All of these state:

> Encode Behavior
>
> If an "onclick" attribute was specified by the user, render this
> JavaScript in a function, and render the user's JavaScript in a
> function. Render both functions in a choice function as follows:
>
> var a=function(){#USER_FUNCTION#}; var b=function(){#JSF_FUNCTION#}; return (a()==false) ? false : b();
>
> where #USER_FUNCTION# is the user's JavaScript and #JSF_FUNCTION# is
> the JavaScript rendered by JSF. The choice function should operate
> such that if the user's JavaScript returns true, then the rendered
> JavaScript will also execute.

Anyone familiar with JavaScript executed in a browser knows the
event handlers are executed a bit differently than normal functions.
So the 'this' reference in event handlers refers to the element the
handler has been registered on, like:

<a href="..." onclick="window.alert(this.href);">...</a>

Invoking a function in the normal way "resets" the 'this' reference
to the global object, i.e. the 'window', so:

<script type="text/javascript">
  function testAlert() {
    alert(this.href);
  }
...
<a href="..." onclick="testAlert();">...</a>

no longer works as expected. The same happens with the JSF specified
way of handling user specified 'onclick' script:

<h:commandLink value="Try me!" action="..." onclick="window.alert(this.href);" />

would render:

<a href="#" onclick="var a=function(){window.alert(this.href);}; var b=function(){#JSF_FUNCTION#}; return (a()==false) ? false : b();">Try me!</a>

The user code in the above example would 'alert' an undefined value
and not the expected 'href' of the link element. The problem is when
one wants to pass the original 'this' reference to the element to a
function for additional processing but this reference gets lost
because of the JSF specification. It is really trivial to have this
done correctly and causing no confusion to newcomers (like me), as:

var a=function(){#USER_FUNCTION#}; var b=function(){#JSF_FUNCTION#}; return (a.call(this)==false) ? false : b();

Note the a.call(this) vs. a() call. This would preserve the 'this'
reference in the #USER_FUNCTION# code, would be more natural to
everyone (no difference between writing the code in a plain HTML
link element or JSF h:commandLink) and would be just better.

Now, I'm not sure the Mojarra devs could do anything about it as it
appears a specification issue, but I hope you (the Mojara devs)
could influence the development of the spec.

-- 
Stanimir