Calculate How Much Web Storage You’re Using

This is a quick one, but it’ll be a post I return to over and over again.

When you use Web storage (a.k.a. DOM storage) – localStorage or sessionStorage – to cache data, you’ll often want to know how much you’ve used already. Each browser gives you a different amount of storage to work with, and you don’t want to run out for no good reason.

You might be surprised what the sites you visit are up to these days. Cookies are old hat; they just don’t give us enough to work with, as they are capped at 4k of data each.

From Wikipedia:

Web storage provides far greater storage capacity (5 MB per origin in Google Chrome, Mozilla Firefox, and Opera; 10 MB per storage area in Internet Explorer; 25MB per origin on BlackBerry 10 devices) compared to 4 kB (around 1000 times less space) available to cookies.

If you need to know how long each browser has offered Web storage, check out the Web storage page on Can I use. If you’d like to understand Web storage in a more practical sense, check out my post Caching SharePoint Data Locally with SPServices and HTML5’s Web Storage.

I’ve adapted some JavaScript I found out in a post on StackOverflow to display the storage used by each object in both localStorage and sessionStorage for the current origin

var storageTypes = ["localStorage", "sessionStorage"];
var x, log = [], total = 0;

for(var i=0; i < storageTypes.length; i++) {
	var thisStorage = window[storageTypes[i]];
	log.push("Statistics for " + storageTypes[i]);
	log.push("--------------------------------");
	for (x in thisStorage) {
		log.push(x + " = " + ((thisStorage[x].length * 2) / 1024).toFixed(2) + "KB / " + ((thisStorage[x].length * 2) / 1024 / 1024).toFixed(2) + "MB");
		total += thisStorage[x].length * 2;
	};
	log.push("Total = " + (total / 1024).toFixed(2) + "KB / " + (total / 1024 / 1024).toFixed(2) + "MB");
	log.push("================================");
	total = 0;
}
console.log(log.join("\n"));

The results will look something like those below, which I got by running the code in a console while I was on a Yammer external network.

Statistics for localStorage
--------------------------------
yj-chat-contact-list-1328414-1512241636 = 0.18KB / 0.00MB
yj-chat-contact-list-428797-1488346713 = 0.18KB / 0.00MB
Total = 0.36KB / 0.00MB
================================
Statistics for sessionStorage
--------------------------------
Total = 0.00KB / 0.00MB
================================

Here are the results on the home page of my Office365 tenant:

 Statistics for localStorage
--------------------------------
Ribbon.Document = 0.04KB / 0.00MB
Ribbon.Read = 0.04KB / 0.00MB
Ribbon.WikiPageTab = 0.05KB / 0.00MB
SPAnimationEnabled = 0.00KB / 0.00MB
SPMySiteLinks = 0.73KB / 0.00MB
SPSuiteLinksDate = 0.11KB / 0.00MB
SPSuiteLinksJson = 46.97KB / 0.05MB
SPSuiteLinksLanguage = 0.01KB / 0.00MB
SPSuiteLinksUserKey = 0.08KB / 0.00MB
SPSuiteNavHeight = 0.01KB / 0.00MB
SPSuiteThemeInfo = 0.74KB / 0.00MB
ShellCacheIndicator = 0.07KB / 0.00MB
Total = 48.86KB / 0.05MB
================================
Statistics for sessionStorage
--------------------------------
SPAnimationEnabled = 0.00KB / 0.00MB
SPCacheLogger0 = 0.26KB / 0.00MB
SPCacheLogger1 = 0.29KB / 0.00MB
SPCacheLogger2 = 0.29KB / 0.00MB
SPCacheLogger3 = 0.27KB / 0.00MB
SPCacheLogger4 = 0.28KB / 0.00MB
SPCacheLogger5 = 0.26KB / 0.00MB
SPCacheLogger6 = 0.26KB / 0.00MB
SPCacheLogger7 = 0.67KB / 0.00MB
SPCacheLoggerSize = 0.00KB / 0.00MB
SPSuiteLinksCached = 0.01KB / 0.00MB
SPUserPhotoToken = 0.03KB / 0.00MB
UserPhotoToken = 0.03KB / 0.00MB
Total = 2.64KB / 0.00MB
================================

Create a Simple SharePoint 2013 Employee Directory on Office365 – Part 3 – Create Display Templates

