For several years, I’ve been using an app called Email AutoComplete (it’s now a private listing) to add auto complete capabilities onto my email address text boxes in the Salesforce email editor. It’s a nice little app. However, Arrowpointe started using Email to Case Premium (an app I highly recommend) and I wanted to have similar capabilities on their forms.

The Email AutoComplete app works well, but it written using s-Controls and Yahoo User Interface Library v2, which adds a lot of confusing code into it. It was too hard for me to change and apply to the Email to Case Premium pages. I looked for a jQuery approach and leveraged ideas from a great blog post on the Vertical Code blog. In my case, however, I was trying to add this capability onto an AppExchange “managed” (i.e. locked down) page and onto the standard email forms from Salesforce. I didn’t have the luxury of an Apex Controller and Visualforce.

Enter the AJAX API and jQuery!

Question: How do I obtain the Session Id?

Answer: Create a Visualforce page to act as a JavaScript file. In this case, I am creating a global JavaScript variable called _my_sfdcSession.

Question: How do I enable API access in Salesforce and turn on jQuery so its usable whereever I am (almost) in Salesforce?

Answer: Use the sidebar to inject the code. I use the Messages & Alerts sidebar item, but the same could also be done using a custom sidebar component. The key is that the component always be in the sidebar.

The code below loads the Visualforce page above to get the Session Id. Then it loads the AJAX toolkit (from Salesforce), jQuery (from Google CDN) and jQueryUI (from Google CSN). Note that the jQuery instance is put into a new variable called $_org using the jQuery.noConflict() method. I chose that variable name because I am assuming it won’t conflict with other solutions that rename jQuery.

If you use the Messages and Alerts sidebar component, do not put empty lines in your code because the system will add a p html tag in it

Use absolute references to your Salesforce pages because managed packages have a different url structure

Question: How do I implement the AutoComplete part?

Answer: Now that jQuery is loaded and we have access to the Salesforce API, we can get down to actual business. The code I am personally using is below. Not being super confident with jQuery selectors, I am hardcoding the element names to add auto complete to into my code. The downside of this is if those element names change, it will stop working, but it’s an easy fix.

This code gets a list of element Ids and then loops through them, adding autoComplete (from jQuery UI) to each one. The “source” property of autoComplete uses the Salesforce API to look for Contacts with a name or email address LIKE what is being typed in. In this case, it is handling the situation where you already have multiple names separated by ; in the email field. You will also notice the line saying sforce.connection.sessionId = _my_sfdcSession;. This line associates the Session Id from that initial page we created to the AJAX API.

I have this code stored as a Static Resource called “AutoComplete_Email”.

Question: Now how do I get this autoComplete code injected into the page?

Answer: Add some more code to the sidebar. The key parts are lines 6-9 below. This injects the script into the page. I personally make sure its only injected into the pages I want it to, which are the standard email pages in Salesforce and the Email to Case Premium “New Comment” page.

@jeremy, nice comment. When I implemented it, I was thinking I should try and make this instance of the AJAX toolkit completely independent of any other that could get loaded onto a page (e.g. an AppExchange app uses it too). That’s why I made my own Session Id variable and also my own jQuery instance. Not sure if I did it the “right” way or not. I couldn’t figure out how to make my sforce object instance into a unique name, but I would if I could. Just to make this implementation of jQuery and AJAX toolkit independent of any other possible instances. Thoughts?

The AJAX toolkit creates the global variable “sforce” and that’s what everyone uses. I think this is only an issue if different versions of the script are loaded; They all use the same global variable name.

I’m also not sure you’re creating your own instance of jQuery. When you use noConflict(), you’ll still be using the same jQuery instance that any scripts that came before you used. If something comes along later and reloads jQuery with a new tag, it will get its own instance, I think. The fact that you’ve used noConflict() is what really matters here.

That’s some nice JavaScript trickery! Definitely tucking this away for future reference. I’m glad my post on autocomplete helped and thanks for the mention. Does JavaScript remoting not work in this situation because of the managed package? On the one hand, it is nice to have it all in JavaScript, but then you can’t write tests to make sure everything works from release to release.

I’ve also found that with my blog posts with pure JavaScript, people have a real hard time debugging problems since there is no compile at page save to catch problems.

@Daniel, in this situation I am trying to add auto-complete onto someone else’s work. In one case, it’s the standard Salesforce pages. In another it’s an AppExchange app that is managed and whose page is locked down. This solution is acting more like a greasemonkey script where it modifies someone else’s app pages.

@andrew yes, the solution is pretty hardcoded, but easy to manage for a Dev if they choose to. Is Salesforce considering stopping script injection like this? If so, what would stop a browser extension or greasemonkey script from doing the same thing?

I updated the code in the post on 11/28 to add a small bit of code to the autocomplete’s “focus” event. Without this, the value in the email field gets overwritten when the items are navigated with the keyboard.

@teejay, there are a few hardcoded areas in the code. You’ll need to look into the equivalents in the console. In the sidebar code, it has an IF statement checking on the URL so it only runs on the right pages. You’d need to include the URL of the console into that mix. In the main JavaScript, you’ll need to do more elems.push statements to include the IDs of the fields you want auto-complete on so that code actually applies autoComplete to those.

The solution I did is pretty hardcoded to the current pages and needs to be modified if Salesforce changes the UI or you want it on new pages.

teejay Said,

I had already modified the code to work on some different fields, using firebug to find the id of the field. However when the email edit page is shown in the cloud console it seems to be wrapped in an iframe which prevents firebug from finding the id for the field. Also the javascript in the sidebar probably doesnt work in the cloud console as the url in the addressbar never seems to change. In fact with the cloud console I’m asking myself if the javascript in the sidebar still works at all, as there is no option to display the sidebar. …

@teejay, the sidebar is the trick to getting the entire bit of code executed at all. If the sidebar is not executed, you can manually execute it in Firebug to make sure it works. Then its a matter of finding a place to put code so that it executes in the console. I’ve never really used the console so I am not sure where to put that.

Paul Said,

I’ve set this up in a dev org and it works great for the send email page in Salesforce. I’m trying to add it to a custom visualforce page and avoid using the ID, since the ID of the field could change if I move it around on the visualforce page (thanks to visualforce’s strange automatic IDs).

How do I change it so that it could select using classes instead? I’ve tried the following but I’m getting a DOM Exception 12.

Paul Said,

For the sake of time and my lack of javascript experience I added another section after the for loop with this:

var Elements = document.querySelectorAll(‘.EmailAutocomplete’);
var thisElem = Elements[0];
$_org(thisElem).autocomplete({
// Everything after here is the same as inside of the loop of indexes

Obviously this only gets the first item that has the Autocomplete class, but that is all I need for now.
Now I can add the EmailAutocomplete task to any visualforce page and it’ll add autocomplete functionality!

I like your class selection approach best for custom pages. Nice job! The ones I was dealing with were Salesforce default ones and one from a AppExchange app, so I could not edit the HTML to get the classes in there.