JavaScript

What will the future of development in SharePoint look like? Pretty much like it does now!

Managing the lifecycle of the components you build, deploy, operate and support on Office 365 is difficult. The platform is new, the cloud is new, and much of your classic DTAP model is simply no longer appropriate. We at Rapid Circle are committed, for some time now, as being a Microsoft Cloud company rather than just a SharePoint company and the recent developments around SharePoint announced at the Future of SharePoint event on May 4th continue to vindicate our stance.

Specifically, the announcement of an upcoming SharePoint Framework (SPFx) makes it clear that client-side development and the use of JavaScript are encouraged and promoted for custom solutions on Office 365!

Some key aspects relevant for developers and administrators that we found very interesting were

  • The framework is fully JavaScript based model.
  • There is no single JavaScript framework mandated. We can still use popular frameworks such as Angular, Knockout and Handlebars.
  • Node.js & Gulp tasks are used for packaging deploying components.
  • The Local development model is going to be very different. A SharePoint workbench is introduced where Gulp and node.js will used to host files locally, so you don’t need to use IIS on your local machine.
  • Visual Studio Code, an open source code editor is being promoted as the preferred tool. Also clearly indicating that Visual Studio is not a must-have requirement for developers.

It's important to note that SPFx not a radically new model. The framework might be new, but we've been doing client-side development for some years now using similar frameworks. Finally though, Microsoft is creating this framework which leverages techniques we already use such as CSOM, REST API's. Taking it a step further Microsoft is openly embracing open source technologies such as node.js, Gulp, Yeoman and more.

Our Rapid ALM tooling is very much aligned to what Microsoft has described in the event. It’s a development & delivery model that’s entirely JavaScript based and enables us to streamline everything from the core development of our Instant Intranet components, integrated with our test teams, and deploying to our client tenants. Furthermore, it’s built on and resides in the SharPoint online platform.

Using Rapid ALM to evolve our Instant Intranet solution we are also “early adopters" for Visual Studio Code as the default editor for our apps development where we use Angular 1.4, Require JS. Moreover, we utilize NPM and Gulp for building, packaging and deploying our Instant intranet apps. Finally we use Git for source code control & versioning.

Future of SharePoint Development model
Future of SharePoint Development model

With this development model, we have successfully created and setup intranet for customers in the first quarter of 2016.  This new development model in SharePoint is giving us the platform for Rapid and Instant service to our customers.

And we're looking forward to the upcoming SharePoint Framework and will continue to evolve & enhance our own to software development lifecycle!

This blog post is part of the series Future of SharePoint. More on this topic can be found at http://08b.4d7.myftpupload.com/tag/FutureOfSharePoint/

SharePoint 2013: Display a User with Presence Indicator in a Custom WebPart

When building a custom WebPart that displays users, I wanted to show the Users as displayed in the people Search. screen1

Just a Picture with a small Presence indicator stroke on the left side. This is how Lync shows users as well. It's possible to use SharePoint JS functions to Render a User like this.

Getting User Data

To render a User the SharePoint 2013 way we need some Contextual Information about the User we want to display. For showing Presence we need the User’s SipAddress. Besides that I want to show the Profile Picture and the Preferred Name. With the new Search REST Api there are lots of easy ways to do this. In this example I'm using Search to retrieve some users based on a Profile Property. My REST Url is as follows:

"https://casvaniersel.sharepoint.com/_api/search/query?querytext='Department=ICT'&sourceid='b09a7990-05ea-4af9-81ef-edfab16c4e31'&rowlimit='100'&selectproperties='FirstName, LastName, PictureURL, SipAddress, PreferredName, WorkEmail'"

I'm looking for people that have their Department property filled with "ICT". The sourceid is the GUID of the Default Result Source "Local People Results" (This is a fixed GUID same for On Prem and SharePoint Online). With selectproperties I can indicate what I want to get back from Search.

Handle Search Results from REST

The result object is a very complex object that needs some parsing. Even when using selectproperties, still some overhead is coming into the results. To get the correct Values based on the Fieldnames we can use the jQuery.grep() function to query the object array and get back the correct values. I use this function:

getValueByKey: function (key, results) { var postItem = jQuery.grep(results, function (e) { if (e.Key === key) return e; })[0].Value;

return postItem; }

The results argument is the Object Array that holds the results, the key argument is the Property Name of which we need the Value.

Next: Create a User Context

To render the User I use a SharePoint function "RenderUserFieldWorker(renderCtx, fieldSchemaData, userData, listSchema)". This function is available in the clienttemplates.js. First we have to Ensure that script file and then create the rendering. This script makes sure everything is in place.