In the prior two parts of the series, I covered the idea of an employee directory (or associate directory, or person directory, or whatever you call the people in your company/organization/commune) and how to create the basic page. Once again, I want to give credit to Ari Bakker’s (@aribakker) post that shows how to set up a simple a Employee Directory on SharePoint 2013: How to: Create a Simple SharePoint 2013 People Directory.

I’m going to start with Ari’s Display Templates, but take them a bit further. What you’ll want to do here will vary based on the characteristics of your organization. What’s useful for an organization with 10 people will be quite different than what’s useful for one with 100k+ people.

The client I needed this directory for has about 100 employees. As with many organizations, the Employee Directory is effectively replacing something that has been maintained in Excel and emailed out regularly. Everyone prints it out and hangs up a copy in their cube. So we really want this directory to look a lot like that old-fashioned phone list. It will have a little more info and if the data maintenance side of things holds up, the data will always be current. At the same time, since we are using Display Templates, we’re well-positioned to expand the information we display over time.

In small- to medium-sized organizations like this, it’s helpful to have an alphabetic filter. I’ve been building similar things in SharePoint for a long time. (See: Alpha Selection of List Items in a Data View Web Part (DVWP)) They are great to add to plain old list views, too. I’ve created a Control Display Template which shows the alphabetical filtering links and an Item Display Template that shows each person’s details.

Here’s what the alphabetic filtering looks like:

Alphabetic Filtering

Note that several of the letters are not “lit up”. That’s because no one in the organization has a last name starting with I, Q, X, or Y. Few things are more annoying than clicking on a link like this only to be told that “Nothing here matches your search”.

Nothing here matches your search

If nothing matches, then why did you show me the link?!?!?! So there’s a little magic in the Control Display Template to figure out which letters should not be lit up. That logic will ensure that we only can click on letters where there are actual results, even as people come and go.

Like I said, there are two Display Templates here. These little buggers tend to work in pairs.

Display Template Layout

Source: http://msdn.microsoft.com/en-us/library/office/jj945138(v=office.15).aspx

Think of the Control template as the outer one and the Item template as the inner one which we iterate for every individual item in the result set coming back from search. This can be a little tricky and also a little confusing. Where should we draw that dotted line? Well, you’ll see a lot of inconsistency on this. In my two Display Templates for the Employee Directory, I’m using the Control template to display the alphabetic filter links and to create the table which will contain the items, but I’m rendering the table header in the Item template. That just seems to make more sense to me because that way the column headers sit with the rendering of the actual data, not is a separate place (the Control template). Another thing to consider here is that ideally we want the two types of Display Templates to work atomically: we should be able to mix and match different Control and Item templates based on our needs. For instance, in a really large organization, we may not need to check for which letter to light up, so we could just use a Control Template that doesn’t do that piece.

OK, enough chit-chat. Let’s look at the code.

I’ve created a folder in the Site Collection under _catalogs/masterpage to hold everything I’m doing here.

Employee Directory Code

In the real installation, that folder is named for the client, but here I’ve called it “_EmployeeDirectory”. Note the leading underscore: that ensures that the folder will always show up at the top of the listing under masterpage; otherwise I have to scroll a lot.

As you can see, I’m pretty organized about how I store things in the folder. I have subfolders for:

  • css – Any CSS files that are a part of this solution.
  • Display Templates – This folder structure mimics the one that SharePoint uses out of the box. I even mirror the subfolder names, like Search, so that it’s clear what type of Dsiplay Templates are in there. Because each of the Display Templates has a Content Type in it, SharePoint knows how to find the files in these custom folders.

Control Display Template If I had any custom JavaScript in the solution, I’d have a js folder, images files would go into an images folder, etc.

