Autocomplete for SharePoint people picker

26.03.2010 Updated code to be able to clear the selection It’s only the code for the file “AutocompleteForPeoplePicker.js” that has changed. Thanks to Steve for pointing out the bug.

This solution adds auto complete functionality to a standard SharePoint people picker.

This solution is built with the autocomplete widget from jQuery UI. The values are pulled from the user list based on a query. All users with an email address are available.

Limitations:

  • Single choice only
  • No filter against user group, all users are displayed

As always we start like this:
Create a document library to hold your scripts (or a folder on the root created in SharePoint Designer). In this example i have made a document library with a relative URL of “/test/English/Javascript” (a sub site named “test” with a sub site named “English” with a document library named “Javascript”):
IMG

In addition to the above scripts, i have the jQuery UI 1.8 in a separate folder. See the CEWP code and point the links to your jQuery UI location.

The jQuery UI-library is found here. The pictures and the sourcecode refers to jquery-ui-1.8. The autocomplete widget is not found in previous releases.

The jQuery-library is found here. The pictures and the sourcecode refers to jquery-1.4.min. The autocomplete widget is not supported in previous releases.

The scripts “interaction.js” and “stringBuffer.js” is created by Erucy and published on CodePlex.

The sourcecode for the file “AutocompleteForPeoplePicker.js” is found below.

Read here how to add a CEWP to the NewForm or EditForm, how to find the list Guid of your list, and how to find the FieldInternalName of your columns.

Add a CEWP below the list form in NewForm or EditForm, and insert this code:

<style type="text/css">
.ui-menu .ui-menu-item {
	font-size:xx-small;
}
</style>
<link type="text/css" href="/test/English/jQueryUI18/smoothness/jquery-ui-1.8.custom.css" rel="stylesheet" />
<script type="text/javascript" src="/test/English/Javascript/jquery-1.4.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/interaction.js"></script>
<script type="text/javascript" src="/test/English/Javascript/stringBuffer.js"></script>
<script type="text/javascript" src="/test/English/jQueryUI18/jquery-ui-1.8.custom.min.js"></script>
<script type="text/javascript" src="/test/English/Javascript/AutocompleteForPeoplePicker.js"></script>
<script type="text/javascript">
fields = init_fields();

// Find all users from userlist. Parameters "userListBaseUrl" and "userListGuid"
var allUsers = getUsers('','570D772F-0EAB-45A8-8C54-9CCD4EC6A0AF');

// Call with FieldInternalName of your people picker field(s)
$(document).ready(function(){
	peoplePickerAutoclomplete('MyPeoplePicker');
	peoplePickerAutoclomplete('AnotherPeoplePicker');	
});
</script>

Parameters explained:

  • userListBaseUrl: The base URL of the site the user list resides. If your site is in a managed path, it must reflect this managed path. If not, this parameter is most likely an empty string (“”)
  • userListGuid: The list Guid of the user list.

The sourcecode for the file “AutocompleteForPeoplePicker.js” looks like this:

/* Add autocomplete functionality to a SharePoint people picker
 * -----------------------------
 * Created by Alexander Bautz
 * alexander.bautz@gmail.com
 * https://spjsblog.com
 * v1.0
 * LastMod: 24.03.2010
 * -----------------------------
 * Must include reference to jQuery 1.4, jQuery UI 1.8 and to the folloving scripts:
 * ----------------------------------------------------
 * interaction.js - http://spjslib.codeplex.com/
 * stringBuffer.js - http://spjslib.codeplex.com/
 * ----------------------------------------------------
*/

function peoplePickerAutoclomplete(FieldInternalName){
if(typeof(fields)=='undefined')fields = init_fields();

var myPicker = $(fields[FieldInternalName]);
if(myPicker.find('div.ms-inputuserfield:visible').length>0){
	var ie=true; // Internet Explorer
	var toFind = 'div.ms-inputuserfield';
	var inputStyle = "margin:-1 0 -1 0;height:18px;font-family:Verdana,sans-serif;font-size:8pt;width:100%;display:none";

}else{
	var ie=false; // Firefox
	var toFind = 'textarea:first';
	myPicker.find('textarea:first').css({'height':'18px'});
	var inputStyle = "margin:1 0 1 0;height:18px;font-family:Verdana,sans-serif;font-size:8pt;width:100%;display:none";
}
	myPicker.find(toFind)
		.before("<input hiddenval='' style='"+inputStyle+"' id='"+FieldInternalName+"'/>")
		.focus(function(){
			$(this).hide().prev().show().focus();
		});

	// Add autocomplete
	$("#"+FieldInternalName).autocomplete({
			source: allUsers,
			select: function(event, ui) {
				fillPicker(ie,myPicker,FieldInternalName,ui.item.writeBackValue,ui.item.value);				
				return false;
			}		
		}).blur(function(){
			var currVal = $(this).val();
			var prevVal = $(this).attr('hiddenval')
			if(currVal!=''&&currVal!=prevVal){
				$(this).val($(this).attr('hiddenval'))
			}else if(currVal==''){
				fillPicker(ie,myPicker,FieldInternalName,'','');	
			}
			$(this).hide().next().show();
	});	
}