EnsureScriptFunc("clienttemplates.js", "RenderUserFieldWorker", function () { ULS2Vv:; //Parse Results var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results; for (i = 0; i < results.length; i++) { //Get the correct properties var item = results[i]; var itemCell = item.Cells; var itemResults = itemCell.results; //Get Values for User var sip = getValueByKey("SipAddress", itemResults); var userPic = getValueByKey("PictureURL", itemResults); var fullname = getValueByKey("PreferredName", itemResults); var lastname = getValueByKey("LastName", itemResults); var email = getValueByKey("WorkEmail", itemResults); //Use SharePoint Render Template to render User with Presence var renderCtx = new ContextInfo(); renderCtx.Templates = {}; renderCtx.Templates["Fields"] = {}; var fieldSchemaData = { "PictureOnly": "1", "PictureSize": "Size_72px" }; var listSchema = { "EffectivePresenceEnabled": "1", "PresenceAlt": "User Presence" }; var userData = { "title": fullname, "email": email, "picture": userPic, "sip": sip }; var user = RenderUserFieldWorker(renderCtx, fieldSchemaData, userData, listSchema); } //Enable Presence ProcessImn(); )};

The variable user now contains the HTML to render a User’s profile picture with the Presence Stroke. The final step to activate the Presence is the function ProcessImn(). That function makes sure that all Presence Controls on the Page are showing the latest status.

The Presence only becomes available when you have Lync setup correctly. For Office 365 use the Desktop Setup to accomplish this. https://portal.microsoftonline.com/OLS/mysoftware.aspx?source=ehome

Download a complete example right here!

JSLink with Paging for Rendering List Views

Today I dove into JSLink. There are many BlogPosts on how it works but none were showing how I can implement the SharePoint paging that is part of a SharePoint List View. It's surprisingly easy! I started with this BlogPost to figure out how this JSLink property works: http://www.idubbs.com/blog/2012/js-link-for-sharepoint-2013-web-partsa-quick-functional-primer/

Custom Item Rendering

When you just want to change the rendering of the Fields inside the View, the paging section will still be on the Page because it's rendered in the Footer. However if you want to use custom rendering for all Items including Header and Footer, you'll have to implement paging yourself.

Luckily all the data we need to provide Paging in the likes of the default Paging is in the Context. We need to read from ctx.ListData in our render function. ListData contains the following properties:

  • ctx.ListData.FirstRow;
  • ctx.ListData.LastRow;
  • ctx.ListData.PrevHref;
  • ctx.ListData.NextHref;

This is all the information we need. We can render the HTML ourselves in the Footer of the Template. An example:

pagingControl: function (ctx) { var firstRow = ctx.ListData.FirstRow; var lastRow = ctx.ListData.LastRow; var prev = ctx.ListData.PrevHref; var next = ctx.ListData.NextHref; var html = "<div class='Paging'>"; html += prev ? "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='" + prev + "'><span class='ms-promlink-button-image'><img class='ms-promlink-button-left' src='/_layouts/15/images/spcommon.png?rev=23' /></span></a>" : ""; html += "<span class='ms-paging'><span class='First'>" + firstRow + "</span> - <span class='Last'>" + lastRow + "</span></span>"; html += next ? "<a class='ms-commandLink ms-promlink-button ms-promlink-button-enabled' href='" + next + "'><span class='ms-promlink-button-image'><img class='ms-promlink-button-right' src='/_layouts/15/images/spcommon.png?rev=23'/></span></a>" : ""; html += "</div>"; return html; }

The complete rendering JS template can be downloaded here. Just upload the JS file to a Library and refer from a Blogs Posts list View WebPart to the js file. The JS file is set to render BaseViewID = 1 which is AllPosts.aspx.

Note: For this example to work, add the Field "Body" to the View Note: You can use the ~sitecollection token in the JSLink property.

Result

Before:

Schermafbeelding 2013-02-18 om 16.06.20

After:

Schermafbeelding 2013-02-18 om 16.14.37

SharePoint Apps and Relative DateTime

When working with Apps, JSOM and the new SharePoint REST API there's always a challenge when it comes to displaying moments in time or dates. New in SharePoint 2013 is the display of Time Delta's like "A moment ago" or "2 days ago". The Newsfeed is a good example of this.

ISO8601 standard

SharePoint 2013's new cool REST API returns DateTime field values in ISO8601 format. This can be a value in the likes of "2013-01-29T13:37:00Z". Unfortunately there is no helper function (or I haven't found it yet) in the SharePoint JS Object Model to parse this format into a Time Delta.

Moment.js

This is where a tiny, free JavaScript library called moment.js comes in handy. With these very simple lines of code this library gives you the right output.

var spDate = "2013-01-29T13:37:00Z"; var deltaToNow = moment(spDate, "YYYY-MM-DDTHH:mm:ss Z").fromNow();

Displaying deltaToNow will output the relative value from the given date till the moment of execution.

Cheers!

Loading JS files in a SharePoint Online Environment

For any of you that don't follow Wouter van Vugt, he had a great session at the Dutch SPC a while ago about loading JavaScript files in an On Premise SharePoint 2010 Environment. Very cool solutions were discussed however none of them are applicable when having a SharePoint Online environment. It's true the possibilities are very limited but still some cool techniques can be used to keep amount of scripts loading down to an acceptable level.

ScriptLink

The easiest way to add script to your page from a feature is to use the ScriptLink. By default this control is on every SharePoint Masterpage and by using a <CustomAction> a script can easily be added to the page without the need of changing the MasterPage or Page Layout. The Custom Action to do this can look like this:

<CustomActionLocation="ScriptLink" ScriptSrc="~SiteCollection/Scripts/jquery-1.6.min.js" Sequence="105" />

This example loads the jQuery library to the page. This approach is a nice one to load Shared Libraries (like jQuery) on every page. Even on the system pages based on the default v4.master the jQuery library is loaded because of this Custom Action. That is an important consideration whether to use this in your solution or not.

ScriptTag

Using the HTML tag <script/> is a good way to always load a script. Actually the SharePoint ScriptLink also renders a <script/> tag eventually. However for this approach the MasterPage needs to be updated and if you want your script to load on system pages (Forms, Views etc.) you also have to edit the default MasterPage which is not a best practice.

Script On Demand

A good way of loading scripts is only load them when you are actually gonna use them. The SharePoint Client OM accommodate you with the SP.SOD (Script On Demand) class. With a few steps we implement this:

1) Deploy your script using a Module (i.e. to the folder '/Scripts/MyFile.js')

