VisualForce Element Ids in jQuery selectors
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.
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
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
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
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
Cool!
Joel Dietz
February 19, 2010 at 9:34 pm
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
[…] 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 […]
VisualForce Form Validation Enhanced « The Silver Lining
March 2, 2010 at 11:45 am
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
Very true, thanks for the tip.
Wes
December 29, 2010 at 9:08 pm
[…] VisualForce Element Ids in jQuery selectors […]
jQuery UI datepicker in Visualforce | Avishaybl's Blog
January 11, 2011 at 3:12 pm
[…] VisualForce Element Ids in jQuery selectors […]
jQuery UI datepicker in Visualforce « Avishaybl's Blog
January 11, 2011 at 4:15 pm
[…] post means that my older posts here and here are now retired in favour of this […]
Salesforce: A better way to work with Visualforce Component Ids and JavaScript « The Silver Lining
June 24, 2011 at 2:36 pm
[…] 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 […]
Alternatives to the Average AJAX ActionStatus | Sundog
July 22, 2011 at 5:21 pm
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
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
Hey, right at the start of the article I’ve noted that this approach is retired. There’s a much better way noted here: https://th3silverlining.com/2011/06/24/salesforce-a-better-way-to-work-with-visualforce-component-ids-and-javascript/
Wes
April 30, 2012 at 9:09 am