User Profile Services via Client Object Model

I was recently thinking through ways to help drive adoption of an intranet and engage users to explore the various capabilities of the system. One thought was to alert users if they have not supplied a profile photo, or a short bio in their MySite. Sure we could do this with web services, but I thought I’d figure out how to do it with the client object model with ECMAScript. After a lot of searching, I kept finding blog posts that said I was out of luck and there was no way to query User Profiles via the client object model. At a high level, that assessment is correct, but what we can do is query the user info list of the current site.

When I first started this, none of the test users in my lab had a profile picture, so I added one and found that my script kept returning a null object instead of my picture. The hidden Easter egg here is that the site’s user info list isn’t updated in real time. If you head over to Central Administration -> Monitoring -> Review job definitions and dig down the list you’ll find a job called “User Profile Service Application – User Profile to SharePoint Full Synchronization“. This timer job will execute every hour and synchronize the properties of your User Profile Services to the site user info list, so the picture that was set on the MySite is now accessible via the user info list.

First things first, we need to find out the ID of the user that’s currently viewing the page (this is the physical numerical record of the user in the site’s user info list, not the login username). Credit to Mike Oryszak (@next_connect) and his blog post on using the status bar to display active workflows for getting me in the right direction on this piece. We’ll start out by grabbing the current web context and fire off that query. If the query is successful in executing, it’ll call the onUserSuccessMethod function.

var context = null;
var web = null;
var curUser = null;

function getUser() {
	context = new SP.ClientContext.get_current();
	web = context.get_web();
	curUser = web.get_currentUser();
	curUser.retrieve();
	context.load(web);
	context.executeQueryAsync(Function.createDelegate(this, this.onUserSuccessMethod), Function.createDelegate(this, this.onFailureMethod));
}

Now that we have our context we’ll create a variable called user and assign it to the current user object, and call our loadProfile function to do the profile query.

function onUserSuccessMethod(sender, args) {
	var user = web.get_currentUser();
	loadProfile();
}

The loadProfile function defines the user info list, builds the CAML query to get the record for the current user, and fires that query off. If the query is successful in executing, it’ll call the onProfileSuccessMethod function.

function loadProfile() {
	context = SP.ClientContext.get_current();
	web = context.get_web();
	userInfoList = web.get_siteUserInfoList();
	camlQuery = new SP.CamlQuery();
	camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name=\'ID\'/><Value Type=\'Number\'>' + curUser.get_id() + '</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>');
	this.listItems = userInfoList.getItems(camlQuery);
	context.load(listItems);
	context.executeQueryAsync(Function.createDelegate(this, this.onProfileSuccessMethod), Function.createDelegate(this, this.onFailureMethod));
}

Now that we have the result set from our query (in the form of a listItems object), all we need to do is grab the first (and only item), this will be on index 0 in the array, and analyze the picture field to see if there’s a value there or not. If there is a picture object, we’ll grab the Url to it and save it in a new variable (pictureURL) just in case we want it. If there is no picture object, we’ll fire off a call to SP.UI.Status to add a new status bar telling the user they don’t have a photo, with a link to their profile where they can add one.

function onProfileSuccessMethod(sender, args) {
	var item = listItems.itemAt(0);
	var picture = item.get_item('Picture');
	if (picture) {
		var pictureURL = picture.get_url();
	} else {
		noPicture = SP.UI.Status.addStatus('Profile Photo', 'You have not added a profile photo to your account. <a href=\'http://mysites/person.aspx\'>Add one now!</a>');
		SP.UI.Status.setStatusPriColor(noPicture, 'blue');
	}
}

You’ll notice that both getUser() and loadProfile() have references to an onFailureMethod function, in the event that our query fails. This will be a simple function to just alert our error.

function onFailureMethod(sender, args) {
	alert('Error: ' + args.get_message() + '\n' + args.get_stackTrace());
}

Now that we’ve got all of our functions written, all we need is a simple call to our getUser() function (after the core SharePoint JavaScript has loaded, of course).