2) In the MyFile.js file at the bottom add "SP.SOD.notifyScriptLoaded('MyFile.js');"

3) On the page where the call to this script is made add "SP.SOD.registerSod('MyFile.js', '/Scripts/MyFile.js');"

4) When the script is needed make a function call like this "SP.SOD.execute(MyFunc, 'MyFile.js');"

Now the SP.SOD.execute will make sure the Function is execute after the MyFile.js is loaded. At PageLoad this script is not loaded this way.

Script Storage

Because SharePoint Online is bound to SiteCollection level and because we are not able to write to the _layouts folder on the server, the storage of all Script files is important to think about. The logical place after _layouts would be in the Style Library, but there the possibility exist that user are going to mess up your code. In a SharePoint Online environment we can never cover this entirely but a more secure location to store your script would be just in a Folder of the RootWeb. Then people can only touch your code using SP Designer which is more difficult to most users.

Minify your scripts

In order to keep the JS files to a minimum, don't create too much different JS files and remember to Minify them. The nice VS add-on from Mavention is a very powerful tool to get this done. http://visualstudiogallery.msdn.microsoft.com/04ef7cbc-23dd-49f8-b4a2-ab87885ad065

Get User Information from Client OM (JS)

When I was exploring the possibilities to read from a User Profile in a SharePoint Online environment I realized there are lots of properties that are being synced back to the UserInfoList, but only when they are filled in the User Profile.

User Info List

We know by now it's impossible from a Sandboxed Solution (or Client Side OM Solution) to access a Users Profile directly as you would in a On-Premise environment. Our scope is the SiteCollection that runs our custom code. In that scope there is one important resource we can use to get information about a User, the UserInfoList. The list contains some Properties that are populated by the SharePoint Profile. So somehow this is synced.

Synced Properties

The synchronization process is done (On-Premise) by a TimerJob called: "User Profile Service Application - User Profile to SharePoint Full Synchronization". This TimerJob normally runs "Hourly". I didn't test this out but my guess is that this will be the case with SharePoint Online too. The important part being that there is a delay in this procedure. That being said, which properties of the User Profile are being synced by this TimerJob?

Property StaticName (Client OM) Returns
Account name Name domainierselca or claim
User name UserName ierselca
Name (DisplayName) Title Cas van Iersel
First name FirstName Cas
Last name LastName van Iersel
Title JobTitle SP Consultant
Email EMail cas@rapidcircle.com
Work phone WorkPhone 0123456789
Mobile phone MobilePhone 0123456789
Picture Picture http://linktoimage *
Department Department R&D
About me Notes Inner HTML of About field as a string
Web site WebSite http://mywebsite.com *
SIP SipAddress sip format string
Office Office Rapid Circle
Ask me about SPSResponsibility SharePoint, C#, ASP
If User Is Site Admin IsSiteAdmin true | false

* You'll need to do .get_url() on the return object

This is an example on how to get the information based on the UserID in the Context of the current web (You can obtain this from the SPUser object or use javascript to get from a people link "person.aspx?ID={UserID}":

//Get the Context, Web and SiteUserInfoList for User Info var clientContext = SP.ClientContext.get_current(); var web = clientContext.get_web(); var collListItem = web.get_siteUserInfoList().getItemById(userID);

//Load the objects async clientContext.load(collListItem); clientContext.executeQueryAsync( Function.createDelegate(this, function(){ //Read all properties from the Item var userName = collListItem.get_item('Name'); var website = collListItem.get_item('WebSite').get_url(); }), Function.createDelegate(this, function(){ //On Fail }));

Note: When the field is empty in your profile the get_item() Method will return null on the property.

Profile Picture

On property that can be slightly inconvenient is the Profile Picture. The URL is stored in the UserInfoList so that will be returned perfectly. But with SharePoint Online the Picture is most definitely stored in the MySite Host webapp. This means the user is challenged for credentials when this URL is used in an <img /> tag for instance.

Summary

There is a lot of User Information we can work with using the Client OM. It's very easy to obtain the information using Javascript and to do cool stuff with it. Just keep in mind that the syncing process can take some time and no custom properties are being synced.