2

When defining an element in XPages like this:

    <xp:div id="chartSurface"></xp:div>

the resulting HTML looks like this:

    <div id="view:_id1:_id4:chartSurface"></div>

which is "necessary" since the ID must be unique and the JSF/XPages element could be repeated many times. While I can get the client id using #{id:chartsurface}, this makes addressing elements unnecessarily difficult since the ":" clashes with CSS pseudo selectors and libraries like d3js fail (haven't tested it with jQuery, dojo.byId seems to work). Is there a way to tell JSF/XPages to use a different delimiter (e.g. NONE or %) so the result would look like this:

    <div id="view_id1_id4chartSurface"></div>
    <div id="view%_id1%_id4%chartSurface"></div>

Bonus question: Which delimiters would be save to use?

stwissel
  • 20,110
  • 6
  • 54
  • 101
  • 1
    Related: [Is it possible to change the element id separator in JSF?](http://stackoverflow.com/a/2146524/1065197) I don't know if it's a duplicate question because I never heard of XPages. – Luiggi Mendoza Feb 13 '13 at 05:32
  • @LuiggiMendoza yep, duplicate. XPages is a JSF implementation that runs on an IBM Domino server and adds server side JavaScript and a NoSQL database including directory to it. But it has its own twists, so maybe only 80% duplicate. Thx for pointing out – stwissel Feb 13 '13 at 05:43
  • You're welcome. Notice that the init parameter works only for JSF 2 (so check if XPages is based on JSF 2). – Luiggi Mendoza Feb 13 '13 at 05:49
  • XPages is derived from JSF 1.1 but strayed from the JSF 2 spec despite implementing many of the same features. – Tim Tripcony Feb 13 '13 at 06:01
  • As you said: controls may repeat in one page. So what do you insist on ID attribute (what is not recommended anyway)? You can make it easy by styleClass property and use class in selector. – Frantisek Kossuth Feb 13 '13 at 08:58
  • @FrantisekKossuth I use in scriptBlocks quite often getClientId(somecontrol) to then call a function with the control as parameter. Then it can be multiple times on a page - which I wouldn't care then since I would get the right one at the right time. – stwissel Feb 13 '13 at 13:34
  • @stwissel In this particular case: in script block use function, which takes id as param. Then, in context of your control, call it by function("#{id:...}") - that way your code will call the function with proper id - assuming the call is made "inside" control that repeats, so id matches the control in right "context". – Frantisek Kossuth Feb 14 '13 at 11:36

2 Answers2

1

As far as I know there is no way to change the separator with use of configuration as it is hardcoded into the xpages source (into UIComponentBase to be more specific).

Theoretically You can try to replace the clientId with use of Renderer. There is public method convertClientId(FacesContext context, String clientId) which can be overriden and can for example replace all ':' with other char sequence.

Unfortunately Im not sure if findComponent function will work properly after this change.

W_K
  • 868
  • 4
  • 9
0

As @W_K pointed out, there is no easy way. In conclusion there are 4 strategies to deal with the situation:

  1. Shrug and move one
  2. Overwrite the Renderer
  3. Fix the clientid on the client side
  4. Fix your queries

1 & 2 are in the eye of the beholder. For #3 I currently use 2 functions, one SSJS, one CSJS:

   function getSimpleClientID(oldID) {
   /* Server side function */
        // Removes the : from a clientID, so it can be used easily in CSS3 selectors
        return oldID.replace(/:/g,"");
   }

   function fixClientIds() {
   /* Client side function */
   // Update all ID function with simplified IDs    
      dojo.query("*[id]:not([type='hidden'])").forEach(function(node, index, arr){
         if (node.className != "xspForm") {
             node.id = getSimpleClientID(node.id);
         }
      });   
    }

In my SSJS instead of calling getClientId("myControl") I do getSimpleClientID(getClientId("myControl")) and I call the fixClientIds() in the XSP.addOnLoad().

Thx to the link Luiggi pointed out, the 4th option is to just adjust the query you might pass on using escapeClientID(getClientId("myControl")) with this function:

   function escapeClientID(oldID) {
   /* Server side function */
        // Removes the : from a clientID, so it can be used easily in CSS3 selectors
        return oldID.replace(/:/g,"\\:");
   }

(I haven't tested that one properly)

stwissel
  • 20,110
  • 6
  • 54
  • 101