People Picker customization in SharePoint 2010

If you are still stuck in 2010 land, this might help you. In one of my recent projects I had to customize the out of box people picker (multi user) in a custom visual web part  and the old faithful jQuery helped me out.

The requirement was to change the people picker from this :

To this:

The list of changes is really simple :

  1. Hide the image  .
  2. Move the browse image  above the text box.
  3. Add help text before the browse image  .

To start with, here is the  high level html structure which is rendered by the SharePoint for a multi user people picker :

<SPAN ....>
 <TABLE class=ms-usereditor ....>
 <TBODY>
 <TR>//TextBox</TR>
 <TR>//Row to display errors</TR>
 <TR>//Row with buttons </TR>
 </TBODY>
 </TABLE>
</SPAN>

I have removed all the metadata to highlight the structure. You can also access the complete structure here.

Also, if you have not looked at the complete structure, here is the highlight from the row with buttons to look at how the images are being rendered.

Once you have gone through the structure, you will realize that  hiding the check names image is easy as it can be selected by the img title tag and then hidden by jQuery.

 <1> $("img[title='Check Names']").hide();

Remember to limit the selector’s range by providing the div/table id which will contain the people picker to be changed as the script above will hide all images with title of ‘Check Names’ on the page.

For our second requirement, adding the text is also straight forward as SharePoint adds an empty cell before the check names and browse buttons, with a span. We can update the text in the span with our required help text and apply the CSS we want.

<1> var row = $("img[title='Check Names']").
closest('tr');
<2> row.find('td:first').find('span').
text('<Custom Text>');
<3> row.find('td:first').find('span').
addClass('<Custom CSS Class>');

For our third requirement, we need to move the last row containing buttons to the top of the text box i.e. move the last row to the top.

What we have currently have from the above script is a row object which is in a nested table in the last row. So the first task of action is to get the parent row object to work on, which can be done via:

 <1> var topRow = $(row).parentsUntil('tr');
 <2> topRow = topRow[topRow.length - 1];
 <3> topRow = $(topRow);
 <4> topRow = $(topRow.parent());

In the above script, the first line gets all the objects till the top level row (which will be TD since parentsUntil  only gets the objects till the parent without including the parent), line 2 gets the top object of this collection and then in line 3 we cast the object as a jQuery object. In line 4 we get the parent of the cell which is the row we need to push to top of the parent table.

Now we move this row to the top using :

topRow.prev().prev().before(topRow);

This will select the two previous objects (Row 2 and then Row 1) and move the row before the first row in the table.

The final structure changes to this:

<SPAN ....>
 <TABLE class=ms-usereditor ....>
 <TBODY>
 <TR>//Row with buttons</TR>
 <TR>//TextBox</TR>
 <TR>//Error Row</TR>
 </TBODY>
 </TABLE>
</SPAN>

You can download the complete script here : peoplepicker2010.js