Create a Horizontal Progress Bar for SharePoint

Tags: CSS, JavaScript, SharePoint 2007, SharePoint 2010

Today was an interesting day.  I was presented with the problem of creating a horizontal progress bar that would be
displayed on a standard SharePoint web page and could be easily updated.  I’ve got it working and wanted to share
the experience with anyone who’s interested.  Ultimately, I wanted some documentation around this in case I ever
need to go through it again, but if it helps someone I guess that’s ok too.

I would like to point out that this works in both SharePoint 2007 and SharePoint 2010.  Here’s a link to the final product:  http://www.sharepointnerd.com/dr/SitePages/Progress-Bar.aspx.  If you’ve seen the final product and are still interested,
then read the rest of the nonsense that follows and I’ll do my best to describe how this works.

Key Points

    1. The data behind this is stored in a standard SharePoint list.  Any kind of list will do, but in this example, I’m
      using a Project Tasks list.  Here’s a link to my list for your convenience: 
      http://www.sharepointnerd.com/dr/Lists/ptasks/AllItems.aspx
      .  Notice the “Progress Bar” column and how ugly it
      is?  Keep reading and we’ll fix it up.

    1. The data is stored in a list, so it’s easily updateable by any Member (Contributor).

    1. There’s a calculated column involved.

    1. There’s some JavaScript involved.

Now that we’ve covered the key points, on to the details.

Steps

    1. Create a Project Tasks list in some SharePoint site.  Use a test/dummy/poc/temp/sandbox kind of a site…you
      know the drill.

    1. Add a sample project task.  Call it whatever you want and fill in each of the fields with some value.  As usual,
      the Title column is required, so at least fill that out and set the % Complete column to a value like 18 or
      something else greater than zero (so you have something to look at while you work).

    1. Now comes the fun part.  I’m no genius and always hit up Bing for some web research time.  My efforts yielded
      the following resources.  Always credit your sources.

    1. Now that you’ve got your list and a sample task, it’s time to create the calculated column.  Mine is called
      “Progress Bar” (the internal name is just “pb”), but you can call yours whatever you like.  Paste the following
      code in as the column’s formula (take care while doing this as a calculated column often despises being pasted
      into):

   1:  ="<DIV ID='pbIncomplete' style='background-color:#FFFFFF;'>

   2:  <DIV ID='pbComplete' style='background-color:#6ABD46; width:"&([%
Complete]*100)&"%;'>

   3:  <DIV ID='pbInnerText' align='center'
style='position:relative;top:11px;font-size:25px;color:#FFFFFF'>

   4:  "&[% Complete]*100&"%</DIV>

   5:  </DIV>

   6:  </DIV>"

    1. If you read over that first link I mentioned in Step 3 above, then you know where we’re going with this.  Once
      you’ve entered the formula in the calculated column and saved it, the value actually displayed in your “Progress
      Bar” column should look something like this: 

   1:  <DIV ID='pbIncomplete' style='background-color:#FFFFFF;'>

   2:  <DIV ID='pbComplete' style='background-color:#6ABD46; width:63%;'>

   3:  <DIV ID='pbInnerText' align='center' style='position:relative;top:11px;
font-size:25px;color:#FFFFFF'>63%

   4:  </DIV>

   5:  </DIV>

   6:  </DIV>

    1. We’re about half way there at this point.  Now we need to take all that ugly stuff and make it look nice.  Again,
      this requires that you’ve read over and understand those links (seeing the pattern yet?).

    1. Create a new view in your Project Tasks list that only shows the “Progress Bar” column.  I called my view “Progress.”

    1. Create new web part page.

    1. Add the Project Tasks list web part to it.

    1. Set the view of the web part to the “Progress” view that you created in Step 7.  Looks ugly, right?  Yep.

    1. Add a Content Editor Web Part to the page, edit it, open its Source Editor and paste in the following JavaScript
      (please be aware that this code is an exact copy of Christophe’s code in his blog post):

   1:  <script type="text/javascript">

   2:  //

   3:  // Text to HTML

   4:  // Feedback and questions: Christophe@PathToSharePoint.com

   5:  //

   6:  var theTDs = document.getElementsByTagName("TD");

   7:  var i=0;

   8:  var TDContent = " ";

   9:  while (i < theTDs.length) {

  10:  try {

  11:  TDContent = theTDs[i].innerText || theTDs[i].textContent;

  12:  if ((TDContent.indexOf("<DIV") == 0) &&

  13:  (TDContent.indexOf("</DIV>") >= 0)) {

  14:  theTDs[i].innerHTML = TDContent;

  15:  }

  16:  }

  17:  catch(err){}

  18:  i=i+1;

  19:  }

  20:  //

  21:  // ExpGroupRenderData overwrites the default SharePoint function

  22:  // This part is needed for collapsed groupings

  23:  //

  24:  function ExpGroupRenderData(htmlToRender, groupName, isLoaded) {

  25:  var tbody=document.getElementById("tbod"+groupName+"_");

  26:  var wrapDiv=document.createElement("DIV");

  27:  wrapDiv.innerHTML="<TABLE><TBODY id=\"tbod"+ groupName

  28:  +"_\" isLoaded=\""+isLoaded+ "\">"+htmlToRender+"</TBODY></TABLE>";

  29:  var theTBODYTDs = wrapDiv.getElementsByTagName("TD"); var j=0; var
TDContent = " ";

  30:  while (j < theTBODYTDs.length) {

  31:  try {

  32:  TDContent = theTBODYTDs[j].innerText || theTBODYTDs[j].textContent;

  33:  if ((TDContent.indexOf("<DIV") == 0) && (TDContent.indexOf("</DIV>")
>= 0)) {

  34:  theTBODYTDs[j].innerHTML = TDContent;

  35:  }

  36:  }

  37:  catch(err){}

  38:  j=j+1;

  39:  }

  40:  tbody.parentNode.replaceChild(wrapDiv.firstChild.firstChild,tbody);

  41:  }

  42:  </script>

    1. It’s important to be sure that you have placed this Content Editor Web Part lower on the page than the list web part that’s displaying the progress bar data.  Once you’ve done that and saved your page, you should see a working progress bar!  Now go change the completion percentage in the task itself and watch in wonder as your progress bar gets filled in.

    1. (Optional):  In the list web part that’s displaying the progress bar, I wanted to hide the row that showed the column headers.  To do this, I added one more Content Editor Web Part to the page and added the following CSS code to it.

   1:  <style type="text/css">

   2:  .msviewheadertr

   3:  { 

   4:   display:none;

   5:  }

   6:  </style>

    1. Voila!  All that’s left is the progress bar itself.

I think the client will be happy with it.  Is it the coolest thing ever?  No.  However, considering that I am not allowed to have access to the servers (no third-party solutions or my own custom code) and the fact that I am not allowed to use SharePoint Designer (IT has deemed custom SharePoint Designer-based solutions to be unsupported going forward, and that’s understandable), I think this is a pretty great way to provide the client with a solution that works, is documented, and can be handed off to them without the worry of having to bring me or someone else back to make a minor change.  Mission complete.

In my next post (assuming I go in the order I want to) I’m going to show you how awesome the Internet Explorer Developer Toolbar really is and how, when it comes to SharePoint, it will save you hours of your life!