Provira
Provira

Reputation: 11

People Picker on MSPO's "Create a new project" Page

I'm trying to create a People Picker field on MSPO's "Create a new project" Page.

I've been using the script in the following post to create People Picker fields within Project Detail Pages. This has worked very well.

People Picker in Microsoft Project Online

Now I'm trying to create a People Picker field on MSPO's "Create a new project" page. The issue I ran into was that all fields on the CreateProject.aspx page exist within an iframe, so the script couldn't find the desired "Project Sponsor" field.

I modified the script to look for the "Project Sponsor" field within a specified iframe ('iframe.pwa-animate-in'), and now it is able to find the field. However, when I test my script in the console, I receive the following error:

Uncaught TypeError: Cannot set properties of undefined 
(setting 'OnControlResolvedUserChanged')

"OnControlResolvedUserChanged" is undefined 
because "newPeoplePicker" is undefined. "newPeoplePicker" is undefined because 
"SPClientPeoplePickerDict" is undefined.

Why is "SPClientPeoplePickerDict" undefined?

<script>

$(document).ready(function () { ExecuteOrDelayUntilScriptLoaded(CustomAction, "sp.js"); });
function CustomAction() {

    // Set the following to be an array of fields you would like to change into a people-picker
    // Example: var targetFields = ['Custom Field'];
    var targetFields = ['Project Sponsor'];

    // Safely load JQuery
    if (typeof jQuery == 'undefined') {
        var s = document.createElement("script");
        s.src = '//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js';
        if (s.addEventListener) {
            s.addEventListener("load", function () { myJQueryCode() }, false);
        } 
        else if (s.readyState) {
            s.onreadystatechange = function () { myJQueryCode() };
        }
        document.getElementsByTagName('head')[0].appendChild(s);
    } 
    else {
        console.log('jQuery loaded');
        myJQueryCode();
    }

    var iframe = document.querySelector('iframe.pwa-animate-in');
    console.log('iframe found');
    var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
    console.log(innerDoc.body);
    if (innerDoc) {
        // Now search within the iframe's document using jQuery
        var $innerDoc = $(innerDoc); // Wrap the inner document with jQuery
        console.log('inner document wrapped with jQuery');
    } else {
        console.log('Could not access iframe content document.');
    }

    function myJQueryCode() {
        $(document).ready(function () {
            var scriptRoot = _spPageContextInfo.siteAbsoluteUrl + '/_layouts/15/';
            $.when(
                $.getScript(scriptRoot + "clienttemplates.js"),
                $.getScript(scriptRoot + "clientforms.js"),
                $.getScript(scriptRoot + "clientpeoplepicker.js"),
                $.getScript(scriptRoot + "autofill.js")
            )
            .done(function () {
                window.console && console.log('Scripts loaded');
                    console.log(scriptRoot + "clienttemplates.js");
                    console.log(scriptRoot + "clientforms.js");
                    console.log(scriptRoot + "clientpeoplepicker.js");
                    console.log(scriptRoot + "autofill.js");
                renderPeoplePickers();  
            })
            .fail(function (message) {
                window.console && console.error('Loading scripts failed: ' + message);
            });
        });
    }

    function renderPeoplePickers() {
        console.log('renderPeoplePickers called');
        for (var fieldIndex = 0; fieldIndex < targetFields.length; fieldIndex++) {
            if (typeof innerDoc == 'undefined') {
                $("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
                    console.log('Elements found');
                    this.style.color = "green";
                    console.log('Color defined');
                    renderPeoplePicker(this);
                    window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
                });
            } else {
                $innerDoc.find("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
                    console.log('Elements found');
                    this.style.color = "green";
                    console.log('Color defined');
                    renderPeoplePicker(this);
                    window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
                });
            }
        }
    }

    function renderPeoplePicker(targetInput) {  
        console.log(targetInput); // Check what is being logged
        var divPeoplePicker = document.createElement('div');
        var idPeoplePicker = targetInput.id + '_PeoplePicker';
        console.log('idPeoplePicker defined:', idPeoplePicker);
        var targetValue = $(targetInput).attr('value');
        divPeoplePicker.id = idPeoplePicker;
        $(targetInput).parent().append(divPeoplePicker);
        initializePeoplePicker(idPeoplePicker);
        console.log('this defined:', this);
        console.log('SPClientPeoplePicker defined:', SPClientPeoplePicker);
        console.log('SPClientPeoplePickerDict defined:', SPClientPeoplePicker.SPClientPeoplePickerDict);
        var newPeoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict[idPeoplePicker + '_TopSpan'];
        console.log('newPeoplePicker defined:', newPeoplePicker);
        $(targetInput).hide();
        console.log('hide targetInput');
        if (typeof targetValue !== "undefined") {
            console.log('targetValue undefined');
            var selectedUsers = targetValue.split(";");
            for(i=0;i<selectedUsers.length;i++) {
                if(selectedUsers[i] && selectedUsers[i] != "") {
                    newPeoplePicker.AddUnresolvedUser( {
                        Key: selectedUsers[i],
                        DisplayText: selectedUsers[i]
                    }, true);
                }
            }
        }

        newPeoplePicker.OnControlResolvedUserChanged = function () {
            console.log('newPeoplePicker called');
            if (this.TotalUserCount > 0) {
                var fieldVal = '';
                for(i=0;i<this.GetAllUserInfo().length;i++) {
                    // We have a resolved user
                    var resolvedUser = this.GetAllUserInfo()[i];
                    fieldVal = fieldVal + resolvedUser.DisplayText + ";";
                }
                // Set the underlying field value
                $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', fieldVal);
                // If value has changed then mark the PDP dirty to enable save
                // Thank you to Martin Laukkanen (nearbaseline.com) for this fix!
                if ($('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('origvalue') !== $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value')) {
                    WPDPParts[0].IsDirty = true;
                }
            } 
            else {
                // We have nothing - so clear out the target field
                $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', '');
            }
        }
    }

    // Render and initialize the client-side People Picker
    function initializePeoplePicker(peoplePickerElementId, defaultValue) {
        var users;
        if ((defaultValue != undefined) && (defaultValue != "")) {
            users = new Array(1);
            var defaultUser = new Object();
            defaultUser.AutoFillDisplayText = defaultValue;
            defaultUser.AutoFillKey = defaultValue;
            // defaultUser.Description = user.get_email();
            defaultUser.DisplayText = defaultValue;
            defaultUser.EntityType = "User";
            defaultUser.IsResolved = false;
            defaultUser.Key = defaultValue;
            defaultUser.Resolved = false;
            users[0] = defaultUser;
        } 
        else {
            users = null;
        }
        // Create a schema to store picker properties, and set the properties.
        var schema = {};
        schema['PrincipalAccountType'] = 'User';
        // schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
        schema['SearchPrincipalSource'] = 15;
        schema['ResolvePrincipalSource'] = 15;
        schema['AllowMultipleValues'] = false;
        schema['MaximumEntitySuggestions'] = 50;
        schema['Width'] = '360px';
        // Render and initialize the picker. 
        // Pass the ID of the DOM element that contains the picker, an array of initial
        // PickerEntity objects to set the picker value, and a schema that defines
        // Picker properties
        this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, users, schema);
    }

}

