Announcing the Top 25 SharePoint Influencers for 2014

HomeLast Wednesday at the Microsoft SharePoint Conference in Las Vegas – in a clear lapse of judgment – harmon.ie named me the seventh most influential SharePoint person for 2014. Read more in Announcing the Top 25 SharePoint Influencers for 2014 on the harmon.ie blog.

I’m honored and humbled to be recognized as even in the same league as the other 24 people on the list. They are some of the smartest and most dedicated people in the SharePoint community. I hardly belong there with them. Thanks to harmon.ie for the recognition. Thanks also to anyone out there who finds my musings and activities useful and voted for me for this honor.

The Top 10

  • Andrew Connell, Co-Founder, Co-Host, Microsoft Cloud Show (@andrewconnell).
  • Joel Oleson, Global Collaboration Evangelist, Community Builder and Strategist (@joeloleson).
  • Todd Klindt, SharePoint Consultant, Rackspace Hosting (@toddklindt).
  • Christian Buckley, Chief Evangelist, Metalogix (@buckleyplanet).
  • Laura Rogers, Senior SharePoint Consultant, Rackspace Hosting (@WonderLaura).
  • Jeremy Thake, VP of Global Product Innovation, AvePoint Inc. (@jthake).
  • Marc D. Anderson, Management and Technology Consultant, Sympraxis Consulting LLC (@sympmarc).
  • Dux Raymond Sy, VP of Customer Strategy & Solutions, AvePoint Public Sector (@meetdux).
  • Jeff Willinger, Director of Collaboration, Social Business and Intranets, Rightpoint, World-wide SharePoint Speaker and Evangelist (@jwillie).
  • Spencer Harbar, Managing Director, Triumph Media Limited, Enterprise Architect, Microsoft (@harbars)

As a service to the business community, harmon.ie has commissioned the third annual ranking of the “Top 25 SharePoint Influencers.”  Prominent industry analyst Dana Gartner and Scratch Marketing + Media were tapped to identify those leaders who are helping others navigate the SharePoint/Yammer platform. Based on a finalist list of top 100 SharePoint professionals, a weighted formula was used to identify the top 25 U.S. SharePoint influencers. Selection was based on: each professional’s SharePoint knowledge and business impact; digital and social presence and influence; blog reach and frequency; depth of SharePoint topic coverage; citations by other influential bloggers; and more than 3,000 qualified community votes.

Microsoft Cloud Show Episode 016 – Interview with Marc Anderson on Recent Changes Impacting Customers on Office 365

MSCloudShow

Microsoft Cloud Show

A few weeks back, I sat down (virtually, of course) with Andrew Connell (@AndrewConnell) and Chris Johnson (@LoungeFlyZ) to record an episode of the Microsoft Cloud Show. Andrew was in Florida, I was in Boston, and Chris was way around the world in New Zealand. Ah, the wonders of modern technology.

The only place to stay up to date on everything going on in the Microsoft cloud world including Azure and Office 365.

Whether you are new to the cloud, old hat or just starting to consider what the cloud can do for you this podshow is the place to find all the latest and greatest news and information on what’s going on in the cloud universe.  Join long time Microsoft aficionados and SharePoint experts Andrew Connell and Chris Johnson as they dissect the noise and distill it down, read between the lines and offer expert opinion on what is really going on.  Just the information … no marketing … no BS, just two dudes telling you how they see it.

I was honored to be the very first guest on the show, which already had 15 excellent episodes in the can.

In Episode 016 – Interview with Marc Anderson on Recent Changes Impacting Customers on Office 365, we talked about a number of extremely important things that have been going on with Office365 lately.

I had done a post about one issue that has caused me and users of SPServices the most consternation, Office 365 Update Changes ‘Display Name’ on Required Fields and Andrew had posted about a few others one his blog in Office 365 Needs to Treat the UX as an API if Our Customizations are to Stay Off the Server.

