i need jquery to fire when people picker returns the value to the main form from the browse pop up window

StackOverflow https://stackoverflow.com/questions/7328016

Question

has anyone attempted trying to fire jquery change event when people picker returns the value to the main form from the pop up browse window? i have tried several tags in the jquery statement but nothing seems to work. (SP 2010)

<wssawc:PeopleEditor AllowEmpty="false" AcceptAnyEmailAddresses="true" ValidateResolvedEntity="true"
ShowButtons="true" ShowDataValidationErrorBorder="true" ShowEntityDisplayTextInTextBox="true"
ShowErrorPlaceHolder="true" ValidatorEnabled="true" MultiSelect="false" ID="primaryOwnerPicker"
runat="server" SelectionSet="User" Width="12em" AllowTypeIn="false" DoPostBackOnResolve="false"
EnableBrowse="true" ForceClaims="true" Title="Primary Owner People Picker" />

i have tried

$("textarea[title='Primary Owner People Picker']").change(function ()
{
    alert("here");
});

any help would be greatly appreciated...

Was it helpful?

Solution

You didn't specify the version of SharePoint but the following explanation applies to SharePoint 2007 and was not confirmed in 2010.

The people picker's value can be set by clicking the 'Check Names' icon or the 'Browse' icon.

If you click the 'Check Names' icon which is an anchor tag, the onclick event invokes 'WebForm_DoCallback' which will asynchronously make an HTTP request to the SharePoint server to validate the name entered into the people picker.

Following is the WebForm_DoCallback signature:

function WebForm_DoCallback(eventTarget, 
eventArgument, 
eventCallback, 
context, 
errorCallback, 
useAsync){
...
}

One of the WebForm_DoCallbacks argument that that you will be most interested in is 'eventTarget', the people picker text area. You will also be interested in 'eventCallback' as it's the callback method invoked after the async HTTP request returns. In this case, it's 'EntityEditorHandleCheckNameResult(result, ctx)' defined in core js.

Following is the definition of the EntityEditorHandleCheckNameResult function

function EntityEditorHandleCheckNameResult(result, ctx)
{
   EntityEditorClearWaitCursor(ctx);
   EntityEditorCallback(result, ctx);
} 

Notice that it delegates the event handling to the EntityEditorCallback method. This is also the case if you click the 'Browse' icon which opens a dialog for you to find and select a user. The 'Browse' icon obviously leverages a different call stack but as they both rely on EntityEditorCallback, I will focus on this method as the solution works when you click 'Check Names' or 'Browse'.

To execute your code after EntityEditorCallback is invoked, you can leverage the following code:

var invokeAfterEntityEditorCallback =  function(func) {
    var old__EntityEditorCallback = EntityEditorCallback;
    if (typeof EntityEditorCallback != 'function') {
        EntityEditorCallback = func;
    } else {
        EntityEditorCallback = function(result, ctx) {
            old__EntityEditorCallback(result, ctx);
        func(result, ctx);
        }
    }
};

Following is a custom people picker event handler which alerts the result and the ID of the people picker text area:

function onPeoplePickerFieldSet(result, ctx){
    alert(result);
    alert(ctx); 
}

Following is logic that will allow the onPeoplePickerFieldSet method to be invoked after the people picker name is checked or selected from the browse dialog. Also, this statement can be invoked in the document.ready event handler if you are using jQuery.

invokeAfterEntityEditorCallback(onPeoplePickerFieldSet);

The 'result' argument of the onPeoplePickerFieldSet method is an XML result indicating successful validation as well as the domain quailified user name. The following XML is an example resulting from click the 'Check Names' icon:

<Entities Append="False" Error="" Separator=";" MaxHeight="3">
   <Entity Key="HOLLOWAY\csteel" DisplayText="Craig Steel" IsResolved="True" Description="HOLLOWAY\csteel">
      <ExtraData>
         <ArrayOfDictionaryEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <DictionaryEntry>
               <Key xsi:type="xsd:string">DisplayName</Key>
               <Value xsi:type="xsd:string">Craig Steel</Value>
            </DictionaryEntry>
            <DictionaryEntry>
               <Key xsi:type="xsd:string">Email</Key>
               <Value xsi:type="xsd:string">csteel@holloway.net</Value>
            </DictionaryEntry>
            <DictionaryEntry>
               <Key xsi:type="xsd:string">SPUserID</Key>
                <Value xsi:type="xsd:string">16</Value>
            </DictionaryEntry>
            <DictionaryEntry>
               <Key xsi:type="xsd:string">PrincipalType</Key>
               <Value xsi:type="xsd:string">User</Value>
            </DictionaryEntry>
         </ArrayOfDictionaryEntry>
      </ExtraData>
      <MultipleMatches />
   </Entity>
</Entities>

The 'ctx' argument is the ID of the people picker text area and can be used in a jQuery selector statement.

That's it!

OTHER TIPS

I used the answer from Athens Holloway above, with a couple tweaks. My use case was excluding a particular user from the people-picker. You can exclude a user from people-picker using peoplepicker serviceaccountdirectorypaths on the central admin server, but for various change control reasons that wasn't an option for us. Adding Javascript to the one particular site let us get the job done without affecting the whole site collection.

This is the complete script that excludes a single user from the People picker:

  var peoplePickerCtx;

  var invokeAfterEntityEditorCallback =  function(func) {
    var old__EntityEditorCallback = EntityEditorCallback;
    if (typeof EntityEditorCallback != 'function') {
        EntityEditorCallback = func;
    } else {
        EntityEditorCallback = function(result, ctx) {
            old__EntityEditorCallback(result, ctx);
        func(result, ctx);
        }
    }
};

function onPeoplePickerFieldSet(result, ctx){
    // gets the long ID string of the people-picker control when the user touches the control
    if (result != undefined) {
      var checkThis = result.toString();
      peoplePickerCtx = ctx.toString();
    }
}

function userMessage (checkThis)
{
    if (checkThis.indexOf("USERNAME TO EXCLUDE GOES HERE") !=-1) 
    {
      alert ('That account is not valid YOUR ERROR MESSAGE GOES HERE')
      return false;
    }
    return true;
}

  function PreSaveAction() {
    // this is a standard function - give it this name and it runs pre-save
    var returnMe = false;

  // used simple getElementById instead of jQuery because it picks up what is actually in the blank. 
  // jQuery picked up the old value until after the user clicked CheckNames button
    var checkThis= document.getElementById(peoplePickerCtx+"_upLevelDiv").innerText.toLowerCase()
    if (checkThis!=undefined) 
    {
        returnMe = userMessage (checkThis)
    }

   return returnMe ;
  }; 


invokeAfterEntityEditorCallback(onPeoplePickerFieldSet);


</script>

Try this instead:

$("textarea[title='Primary Owner People Picker']").live(function ()
{
    alert("here");
});

And it would be helpful to understand your problem if you can post full html/js code.

How about this:

$("textarea[title='Primary Owner People Picker']").on('change', function ()
{
    alert('here');
});

Athen's answer worked like a charm for me. Since validation sometimes throws an error (like multiple matches to a name) I don't want to do my code to run until validation returns no errors. Unfortunately this requires users to click the validation button again after they select the correct name from the multiple returned. Here is just a little additional code I used to parse the result:

function onPeoplePickerFieldSet(result, ctx){
    xmlDoc = $.parseXML(result);
    $xml = $(xmlDoc)
    if($xml.find("Entities").attr("Error") == "")
    {
        getUserData($xml.find("Entity").attr("Key")); //this is the username
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top