ExecuteOrDelayUntilScriptLoaded(getUser, "sp.js");

Putting it all together:

My “Michael Greene” account has a user profile image, so we just see normal SharePoint with no profile photo alerts.

My “Setup Account” account does not have a profile image, so SharePoint prompts us that we should add a photo.

Due to the fact that we have to wait on the timer job to run and update the user info list with the new photo, it’s possible that the user could add a photo then still see the prompt telling them they haven’t. In a true application of this, we could add a condition to check the Modified time of the user info list record to see if the record has been “updated” in the last hour, to avoid that false positive. Only if the record has been updated within the hour and has no photo, should we alert the user.

Enhancing the SharePoint 2010 UI: Scripted Orientation Aware Content

In my previous post we looked at enhancing the SharePoint 2010 UI through CSS based orientation detection. In this post, we will take it one step further and use some client side script to detect orientation and output content accordingly.

The CSS approach utilizes orientation aware style sheets which are loaded based on the appropriate orientation of the device (in this case an iPad). While this approach is simple to implement, it’s not necessarily the most robust solution or the most scalable solution. The CSS approach is best suited to deployment with your site’s branded master page, when orientation detection is a big part of your design. What if you only wanted it on one or two pages of your site, if you don’t have access to deploy a new master page, or if you want more advanced orientation detection?

Read more →

Enhancing the SharePoint 2010 UI: iPad Orientation Detection

I recently had a chance to sit down and rapid prototype some iPad UI Enhancements for SharePoint 2010. I had previously done some light orientation detection for the iPod and iPhone, but with the iPad there’s a lot more power in utilizing orientation detection. As the iPad gains more traction in the business world I expect to see more and more requirements to make enterprise platforms [like SharePoint] usable on the iPad. With Microsoft’s commitment to cross-browser functionality in SharePoint 2010 we’re fortunate that SharePoint 2010 will render on the iPad without any customizations needed.

The typical approach to porting desktop content to a mobile device is to scale content down to fit it all within the mobile device’s display. With orientation detection we can turn off specific regions of content, or change the layout completely in order to maximize on the screen real estate and mitigate the need to scale down content–relative to how the user is holding the device. If we use the iPad as an example, in landscape orientation the resolution is 1024 x 768 but when we move it to portrait orientation the resolution swaps to 768 x 1024 (~250 pixels less on the width). Again, typically we’d just scale everything down to compensate for that drop on horizontal screen real estate. With a platform like SharePoint, making things smaller inherently makes it more difficult to navigate and the two-finger horizontal scroll on the iPad isn’t really all that intuitive. The solution is to detect the orientation of the device and restructure content accordingly.

Read more →

2007 jQuery Form Enhancements; Preserving Site Definition

During a recent discussion with @TashasEv, the topic came up of preserving site definition when rolling out jQuery form enhancements. The preservation of site definitions is something that many people ignore, but in the interest of best practices I figured it was worth a blog post to explain some of the pros and cons, and offer some solutions.

Many of us (myself included) use jQuery to enhance out of the box (OOTB) SharePoint forms. jQuery allows us to make a variety of minor or major changes to the usability and functionality of forms either through straight jQuery or with Marc Anderson’s (@sympmarc) popular jQuery Library for SharePoint Web Services (SPServices). Cascading dropdowns, content relevant fields, dynamic changes to styling, and other enhancements can greatly improve the user experience and the data entry side of a form, but can be the achilles heel of your support model if done incorrectly.

In layman’s terms, the site definition is the foundation on which all OOTB SharePoint sites, templates, forms and pages are based. Essentially, this allows you to manage assets within the site by managing the site definition. An easy to understand example would be upgrading your SharePoint environment. If a version upgrade or service pack comes along that touches the site definition, all objects using that site definition will be updated accordingly. The issue lies in the fact that when you open your OOTB SharePoint form in SharePoint Designer and edit it, you essentially disconnect that form from the site definition. Six months down the road when you upgrade your environment or push that next service pack, your form will now not be updated. Additionally, if you find yourself in a position where you need to consult Microsoft for support, Microsoft can very well point out that you’ve customized the OOTB code, and refuse your support request.