Here are the custom parts of the Control Display Template. The basic logic is this:

  • Line 3 – Include some custom CSS. In a full installation this would probably occur in the master page, but I’ve chucked it out to share the important bits here.
  • Line 4 – Include jQuery. I’m using jQuery to handle a bunch of things since it makes life easier.
  • Line 7 – This div is just the outer container for the template.
  • Lines 10-15 – Declare some variables we’ll need later
  • Lines 19-36 – Emits the markup for the alphabetic filters.
  • Lines 22-28 – Loop through all of the letters in the alphabet and make the calls to search to find out if that letter should be “lit up”.
  • Line 31 – Emit the hard-wired “All” link.
  • Lines 38-53 – This block is where I figure out which letters to unlight change the CSS for each. Yes, After fiddling around with this for a while, I decided to load the page with *all* the letter lit up, and turn off the ones that don’t have data behind them. This makes for a good regression if we have one: all the links will be lit up even if the script fails.
  • Lines 55-76 – This function called getSearchResultsUsingREST makes a call to the Search Service using REST and passes back a promise. Each call requests just the first result (rowlimit=1) and only the WorkId property (selectproperties=’WorkId’). This makes the call extremely “light”. We don’t need to know how many people fall into the letters bucket; we just want to know if *any* do.
<body>
	<script>
		$includeCSS(this.url, "~sitecollection/_catalogs/masterpage/_EmployeeDirectory/css/EmployeeDirectory.css");
		$includeLanguageScript(this.url, location.protocol + "//code.jquery.com/jquery-1.11.2.min.js");
	</script>

    <div id="Control_SearchResults">

<!--#_
		// Make REST calls to the Search API to "light up" the letters.
		var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		var letters = alphabet.split("");
		var lettersSearch = []; // Array to hold the AJAX promises
		var currentSearch = (location.href.indexOf("k=lastname%3A") > 0) ? location.href.split("k=lastname%3A")[1].substr(0, 1) : "";
		var thisPage = location.pathname;
_#-->                    

		<!-- Alpha selector container -->
		<div id="edir-alpha-links">
			<span><a href=_#=thisPage=#_>All</a></span>
<!--#_
		// Loop through the alphabet and make a call to the search API for each starting letter
		for(var i=0; i < letters.length; i++) {
			var searchTerm = letters[i];
			var letterClass = (currentSearch === searchTerm) ? "selected" : "";		

			// TODO Build the calls into one REST $batch. See: http://www.andrewconnell.com/blog/part-1-sharepoint-rest-api-batching-understanding-batching-requests
			lettersSearch[i] = getSearchResultsUsingREST("LastName%3A" + searchTerm + "*");
_#-->
			<span id="edir-alpha-links-_#= searchTerm =#_">
				<a class="_#=letterClass=#_" href="_#= location.pathname =#_#k=lastname%3A_#= searchTerm =#_*">_#= searchTerm =#_</a>
			</span>
<!--#_
		}
_#-->
		</div>
<!--#_
		// When all the requests have completed...
		$.when.apply($, lettersSearch).done(function() {

			for(var i=0; i < letters.length; i++) {

				var searchTerm = letters[i];
				var count = this[i];

				var letter = $("#edir-alpha-links-" + letters[i]);
				if(count == 0) {
					letter.html(searchTerm);
					letter.addClass("no-link");
				};
			}

		});

		function getSearchResultsUsingREST(queryText) {

			var result = new $.Deferred();
			var resultCount = 0;

			// We only need to fetch the first result for each letter to know if we should light it up
			// The sourceId is the GUID for the 'Local People Results' Result Source
			var searchUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext='" + queryText + "'&sourceId=%27b09a7990-05ea-4af9-81ef-edfab16c4e31%27&rowlimit=1&selectproperties='WorkId'";

			var p = $.ajax({
				url: searchUrl,
				method: "GET",
				headers: { "Accept": "application/json; odata=verbose" }
			});

			p.done(function(data) {
				// Return just the count of results, which will be 0 or 1
				result.resolveWith(data.d.query.PrimaryQueryResult.RelevantResults.RowCount);
			});

			return result.promise();
		}

_#-->

Next up is the Item Display Template. In this one, I’ve gone as simple as possible. Ive gotten rid of a lot of the encoding, null value tests, etc. that most of the out-of-the-box Displey Templates have just to keep it simple. Below I’m showing *everything* in the body of the template. It’s really stripped down.

 

  • Line 9-21 – If this is the first item in the result set, emit the table header.
  • Line 23-33 – Emit the details for each person in the rsult set. Here I’m showing:
    • Name (full name)
    • Work Phone
    • Email
    • Department
    • Office

Your organization will undoubtedly have a few other fields you want to add, you may one to remove one or two of these, etc.

<body>
    <div id="Item_Person">
