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.

Find That Missing Web Part

Have you ever “lost” a Web Part on a SharePoint page? That happened to me (again) today. I tried and tried to figure out why I wasn’t seeing the contents of the Web Part. I knew it had some, and I knew what it should look like.

Where's my content?I’ve been bitten by this before, so I figured I’d write a note here to my future self in the hopes that I’m smart enough to search for “missing Web Part” and find this post. Of course, this bites me infrequently, so I never remember that it happened to me before. It’s gotten me in every version of SharePoint, too, I’ll bet.

It turns out that I had accidentally clicked on the Minimize option in the Web Part settings dropdown:

Minimize Web Part

You can set this back from the same dropdown menu, where Minimize will have been replace with Restore. You can also fix it in the Web Part Tool Pane.

Chrome State

It can actually be worse, though. There’s another place that you can do yourself in that’s even harder to spot. (I hit myself with this as a double whammy today.)

Right below the Chrome State above is the Chrome Type. The options there are generally “Default”, “None”, “Title and Border”, “Title Only”, and “Border Only”. If, like I did today, you accidentally select the “None” option, then your Web Part disappears altogether! With the branding I have on the site I’m working with today, the Web Part simply collapsed to a blue line.

Where's my Web Part?

At least I could tell it was there, but since it was a Content Search Web Part and I was working on the Display Templates, I assumed it was my code that was breaking it.

Live and learn, I guess. And always try to write future you a note so that you can fix it more easily the next time.

SharePoint Forms and Workflow – A Different Perspective

advanced-formWhenever I get into conversations about forms in SharePoint (or anywhere else for that matter), the conversation almost always turns immediately for workflow. It seems to greatly surprise a lot of people when I say that sometimes workflow is irrelevant for forms. I’d say that 80%+ of SharePoint forms have no workflow at all. (I think it’s a higher percentage, but I know many of you live and die by workflow.)

I think forms and workflow are too often intertwined as concepts, making the forms discussion overly complex.

IMO, forms are for collecting or editing data. Workflows are for managing that data. By keeping those two concepts discrete, we can have excellent forms that just do what forms should do.

Conflating the two will probably delay the possibility of a robust new form tool for SharePoint. We know that something is coming to replace InfoPath, but we don’t know what it is yet.

We learned early in 2014 that InfoPath is dead. In actuality, it’s not dead; it’s only entered its twilight years. We have until 2023 before it isn’t “supported” anymore, and it will probably be useful for many people even after that. (I won’t make any snarky comments about “supported” software.)

I made up the 80% number above based on my own experience. It really depends on type of SharePoint installation you’re working in. My work is more toward the KM and Intranet side of things, and it’s very rare that I end up implementing a workflow. Knowledge workers can be trusted to do their work in the right way to create value, and it’s rarely a sequential or predictable thing. The few cases where workflows matter – time sheet submission, time off requests, article posting, etc. – the workflows tend to be very simple.

For similar reasons, I haven’t seen much need for InfoPath. With a little JavaScript and CSS, I can usually layer a veneer over the default list forms to give them any boost they need to meet business needs. Even so, the default list forms are fine probably 90%+ (another number I’m making up) of the time.

So much of this depends on the culture of the organization, too. If it’s an open and trusting culture, workflows come up infrequently. If it’s more of a command and control culture, they want workflows for everything. That is until you ask them to describe the repeatable process and they realize that there really isn’t one. Either they have to define a real process (lots of hard work) or they keep doing things the way they have – in a slightly disorganized way that still works.

My point is that assuming that there’s always a coupling of forms and workflow means that everything gets more complicated fast. I like the fact that forms and workflow are separate but connectable in SharePoint now. It means I can plug in a workflow if and when I need it; the forms engine isn’t too cluttered by the workflow artifacts.

What is your experience on this? Are forms and workflow always intertwined or are they really two separate ideas? I’ve created a little poll below to capture your feelings on this. Add your voice into the mix and I will try not to use the statistics inappropriately, as do may others.

Upcoming Bonzai Intranets Webinar – Wednesday November 26th at 10am PST

DynamicOwlLogoMy good friends at Dynamic Owl in Vancouver have been doing some amazing things of late. Not only are they some of the smartest people in SharePoint consulting, they have a relatively new product offering called Bonzai Intranet.

Based on their years of consulting, the folks at Dynamic Owl realized that they had been building similar capabilities for their client’s Intranets over and over again. By capturing those patterns and repeatable components, they have come up with a tool set in Bonzai that can get anyone up and running with an Intranet on top of SharePoint faster and more effectively.

But that’s not the half of it. I’ve been looking into their offering; from the surface at first, and then more deeply as they take me through the architecture. This is a gorgeous Intranet offering. By gorgeous, I mean is simply looks fantastic. Of course, that could all be lipstick on a pig, but it isn’t. As I’ve seen how they have built things, I’m truly impressed. It’s the right mix of server side code and client side code, with a slant toward the latter, as it should be in this cloudy world of ours. It’s extensible, robust, and reliable, too.

There’s a post on Michal Pisarek’s blog about the webinar, and I’ve stolen some of that content below. If you’re considering using SharePoint to run your Intranet and see it as a daunting set of tasks, you owe it to yourself to check out Bonzai and the webinar on Nov. 26th.


 

As part of the recent launch of Bonzai Intranet for SharePoint we have been receiving many questions about Bonzai such as:

  • What is the difference between Bonzai and a template/skin?
  • How the hell did you make Bonzai not look like SharePoint?
  • What is the 80% of common Intranet functionality that most organization have? How does Bonzai handle these?

In order to provide you with the answers to these questions and to show you a sneak peek at some of the great features of Bonzai we are hosting a webinar on Wednesday November 26th at 10am PST titled “Rethinking SharePoint Intranets with Bonzai”  In this webinar we will go through our thinking behind Bonzai and take a look at some of the features that we think makes Bonzai an amazing Intranet platform.

http://www.sharepointanalysthq.com/wp-content/uploads/2014/11/Bonzai-Employee-Directory-Landing-Page.png