Read more →

Application Wide Quick Launch Control

I ran into a unique challenge on a recent project related to the use of the Quick Launch. I had a Web Application that was broken into about 10 Site Collections to facilitate access control, but had the potential to become an absolute bear to manage. The Quick Launch needed to be the same across all of the Site Collections, which resulted in having to physically touch the configuration of each Site Collection or Subsite every time a link needed to be added or changed. There had to be a better way, right? Enter the SPServices jQuery library by Marc Anderson (@sympmarc). It should be pointed out that I’m working in WSS 3, but I don’t know of anything that would prevent this from working in MOSS (although the jQuery selectors may need to be changed).

Read more →

22
Apr 2010
CATEGORY

Technology

COMMENTS 5 Comments

SharePoint List Attachment Technical Brief

I recently found myself searching (to no avail) for information on how the SharePoint list attachment process actually works; it seemed as if there was no documentation or previous experiences available anywhere. In my particular scenario, I needed to be able to produce an auditable list which showed the date/time, filename, and username for every upload, a report which WSS doesn’t offer out of the box.

My solution became the creation of a second list, which would serve as this master record of all uploads. Once I understood how SharePoint actually processes the file attachments, I was able to use a combination of the PreSaveAction function and the jQuery Library for SharePoint Web Services to log each of the file names into my list.

This article isn’t meant to address the complete breadth of capability, but more to offer the technical ins and outs. I should point out that for the purposes of the article I’m making the assumption that you’re working on the default NewForm.aspx or EditForm.aspx forms. While I would imagine the document model and process is very similar for custom list forms, I have yet to dive into that world.

Read more →

23
Jan 2010
CATEGORY

Technology

COMMENTS 2 Comments

jQuery: Value Add or No?

You may remember reading my post from a few weeks called jQuery Introduction, where I mentioned my new discovery of this incredibly powerful library and discussed some very basic uses of it.

At the end of the day, when the rubber meets the road, jQuery is an incredibly powerful library, which has its uses far beyond pop-up windows and quirky little effects that most professional designers agree are better left out. The practical uses include the execution of web services (also mentioned in my initial article), data and content delivery, and user experience enhancements (to things such as forms) that add value in the eyes of the end user.

There’s been a lot of discussion lately across Twitter and on several blogs about the efficiency of jQuery. jQuery is JavaScript, and JavaScript add’s overhead–that isn’t being debated. Marc (who I have great respect for) has stood up in defense of the library, and rightfully so. There’s been a lot of discussion on his blog (Putting the Brakes on SharePoint with jQuery – Or Not, and Putting the Brakes on SharePoint with jQuery – Or Not (Some More)) regarding the issue, but as opposed to clogging up his comments too much, here’s my general thoughts on the issue.

Read more →

30
Dec 2009
CATEGORY

Technology

COMMENTS 1 Comment

Flash Tag Clouds in SharePoint

So I was at work last week when one of my colleagues came over and asked about the ability to make a dynamic tag cloud in SharePoint. We had collected a bunch of ideas from the workforce and they wanted an intuitive way to display them all in a dynamic fashion. My first thoughts were of the cumulus WordPress plugin that I use here on my blog, and after turning to trusty Google I discovered that I wasn’t the only one who had this idea. We based our work off of this blog post, with of course a few tweaks of our own.

This of course emphasizes my points of the usefulness of and my discovery of jQuery as it uses some simple jQuery to access the SharePoint list data. We made our integration a bit cleaner by utilizing the jQuery Library for SharePoint Web Services. We also used jQuery to fade the screen and display the tag cloud in a “floating” popup over the page content so we could keep it nice and big, positioned on top of the SharePoint page.