Last week, I released SPServices 2014.01, which addresses the title changes (adding ” Required Field” to the title attribute of some required dropdowns), but there’s a bigger set of issues at play here, as Andrew alludes to in his post.

In the podcast, we talked about the impact of these changes as well as the mindset behind them from the Microsoft side.

If you do any client side development with SharePoint – and that’s where everyone is headed – you owe it to yourself to listen to the podcast. You’ll understand more about what changes to the DOM might mean for you as a developer, or even what might happen to you as a user of customizations that rely on the DOM being stable and predictable.

One things seems certain: we’ll see more changes like the ones we discussed in the podcast and they will have an impact on everyone, not just people replying on Office365. (The same issues started to crop up for people who have applied the December 2013 Cumulative Update (CU) for SharePoint 2010 on premises.)

I want to thank Chris and Andrew for inviting me in for a chat. Assuming I didn’t annoy them too much with my scatological terminology, maybe I’ll be able to visit with them again the next time a round of changes like this pop up and cause ripples in the SharePoint time-space continuum.

KnockoutJS with SharePoint: Fixing ‘Error: You cannot apply bindings multiple times to the same element.’

KnockoutJS LogoI’ve been using KnockoutJS to build functionality into SharePoint pages for a while now. (In case you’ve ever wondered, yes, it’s the same thing people mean when they simply say “Knockout” or “KO”.)

Setting everything up with KnockoutJS can take a bit longer than hard-wiring things with jQuery – depending on what you are trying to accomplish and what your background may be – but once it’s all in place, changes to functionality become much easier. Some people naturally think in the Model-View-View Model (MVVM) pattern, but it took some time for me to get my head around the idea. Early on it felt like not just a separation of church and state, but also separation of the apse from the nave and Arkansas from middle, lower Arkansas.

I’ve probably run into every newbie error in the book, and this one has gotten me multiple times.

Error: You cannot apply bindings multiple times to the same element.

Error: You cannot apply bindings multiple times to the same element.

The screen snippet above is from my favorite debugger, Firebug. The error message itself doesn’t give you much to go on. It makes basic sense, since multiple bindings on the same element would seem to be a bad idea, but it doesn’t tell you anything about why it’s happening or what you’ve done to trigger the error. It just kills the page load.

Let’s take a simple example. In one of the sets of pages I’m working on, we want to have a header section driven by one view model and a body section driven by another. The two bindings are in separate .js files because the header logic is reused across pages, while the body section is unique to individual pages. (We’re using SharePoint 2010 more as a back-end repository and identity management provider in this application and replacing virtually all the UI with custom pages.) Each of the .js files performs the binding for which it is responsible.

The markup – at a high level – looks something like this:

<div id="abc-page-header">
...
</div>
<div id="abc-page-body">
...
</div>

and the bindings occur in the JavaScript looking something like this:

ko.applyBindings(new HeaderViewModel(), document.getElementById("abc-page-header"));
...
ko.applyBindings(new BodyViewModel(), document.getElementById("abc-page-body"));

As you can see, each binding is scoped to the container for which it has responsibility. Using document.getElementById is straighforward: we should get a JavaScript object reference to the containing element with that id.

All well and good, right? The problem in this case comes in when you have no second argument, or even worse, a typo in the id. For instance, I ran myself silly with document.getElementById("ab-page-body"). Because the document.getElementById function returned null (the id wasn’t in the page), the binding occurred on the entire document, and therein arises the problem. Elements with data-bind now become bound twice, throwing the error.

It would be much better if the error told us a little more about what was happening, of course. For instance, the error might mention which binding is currently applied to the particular element where the issue arises. Even better would be some sort of warning when you attempt to apply bindings with a null parameter. Alas, this is not the case.

The simple fix is to find the place in your code where a ko.applyBindings is applied incorrectly. It’s not so hard if you know that’s the right thing to do. If you don’t, you may end up tearing down your code and starting afresh, which is rarely productive.