<!--#_
		if(!$isNull(ctx.CurrentItem) && !$isNull(ctx.ClientControl)){
			var encodedPath = $urlHtmlEncode(ctx.CurrentItem.Path);
_#-->
<!--#_
			// If this is the first item in the results, emit the table header
			if(ctx.CurrentItemIdx === 0) {
_#-->
				<thead>
					<tr class="ms-viewheadertr ms-vhltr">
						<td class="ms-vh2">Name</td>
						<td class="ms-vh2">Work Phone</td>
						<td class="ms-vh2">Email</td>
						<td class="ms-vh2">Department</td>
						<td class="ms-vh2">Office</td>
					</tr>
				</thead>
<!--#_
			}
_#-->
			<tr>
				<td class="ms-vb2">
					<a clicktype="Result" id="NameFieldLink" href="_#= encodedPath =#_" title="_#= ctx.CurrentItem.PreferredName =#_">_#= ctx.CurrentItem.PreferredName =#_</a>
				</td>
				<td class="ms-vb2">_#=ctx.CurrentItem.WorkPhone=#_</td>
				<td class="ms-vb2">
					<a href="mailto:_#=ctx.CurrentItem.WorkEmail=#_">_#=ctx.CurrentItem.WorkEmail=#_</a>
				</td>
				<td class="ms-vb2">_#= ctx.CurrentItem.Department =#_</td>
				<td class="ms-vb2">_#= ctx.CurrentItem.OfficeNumber =#_</td>
			</tr>
<!--#_
	}
_#-->
    </div>
</body>

Finally, here’s the CSS I included above:

/* Alpha links for search */
#edir-alpha-links {
	margin-top:10px;
}
#edir-alpha-links span {
	padding:0 3px 0 3px;
	width:35px;
	font-size:18px;
}
#edir-alpha-links span.no-link {
	padding:0 6px 0 6px;
}
#edir-alpha-links span a {
	padding:0 3px 0 3px;
	border-radius:6px 6px 6px 6px;
	background-color:#005581;
	color:#fff;
}
#edir-alpha-links span a.selected {
	background-color:#E08B24;
}
/* Alpha links for search */

Please don’t use this as-is. I’m so disappointed when I see one of my examples shows up somewhere with exactly the same colors and fonts!

Once we’ve switched to these Display Templates, we have something like this:
Employee Directory - Part 3

You can see we still have a few oddities here. This screen grab is from my demo environment, so there aren’t that many real people in the results. (Note that only a few of the letters are lit.) We’re also seeing some odd “people” that aren’t people at all. There’s probably some other filtering we’d like to do, maybe a few more settings to tweak. Next up I’ll show you some of the things you’ll probably want to do with your Search Schema to make things work a little better. WARNING: Powershell is coming. Sad, but true.

Here are the files from this post in a ZIP file: _EmployeeDirectory Display Templates and CSS

Semantic Versioning for SPServices?

Late last year I committed to put SPServices onto Github to encourage greater collaboration and contribution from the community. It’s definitely there now, and there are several things I’ve been struggling with since I moved it there:

  • What to name each version
  • How many versions to move into the repo
  • Whether it actually will increase community submissions at all
  • etc.

