Tuesday, February 14, 2017

Set initial value to Sharepoint people picker via javascript

Suppose that in our Sharepoint Online site we want to use Azure groups for configuring permissions on securable objects (sub sites, document libraries, etc.) and that all Azure groups’ names start with common prefix “azure_” which is set as part of naming convention used in the company. In this case users will always need to type this prefix in people picker each time they want to grant permissions to some Azure group. Is it possible to help them and set common prefix as initial value of people picker? Yes, it is possible with using the following trick:

   1: var peoplePickerUtility = {
   2:  
   3:     isPeoplePickerOpened: false,
   4:     isPeoplePickerChanged: false,
   5:  
   6:     addPrefixToPeoplePicker: function() {
   7:         if (window.location.href.toLowerCase().indexOf("/user.aspx") < 0) {
   8:             return;
   9:         }
  10:  
  11:         setTimeout(function(){
  12:             try {
  13:                 if (typeof(SPClientPeoplePicker) != "undefined" &&
  14: $("#" + SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePicker_TopSpan.EditorElementId).is(":visible")) {
  15:                     peoplePickerUtility.isPeoplePickerOpened = true;                    
  16:                 }
  17:                 else {
  18:                     peoplePickerUtility.isPeoplePickerOpened = false;
  19:                     peoplePickerUtility.isPeoplePickerChanged = false;
  20:                 }
  21:                 
  22:                 if (peoplePickerUtility.isPeoplePickerOpened &&
  23:                         !peoplePickerUtility.isPeoplePickerChanged) {
  24: $("#" + SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePicker_TopSpan.EditorElementId).val("azure_");
  25:                     peoplePickerUtility.isPeoplePickerChanged = true;
  26:                 }
  27:                 
  28:                 peoplePickerUtility.addPrefixToPeoplePicker();
  29:             }
  30:             catch(e) {
  31:                 console.log("Error in peoplePickerUtility.addPrefixToPeoplePicker: " + e.message);
  32:             }
  33:         }, 1000);
  34:     }
  35: };
  36:  
  37: $(function() {
  38:     peoplePickerUtility.addPrefixToPeoplePicker();
  39: });

The idea is that we run function the loop each 1 sec (line 11) which checks whether people picker is opened via SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePicker_TopSpan object. If it is visible it sets its initial value (“azure_”) and sets flag which says that it is already changed (line 25), so it won’t change it twice once it is opened and override value added by user. If people picker will be closed and opened again, it will set initial value again. This code works only on granting permissions page (user.aspx) in order to not affect whole site. Of course this is not perfect solution, but it works. After that people picker will have “azure_” text as initial value:

Hope that this information will help someone.

Friday, February 3, 2017

Improve Yammer embed feed performance on Sharepoint Online

Yammer embed feed is often added to the front page of the company intranet in Sharepoint. From one side it adds value to customers as users may see corporate feed together with other important content on the same page. From other side it adds drawback: increase of the total page load time (by total time I mean time needed for both server and client side components. Yammer adds more time to the client part). We measured that Yammers adds ~3-4 seconds to the scripting part of the page load time. Is there a way to improve situation?

Let’s check how Yammer embed feed is added on the page. In most cases it is added via Content editor web part and the following code:

   1: <!DOCTYPE HTML>                                          
   2: <html>
   3:     <head></head>
   4:     <body>
   5:         <script type="text/javascript"
   6: src="https://c64.assets-yammer.com/assets/platform_embed.js"></script>
   1:                                                   
   2:         <div id="embedded-feed" style="height:1000px;width:400px;"></div>
   3:         <script>
   4:             yam.connect.embedFeed({"config": { "header": false },
   5:                 "container": "#embedded-feed",
   6:                 network: 'example.com' });
   7:             $(window).load(function () {
   8:                 $('.frontpage #embedded-feed').width('100%');
   9:             });
  10:         
</script>
   7:     </body>
   8: </html>

As you can see script is loaded from Yammer CDN https://c64.assets-yammer.com/assets/platform_embed.js. So the first thing I tried was to move this script to the Sharepoint doclib, but it didn’t give visible results (internally this script loads a lot of other scripts and css files from CDN and also adds iframe dynamically).

After that I tried to use another approach which gave some results. First of all create new page (e.g. yammer.aspx) in Pages doclib and detach it from Page layout via Sharepoint Designer. After that remove all code from there and add only Yammer code shown above.

Then we need to modify the page where we show embed Yammer feed: instead of Content editor web part which was used for Yammer initially we will use Page viewer web part and configure it to use newly created page yammer.aspx as a source (that’s why we needed to detach this page from page layout – it should not contain any UI elements like headers, navigation, etc. It should only contain Yammer widget). I.e. after that page will look the same, but technically there is difference how Yammer is shown there. Now Yammer is shown in sub page via iframe in separate http request and its scripts not affect load of basic page. At least for us after that our testing showed that scripting time was reduced on ~2 seconds. Hope that information will be helpful for you.