The Silver Lining

Lessons & Learnings from a salesforce certified technical architect.

VisualForce Element Ids in jQuery selectors

with 19 comments

I have retired this approach in favour of a much neater solution that can be found here.

This tricky topic had me puzzled for some time and in earlier posts I went the way of using CSS classes to identify DOM elements; but was always a touch dissatisfied with the solution. Not only is it less efficient – valid XHTML pages should only have one element with any Id, although CSS classes can be shared by many elements – but it also feels all hacky ‘n stuff. I’m a bit older now, a bit more experienced and I RTFM. Without further ado, here is why it’s tricky, and how to fix it.

As we know the elements within VisualForce pages are given unique Ids when they are rendered as HTML. Salesforce is super smart and generates these in a way such that each element Id is unique i.e. if your VisualForce code is structured so,

<apex:page id="page">
	<apex:outputPanel id="panel">
	</apex:outputPanel>
</apex:page>

The rendered HTML for the outputPanel would be

<span id="page:panel">
</span>

If you don’t specify Ids in your VisualForce code Salesforce generates the element Ids automatically, but will use the same Id pattern of ‘…:greatGrandParentId:grandParentId:parentId:elementId’. This creates a problem when try use Ids as jQuery selectors, and the reason is that jQuery uses CSS syntax when selecting elements. But the colon character is used to indicate pseudo classes within CSS code! How do we fix this? By escaping the character of course… all we need is a simple method that uses regular expressions to find the troublesome colon (there’s a punny joke in there somewhere) and escape the little guy(s),

function esc(myid) {
   return '#' + myid.replace(/(:|\.)/g,'\\\\$1');
 }

Note 1: We’re escaping both ‘.’ and ‘:’ for completeness.
Note 2: We have to escape the escape as the VisualForce parser seems to unescape the first escape :$

There, that should do it. A full example might be,

<apex:page id="page">
	<script>
		$(document).ready(function(){
			$(esc(pnl)).css('background-color','blue');
		});
		function esc(myid) {
		   return '#' + myid.replace(/(:|\.)/g,'\\\\$1');
		}
	</script>
	<script> <!-- I've list this code seperately as it's part of another work-around* (but is still necessary if we're using Ids) -->
		var pnl = '{!$Component.panel}';
	</script>
	<apex:outputPanel id="panel">
	</apex:outputPanel>
</apex:page>

*Post detailing the work-around
Now we have the freedom to select elements using either CSS classes or element Ids, and don’t have to worry about inefficient selectors or hacky code, errr… sortof.

Written by Wes

February 17, 2010 at 12:29 pm

19 Responses

Subscribe to comments with RSS.

  1. Some alternates that i use 🙂

    if you just want to match the id you selected entered in the component id parameter:

    – for your example you could do this:

    – jQuery(“#page\\:panel”) need to double escape it.

    – jQuery(“#:contains(‘XYZ’)”) -> will match all ids that contain xyz ie the above 🙂

    As always a great post wesman

    cameron cronin

    February 17, 2010 at 2:33 pm

    • seems to have removed my visualforce line the empty – should read:

      – \

      cameron cronin

      February 17, 2010 at 2:35 pm

      • apex:outputPanel id=”xyz” (it wont let me use brackets 😦 )

        cameron cronin

        February 17, 2010 at 2:36 pm

  2. Nice post Wes. It is great to see more people using jQuery in vforce. Nice to know there are others battling the same issues lol.

    Richard

    February 17, 2010 at 5:19 pm

  3. Great post! The one piece that scares me a little bit is Note 2:

    “We have to escape the escape as the VisualForce parser seems to unescape the first escape :$”

    Whatever is happening here, it is not normal, and if this behavior ever changes the script would stop working.

    Jason

    February 17, 2010 at 5:28 pm

  4. Jason,

    The visualforce parser sucks at parsing javascript that is embedded into the page. For example, write a for loop that iterates through an array of child nodes. Every time I have done that it hoses the javascript. As a general rule of thumb I move all of my JS into js file resource. The parser never touches it then.

    Richard

    February 17, 2010 at 5:42 pm

  5. Cool!

    Joel Dietz

    February 19, 2010 at 9:34 pm

  6. BTW, the contact form on your website doesn’t seem to work.

    Joel Dietz

    February 19, 2010 at 9:52 pm

    • Ah geez, thanks for the heads up. Just checking it out now and it seems my host has disable secure mail for some reason 😐 I’ll sort that out (or find a new host, which will probably be quicker).

      Wes

      February 21, 2010 at 11:03 pm

  7. […] you may want to read this article on VisualForce and JavaScript, as well as this writeup on using VisualForce Ids with jQuery. Both will pad out some concepts used in the […]

  8. Another alternative – relys on visualforce prepending its structured heirarchy naming – and ending with the id (making sure that it includes the leading semicolon). If you want to match items in a repeat/table you could use $(‘[id*=”:panel:”]’)

    $(document).ready(function(){
    $(‘[id$=”:panel”]’).css(‘background-color’,’blue’);
    });

    Ryan

    December 29, 2010 at 9:06 pm

  9. […] VisualForce Element Ids in jQuery selectors […]

  10. […] VisualForce Element Ids in jQuery selectors […]

  11. […] post means that my older posts here and here are now retired in favour of this […]

  12. […] use in jQuery selectors, and was a solution created by Wes Nolte. See his blog post on the solution here. Beyond that, we’re just selecting the loadingDiv and setting some styles, pretty simple. To get […]

  13. Great tutorial piece on selectors, also check out this tutorial on creating your own selectors: http://www.websanova.com/tutorials/jquery/12-awesome-jquery-selector-extensions

    websanova

    March 12, 2012 at 4:40 pm

  14. Thanks for the post, FYI – I had to change the esc function to only single escape when I uploaded my function as a static resource and used in the html head.

    function esc(myid) {
    return ‘#’ + myid.replace(/(:|\.)/g,’\\\$1′);
    }

    Alex Gum

    April 30, 2012 at 1:05 am


Leave a comment