The Medium Has the Message and My Blog Is Trying to Catch Up

I’ve really been digging the content I’ve been finding through Medium for the last few months or so. The Web is ever-evolving and to me Medium represents a new paradigm for Web publishing and content consumption. It’s sort of blogging combined with content crowd-sourcing combined with highlighting like I have on my Kindle combined with… Well, it’s unique, so it’s not really just the sum of those parts.

To me, one of the best parts of Medium is the Staff Picks and Top Stories. These two categories give me solid content to read that is either vetted by the platform owners or popular with the platform readers. One of the cool things about this is that it cuts across all topic areas. I’m as likely to want to read one of Eric Elliott’s (@_ericelliott) excellent posts about JavaScript and its communities like this or this or something like When the heck did learning to code become cool? And why it sucks to be a beginner today… which are squarely in my own wheelhouse to interesting takes on Web design like Optical Adjustment – Logic vs. Designers.

But what makes it even more fun is the stuff I run across that to many people would seem sort of random. None of us is so one-dimensional that we cannot enjoy reading something completely new to us. Medium ensures that when we go off on one of those mental tangents, that it’s a higher quality one.

When I spot one of these seemingly random posts, I can see about how long it might take me to read it, so it’s clear going in if how much time I’ll need to invest. (I’m a pretty fast reader, so for me the number is usually an upper bound – YMMV.) Those times must be built up magically based on how long people really spend and the posts and seem pretty accurate to me.

How many minutes?

The biggest thing I notice as I read posts on Medium is that I feel a need to up my own game, to write more pithy and valuable posts. Ever since I started blogging, I’ve had a little voice in my head that writes posts that come out of ordinary, every day experiences. These aren’t the “here’s a piece of code to fix a particular problem” posts, but often the softer stuff that makes the fact that the code exists have more purpose. It might have nothing to do with my professional life at all. (Maybe it’s hard to believe, but I do have a few other interests besides SharePoint.) I wish I actually spent the time to get more of those posts written.

I found an article that shows how to make your own blog a bit more “Medium-like” and I’ve added some new plugins to my blog here based on those suggestions. (See WordPressium: Creating a Medium-like Experience)

As of today, you can do a few new things on my blog…

Selection Sharer

Courtesy of Hans van Gent’s Selection Sharer plugin, you can now highlight any piece of text in one of my posts and send it as a Tweet, post it to LinkedIn, or send it in an email. (This assumes I ever say anything quotable, which I know is a huge assumption.) I would expect that he’ll add some more sharing options over time.

Reading Time

The Reading Time plugin adds some info on how long a post might take to read. You’ll see the estimate based on an average reading speed at the top of each post as you visit it. As you stay on the page, a little progress bar shows how much of that time has elapsed. Of course, reading a post full of code is different than just reading prose, so time will tell how useful this is. It can at least be a little game; can you beat the progress bar?

I hope that you find these two new capabilities useful. Let me know what you think!

SharePoint Evolution Conference 2015 Wrap Up

It’s been a busy few weeks in my life. First I was in London at the SharePoint Evolution Conference, then home for a week, then off to Microsoft Ignite in Chicago, then back home, and boom! I was heading out the back to put some burgers on the grill, I missed the second to the last step (of a grand total of 3!), fell, and was in excruciating pain with a broken ankle. After surgery, I’m the proud owner of some new hardware in my ankle and a 6-8 week “no weight bearing” edict.

I usually try to do a bigger write up after a great conference like SharePoint Evolution, but I’m going to flake out and just post my presentations. I do want to thank Steve Smith and Zoe Watson, along with their entire team, for an incredible experience.

New GitHub Repository for KnockoutJS Binding Handlers

KnockoutJSYesterday I created a new GitHub repo for KnockoutJS binding handlers for use with SharePoint. I’ve been using KnockoutJS for over a year now, and love working with it to build Single Page Application (SPAs) and other interactive functionality inside SharePoint.

I thought starting a repo that could store bindingHandlers for KnockoutJS that are generally useful for working with SharePoint would be useful for a lot of people.

sympmarc/KOBindings on GitHub

See the Creating custom bindings section of the KnockoutJS documentation for an overview on what binding handlers are all about.

I’ve collected some of these binding handlers and built others. Where possible, I give credit to the source in each file. Unfortunately, in my first year or so of using KnockoutJS, I collected a lot of these without maintaining the source location. If you see your work here, please let me know and I will give you credit!

  • /src contains one file per bindingHandler
  • /html contains example usage of the corresponding bindingHandler