function fillPicker(ie,field,fin,loginName,dispName){
	if(ie){
		// IE
		field.find('.ms-inputuserfield').html(loginName);
		$("#"+fin).val(dispName).attr('hiddenval',dispName);
		field.find('img:first').click();
	}else{
		// FF
		field.find("textarea:first").val(loginName);
		$("#"+fin).val(dispName).attr('hiddenval',dispName);
	}
}

function getUsers(userListBaseUrl,userListGuid){
	var query = "<Where><And><IsNotNull><FieldRef Name='EMail' /></IsNotNull>" +
				"<Eq><FieldRef Name='ContentType' /><Value Type='Text'>Person</Value></Eq></And></Where>" +
				"<OrderBy><FieldRef Name='Title' Ascending='TRUE'/></OrderBy>";
	wsBaseUrl = userListBaseUrl + '/_vti_bin/';	
	var res = queryItems(userListGuid,query,['ID','Title','Name','EMail','ContentType']); 
    var ret = [];
    $.each(res.items,function(idx,item){ 	
    	ret.push({label:item['Title']+"<br>"+item['EMail']+"<br>"+item['Name'],value:item['Title'],writeBackValue:item['Name'],desc:'Test'});	
    });
    return ret;    
}

function init_fields(){
var res = {};
$("td.ms-formbody").each(function(){
if($(this).html().indexOf('FieldInternalName="')<0) return;
var start = $(this).html().indexOf('FieldInternalName="')+19;
var stopp = $(this).html().indexOf('FieldType="')-7;
var nm = $(this).html().substring(start,stopp);
res[nm] = this.parentNode;
});
return res;
}

Save as “AutocompleteForPeoplePicker.js”, mind the file extension, and upload to the script library as shown above.

I will update the article on Edit date, single line text, number or boolean columns directly in list view based on this script to allow setting a people picker field directly in a list view.

Ask is anything is unclear.

Regards
Alexander