See Creating view models with observables for the [rather sparse] documentation on ko.applyBindings. Note that the second parameter must be a JavaScript DOM node, not a jQuery object. If you try to get fancy like this:

ko.applyBindings(new HeaderViewModel(), $("#abc-page-header"));

You’ll get a very clear error:

rror: ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node

Error: ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node

Moral of the story: always scope your bindings carefully!

jQuery Library for SharePoint Web Services (SPServices) 2014.01 Released

SPServicesHot on the heels of the short-lived SPServices 2013.02 and it’s younger, wiser sibling 2013.02a, comes SPServices 2014.01. I wanted to do a new release with some cool new functionality, but Microsoft really forced my hand with some changes to title attributes on some column types. (See: Office 365 Update Changes ‘Display Name’ on Required Fields)

I recommend jQuery 1.10.x with this release. Even if you are a happy user of an older release of SPServices, I’d recommend upgrading to this release.

The headlines for this release:

  • Fix for the ” Required Field” change to column titles noted above on Office365 buildversion 16.0.2510.1204 (or thereabouts) and above and SharePoint 2010 with the December 2013 CU
  • New function SPGetListItemsJson
  • Exposed existing private function DropdownCtl as public function SPDropdownCtl
  • New objectType for SPXmlToJson: JSON
  • Case insensitive query string values with $().SPServices.SPGetQueryString
  • Added ClaimRelease operation to the Workflow Web Service

The SPGetListItemsJson function is pretty cool, if I do say so myself. When I fixed the operation GetListItemChangesSinceToken in 2013.02, I saw the possibility for an auto-conversion of the returned data to JSON with only one SOAP call. Because GetListItemChangesSinceToken returns both the list schema and the data, I’m able to parse the schema and return the data as JSON using SPXmlToJson. You can also pass in your own mappingOverrides if you need to.

GetListItemChangesSinceToken is also cool because it allows you to retrieve content deltas by passing in the old changeToken, and SPGetListItemsJson returns the changeToken and also accepts it for future calls. This is great support for the types of Single Page Applications I discuss in my ongoing blog series Single-Page Applications (SPAs) in SharePoint Using SPServices.

While I was building SPGetListItemsJson, I was working on a client project where we stored JSON as text in a Multiple lines of text column. To facilitate conversion of that data to internal JSON, I added an objectType to SPXmlToJson of “JSON”. This allows us to request automatic conversion of text-based JSON data to internally represented data simply by specify the JSON objectType in a mappingOverride. (The function uses jQuery’s $.parseJSON.)

With the kerfuffle about the Office 365 Update Changes ‘Display Name’ on Required Fields and the attendant fixes I needed to do in SPServices, I decided to make the SPDropdownCtl function I’ve been using for years public.  It’s not for the faint of heart, as it passes back a variable object depending on the type of “dropdown”, but it should help some people in building their own applications.

As usual, there are also a number of additional changes to fix existing bugs or improve efficiency (yes, I’m still able to improve on my old code, and I expect that will continue).

You can see the full list of enhancements and improvements on the download page. Note the link to the Issue Tracker items for this release. For posterity, here are links to the release notes showing all the fixes and improvements from the Issue Tracker on Codeplex.

New Functionality

Alpha Issue Tracker Item Function Description
ALPHA1 10216 $().SPServices.SPGetListItemsJson New Function: SPGetListItemsJson
ALPHA1 10221 $().SPXmlToJson Add new objectType to SPXmlToJson for text columns containing JSON
ALPHA1 10218 $().SPXmlToJson Add sparse parameter to SPXmlToJson
ALPHA1 10195 $().SPServices.SPGetQueryString Case insensitive SPGetQueryString?
ALPHA3 10229 $().SPServices.SPDropdownCtl Make DropdownCtl Function Public
ALPHA4 10230 $().SPServices.SPDropdownCtl Return optHid input element in SPServices.SPDropdownCtl

New Operations