If you’ve been working with KnockoutJS and SharePoint and would like to contribute, feel free to issue a pull request. I’m hoping this will become a repo that is useful for the SharePoint community as well as the KnockoutJS community at large.

I’m also very open to suggestions on how to structure the repo to make it optimally useful. To get things rolling, I’ve posted some of the simpler binding handlers I use, most of which help in working with jQueryUI capabilities.

Using the SharePoint Color Palette Tool to Create Customized Composed Looks

At the great SharePoint Evolution Conference last week, someone – I wish I could remember what session it was! – mentioned this great little tool. It helps you to create a very detailed theme for SharePoint 2013. You can save the file into a .spcolor file, which you can upload to the Theme Gallery in your SharePoint Site Collection.

Go to the Microsoft Download Center to grab the SharePoint Color Palette Tool. It’s a quick download and install. Once you have it loaded and launch it, you’ll see this:

The color palette tool provides color palette functionality for use with SharePoint designs.

SharePoint Color Palette Tool

In my example below, you can see an example of a customized theme. I found a photo of the lovely Sonya Koptyev (@SonyaKoptyev) presenting at SPC last year to use as my background and I made one other small color change to the suite bar. Then I saved the file as Sonya.spcolor.

The Sonya Color Palette

The Sonya Color Palette

Next we upload the .spcolor file to the Themes Gallery. (Site Settings -> [Web Designer Galleries] Themes) In this case, I uploaded my .spcolor file to the 15 folder because it’s built for that version (2013) of SharePoint.

Theme Gallery

Theme Gallery

Once you’ve uploaded your new palette file, you can create a new Composed Look with it (Site Settings -> [Web Designer Galleries] Composed looks). The image below shows all of the out-of-the-box Composed Looks.

The Composed Looks Gallery contains all of the looks designed for your Site Collection.

Composed Looks Gallery

When you create a new Composed Look, you specify a Master Page URL, a Theme URL, an Image URL, and a Font Scheme URL. The combination of these components make up a Composed Look.

In the screenshot below, you can see how I’m creating a new Composed Look using my Sonya.spcolor file.

Sonya Composed Look

Sonya Composed Look

