how to trigger event on a People picker and retrieve its changed value.

Sep 9, 2014 at 2:16 PM
I am using SharePoint 2007 (MOSS), and loading successfully jQuery 1.10 and SP Services 2014.01

I am trying, without any luck, to first trigger a function on change in a people picker, second, get the value that was entered, thirdly will then do something with this information in a separate function. I have 7 people pickers on the page. I am not receiving any errors in my javascript. Your documentation is pretty clear on how to identify a people picker, but not very clear on how to get the value and how to trigger the change event on a People Picker the following is a snippet from my non-working code:
``` var CSMpplpkr = "";
var CSMselected = "";

$(document).ready(function(){

CSMpplpkr = $().SPServices.SPFindPeoplePicker({
peoplePickerDisplayName: "CSM"
});

$(CSMpplpkr).change(function() {
CSMselected = CSMpplpkr.CurrentValue;
alert("CSM selected: " & CSMselected);
//var CSMemployeeEmail = CSMpplpkr.dictionaryEntries[0].Email;
//var CSMemployeeLoginID = CSMpplpkr.dictionaryEntries[0].AccountName;
});
});

.........
Sep 9, 2014 at 4:33 PM
I am getting values when I look at them outside of the change event I was trying. To what element do you attach the change event in order to trigger and get the updated values. This is the following that is returning information for me now:
CSMpplpkr = $().SPServices.SPFindPeoplePicker({
  peoplePickerDisplayName: "CSM"
}); 
 alert(CSMpplpkr.currentValue);
 alert(CSMpplpkr.dictionaryEntries[0].Email);
 alert(CSMpplpkr.dictionaryEntries[0].SPUserID);
Sep 10, 2014 at 3:15 PM
To what element do you attach the jQuery change event in order to trigger and get the updated values? I have tried attaching it to the following, with no luck yet: "CSMpplpkr" element created by using $().SPServices.SPFindPeoplePicker, the hidden input areas, and the textarea. jQuery does not let you attach it to the div where the text appears. I have no problem getting the values from my CSMpplpkr element (as see n in last thred),I just need to attach a change event to it. Any insight on how to trigger a function on change in the above CSMpplpkr element would be most apprecaited. I am dealing with 7 people pickers on one page in SharePoint 2007.
Sep 11, 2014 at 12:43 AM
In watching this thread one thing jumps out to me: your assuming that Sharepoint's people picker widget actually triggers the event when it sets the value. That might not be the case. In javascript you can set the value of a input and not trigger it's change event. Actually: triggering the event needs to be an explicit action.

If you can prove/confrm that an event is not being triggered, then your only other alternative is to "monitor" the input for when the value changes. Meaning: check its value every x amount of milliseconds looking for a change.

If I get some time I'll try it out and see if I can get it to work give the approach I detailed above.

Good luck.


--
Paul T.

-- Sent from Mobile

Sep 11, 2014 at 3:36 PM
Edited Sep 12, 2014 at 3:07 PM
Thanks Paul, In the meantime, I found some promising script and explanations, that I think I'll be able to modify to my needs. The solution deals with the "EntityEditorCallback'. Solution provided by Athens Holloway at Stackoverflow http://stackoverflow.com/questions/7328016/i-need-jquery-to-fire-when-people-picker-returns-the-value-to-the-main-form-from I'll let you know what I come up with.
Sep 12, 2014 at 3:17 PM
By using the code that I found at Stackoverflow, I was able to effectively identify non-resolved people pickers on my page. It was in the function "onPeoplePickerFieldSet" that I was able to add my needed functionaility. I have one more function to create that will enable/disable the OK/Save/Check-In button based on the outcome of the resolved People pickers, however in that function I will resort back to using the elements created by using $().SPServices.SPFindPeoplePicker in that function's 'if' statements.

//------from stackoverflow.com/questions/7328016/i-need-jquery-to-fire-when-people-picker-returns-the-value-to-the-main-form-from
//-------------------code To execute after EntityEditorCallback is invoked-------
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);
    var subStr = 'IsResolved\=\"True\"'; //used this as my qualifier for resolved names in returned EntityCallback for people pickers
    if(result.indexOf( subStr ) === -1 ){
        //alert("entity is not resolved");
        //-----------outline td for unresolved people picker
        $("#"+ctx).closest("td").css("border","3px solid red");
    }else{
        //alert("entity is resolved");
        //-----------remove outline around td for resolved people picker
        $("#"+ctx).closest("td").css("border","none");
    }
    //---- place a call to enable or disable the OK or Check-in button if people pickers are empty
}
//-----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. This is used on page load too.
invokeAfterEntityEditorCallback(onPeoplePickerFieldSet);
Jan 13, 2015 at 5:42 PM
Hi John. I tried your idea but nothing happens, other than the one alert ("here);

My peoplepicker is called "Person" and here is what I used. You say this works for you?
<script src="/commonwebsol/templates/wet-boew-v3.0/build/js/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://some_site/jQuery/jquery.SPServices.min.js"></script>
<script type="text/javascript">

alert ("here");
var CSMpplpkr = ""; 
var CSMselected = ""; 

$(document).ready(function(){ 

CSMpplpkr = $().SPServices.SPFindPeoplePicker({ 
peoplePickerDisplayName: "Person" 
}); 

//------from stackoverflow.com/questions/7328016/i-need-jquery-to-fire-when-people-picker-returns-the-value-to-the-main-form-from
//-------------------code To execute after EntityEditorCallback is invoked-------
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);
    var subStr = 'IsResolved\=\"True\"'; //used this as my qualifier for resolved names in returned EntityCallback for people pickers
    if(result.indexOf( subStr ) === -1 ){
        //alert("entity is not resolved");
        //-----------outline td for unresolved people picker
        $("#"+ctx).closest("td").css("border","3px solid red");
    }else{
        //alert("entity is resolved");
        //-----------remove outline around td for resolved people picker
        $("#"+ctx).closest("td").css("border","none");
    }
    //---- place a call to enable or disable the OK or Check-in button if people pickers are empty
}
//-----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. This is used on page load too.
invokeAfterEntityEditorCallback(onPeoplePickerFieldSet);

}); // End $(document).ready

</script> 
I cant beleive it's this much work and research just to retreive some simple information. I could've manually inserted the info for all our people using the time I've wasted on the internet researching this.

CW
Jan 13, 2015 at 6:53 PM
Hi Carl,
As you have discovered, it is an arduous process to get everything working and I had added extra requirements to get my stuff to work. I was also dealing with mutliple people pickers at once on the form and needed to capture both on page load, and on change. Do keep in mind, the code below was for a MOSS environment. Hope the following is of some help to you. What is below was very specific to my pickers and form validation requirements.

1) I always check with an alert, just inside the document ready function, to ensure my references to jquery and spservices are correct first.
2) I then as you saw in the above code declared my people picker with the following as you did.
var CSMpplpkr = $().SPServices.SPFindPeoplePicker({peoplePickerDisplayName: "CSM"});
var CSMDirpplpkr = $().SPServices.SPFindPeoplePicker({peoplePickerDisplayName: "CSM Director(s)"});
var Adjudpplpkr = $().SPServices.SPFindPeoplePicker({peoplePickerDisplayName: "Adjudicator for Credit Request"});
var GRMdirpplpkr = $().SPServices.SPFindPeoplePicker({peoplePickerDisplayName: "GRM Director"});
var GRMVPdirpplpkr = $().SPServices.SPFindPeoplePicker({peoplePickerDisplayName: "GRM VP"});
var BusHeadspplpkr = $().SPServices.SPFindPeoplePicker({peoplePickerDisplayName: "Business Head(s)"});
var OtherCCpplpkr = $().SPServices.SPFindPeoplePicker({peoplePickerDisplayName: "Other CC Email Recipient(s)"});
I then mostly employed what you saw from stack overflow with addtional validation on whether the picker had been resolved or not, with a call back out to my own function(s) for checking the people pickers . The stackoverflow stuff was primarily for page load and on action after resolving a name and styling and enabling/disabling save/OK as needed. I did move the 'invokeAfterEntityEditorCallback function to another area so it was not invoked too many times:
    //------------  stuff from stack overflow.com/questions/7328016/i-need-jquery-to-fire-when-people-picker-returns-the-value-to-the-main-form-from. This gets invoked on load  and confirm also -------
    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){
        //alert("result is"+result);
        var subStr = 'IsResolved\=\"True\"';
        if(result.indexOf( subStr ) == -1 ){
            $("#"+ctx).closest("td").css("border","3px solid red");
            disableOK();
        }else{
            $("#"+ctx).closest("td").css("border","none");
            $("#"+ctx).closest("td").css("border-top","1px solid #e08d53");
            CheckAllPplPkrFields();
        }
    }
    //invokeAfterEntityEditorCallback(onPeoplePickerFieldSet); //---you would need to uncomment this line and use approprietely.
    //------------  end of stuff from stack overflow
    //----------- on my second ppl pkr field in form if changed, grab display names and populate the input field CSMDirectorsNames--------------
    $("textarea[title='People Picker']:eq(1)").change(function(){
        var pplpkrCSMDirNames = CSMDirpplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        alert(pplpkrCSMDirNames);
    });
I then added another function to invoke when someone actually typed something into the fields and needed to trigger on that action, versus page load. As the People picker does not actual use a text field for entry but an editable div, I had to bind event on focus of any of my picker editable divs as such :
//------------ function to bind Focus on editable people picker divs and trigger change event if before and after values do not match ------
    $("div").on('focus', '[contenteditable]', function(){
        var pplpkrfield = $(this);
        pplpkrfield.data('before', pplpkrfield.html());
        return pplpkrfield;
    }).on('blur', '[contenteditable]', function(){
        var pplpkrfield = $(this);
        if (pplpkrfield.data('before') !== pplpkrfield.html()){
            pplpkrfield.data('before', pplpkrfield.html());
            pplpkrfield.trigger('change');
        }
        //alert("you typed "+pplpkrfield.text());
        var HTMLofpplpkrDiv = pplpkrfield.parent().html();
        //alert("HTMLofpplpkrDiv is "+HTMLofpplpkrDiv);
        var InputsubStr = 'isresolved\=\"True\"'; //property to check for
        //alert("InputsubStr is "+InputsubStr);
        var pplpkrID = pplpkrfield.attr('id');
        //alert("pplpkrID is "+pplpkrID);
        var pplpkrTD = $("#"+pplpkrID).closest("td.ms-formbody");
        if(HTMLofpplpkrDiv.indexOf(InputsubStr) == -1 ){
            pplpkrTD.css("border","3px solid red");
            disableOK();
        }else{
            pplpkrTD.css("border","none");
            pplpkrTD.css("border-top","1px solid #e08d53");
            CheckAllPplPkrFields();
        }
        return pplpkrfield;
    });
And then my other functions which might be useful for you: I then created a further function to check the fields and then either re-enable my save/OK button. I was checking if names selected were resolved or not in each of the pickers:
function CheckAllPplPkrFields(){
        var CSMpplpkrResolvedTtl=CSMpplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        //alert("CSMpplpkrResolvedTtl is "+CSMpplpkrResolvedTtl);
        var CSMDirpplpkrResolvedTtl=CSMDirpplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        //alert("CSMDirpplpkrResolvedTtl is "+CSMDirpplpkrResolvedTtl);
        var AdjudpplpkrResolvedTtl=Adjudpplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        //alert("AdjudpplpkrResolvedTtl is "+AdjudpplpkrResolvedTtl);
        var GRMdirpplpkrResolvedTtl=GRMdirpplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        //alert("GRMdirpplpkrResolvedTtl is "+GRMdirpplpkrResolvedTtl);
        var GRMVPdirpplpkrResolvedTtl=GRMVPdirpplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        //alert("GRMVPdirpplpkrResolvedTtl is "+GRMVPdirpplpkrResolvedTtl);
        var BusHeadspplpkrResolvedTtl=BusHeadspplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        //alert("BusHeadspplpkrResolvedTtl is "+BusHeadspplpkrResolvedTtl);
        var OtherCCpplpkrResolvedTtl=OtherCCpplpkr.row.find("span[class='ms-entity-resolved']").attr("title");
        //alert("OtherCCpplpkrResolvedTtl is "+OtherCCpplpkrResolvedTtl);
            if(CSMpplpkrResolvedTtl == undefined || CSMDirpplpkrResolvedTtl == undefined || AdjudpplpkrResolvedTtl == undefined || GRMdirpplpkrResolvedTtl == undefined || GRMVPdirpplpkrResolvedTtl == undefined || BusHeadspplpkrResolvedTtl == undefined || OtherCCpplpkrResolvedTtl == undefined ){
                alert("To ensure proper routing of emails in the authorization process, please select at least one recipient for each role.");
                disableOK();
            }else if(CSMpplpkrResolvedTtl != undefined && CSMDirpplpkrResolvedTtl != undefined && AdjudpplpkrResolvedTtl != undefined && GRMdirpplpkrResolvedTtl != undefined && GRMVPdirpplpkrResolvedTtl != undefined && BusHeadspplpkrResolvedTtl != undefined && OtherCCpplpkrResolvedTtl != undefined ){
                enableOK();
            }
        }

//------------ function to  enable OK/Check-In/Save button ----------
    function enableOK(){
        $("input:button[value='OK']").attr('disabled', false);
        $("input:button[value='Check In']").attr('disabled', false);
        $("input:button[id$='_diidIOSaveItem']").attr('disabled', false);
        if ($("input:checkbox[title='Credit Request']").is(':checked')){ 
    var currentCSMDirNames = $("div[title='People Picker']:eq(1), input[id$='_HiddenUserFieldValue']:first").text(); //getting value of this field
    //alert("currentCSMDirNames is "+currentCSMDirNames);
    var currentTextInputCSMDirNames = $("input[title='CSM Director Names']").val(); //comparing against normal input box
    //alert("currentTextInputCSMDirNames is "+currentTextInputCSMDirNames);
    if (currentTextInputCSMDirNames !== currentCSMDirNames){
        $("input[title='CSM Director Names']").val(currentCSMDirNames); //copying value if not equal
    }
       }    
    }
//------------ function to  disable OK/Check-In/Save button ----------
    function disableOK(){
        $("input:button[value='OK']").attr('disabled', true);
        $("input:button[value='Check In']").attr('disabled', true);
        $("input:button[id$='_diidIOSaveItem']").attr('disabled', true);
    }
Jan 13, 2015 at 7:22 PM

Thanks John, I’ll endeavor to whittle it down to my one lonely plppkr. J

I do appreciate your assistance in this matter.

Carl