Alpha Web Service Operation Options MSDN Documentation Issue Tracker Item
ALPHA2 Workflow ClaimRelease item, taskId, listId, fClaim http://msdn.microsoft.com/en-us/library/workflow.workflow.claimreleasetask(v=office.12).aspx 10222

Bug Fixes and Efficiency

Alpha Issue Tracker Item Function Description
ALPHA1 10211 $().SPServices.SPGetQueryString LMenuBaseUrl is undefined
ALPHA1 10192 $().SPServices.SPGetQueryString DeleteWeb needs_SOAPAction Value Incorrect
ALPHA1-2 10219 $().SPServices.SPXmlToJson Various Fixes to SPXmlToJSON
ALPHA2 10224 $().SPServices.SPCascadeDropdowns ParentObject Null in $.fn.SPServices.SPCascadeDropdowns
ALPHA2 10225 $().SPServices.SPXmlToJson SPXmlToJson – Fix Date/Time Conversion
ALPHA2 10226 $().SPServices.SPCascadeDropdowns Cascade Dropdowns Do not work if Fields Are Required
ALPHA4 10231 $().SPServices.SPCascadeDropdowns Title Changed for Required Fields after CU for Sharepoint 2010
BETA2 10238 $().SPServices.SPDisplayRelatedInfo SPDisplayRelatedInfo not working in SPServices 2014.01
BETA2 10236 NA Replace .attr(“value”) usage with .val()
BETA2 10235 $().SPServices.SPRequireUnique SPRequireUnique bug getting entered value

Getting Around SharePoint’s Threshold Limits for Large Reference Lists

In SharePoint 2007, we could build lists that contained as many items as we wanted and access them in any way we wanted. We may have done stupid things that were bad for server performance, but if we knew what we were doing there were few limits. We had the mythical “2000 item” rule of thumb (which had little basis in reality in many, many cases) but otherwise it was up to us. (See: Plan for software boundaries (Office SharePoint Server))

In SharePoint 2010, Microsoft introduced threshold limits to protect us from ourselves. This seemed counter intuitive to me, since with the upgrade to SharePoint 2010, one also had to go to 64 bit architecture and put a heck of a lot more iron behind the SharePoint farm. While we could potentially store 30,000,000 items in a list (30 million!), we had a list view threshold of 5000 items. (See: SharePoint Server 2010 capacity management: Software boundaries and limits)

SharePoint 2013 maintains similar limits to 2010, with 5000 items the limit for a list view. (See: Software boundaries and limits for SharePoint 2013)

List View ThrottlingSomehow, as technology has moved forward – significantly – we’ve got more limits.

5000 items is way too many to ever show in a list view, but it may not be if you want to do some client side processing. It doesn’t matter if you’re trying to build a truly bloated, Bad Idea list view or request data using REST, you’re stuck with that 5000 item limit.

But what if you know what you are doing and the 5000 item limit doesn’t work for you? I’ve written in the past about why we shouldn’t change some of the threshold limits (e.g.,  The SharePoint 2010 “List View Lookup Threshold” and Why We Don’t Change It).

If we’re working on Office365, we simply can’t change the limits – Microsoft gets to decide what they are. Sometimes those limits change without notice, too, so it’s truly out of our hands.

Well, what does all this add up to? Let’s take a specific example.

I needed to provide auto complete functionality in an InfoPath form. It was the classic scenario: we had a list of [in this case] 19,000+ cities and towns and we needed a good UX for entering selections into the form. We run into this sort of thing with data like cities and towns all the time. There are too many choices for a dropdown to make any sense, and SharePoint doesn’t offer up any better alternatives. jQueryUI’s autocomplete function is a perfect solution for this sort of thing.

The data was in a spreadsheet, and it’s easy to upload data from a spreadsheet to a SharePoint list. Bingo, bango, done, right? Well, no. It’s impossible to upload data from a spreadsheet *and* index the column. We need to index the column so that we can make type of requests requests that we need for autocomplete – basically, give me all of the items that begin with or contain this string – or else we run into the 5000 item threshold error on our requests.

