Synchronous XMLHttpRequest Warning with SPServices and Recent Browsers

If you’re working in the latest versions of Chrome (~40+) – and maybe Firefox – and you use SPServices, you may start to see an warning:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user’s experience. For more help, check http://xhr.spec.whatwg.org/.

Vigilant SPServices user frankhale reported this to me the other day in the SPServices discussions on Codeplex, which is – at least at the moment – the best place to get help with SPServices. You can also add an issue on Github (sympmarc / SPServices) if that’s your fancy.

The warning is thrown in jQuery, not SPServices, but it’s an SPServices issue.

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user’s experience.

First off, it’s a warning, not an error. Your code will continue to work in the near term, at least.

Because of some backward compatibility concerns, I’ve left a few synchronous calls internally to SPServices in place. Those calls are what are causing the warning. In particular, it is most likely that the warning is being thrown for you because of a synchronous call on the $().SPServices.SPGetCurrentSite function. The reason for this is that early in the SharePoint 2007 days it was difficult to determine the current site without a call to the Webs.WebUrlFromPageUrl operation. Unfortunately, it seems that I’m making that call in SharePoint 2010 and 2013, even though the current site is available in JavaScript variables.

So, the bottom line is: “Carry on.” I’ll get a fix into the next release of SPServices for this. In the meantime you should be fine.

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!

Don’t Use a Query String Parameter Called ID Unless You Mean the Item ID

The other day I got a question from my pal D’arce Hess (@DarceHess):

I am using jsLink on a couple lists and I have an interesting circumstance I’m running into.

Scenario: I have a list of Work Centers and each work center has associated machines that are in another list.

I’m having an interesting situation that when I click on the link in the Work Center, it is supposed to reload the same page and append the Work Center ID to the url  so that it will load the associated machines in the other list. I have the functionality working, however for some reason, when it adds the ID and reloads the page, it is changing the page layout from the layout that is chosen for the initial .aspx page.

Since it is literally re-loading the same page, just with an additional ID, I’m not creating new pages. Any ideas of what may be causing this?

After some back and forth about it, I realized that D’arce was using a query string parameter named “ID”. (I know, it should have been obvious to me right away, but we have a way of using shorthand when we describe technical issues that always makes a little back and forth useful.)

ID seems to be very reserved in SharePoint. Someone probably left some sort of back door thing in SharePoint once a long time ago, because I’ve seen using the ID parameter on the query string for anything other than the item ID cause issues way back to SharePoint 2007 at least.

By switching from ID to WorkCenter for the parameter name, all was right in the world again. For example, instead of “ID=1″, “WorkCenter=1″. Not only does this fix the issue, you end up with a query string parameter name that is more descriptive. That’s useful down the road for maintenance and will even make more sense to users. “That URL is ugly” may become “Oh, I’m selecting the WorkCenter”.

m4s0n501

SPServices Stories #22 : SPServices SharePoint Attachments in Internet Explorer 9

This entry is part 21 of 21 in the series SPServices Stories

Introduction

This is another story I ran across on Twitter and wanted to add to the SPServices Stories series. I wrote about my own experience getting attachment uploading to work in my post Uploading Attachments to SharePoint Lists Using SPServices. My cheat in that case was to change the DOCTYPE to HTML5 in a SharePoint 2010 master page. It was a cheat in the sense that it broke a lot of basic SharePoint functioning. Luckily I could get away with it in that particular case.

In this story, Jason Williams (@JayWll) explains how he got uploading to work with the fileReader polyfill. As much as all of us would like to be working with the latest and greatest technologies, in reality most organizations – especially larger ones – don’t update their tech very often. In Jason’s case he needed the upload capability to work with IE9, which doesn’t have a lot of the HTML5 spec implemented in it.

I’ve combined two of Jason’s posts here, SPServices addAttachment jquery example and SPServices SharePoint Attachments in Internet Explorer 9. Jason built on a post from Brendon Wilbore (@bjwildbore) to get things up and running. This is one of the great things about the SharePoint community: there are many people out there who are generous enough to post their work so that we can build upon it.

SPServices SharePoint Attachments in Internet Explorer 9

Brendon Wilbore:

If you’re having a few issues adding attachments via ajax and SPServices on SharePoint have a look over the code snippets below.

To upload a file to a list you need to make use of the fileReader javascript class, using the readAsDataURL method and stripping the first part off the dataurl to get the base64 component. Then submit this to SPServices.

I’ve been asked a few times to add the ability to upload attachments to SharePoint tools that I’ve created, and I’ve never been able to achieve it until I eventually came across this blog post last week.

If (like me) you’re developing in a front-end only way without any server-side programming then it seems like this is the way to upload files and attach them to SharePoint list items.

It relies on the javascript fileReader feature so your users will need a fairly modern browser… which is where I ran into trouble. The default browser deployed within my company is Internet Explorer 9, and that doesn’t have fileReader support.

With much work and even more googling I was able to get this technique to work in Internet Explorer 9. In the future I’ll write more about how I managed it, and how you can too!


There was a problem, though – the solution relies on the fileReader JavaScript feature which requires Internet Explorer 10, and the default browser deployed within my organization is Internet Explorer 9. What we need is a fileReader alternative for older browsers. Thankfully, such a thing exists. Today I’m going to post some example code that uses the fileReader polyfill and works in older browsers.