31 Comments on “Autocomplete for SharePoint people picker

  1. This is a great design. I have played with it for a while but have been unsuccessful. I created a new list and am only trying to run this code. I have no errors, but no auto complete. I even copied your directory setup, but sitll not working. I have upgraded all jquery files and UI files. I have updated my listname with my user list ID.
    Any ideas?

    1. never mind, I just got it. I am not sure if this was my issue all the time, but I just updated my source link to a JS file and it works. sorry to bother you.

      great job!

  2. Alexander,

    I thought this seemed pretty cool so I thought I’d try it. I got it to work, but if you use the auto pick, then clear out the field and want to leave it blank instead it will not allow you to. Leave it to me to find an error! -Steve

    1. Alexander,

      Works perfect now! I also modified the js further to only show one of the fields for each entry instead of three. It makes the list quicker to pick through for me. Great work! -Steve

  3. Hi,

    Great post but I am curious to know what is the “User List” actually? Is it a list created by the users or some in-built list?

    1. Thanks I got it to that point. But still my autocomplete is not working…..I know it is difficult to tell from your end but what is the most common cause for not working?

  4. Hi, Alexander.

    Thanks for a arvelous collection of JS solutions. I just wanted to hint at the advantages of using regex in init_fields():

    var regex = /FieldName=”(.+)”s+FieldInternalName=”(.+)”s+/;
    var match = regex.exec(field.parent(“td.ms-formbody”).context.firstChild.nodeValue);
    var fieldTitle = match[0];
    var fieldInternalName = match[1];

    indexOf, 19, 7 and substring are no longer necessary then.

    1. Thank you for the tip, i have done very little with regex, but realize it is quicker and easier. I will make a post of a new init_fields() function and give you credit for the regex.

      Alexander

    1. Hi,
      The “People and groups” list is located at the root of your site collection. Any subsite must refer this list from the root.

      Go to the root of your site collection > go to the “People and groups” list > right click > view source > search for L_Menu_BaseUrl.

      The value for L_Menu_BaseUrl is your managed path “root”.

      Alexander

    2. Thanks for the speedy reply my L_Menu_BaseUrl = “”, so I put in my code “” too, but its still doesnt work and doesnt show any error

  5. My Mistake here is my whole code

    .ui-menu .ui-menu-item {
    font-size:xx-small;
    }

    fields = init_fields();

    // Find all users from userlist. Parameters “userListBaseUrl” and “userListGuid”
    var allUsers = getUsers(‘/testmode/’,’C62DCA67-AF39-4DAB-A5CD-DC2765838840′);

    // Call with FieldInternalName of your people picker field(s)
    $(document).ready(function(){
    peoplePickerAutoclomplete(‘tes’);

    });

  6. This looks awesome and exactly what I would like to incorporate into my environment. I’m a complete noob so I’m really sorry if these are silly issues….

    so I did what you suggested about testing the scripts here:
    https://spjsblog.com/2010/04/02/how-to-troubleshoot-when-the-scripts-does-not-work/

    and it seemed to work fine.

    but I still am not getting it to work on my new form.

    so I must be missing obvious changes. The name of my field is ‘RequestedBy’

    The user list I would like to use is from here:
    http://spservername/_catalogs/users/simple.aspx

    My list where the newform.aspx is on a subsite. What would the base URL be?

    Is this correct: those file names correct in the CEWP code because they weren’t in the downloads. I should change the thenm to 1.8.5 instead of 1.8?

    Also – I have other code on my CEWP:

    $(function() {
    $(‘td.ms-dttimeinput’).hide(); //hides the times on Start Time
    $(‘span[title=All Day Event] > input’).attr(“checked”,”checked”); // checks All Day Event
    //hide all of the check-boxes I don’t need
    $(‘tr:has(span[title=Recurrence])’).not(‘tr:has(tr)’).hide();
    $(‘tr:has(span[title=All Day Event])’).not(‘tr:has(tr)’).hide();
    $(‘tr:has(span[title=Workspace])’).not(‘tr:has(tr)’).hide();
    });

    is this a problem?

    Thanks

    1. Hi,
      If you download another version of the scripts and css you must update the CEWP link.

      To find the baseUrl for the user list, go to the list – view source and look for the variable L_Menu_BaseUrl.

      Alexander

  7. I tried out this script and it works great! How can we extend this script to make the same functionality available to textbox. For example: If a username column is created as single line of text in sharepoint list and would like to get the same funtionality to it.

    Also, currently the program gets users from user information list. Is it possible to get all the users (even if they are not present in user list)?

    Thanks in advance!

  8. Hi, Alexander: Great collection of solutions!

    Is there a way to point the AutoComplete lookup to the same domain lookup that the SharePoint people picker uses rather than the site’s user list? Only entries with email address should be available/visible.

    I have a project where we need users to fill in the ‘Manager Responsible’ required field as an email address and a workflow sends an email to that address. The issue is that the users aren’t validating the field before saving the form so in some cases user ID’s without email addresses are selected or the manager field does not resolve correctly and is saved as blank, hence no email is sent. The form still saves even though the field is required, and blank.

    Ideally, we need the form to not save until the field is truly validated, as any other well behaved required field would. A filtered auto completing people picker would go a long way to easing frustration as well. I’ve seen several auto complete solutions but they all seem to perform a lookup based on a list internal to the site, none perform a domain based lookup. We’d like to avoid using custom forms, unless it’s a last resort so your scripts are appealing.

    I’m not much of a coder, more of a hack, but I seem to be able to bumble my way through…

    ~Thanks

  9. Well done sir! Although the html in the dropdown wasn’t rendering for me. It literally shows tags so I modified your getUsers function to just show item[‘Title’] for the label.
    Thanks a lot for your work!

  10. Hi Alex,

    Amazing work, I just applied it on one of my forms, and its works great. It was not working initially cause I was trying to apply this to a customized form and when I actually used a CEWP on the default forms, it worked. I had to modify your js because I was able to see the HTML tags in the auto complete container.

    Thanks again for such a great solution.

    Regards,
    Waqas Iftikhar

    1. This solution is created for SP2007 and has not been tested in SP2010.

      I suspect it has to be modified to work in SP2010.

      Alexander

  11. HI Alex,
    I can find the BaseURL as you mentioned in your post, but I cannot find the userListGuid for the actual user list. I tried using the GUID of the list where this applies but it doesn’t work,

    If i view source on the user group in People and Groups, what should I look for?

  12. Hello Alexander,

    We want to use this solution together with the Tabs for SharePoint forms v2.2 (or later)

    But the autocomplete only works on the first tab not on the others

    Please advise.

    Kind regards,
    Mario

  13. Hi! I appreciate this solution and am trying to make it work. JQueryUI is up to version 1.10.2, and version 1.8 is not available anymore. The file configurations in 1.10 and 1.9 are different, so I’m not sure which files I need to point to. I have tried replacing

    jQueryUI18/smoothness/jquery-ui-1.8.custom.css

    with

    jquery-ui-1.10.2/themes/base/jquery.ui.autocomplete.css

    and replacing

    jQueryUI18/jquery-ui-1.8.custom.min.js

    with

    jquery-ui-1.10.2/ui/jquery.ui.autocomplete.js

    Is there something I can do to make this work with 1.10.2? Thanks very much.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.