JSRender, SPServices and User Profiles

In a recent project I needed a way to quickly grab user profile information and include it in the context of a custom application for SharePoint. I decided that I wanted to make use of templating to render the HTML for the user profile, so this lead me to look up the various jQuery templating plug-ins. I was a bit disappointed to see that the Microsoft stubs have been abandoned as a lot of my initial searches returned examples using this plug-in.

However, I discovered a new templating engine that seems to be showing a lot of promise called JSRender. This provided some very simple semantics to create a reusable template. When coupled with SPServices and a little bit of creative code parsing, you can quickly declare reusable templates for client side scripts in SharePoint.

The basic declaration of the template:

<script type="text/html" id="UserProfileDetails">
<div class="user-profile">
	<!-- Check for a picture, display it if available -->
	{{if PictureURL}}
	<img src="{{>PictureURL_Large}}" class="idea-author-image"/>
	{{/if}}
	<h1>{{>PreferredName}}</h1>
	<div class="user-metadata">
		<span class="office">{{>Office}}</span>
		<span class="title">{{>Title}}</span>
		<span class="department">{{>Department}}</span>
	</div>
	{{if AboutMe }}
	<div class="about-me">{{:AboutMe}}</div>
	{{else}}
	<div class="about-me empty">You are viewing information about {{>PreferredName}}. {{>FirstName}} has not completed any information in
		his <em>About Me</em> section of his profile. You can encourage {{>FirstName}} to 
		complete this information by sending a quick <a href="mailto:{{>WorkEmail}}?subject=More About You">email</a>.</div>
	{{/if}}
	</div>
</div>
</script>

The JSRender template makes use of place holders ({{…}}) to indicate where text or HTML should be substituted. The properties displayed are properties of the JSON object. You will also notice there is either a greater than symbol (>) or a colon (:) preceeding the property. If the greater than symbol is used this is an indicate to output just the text, excluding HTML tags. If the colon is used, HTML tags will be included.

To get the profile information, SPServices can be used. I created a helper function that takes an options object. This object is returned at the end of the call and will contain the data retrieved by SPServices. The function parses the XML data into a JSON object. This is required for JSRender.

function getUserProfile(options) {
	/*
		Loads a user's profile from the user profile service application
		using SPServices.

		To Call:
		var options = {
			login: "domain\user",
			success: function(options) { },
			failed: function(options) { }
		};
		
		Returned:
		options.login;
		options.success;
		options.failed;
		options.UserProfile;
	*/
	var profile = {};
	
	$().SPServices({
		// use the UserProfileService method GetUserProfileByName
		operation: "GetUserProfileByName",
		// Pass arguments that include the user login -- empty value will get the currently logged in user
		AccountName: options.login,
		// Async or blocked call to AJAX
		async: options.async,
		completefunc: function (data, status) {
			if(status == "success") {
				// Parse the user profile XML into a JSON object
				$(data.responseXML).find("PropertyData").each(function(idx,val) {
					var $val = $(val);
					var name = $val.find("Name").text();
					// JSON doesn't like the hyphen, change to underscore
					if(name.indexOf("-") > 0){
						name = name.replace("-","_");
					}
					if(value.text() != ''){
						profile[name] = value.text();
					}
				});
				// Get the other picture URL's if the PictureURL is available (SharePoint creates these when the user uploads their photo).
				if(profile.PictureURL != "") {
					profile.PictureURL_Large = profile.PictureURL.replace("_MThumb","_LThumb");
					profile.PictureURL_Small = profile.PictureURL.replace("_MThumb","_SThumb");
				}
				// Set the return value
				options["UserProfile"] = profile;
				// Call the function returning values
				options.success(options);
			} else {
				// Oops, do something with the error
				options.failed(options);
			}
		}
	});
}

To call this function, simply build an options object with the proper format. The nice thing about using the options object is that I can tag on extra data that I may need after the call to the web service has completed. In this case, I am passing the authorPanel which is a jQuery object to be updated after the call. I could just as easily created anonymous functions for the success and failed properties of options.

var options = {
		login: "domain\testuser",
		success: setupAuthorProfile,
		failed: showAuthorProfileError,
		target: authorPanel,
		async: true
	};
getUserProfile(options);

With the returned data, JSRender is used to build the new HTML.

function setupAuthorProfile(options) {
	$(options.target).html($("#UserProfileDetails").render(options.UserProfile));
}

The result is something like the following:

Advertisements

3 thoughts on “JSRender, SPServices and User Profiles

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s