Once I’ve saved the new Composed Look, I can apply it to my site ((Site Settings -> [Look and Feel] Change the look). After I select my new Composed Look, voila! A quick new look for my site!

Previewing the Sonya Composed Look

Previewing the Sonya Composed Look

But wait. “Where’s my background image?”, you’ll probably ask. I certainly did.

The background image you select in the SharePoint Color Palette Tool doesn’t automagically get saved in the .spcolor file. That’s what the Image URL is for in the Composed Look. So upload that image (in my case, the lovely Sonya presenting) and add the URL to it in the Image URL for your Composed Look.

Adding the Sonya image to the Composed Look

Adding the Sonya image to the Composed Look

And now: voila for real!

Previewing the Sonya Theme on my Team Site

Previewing the Sonya Theme on my Team Site

The SharePoint Color Palette Tool is just a v1.00 tool, but it seems to work reasonably well. Let’s hope that Microsoft builds something like this right into the UI rather than keeping it a separate tool.

By the way, the reason I still have the image of Sonya presenting is that I love the quote she had in her slide:

"The world hates change, yet it 
is the only thing that has 
brought progress." 
Charles Kettering

 

 

Moving from SPServices to REST, Part 3: JSON vs. XML

Summary: When you move from SOAP to REST, you’ll want to understand the differences between XML and JSON as well. Modern Web developers are most likely to use JSON, and this is a great time to switch.

Most auto mechanics understand that there are several different measurement systems – and therefore toolsets – that they have to use to fix up cars, whether under the hood or on the outside body. Where I sit here in the USA, it’s our unique system versus almost everyone else’s (metric). That’s sort of where we are if we’re still using SOAP and XML instead of REST and JSON.

2014 Fiat 500

Under the hood of a 1956 T-Bird by Mark Turnauckas https://flic.kr/p/f14uV8

The SOAP Web Services speak XML. That is, we send XML in our requests and we get XML in the responses. These days many developers feel those services are “chatty” and that “XML is bloated.” I’m not so sure that’s really the case, but I can go along with it.

When we receive XML in the response from a SOAP call to the server, we have to parse it apart so that we can use the data. The most common operation that people use in SPServices is GetListItems, which allows us to pull list data from the server to the client. With a call to GetListItems we get a packet back that looks something like this from a Tasks list:

call-to-getlistitems-returns-task-list-2

With the SOAP Web Services, XML is our only option. There’s no way to request anything else. REST, on the other hand, is usually used to request JSON.

To bring SPServices more into the modern way of doing things, I added a function in 0.7.1 called SPXmlToJson and then another in 2014.01 called SPGetListItemsJson. These two functions make it easy – really easy – to convert XML to JSON. You don’t have to know much about either method of storing data to get JSON back.

With REST we can still choose to get XML in the response, but we also have the option to request that the server send us JSON. Because JSON is a text representation of JavaScript objects, the conversion is much more straightforward, with just a call to $.parseJSON (assuming you’re using jQuery).

JSON is preferable because it doesn’t require much – if any – translation when we want to use it. You may already be converting the XML you get back with SPServices calls into JSON, either manually or with a call to SPXmlToJson or SPGetListItemsJson.

JSON stands for JavaScript Object Notation. It’s a way to store data in a complex, object-based JavaScript structure rather than what many of you may be used to doing with individual variables.

For example, when I get a task back from GetListItems, I could create a set of variables, like this:

var thisId = $(this).attr("ows_ID");
var thisTitle = $(this).attr("ows_Title");
var thisDueDate = $(this).attr("ows_DueDate");

When I answer questions in the SPServices Discussions, a lot of the code people post does something like this. It’s the way I used to do things, too.

With a call to REST, I get an object back that is all ready to go.

call-to-rest-gives-object-back-3

Taking it one step further, I can build a constructor function that takes the task as I get it back from a call to the server and converts it into a JSON structure of my own choosing, perhaps adding a few new properties I may need down the road:

function Task(data) {
  this.ID = data.ID;
  this.Title = data.Title;
  this.DueDate = moment(data.DueDate);
  this.Status = data.Status;
  // etc.

  this.Complete = this.Status === "Completed" ? true : false;

};

Note the conversion of the DueDate in the function above. In most of my applications these days, I use the MomentJSJavaScript library. It gives us a huge number of date- and time-oriented functions. Dealing with date/time conversions and arithmetic can be extremely messy, and MomentJS makes it easy. So rather than simply storing the text-based value of DueDate that I get back in the XML or JSON from a call, I store the DueDate converted into a “moment,” which is the lingua franca to use MomentJS’s helpful functions.

In the code examples above, I’ve gone from the rather brute force method I used to use where I used a lot of individual variables, to using a JSON representation, to using a constructor function to “build” each task from the results of a call. The first two of these methods require basically the same amount of code, but the second is far easier to work with when we pass the task back out to whatever code we want to work with it next. The third approach, while it introduces yet another level of abstraction, gives us even more flexibility, as we can decide to add a new element to any tasks inside the constructor function and it will be available in tasks everywhere.

Using SPXmlToJson and SPGetListItemsJson is another way to move your code forward without actually converting to the REST services right away, say if you are still on SharePoint 2007 or 2010. In fact, one of the main reasons I wrote these two functions was so that I could start working with JSON in a project on SharePoint 2007 using KnockoutJS. Yes, you can use the tools and frameworks all the cool kids are using even on ancient platforms.

In Part 2, I outlined a way for you to think about abstracting your CRUD calls using SPServices so that you could slide REST underneath at a later point. By using the two XML to JSON capabilities in SPServices, you can also start returning JSON to your applications from those abstractions, taking yourself one step closer to REST.

There are a few caveats here. I didn’t try to match the JSON formats that the SharePoint 2013 REST services return when I built my functions, though the way I hand you the data are similar. Similar doesn’t mean the same, of course.

Here’s an example. When you request list items using SPGetListItemsJson and don’t provide any custom mapping of your own, SPUser fields, which are also known as Person or Group columns, are returned in a JSON object that looks like this:

request-list-items-using-spgetlistitemsjson-returns-json-object-4

If you make a REST call to SharePoint 2013, SPUser fields are returned in a JSON object that looks like this, assuming you have requested the Id and Title using a projection (more on this in a future article in the series):

spuser-fields-returned-in-json-object-5

As you can see, there are some naming and formatting differences. I return “userId” and the REST call returns “Id”, for instance. In my opinion those differences are manageable, but it will take some work when you switch to REST because your application code will expect things in the format that SPGetListItemsJson provides. This is another reason why constructor functions can be helpful: they give us a place to do the isomorphic mapping from one data representation to another.

The upshot here is that you can:

  1. Abstract your CRUD operations as in Part 2, and
  2. Return JSON to your application rather than XML

As before, your application shouldn’t care where the data lives, how it’s stored or how we get it; it should only care about processing data that has a consistent format.

If you follow these suggestions, your code might go from something like this inline request:

var p = $().SPServices({
  operation: "GetListItems",
  ListName: "Tasks",
  CAMLViewFields: "<ViewFields>" +
                "<FieldRef Name='Title'/>" +
                "<FieldRef Name='AssignedTo'/>" +
                "<FieldRef Name='RelatedItems'/>" +
                "<FieldRef Name='Priority'/>" +
                "<FieldRef Name='Status'/>" +
                "<FieldRef Name='DueDate'/>" +
                "<FieldRef Name='Author'/>" +
                "</ViewFields>"
});

To this abstracted request:

// Get all the Tasks data
ProjectName.Promises.Tasks = $().ProjectName.Tasks.readAll();

// Read items from the Tasks list
$.fn.ProjectName.Tasks.readAll = function(options) {

  var opt = $.extend({}, {}, $.fn. ProjectName.defaults, options);
  var p = $().SPServices({
    operation: "GetListItems",
    ListName: "Tasks",
    CAMLViewFields: "<ViewFields>" +
        "<FieldRef Name='Title'/>" +
        "<FieldRef Name='AssignedTo'/>" +
        "<FieldRef Name='RelatedItems'/>" +
        "<FieldRef Name='Priority'/>" +
        "<FieldRef Name='Status'/>" +
        "<FieldRef Name='DueDate'/>" +
        "<FieldRef Name='Author'/>" +
      "</ViewFields>"
  });

  return p;

}; // End $.fn. ProjectName.Tasks.readAll

To this abstracted JSON-based request:

// Get all the Tasks data
ProjectName.Promises.Tasks = $().ProjectName.Tasks.readAll();

// Read items from the Tasks list
$.fn.ProjectName.Tasks.readAll = function(options) {

  var opt = $.extend({}, {}, $.fn. ProjectName.defaults, options);
  var p = $().SPServices.SPGetListItemsJson({
        listName: opt.TasksList,
        CAMLViewFields: opt.TasksListViewFields,
        CAMLQuery: camlQuery,
        CAMLQueryOptions: opt.TasksListQueryOptions,
        mappingOverrides: opt.TasksListMappingOverrides,
        changeToken: opt.changeToken
  });

  return p;

}; // End $.fn. ProjectName.Tasks.readAll

“Hold on here,” you might say. “That’s more code than I was writing before!” Absolutely true. And if you have a little snippet in a Content Editor Web Part (CEWP) that just reads a few items from a list and that’s it, then this effort might not be worth it. However, if you are building Single Page Applications (SPAs) or even little “portlets” for use throughout your Site Collection(s), it may make total sense.

For instance, if you have a customized Tasks or Announcements list in every Team Site that you are reading from and writing to, then abstracting those calls and storing them centrally may be a great idea. I do this sort of thing all the time. I load my data access operations into the master page in the Site Collection and then use them reliably from subsite to subsite. If you’re working on a larger team – which I tend not to do – it will require coordination, but it will also give you the ability to parse out atomic programming tasks across your team. Maybe one person is really good at data access and another is really good at HTML and CSS. This approach lets you parse out the work based on everyone’s skills and interests.

But I digress. The goal of this series is to help you move from SOAP to REST over time, not reorganize the roles on your team. Hopefully you can see that taking a few of these steps now or when you begin your next project, you’ll be putting yourself in a better position for the long run. These approaches may not help with everything you are using SOAP to accomplish – the SOAP services still cover more surface area than CSOM or REST, though that is changing – but it will put your most frequently-used sections of code in a good spot when it is time to move to REST.

Those auto mechanics know that there isn’t a huge difference between using a metric spanner and an Imperial wrench (other than getting everyone to agree on the terminology). XML and JSON are just dialects or different systems that accomplish basically the same thing: wrapping data up in packets that can be deciphered easily on the other end.

This article was first published on IT Unity on April 17, 2015. Visit the post there to read additional comments.