tags:

views:

2574

answers:

3
    <h:commandLink id="#{id}" value="#{value}" action="#{actionBean.getAction}" onclick="alert(this);"/>

In the previous simplified example, the 'this' keyword used in the Javascript function won't reference the generated A HREF element, but will reference to the global window, because JSF generates the following (simplified) code:

<a onclick="var a=function(){alert(this)};var b=function(){if(typeof jsfcljs == 'function'){jsfcljs(document.forms['mainForm'],'generatedId,action,action','');}return false};return (a()==false) ? false : b();" href="#" id="generatedId">text</a>

So because JSF wraps the user defined onclick in a function, this will point to the global window. I don't have access to the id of the element because my code is used in a generic component that can be used in loops etc. and I don't use backing beans (Facelets + JSF).

So my question is, is there a way to access the A HREF element from within my onclick javascript function, without knowing the id?

+2  A: 

var a=function(){alert(this)};var b=function(){if(typeof jsfcljs == 'function'){jsfcljs(document.forms['mainForm'],'generatedId,action,action','');}return false};return (a()==false) ? false : b();

Oh dear lord! That's violently horrible.

And no, it appears to be throwing away 'this' before you get a chance to look at it - it should have said "return (a.call(this)==false)? false : b()".

On IE only you could read the srcElement from window.event, but that's pretty ugly.

How about avoiding JSF's weird event mangling entirely, by using unobtrusive scripting? eg. omit the onclick and say:

document.getElementById('generatedId').onclick= function() {
    alert(this);
    return false; // if you want to not follow the link
}

If you need the link to continue into JSF's event handling, you'd have to save the old onclick event handler and call it at the end of the function, or use Element.addEventListener (attachEvent on IE) to put your scripting hooks in at an earlier stage than the onclick.

bobince
Yes, horrible indeed :)The problem is that in the context of my code, I don't have access to 'generatedId', I don't know its exact value and I can't reference it (since it's generated by JSF _after_ I would like to reference it)
dfuse
A: 

EDIT:

Go here for a small library/sample code for getting the clientId from the id: JSF: working with component IDs


The HTML ID emitted by JSF controls is namespaced to avoid collisions (e.g. the control is a child of UIData and emitted multiple times, or the container is a portlet so the view can be rendered multiple times in one HTML page). This ID is known as the clientId, and is distinct from the ID set on the JSF control.

If you want to emit the clientId in the view, you can use a managed bean to do it.

public class JavaScriptBean {

    public String getOnclickButton1() {
     String id = "button1";
     String clientId = getClientId(id);
     return "alert('You clicked element id=" + clientId + "');";
    }

    public String getOnclickButton2() {
     String id = "button2";
     String clientId = getClientId(id);
     return clientId;
    }

    private String getClientId(String id) {
     FacesContext context = FacesContext.getCurrentInstance();
     UIViewRoot view = context.getViewRoot();
     UIComponent component = find(view, id);
     return component.getClientId(context);
    }

    private UIComponent find(UIComponent component, String id) {
     if (id.equals(component.getId())) {
      return component;
     }

     Iterator<UIComponent> kids = component.getFacetsAndChildren();
     while (kids.hasNext()) {
      UIComponent kid = kids.next();
      UIComponent found = find(kid, id);
      if (found == null) {
       continue;
      }
      return found;
     }

     return null;
    }

}

This is configured in the application's faces-config.xml and bound to the view using the expression language:

<f:view>
 <h:form>
  <h:commandButton id="button1" value="b1"
   onclick="#{javaScriptBean.onclickButton1}" />
  <h:commandButton id="button2" value="b2"
   onclick="alert('You clicked element id=#{javaScriptBean.onclickButton2}');" />
 </h:form>
</f:view>
McDowell
A: 

Hi, this works for me.

<head>
..
<script type="text/javascript">
var myCommandLinkId = "undefined";
</script>
..
</head>

..

<h:commandLink id="myCommandLink" value="Click Me" onmousedown="myCommandLinkId=this.id;" onclick="alert(myCommandLinkId);" />
Adam
This issue has been fixed in the later Mojarra versions. If I recall correctly, it was about after 1.2_08. The latest 1.2 is 1.2_15. You can download it at http://javaserverfaces.dev.java.net/.
BalusC