</script>

Upvotes: 1

Views: 47

Answers (1)

Provira
Provira

Reputation: 11

I was able to resolve this issue by adding the following steps to Integent's initial script (https://www.youtube.com/watch?v=cR0W4umH8ZU):

  1. Find the iframe within the page.
  2. Search for the desired field within the iframe.
  3. Wait for the iframe to load before running the code.
<script>

$(document).ready(function () { ExecuteOrDelayUntilScriptLoaded(CustomAction, "sp.js"); });
function CustomAction() {

    // Set the following to be an array of fields you would like to change into a people-picker
    // Example: var targetFields = ['Custom Field'];
    var targetFields = ['Project Sponsor'];

    // Safely load JQuery
    if (typeof jQuery == 'undefined') {
        var s = document.createElement("script");
        s.src = '//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js';
        if (s.addEventListener) {
            s.addEventListener("load", function () { myJQueryCode() }, false);
        } 
        else if (s.readyState) {
            s.onreadystatechange = function () { myJQueryCode() };
        }
        document.getElementsByTagName('head')[0].appendChild(s);
    }
    else {
        myJQueryCode();
    }

    // Find the iframe
    var iframe = document.querySelector('iframe.pwa-animate-in');
    // Search within the iframe's document using jQuery
    var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
    // Wrap the inner document with jQuery
    var $innerDoc = $(innerDoc);

    function myJQueryCode() {
        $(document).ready(function () {
            var scriptRoot = _spPageContextInfo.siteAbsoluteUrl + '/_layouts/15/';
            $.when(
                $.getScript(scriptRoot + "clienttemplates.js"),
                $.getScript(scriptRoot + "clientforms.js"),
                $.getScript(scriptRoot + "clientpeoplepicker.js"),
                $.getScript(scriptRoot + "autofill.js")
            )
            .done(function () {
                window.console && console.log('Scripts loaded');
                renderPeoplePickers();  
            })
            .fail(function (message) {
                window.console && console.error('Loading scripts failed: ' + message);
            });
        });
    }

    function renderPeoplePickers() {
        for (fieldIndex = 0; fieldIndex < targetFields.length; fieldIndex++) {
            // Ensure that the script will run regardless of whether an iframe exists
            if (typeof innerDoc == 'undefined') {
                $("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
                    this.style.color = "green";
                    renderPeoplePicker(this);
                    window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
                });
            }
            else {
                $innerDoc.find("input[type='text'][title='" + targetFields[fieldIndex] + "']").each(function () {
                    this.style.color = "green";
                    renderPeoplePicker(this);
                    window.console && console.log('PeoplePicker rendered: ' + targetFields[fieldIndex]);
                });
            }
        }
    }

    function renderPeoplePicker(targetInput) {
        var divPeoplePicker = document.createElement('div');
        var idPeoplePicker = targetInput.id + '_PeoplePicker';
        var targetValue = $(targetInput).attr('value');
        divPeoplePicker.id = idPeoplePicker;
        $(targetInput).parent().append(divPeoplePicker);
        initializePeoplePicker(idPeoplePicker);
        var newPeoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict[idPeoplePicker + '_TopSpan'];
        $(targetInput).hide();
        if (typeof targetValue !== "undefined") {
            var selectedUsers = targetValue.split(";");
            for(i=0;i<selectedUsers.length;i++) {
                if(selectedUsers[i] && selectedUsers[i] != "") {
                    newPeoplePicker.AddUnresolvedUser( {
                        Key: selectedUsers[i],
                        DisplayText: selectedUsers[i]
                    }, true);
                }
            }
        }
        newPeoplePicker.OnControlResolvedUserChanged = function () {
            if (this.TotalUserCount > 0) {
                var fieldVal = '';
                for(i=0;i<this.GetAllUserInfo().length;i++) {
                    // We have a resolved user
                    var resolvedUser = this.GetAllUserInfo()[i];
                    fieldVal = fieldVal + resolvedUser.DisplayText + ";";
                }
                // Set the underlying field value
                $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', fieldVal);
                // If value has changed then mark the PDP dirty to enable save
                // Thank you to Martin Laukkanen (nearbaseline.com) for this fix!
                if ($('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('origvalue') !== $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value')) {
                    WPDPParts[0].IsDirty = true;
                }
            } 
            else {
                // We have nothing - so clear out the target field
                $('input#' + (this.TopLevelElementId.split("_PeoplePicker_TopSpan")[0])).attr('value', '');
            }
        }
    }

    // Render and initialize the client-side People Picker
    function initializePeoplePicker(peoplePickerElementId, defaultValue) {
        var users;
        if ((defaultValue != undefined) && (defaultValue != "")) {
            users = new Array(1);
            var defaultUser = new Object();
            defaultUser.AutoFillDisplayText = defaultValue;
            defaultUser.AutoFillKey = defaultValue;
            // defaultUser.Description = user.get_email();
            defaultUser.DisplayText = defaultValue;
            defaultUser.EntityType = "User";
            defaultUser.IsResolved = false;
            defaultUser.Key = defaultValue;
            defaultUser.Resolved = false;
            users[0] = defaultUser;
        } 
        else {
            users = null;
        }
        // Create a schema to store picker properties, and set the properties
        var schema = {};
        schema['PrincipalAccountType'] = 'User';
        // schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
        schema['SearchPrincipalSource'] = 15;
        schema['ResolvePrincipalSource'] = 15;
        schema['AllowMultipleValues'] = false;
        schema['MaximumEntitySuggestions'] = 50;
        schema['Width'] = '360px';
        // Render and initialize the picker. 
        // Pass the ID of the DOM element that contains the picker, an array of initial
        // PickerEntity objects to set the picker value, and a schema that defines
        // Picker properties
        this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, users, schema);
    }

}

// Wait for the iframe to load
window.onload = function(){
    CustomAction();
};

</script>

Upvotes: 0

Related Questions