So far, I have done one release while SPServices has been on Github, which was 2014.02 [Codeplex][ [Github]. Even for that one new release, I wasn’t sure how to structure things. Everyone is moving away for including version numbers in their file names. I’m not sure that’s such a good thing. By including the version number in the file name, we can tell – at a glance – what version we’re working with. Since many SPServices users are more on the end user end of the spectrum rather than the developer end, that’s an excellent thing to be able to do.

Andreas Schultz has recommended that I switch to Semantic Versioning in a pull request for bower.json. Bower is a package manager, and there are a host of others: npm, NuGet, Bower, Ender, volo, component, Jam, and the list goes on. The number of these things is increasing fast. (I’d include links, but these things are easy to find.)

This is a tricky one. I’ve watched as this “semantic versioning” thing gets rolling, and I’m not sure how I feel about it.

Over the first several years I increased the versions for SPServices from 0.2.3 to 0.7.2. The fact that I wasn’t getting to version 1.0 was more me being cantankerous than anything else. Then I had 3 or 4 people tell me – separately – that they weren’t allowed to use software in their organizations unless it was version 1.0 or above. What a crock!

So I switched to numbering like 2013.01 back in May, 2013. The version is greater than 1.0! Since then, I’ve had 2013.02, 2013.02a, 2014.01, and 2014.02. It marches forward and gives some indication of what the versions is, or at least its age.

Semantic versioning seems to give people an excuse to introduce breaking changes. Here’s the summary of the idea from the SemVer site:

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

One of my goals with SPServices going way back to 1999 has been not to introduce *any* breaking changes. I think I’ve done a pretty good job on that, too. Whether you’re using SPServices on SharePoint 2007 with no updates installed or SharePoint 2013 on Office365, it *ought* to work the same way. Code that you wrote with version 0.2.3 *ought* to still work, too, though most likely you’re running a more recent version of jQuery and other things which would make using that ancient version pretty dumb. (That and the fact that the first version didn’t do much.)

If I were to follow the semanatic versioning rules, I’m not sure if I would be at 1.1.14 or 1.14.02 or what. Removing version numbers from files makes me uncomfortable, though.

Switching to semantic versioning seems to be hopping on a train without really understanding if driving is just fine and will get us there at the same time. What are your opinions on this? If you add your $.02 into the comments, please indicate what type of user you are, e.g., end user (“I paste SPCasecadeDropdowns into my forms” or developer “I write solutions using SPServices as the data transport layer” or…

The Year That Will Be: 2015

It’s that time of year when people tend to look back at the prior year or look forward to the new one. In my case, I’m generally choosing to look forward. 2014 was a swell year on most counts, but I’m really looking forward to 2015.

I’m excited about a number of things coming up this year, and I wanted to tell you about some of them.

My 5th Microsoft MVP Award

Yesterday morning I learned that I received my fifth Microsoft MVP award. As it is each time, it’s an incredible honor to be put in the company of such talented people. The MVP program lets me spend time with some of the brightest and most motivated SharePoint / Office365 people on the planet.

Sympraxis Consulting LLC

Sympraxis LogoMany of you who know me may not be familiar with Sympraxis Consulting LLC. It’s my own little company that I started when I went out on my own (sort of; see below). 2015 promises to be a transition year for my little company. (One resolution I should probably make is to come up with a better Web site than the WSS3-based one I’ve had limping along for the last six years!) Back in 2008, my buddy Pete Sterpe (@petesterpe) and I started Sympraxis together with big dreams. The Fall of 2008 seemed like such a great time – not. Sadly, due as much to the economy as anything else, Pete realized about a year in that he needed a more solid paycheck to fit his life goals at the time.

Luckily for me, Pete is rejoining me at Sympraxis. I’ve known Pete since 1996, when we worked together at Renaissance Solutions. Renaissance focused on knowledge management and performance enhancement by utilizing technology and the Balanced Scorecard. You may know better now where some of my rhetoric comes from. (Sadly even the Way Back Machine doesn’t have a good snapshot of Renaissance from those times, though it does have one of the successor company, Renaissance Worldwide.)

Pete will be ramping back up with Sympraxis as his existing work ramps down, and I am delighted to have him back. He’s one of the sharpest people I’ve ever worked with and our business ethics are perfectly attuned. I hope you get a chance to meet Pete in the near future. You can check out his blog to get to know him a little bit. Since he never changed his About page, you can read how he started Sympraxis with me!

Partnerships

I’ve got two nascent partnerships I’m working on that I’m very excited about. I’ve written about them before but I wanted to go over them here again.

Seven Sigma / Glyma

Seven SigmaThe first relationship is with the folks at Seven Sigma down in Perth Australia. Paul Culmsee (@paulculmsee) and Chris Tomich (@christomich82) are two of the smartest folks I know in SharePoint land. It turns out that we’ve been admiring each other from afar for a long time. If they weren’t all the way around the planet in Perth, I’m sure we would have worked together sooner. I was lucky enough to meet both of them when I was down in Australia at ShareThePoint‘s 5th Annual Australian SharePoint Conference in Sydney last July. (It’s a great conference if you are anywhere near there for the next one.) We talked about the fact that it would be great to work together in some way and we’re still trying to figure out exactly how that might work. It will be something we’re both convinced will add value and as the partnership starts to gel I think it’s going to be an exciting thing to work together.

Their Glyma product really gets the knowledge management part of me excited. Using the concept of dialog mapping, it’s a fantastic way to encapsulate and map the knowledge contained within an organization as well as a way to help map strategic focus and direction decisions. Watch for more about Glyma from me in the weeks and months ahead.

Dynamic Owl / Bonzai Intranets

DynamicOwlLogoThe second relationship is with my friends at Dynamic Owl in Vancouver, BC, Canada. Dynamic Owl is headed by Michal Pisarek (@michalpisarek) and he has a small group of incredibly intelligent folks working with him. Michal and I have talked about ways we could work together over the years, but have never come up with something that makes sense.

Bonzai IntranetThe Owls’ product is called Bonzai Intranet and I’m incredibly impressed with what Matthew Carriere (@matthewcarriere) and Shereen Qumsieh (@msshushu) have built in a very short time. They’ve taken the learning that they have over the years working in SharePoint and built some of the most common things that they’ve seen time and time again in customer Intranets. The most impressive thing about it to me is the architecture. The majority of the functionality is driven from the client side using AngularJS and calls to CSOM and REST. I’ve been working with them to think through how their architecture might work with Office 365. As we all know there are some different challenges there, but with a bit of good thinking ahead of time I think they are going to be able to do some amazing things.

I’m not exactly sure where these two relationships will lead, but I’m hoping it will go far beyond just pasting each others’ logos into our Web sites. These are great people with whom I hope to work a lot more in 2015.

Community

SharePoint – and by extension – Office365 – would never be what they are without the incredibly strong community around them.

IT Unity Webinar: #CollabTalk, The Show

ITUnityLogoI’m joining an impressive crew of people to do a new video series on IT Unity. Many of you have probably participated in the #CollabTalk tweet jams that have been going on for the last couple of years. Tweet jams are great, but of course they only have a certain utility since we can type just 140 characters at a time. With this new video series hosted by IT Unity, Christian Buckley (@buckleyplanet), Naomi Moneypenny (@nmoneypenny), Benjamin Niaulin (@bniaulin), and I will be able to go into much more depth about topics that we think are important to people who are interested in Office365. I think we will have a lot of fun and talk about some really important topics at a level of depth that we could never do in a tweet jam.

CollabTalk - Tiny - Tiny

Conferences

I love speaking at conferences. I learn so much talking about what I do with attendees and getting to go to other speakers’ sessions is the icing on the cake. I used to always say I’d like to teach some day, and this is my way of doing a bit of it on a regular basis.

In 2014 I was fortunate to speak at ShareThePoint’s conferences in Sydney and Auckland, which was my first chance to visit that side of the world. We made it into a family trip to Vietnam and Cambodia, so it was quite the globe-trotting romp. (Don’t look at a globe and tell me how ridiculous that was; I know.)

There were lots of other great conferences, too: SEF in Stockholm, Sweden; SPTechCon in San Francisco and Boston; and SharePointFest in Chicago, just to name some of the most prominent ones.

This year I already have SPTechCon in Austin, TX lined up, along with SharePoint Evolution in London. If you’re dying to keep up with where I’ll be, watch the Speaking page here.

Oh, and Clients!

I’ve been very lucky to have some wonderful clients who have engaged me multiple times over the years. As is always my hope, with most of them I have a long-standing, open and honest relationship. Along with all the fun stuff above, I do occasionally focus on earning a living, and my clients are the best. Here’s to a lot of great projects in 2015!

Summary

blackshadesYeah, it may be true. The future may be so bright I’ve gotta wear shades. I don’t mean this in a gloating way by any means. I’m incredibly lucky to be in the position I’m in at this point in my career. For many reasons which I won’t go into here, my time in the sun seems to be in my 50s. Many of my contemporaries may be able to rest on their laurels at this age, having accomplished their world-changing stuff in their 20s or 30s. I’m excited to know that my time is now or may be yet to come. I can’t wait to see what else 2015 has in store for me. Happy New Year!

Create a Simple SharePoint 2013 Employee Directory on Office365 – Part 2 – Set up an Employee Directory Page

The first step is, of course, to create a page where the Employee Directory will live. The approach we’re taking here is to use a page in the Search Site Collection in Office365. By default – at least in the tenants I’ve worked with – the Search Site Collection lives at https://[tenant name].sharepoint.com/search. This isn’t a sneaky hidden Site Collection like the ContentTypeHub (See: Hidden Content Type Hub on Office365 Tenants), but one that lives right out in the open.

When you go to the Search Site Collection directly, you’ll land on a very bland search page:

Search home page

You may also have created your own Enterprise Search Center, which may look a little different. It doesn’t really matter, though. All we want to do is to create a new page in the Search Site Collection you are using to house the Employee Directory.

Click on the cog (See the cog on the left as of this writing. It’s not unlikely that it’s taken on a new shape or color since then.The Cog) and then Site Content. This should show you all of the Apps lists and libraries available in the Site Collection root. If you can’t get this far, then you may not have the appropriate permissions. Go directly to Jail, do not pass Go, and do not collect $200. You’ll need to talk to your Tenant or Site Collection Administrator to get the right permissions.

If permissions aren’t a problem, then click on the Pages App Library icon.

Pages Library

Once in the Pages library, go to the ribbon and create a new page.

Add a new page

When you select Page, you’ll end up on the page where you can create the page. What you’re looking for here is the “(Welcome Page) Search People” page layout. In the image below, the page layout is not available. If it is, choose it and keep rolling. If not, first take this little detour.

Choose Page LayoutClick on the cog, go into Site Settings, and choose “Page layouts and site templates” under the “Look and Feel” section at the top of the right column. (For some reason, even when I know where something is on this page, I have a tough time spotting the right link: everything looks the same. My trick is to use Ctrl-F in the browser to search for the right word rather than just scanning for it.)

Page layouts and site templates

In the Page Layouts section, add the “(Welcome Page) Search People” page layout.

 

Enable a page layout

The section should then look like this:

Enable a page layoutNow go back to the Pages library and create a new page. I’m calling mine “Employee Directory” with the URL set to Employee-Directory.aspx. Be sure to choose the “(Welcome Page) Search People” page layout.

Create Employee Directory page

When you click Create, you’ll end up back in the Pages library. Click on the Employee Directory page. It’ll look something like this, though if you see my photo it’ll be a little weird.

Employee Directory - CreatedBelieve it or not, you now have a fully functional page that will do much of what you want. For instance, if you type “Lastname:A*” in the search box, you’ll get all of the people whose last name starts with the letter A.

Lastname:A*But we don’t want to land on the page with nothing showing. That would require more work than we want people to do. Instead, let’s set the Search Results Web Part up so that it shows some of the people in the tenant by default.

Click on the cog and Edit Page. If you’ve never done this on a Search Results page before, you may be surprised to realized that it’s just a Web Part Page with some special Web Parts already set up for you. You’ll see that you have two Web Part Zones.

  • On the left, you have the Navigation zone. It contains only one Web Part: the Refinement Web Part
  • On the right, you have the Main Zone. It contains two Web Parts: the People Search Box Web Part and the People Search Core Results Web Part.

Employee Directory in edit mode
Click on the dropdown at the top left of the People Search Core Results Web Part and choose Edit Web Part. This will open the Tool Pane for the Web Part.

People Search Core Results Web Part Tool PaneThere’s a great deal we can do with these settings, but for now we are going to just do one simple thing. Click on the Change Query button. In the Query text box, simply add contentclass=spspeople. This sets the default search to return all people, filtered by whatever is in the search box. If you click the Test query button, you should see at least a few people show up on the right in the Search Result Preview box.

Checnge query to search for peopleClick OK to save the query, OK to save the Web Part settings, and Save on the ribbon to save the page. Now you should have a very rough first pass at an Employee Directory. You should see up to 10 people in the results, perhaps along with a photo (if they have one in their profile) and a little information about each person (if certain profile properties are populated). You my also see some strange “people-like” entities. These will usually be some crawler accounts, etc. We’ll take care of those later.

OOB People Search ResultsWhew. That’s probably enough for now. If you want to, try adjusting some of the settings in the Tool Pane for the People Search Core Results Web Part, but don’t go too crazy. In the next post in this series, we’ll look at how we can make some changes to the Display Templates so that our results are more helpful and robust.

Note: Mikael Svenson (@mikaelsvenson), my search guru and Jedi master, pointed out to me that adding contentclass=spspeople isn’t actually necessary. Once we have some other criteria in the search query, we won’t need it there. However, at this point since we don’t, and we’d like to see some people in the results, it serves a purpose.