No problem! We’ll just upload the data and *then* index the column. Not so fast, mister. When you try to index the column you run into – you guessed it – the 5000 item limit. No indexee, no laundry.

So seemingly we’re stuck. But wait – we can just create the list in the UI, add the index, and paste all 19,000 items into the Brave New World of SharePoint 2013′s “data sheet view” aka “Quick Edit”. Sadly, when I tried to paste in more than a few hundred items, the browser hung on me. This was on Office365, and I tried several different browsers. SharePoint Online seems to prefer nibbles to big bites of data. Unless I spent days just doing the pasting, this was never going to happen.

In this case, I decided to simply store the data in a text file containing JSON rather than trying to force it into a list. Thanks to @bpmccullough for the suggestion on Twitter.

The data I originally had received for the sities and towns was in a CSV file. I found a nice little site that would convert the CSV format to JSON (bookmark this one; you’ll need it in this JSON-oriented world).

Once I had the JSON file uploaded to a Document Library, the code below is what I used to set up the autocomplete. We wanted the autocomplete to allow multiple choices, so there’s a little monkeying around to enable that. It wasn’t tremendously peppy (19,000 cities, after all), but it worked. Remember, kids: this is an example. Don’t expect to drop it into your page and have it work.

var citiesAndStates = [];

// Get the City and State data from the file with JSON data
$.getJSON(&quot;/Shared%20Documents/CityState.txt&quot;, function(data) {
  var results = $(data);
  // Push the data into an array which is appropriate for jQueryUI autocomplete
  citiesAndStates = ($.map(results, function(item) {
    return {
      label: item.State + &quot; - &quot; + item.City, // Show &quot;State - City&quot; [e.g., MA - Boston] for selection
      value: item.City + &quot;, &quot; + item.State // Show &quot;City, State&quot; [e.g., Boston, MA] upon selection
    }
  }));
});

// When the field is available and gets focus, set up the autocomplete behavior
//ctl00_ctl42_g_6069846d_1b7f_4890_b767_2bdc15d2b133_FormControl0_V1_I1_S15_I4_T5
$(document).on(&quot;focus&quot;, &quot;input[id$='FormControl0_V1_I1_S15_I4_T5']&quot;, function() {
  if ($(this).data(&quot;autocompleteSet&quot;) === undefined) {
    $(this).data(&quot;autocompleteSet&quot;, true);

    $(this)
    // Don't navigate away from the field on tab when selecting an item
    .bind(&quot;keydown&quot;, function(event) {
      if (event.keyCode === $.ui.keyCode.TAB &amp;&amp; $(this).data(&quot;ui-autocomplete&quot;).menu.active) {
        event.preventDefault();
      }
    }).autocomplete({
      source: function(request, response) {
        // Delegate back to autocomplete, but extract the last term
        response($.ui.autocomplete.filter(citiesAndStates, extractLast(request.term)));
      },
      minLength: 3,
      focus: function() {
        // Prevent value inserted on focus
        return false;
      },
      select: function(event, ui) {
        var terms = split(this.value);
        // Remove the current input
        terms.pop();
        // Add the selected item
        terms.push(ui.item.value);
        // Add placeholder to get the semicolon-and-space at the end
        terms.push(&quot;&quot;);
        this.value = terms.join(&quot;; &quot;);
        return false;
      }
    });
  }
});

function split(val) {
  return val.split(/;\s*/);
}

function extractLast(term) {
  return split(term).pop();
}

One note here: This approach basically violates my “put all data into a list so that end users can maintain it” rule. However, the approach I came up with was the best one for the situation. It’s still possible for a reasonably savvy (meaning “non-developer”) user to manage the data by downloading the file and using a JSON-aware editor.

The main thing was that we were able to set up something that worked, regardless what the Office365 limits may change to.