What You Need

The code has several pre-requisites. You’ll need jQuery, jQuery UI, SPServices, SWFObject and the JavaScript and flash file that form the fileReader polyfill.

For the purposes of my demo I created a simple SharePoint list called “File Attachment Test.” The list has a single field – title – and attachments to the list are enabled. Your list is probably named differently, so you’ll need to change the references in the code to reflect your list name.

The Code

<html>
<head>
  <meta charset="utf-8" />
  <title>File Attachment Test</title>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
  <script type="text/javascript" src="js/jquery.FileReader.min.js"></script>
  <script type="text/javascript" src="js/jquery.SPServices-2013.01.min.js"></script>
  <script type="text/javascript">
    var selectedfile = false;

    $(document).ready(function() {
      $('input#itemfile').fileReader({filereader: 'js/filereader.swf'});

      $('input#itemfile').change(function(e) {
        selectedfile = e.target.files[0];

        $('span#filename').html(selectedfile.name);
        $('span#fileinput').hide();
      });

      $('input#createitem').click(function() {
        $().SPServices({
          operation: 'UpdateListItems',
          async: false,
          listName: 'File Attachment Test',
          batchCmd: 'New',
          webURL: '/demo',
          valuepairs: [
            ['Title', $('input#itemtitle').val()]
          ],
          completefunc: function(xData, Status) {
            if (Status == 'success' && $(xData.responseXML).find('ErrorCode').text() == '0x00000000') {
              currentitem = $(xData.responseXML).SPFilterNode("z:row").attr("ows_ID");
              alert('List item created with ID ' + currentitem);

              if (selectedfile) {
                filereader = new FileReader();
                filereader.filename = selectedfile.name;

                filereader.onload = function() {
                  data = filereader.result;
                  n = data.indexOf(';base64,') + 8;
                  data = data.substring(n);

                  $().SPServices({
                    operation: 'AddAttachment',
                    async: false,
                    listName: 'File Attachment Test',
                    listItemID: currentitem,
                    fileName: selectedfile.name,
                    attachment: data,
                    completefunc: function(xData, Status) {
                      alert('File uploaded');
                    }
                  });
                };

                filereader.onabort = function() {
                  alert('Upload aborted');
                };

                filereader.onerror = function() {
                  alert('Upload error');
                };

                filereader.readAsDataURL(selectedfile);
              }
            } else alert('List item creation failed');
          }
        })
      });
    });
  </script>
</head>
<body>
  <p>Title:<br><input type="text" id="itemtitle"></p>
  <p>File:<br><span id="fileinput"><input type="file" id="itemfile"></span><span id="filename"></span></p>
  <p><input type="button" id="createitem" value="Go!"></p>
</body>
</html>

Notes

The fileReader polyfill takes the file input box and puts the flash file on top of it, so that the file selection and upload is handled by flash instead of natively in the browser. I found that this fell apart if the file input box didn’t remain in the same place on the page. In other words, I had problems if I tried to use jQuery’s .show() and .hide() functions (or similar).

I solved this by putting the file selection form in a pop-up window. If the page you place your form on is static (i.e. nothing changes after the DOM is loaded) then you shouldn’t have this problem.

Enjoy!

Simple Rules for SharePoint Permissions

PermissionsI get questions all the time about how to set up permissions in SharePoint.

Permissions are hard. It’s not just you. And if you don’t do them right, they turn into a tangled ball of string in a drawer that no one can ever get untangled.

Here are some of my rules of thumb. They are intentionally broad brush and some of them may not apply directly to you, yadda, yadda. But time and time again, these rules seem to work.

KISS

First and foremost, keep it simple. Complexity is your enemy. The site topology and list structures should be driven partly as a way to keep “keep it simple” true.

Open Is Good

Collaboration is hard when permissions are tight. Yes, you’ll want to lock things down for some content. That’s normal. But if you create separate Site Collections for everything – Site Collections are a permissions barrier – then you will find that your collaborative goals may not come true.

Highest: Best

Apply permissions at the highest level and only break inheritance when you need to. Permissions can be applied at the Site, List/Library, and item levels. Whenever possible, you want to avoid item-level permissions. There are performance concerns, but they are tiny compared to the administrative nightmare they turn into.

Out of the Box

Use the out of the box permissions unless you need something else. You know what these are:

  • Read
  • Contribute
  • Full Control

90+% of the time, those three permissions levels cover things. Most of the other out of the box permission levels are too esoteric to be useful (e.g., Design).

Groups, Not Individuals

Always use permissions groups, never individuals. For instance, we should have an HR Department permission group and not just give permissions to a person directly. This is even true if there is just one person in a group. If someone leaves the organization, you simply swap them out of groups for their replacement and you’re all set.

Distribute

Let site owners manage their own permissions if you can. SharePoint has a distributed permission model, and you want to let it work. That means that teams should be allowed to mess up their own permissions and external sharing and also be able to fix it. You simply can’t do it all. But you absolutely should be available to help if things get out of hand.

Finally…

Following these simple rules can save you so many headaches. If you’ve had SharePoint up and running for more than a few months, your ball of string is probably already a bit snarled. Don’t let it get much worse before you take a pass through and clean the permissions up. It only gets worse.