6/28/2010

SharePoint 2010: Color Coded Calendars!

An expanded version of this article, along with many other customization examples and how-tos can be found in my book, SharePoint 2007 and 2010 Customization for the Site Owner.

 

 

Updated 9/6/11

Service Pack 1 broke my color coded calendar code! For details see here. The code below has been updated to work with both the pre-SP 1 and SP 1 installations.

 

Updated 2/20/11

As I’m working on my customization book I am revisiting every one of my past “quick tips”. As I do so I am often finding a better way to do something. I ran into some issues working around the asynchronous loading of calendar events with the article below. After digging more into the code behind the calendar pages in 2010 I have found a much better way to trigger the color coding code.  The sections that have been replaced below are now crossed out (aaaaaa) and the new content added.

This update also solves most of the issues found in the comments at the end of this article, especially the “more items” problem.

 

 

Color Coded Events in SharePoint 2010 Calendars

Back in 2008 I wrote a little blog article on adding color to SharePoint 2007 calendar events. Several people have been pestering me to update it for SharePoint 2010, so here goes...

Several things have changed between SharePoint 2007 and 2010 to prevent the old example from working. For fellow “SharePoint client side hackers” I thought I would document the trail I followed to get color coding to work in 2010. For those who do not care about the details, just scroll on down to “Color Coded Events in SharePoint 2010 Calendars Step by Step”.

They broke the Content Editor Web Part!

In 2010 it’s now just called “Content Editor” and is in the “Media and Content” section of Add a Webpart:

image

 

When you add this web part you get a “wiki style” editor. Just click in the new web part and start typing. The Ribbon will then be updated to show all of the Rich Text editor options.

image

 

How do you add HTML?

You can just click the HTML button in the Ribbon (image ). But read on for some fun issues with this option…

image

But when you add CSS or JavaScript you may get this nice little message!

image

As a trivial example I entered:

  <style>
    .s4-titletext h1 a
    {
      color:red
    }
  </style>

and it reformatted it as:

  <style>

    .s4-titletext h1 a
    {
      color:red
    }</style>

and each time you go back into the HTML editor and click OK and adds another blank line after <STYLE>

  <style>

    .s4-titletext h1 a
    {
      color:red
    }</style>

It has even changed capitalization. In one of my edits it changed color:red  to  COLOR:red.

Who knows why….

 

So add your code directly to the page

Use SharePoint Designer and add the code to the bottom of the view page. The best place is most likely  between the “</WebPartPages:WebPartZone>” tag and the “</asp:Content>” tag. If you are using SharePoint Designer 2010 you will need to click “Advanced Mode” in the ribbon to edit that area.

 

Or just link to your code!

Both 2007 and 2010 offer the option to link from the CEWP to a text file with our content. So for 2010 I usually upload a text file containing the code to a library. Then in the CEWP just click the “Edit Web Part” option in the dropdown and add the link to the code file.

image

 

 

They broke the Calendar!

Not really, but is sure has changed. In 2007 the calendar was created entirely server side. The HTML sent to the browser was the final, ready to display HTML. All we needed to do was to write a little JavaScript and/or CSS to “customize” it.

Why it’s now a bit harder to code…

In 2010 the data for the calendar is now asynchronously loaded using a JavaScript function call after the page is loaded. That means that the data we want to change is not yet in the browser when our JavaScript is loaded from a Content Editor Web Part. If you have played with SharePoint client side JavaScript then you have seen the following command used to run a function after the page has loaded.

_spBodyOnLoadFunctionNames.push("_spAjaxOnLoadWaitWPQ2")

Note: _spBodyOnLoadFunctionNames is just a JavaScript array and push is a JavaScript method to add a new item to the end of the array. When a SharePoint page is loaded each function listed in this array is called in order.

I have used this often in 2007 to make sure the page is fully loaded before my JavaScript runs. The problem is where Microsoft loaded this for calendars in 2010… at the very end of the page. That means that when I use a Content Editor Web Part to add my JavaScript it will be in the “queue” before the JavaScript used to add the calendar events. So my challenge now is to get my code to run after the code that loads the calendar.

The work around?

The work around? We have to get our function added to _spBodyOnLoadFunctionNames after SharePoint's calendar update function. One way is to add our JavaScript in the master page and write the code so it only impacts calendars. But that’s a bad workaround. We would then have JavaScript that’s only needed for calendars added to every page.

So here’s another workaround… (Have a better idea? Let me know!)  Add a bit of JavaScript at the bottom of the master page that checks for an array of my functions that need to be run. If there’s no array, then do nothing…

  <script type="text/javascript">
    if (window.mikesCode)
    {
      for (var i=0;i<mikesCode.length;i++)
      { 
        _spBodyOnLoadFunctionNames.push(mikesCode[i]);
      }
    }
  </script>

Then in the Content Editor Web Parts (or anywhere else) add a custom function and add it to my little array.

  function DoSomethingCool()

  {

    // code here

  }

  if (!window.mikesCode)
  {
    mikesCode=new Array();  // create mikesCode if it does not exist
  }
  mikesCode[mikesCode.length] = "DoSomethingCool";   //add the function to run

 

Now we have all of the pieces…  (but I’m not finished with this article… I want to find a way to do this without the master page edit)

 

The new “work around!”

To get our code to run at the right time we need to hook into the SharePoint code that loads the calendar items. Once such place is a function named "SP.UI.ApplicationPages.CalendarNotify.$4a".We also need to delay the load of our code, and we can do that with a SharePoint feature named "_spBodyOnLoadFunctionNames.push".

As a result of this change I can now eliminate the need for the master page edit. (That trick is still useful for other kinds of customizations.)

 

 

Color Coded Events in SharePoint 2010 Calendars Step by Step

 

Add a little piece of code to the master page

  1. Open SharePoint Designer 2010 and open your site
     
  2. In the Navigation pane and in the Site Object section click Master Pages
     
  3. Click your master page (most likely “v4.master”) and if asked, check it out
     
  4. In Customization section click “Edit file”
     
  5. Scroll to the bottom of the file and just before the </body> tag add the script below
     
  6. Save the file and then check it in

<script type="text/javascript">
  if (window.mikesCode)
  {
    for (var i=0;i<mikesCode.length;i++)
    {
      _spBodyOnLoadFunctionNames.push(mikesCode[i]);
    }
  }
</script>

 

Setup the Calendar

The steps here are identical to the SP 2007 article.

  1. Create or open a calendar
     
  2. Add a new column named "Color" – most likely type will be "Choice" with choices like "Red, Green, Blue, Black", but this could be a lookup or a single line of text.
    (See here for an HTML color chart: http://www.w3schools.com/html/html_colornames.asp)
     
  3. Add a new column named "CalendarText"
    1. Column Type is Calculated
    2. Equation is:
          ="<font color='" & Color & "'>" & Title & "</font>"
      image
    3. Data type returned = single line of text
       
  4. Modify the existing view, or create a new view such as "Color Calendar"
     
  5. Change the field used for the Month View Title AND Day View Title AND Week View Title to "CalendarText"
    image
     
  6. Save and exit (The HTML for "<FONT" will now be displayed. Some JavaScript will be needed to fix the HTML tags)

Create the JavaScript file

Two Solutions!

1) Add a Content Editor Web Part as we have done in many of the other customizations. The problem with this approach is that SharePoint 2010 will no longer treat this page as a view. When this page is displayed you will see two changes:

· The View dropdown list in the site title area is missing

· The Ribbon will not be displayed when the page is first loaded, but will be displayed when any event item is clicked.

2) Add the custom JavaScript using SharePoint Designer. The page will then display as an ordinary view no odd behavior.

I recommend #2.

 

Option #1: Using the Content Editor Web Part

I usually add a library named Scripts, ScriptFiles or similar for these kinds of files. The steps below will just use the Shared Documents library.

  1. Open Windows Notepad and add the script below
  2. Save the file with a name like “CalendarColorScript.txt”
  3. Upload the text file to your library (Shared Documents in this example)

<script type="text/javascript" language="javascript">

  function CalColor()
  {
    var x = document.getElementsByTagName("div")
    var i=0;
    for (i=0;i<x.length;i++)
    {
      if (x[i].className=="ms-acal-item")
      {
        x[i].innerHTML= x[i].innerHTML.replace(/&lt;/g,'<').replace(/&gt;/g,'>')
      }
    }
  }

  // hook into the SharePoint JS library to call our code
  // whenever the calendar is updated
  function CalHookIntoSPUI()
  {
    var originalCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4a;
    //var originalresetSelection = SP.UI.ApplicationPages.CalendarViewBase.prototype.resetSelection;

    SP.UI.ApplicationPages.CalendarNotify.$4a = function()
    {
      originalCalendarNotify();
      CalColor();
    }
  }

  // add to the array of functions to run from the master page code
  if (!window.mikesCode)
  {
    mikesCode=new Array();
  }
  mikesCode[mikesCode.length] = "CalColor";
  mikesCode[mikesCode.length] = "CalHookIntoSPUI";

</script>

 

(updated 9/6/2011)

<script>
// Color coded calendars for SharePoint 2010
// TechTrainingNotes.blogspot.com

// load our function to the delayed load list
_spBodyOnLoadFunctionNames.push('colorCalendarEventLinkIntercept');

// hook into the existing SharePoint calendar load function
function colorCalendarEventLinkIntercept()
{

  if (SP.UI.ApplicationPages.CalendarNotify.$4a)
  {
    var OldCalendarNotify = 

SP.UI.ApplicationPages.CalendarNotify.$4a;
    SP.UI.ApplicationPages.CalendarNotify.$4a = function () 
      {
        OldCalendarNotify();
        colorCalendarEventLinks();
      }
  }
  if (SP.UI.ApplicationPages.CalendarNotify.$4b)
  {
    var OldCalendarNotify = 

SP.UI.ApplicationPages.CalendarNotify.$4b;
    SP.UI.ApplicationPages.CalendarNotify.$4b = function () 
      {
        OldCalendarNotify();
        colorCalendarEventLinks();
      }
  }
  // future service pack change may go here!
  // if (SP.UI.ApplicationPages.CalendarNotify.???)

}

// hide the hyperlinks
function colorCalendarEventLinks()
{

  // find all DIVs
  var divs = document.getElementsByTagName("DIV");
  for (var i=0;i<divs.length;i++)
  {
    // find calendar item DIVs
    if (divs[i].className.toLowerCase()=="ms-acal-item")
    {
divs[i].innerHTML = divs[i].innerHTML.replace(/&lt;/g,'<').replace(/&gt;/g,'>');
    }

    // find "x more items" links and re-remove links on Expand/Contract
    if (divs[i].className.toLowerCase()=="ms-acal-ctrlitem")
    {
      var links = divs[i].getElementsByTagName("A");
      if (links.length==1)
      {
        links[0].href="javascript:colorCalendarEventLinks();void(0);"
      }
    }

  }
}

</script>

 

Add a Content Editor Web Part to hold the JavaScript

  1. Go to the document library where you uploaded the script file, right-click the file name and select Properties
     
  2. Copy the URL to the file and click OK
     
  3. Display your calendar and select the view you modified earlier
     
  4. Click Site Actions and then Edit Page
     
  5. Click “Add a Web Part” and select the Content Editor web part
    image
     
  6. In the new web part’s dropdown menu click “Edit Web Part”
    image
     
  7. Paste in the URL to the script file you copied in step 2
     
  8. Click OK
     
  9. In the Ribbon click “Stop Editing” (in the Page tab)

 

Option #2 Using SharePoint Designer

This is the preferred method as it does not break view related functionality as does adding a web part.

  1. Go to the calendar in the browser and create a new view (maybe "Calendar - No Links")
     
  2. Open your site in SharePoint Designer 2010
     
  3. Click Lists and Libraries in the Site Objects pane
     
  4. Click your calendar list and click the new view
     
  5. In the ribbon click the "Advanced Mode" link (so you can edit the entire page)
     
  6. Search for "</WebPartPages:WebPartZone>" and insert a new line just after this tag
    </WebPartPages:WebPartZone>
      your customization goes here (don't type this J )
    </asp:Content>
     
  7. Add the JavaScript from below
     
  8. Save your changes in SharePoint Designer
     
  9. Go to the calendar, add a new event and select a color, and see if the colors are displayed.

 

Everything (or at least option #1) comes with a price   :-(

The above works! But… you lose one feature. When you add a web part to a view you lose the ability to select a view from the crumb trail. (This is not a problem if you add the code using SharePoint Designer)

Without a web part on the page:

image

 

With a web part on the page:  (this is our “Color Calendar” view)

image

 

Notice that the crumb trail now only has the list name. The view name is missing. When the view name is displayed then you also have the dropdown to select other views

You can still switch views, but you must first click in the calendar to display the ribbon.

Bug?  Probably.  (So use option #2 – add the code with SharePoint Designer)

 

Some thoughts on color options…

Just change the FONT tag to a SPAN tag and use a style. Example:

    ="<span style='background-color:"&Color&"'>"&Title&"</span>"

This works, but the background is for just the width of the text, not the entire table cell.

You will probably want to use colors like lightblue, lightgreen, tomoto (light red would just be Pink!), etc. or make the text white or a light color:

    ="<span style='color:white;background-color:"&Color&"'>"&Title&"</span>"

image

 

Closing Notes

  • Document everything, and add to your disaster recovery plan (otherwise you’ll never remember how you did this,and consider the poor person who inherits this site from you)
     
  • In researching the SP.UI.ApplicationPages.CalendarNotify update I found a blog article by Mark Wilson that also intercepted the SP.UI.ApplicationPages.CalendarViewBase.prototype.resetSelection function. My code seems to work fine without it. But in any case go take a look at Mark’s article to see another approach to color coded calendars.
     
  • This has been tested only with IE 8 and FF 3.5.9 so far.
     
  • Batteries not included, your mileage may vary, please test, test, test…

.

84 comments:

Anonymous said...

I used your example and it works great. I only have one problem though and that is when I am in month view. If I have a day that has more items link and click the link, the font tags show up again. The only way to get rid of them is to click the month icon on the ribbon again.

Ideas?

Anonymous said...

I have the exact same issue. Not sure what to do to resolve it.

Love the work that you did on this though. This is going to work out perfectly for our Birthday and Anniversary calendar on our intranet site.

Mark Slavik said...

i have the "more items" problem too has any one got a solution

Dean said...

I have noticed that the Title field in calendar events does not wrap like it did in 2007. Any ideas on how to get the text to wrap?

Mike Smith said...

Mark and Dean,

These are on my to-do list. I'll try to get to them over this holiday break. :-)

Mike

Anonymous said...

Thanks, Mike.

Excellent work.

Eggs said...

Mike, my "Advanced Mode" is greyed out...am I in some sort of limited editing mode?

Mike Smith said...

Eggs,

> my "Advanced Mode" is greyed out...

Make sure you have clicked in the code window first.

Otherwise, what permissions do you have on the site? Are you a site owner?

Mike

Frank said...

Hey Mike. Thanks a million! This helped much. I used what you have done to perform a similar task, which is launching the dispform for a child calendar event within a parent overlay. OOTB, this will open the calendar in a new browser window, but with the following in place of the code in colorCalendarEventLinks:

var divs = document.getElementsByTagName("DIV");
for (var i = 0; i < divs.length; i++)
{
if (divs[i].className.toLowerCase().indexOf("ms-acal-item") > -1 && divs[i].className.toLowerCase().length > 12)
{
var link = divs[i].getElementsByTagName("A")[0].href;
divs[i].getElementsByTagName("A")[0].href = "javascript:;";
divs[i].getElementsByTagName("A")[0].onclick = function(){ShowPopupDialog(link);};
divs[i].getElementsByTagName("A")[0].removeAttribute('target');
}
}

Frank said...

ok, my above code needs a tweek as follows to work for multiple events:

_spBodyOnLoadFunctionNames.push('calendarEventLinkIntercept');
function calendarEventLinkIntercept()
{
var OldCalendarNotify4a = SP.UI.ApplicationPages.CalendarNotify.$4a;
SP.UI.ApplicationPages.CalendarNotify.$4a = function ()
{
OldCalendarNotify4a();
updateEventLinks();
}
}
function updateEventLinks()
{
var divs = document.getElementsByTagName("DIV");
for (var i = 0; i < divs.length; i++)
{
if (divs[i].className.toLowerCase().indexOf("ms-acal-item") > -1 && divs[i].className.toLowerCase().length > 12)
{
var link = divs[i].getElementsByTagName("A")[0].href;
var setshowpopup = setShowPopup(link);
divs[i].getElementsByTagName("A")[0].onclick = setshowpopup;
divs[i].getElementsByTagName("A")[0].href = "javascript:;";
divs[i].getElementsByTagName("A")[0].removeAttribute('target');
}
}
}

var setShowPopup = function(_link) {
return function() {
ShowPopupDialog(_link)
}
};

Anonymous said...

Mike,
in Option 2, you stated to input custom code. What custom code are you referring to?
In the next step, you stated to paste the javascript from below. There is no javascript below.
Please clarify.

Mike Smith said...

Anonymous,

Both methods use the same JavaScript. The only difference that that #1 uses a Content Editor Web Part and #2 uses SharePoint Designer to edit the page.

Mike

Michael said...

Just wondered if anyone has made progress on the text wrapping, or more importantly, the "More Items" link breaking the code!

Jean Bernier said...

Hi Mike, Thanks a lot for your post.

For me all works fine but after install MOSS 2010 SP1 and June Update stop works. How can I resolve it.

Thanks for any help.

Mike Smith said...

Jean,

I will do a test in the next day or two and find out.

Mike

Mike Smith said...

Sorry to take so long, but I now have a fix for SP1.

The quick edit is to change all "4a" entries to "4b".

To make the code work for both pre and post SP1, replace the colorCalendarEventLinkIntercept function to:

function colorCalendarEventLinkIntercept()
{

if (SP.UI.ApplicationPages.CalendarNotify.$4a)
{
var OldCalendarNotify =

SP.UI.ApplicationPages.CalendarNotify.$4a;
SP.UI.ApplicationPages.CalendarNotify.$4a = function ()
{
OldCalendarNotify();
colorCalendarEventLinks();
}
}
if (SP.UI.ApplicationPages.CalendarNotify.$4b)
{
var OldCalendarNotify =

SP.UI.ApplicationPages.CalendarNotify.$4b;
SP.UI.ApplicationPages.CalendarNotify.$4b = function ()
{
OldCalendarNotify();
colorCalendarEventLinks();
}
}
}

Mike

BettyBLS said...

The helped me SOOOOOOOOOOO much. And I would be happy to share my code.

==============================
// Calendar view of a list modification for SharePoint 2010
// -Remove all 12:00 time displays. They are incorrect.
// -Remove the 12:00 text from tool tip also.
// -Change item links to go to Edit form instead of Display form

// the "populateCalendarEventLinkIntercept" technique came from Mike Smith:
// http://techtrainingnotes.blogspot.com/2010/06/sharepoint-2010-color-coded-calendars.html
// this technique handled all calendar view changes (day-week-month; previous/next)
// except the "n more Items" and "collapse" links when more than 3 items are on a month day.
//
// the setTimeout technique was suggested by Marc Anderson.
// it handles the more/collapse scenario

// load our function to the delayed load list
_spBodyOnLoadFunctionNames.push('populateCalendarEventLinkIntercept');

// hook into the existing SharePoint calendar load function
function populateCalendarEventLinkIntercept()
{

if (SP.UI.ApplicationPages.CalendarNotify.$4a) // 20111006 pre-SP1 - Office 365
{
var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4a;
SP.UI.ApplicationPages.CalendarNotify.$4a = function ()
{
OldCalendarNotify();
doModifyCal();
}
}
if (SP.UI.ApplicationPages.CalendarNotify.$4b) // SP2010 SP1
{
var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4b;
SP.UI.ApplicationPages.CalendarNotify.$4b = function ()
{
OldCalendarNotify();
doModifyCal();
}
}
// future service pack change may go here!
// if (SP.UI.ApplicationPages.CalendarNotify.???)

}


function doModifyCal() {

// if there is a more/collapse control (which happens when there are more than three items on month date)
// set its click event to execute this doModifyCal function.
// include a pause to allow for latent data population from separate asynchronous thread

if ($("a.ms-cal-nav").eq(0).length) {
$("div.ms-acal-ctrlitem").eq(0).click(function() {
window.setTimeout(doModifyCal, 0);
});
}

// if there is at least one "12:00" display, clean it up

var y=$('div.ms-acal-rootdiv:eq(1) div[title^="12:00 am"]').filter(":first");
if(y.length) {
var urlString = urlencode(location.href);
var CalData = $('div.ms-acal-rootdiv').eq(1);
$("div.ms-acal-time", CalData).remove();
$('div.ms-acal-sdiv', CalData).each(function() {
if($('div', this).length == 0) {
str=$(this).html();
str=str.replace("12:00 am","");
$(this).html(str);
};
});
$('div[title]', CalData).each(function() {
str=$(this).attr("title");
str=str.replace("12:00 am - 12:00 am ","");
$(this).attr("title",str);
});

// additionally, change item links to go to non-modal Editform
// instead of modal Dispform

var Links = $("a", CalData);
Links.each(function() {
str=$(this).attr("href");
str=str.replace("DispForm","EditForm");
str=str + '&Source=' + urlString;
$(this).attr("href",str).removeAttr("onclick");
});
}

};
function urlencode(link) {
link = encodeURI(link);
link = link.replace('+', '%2B');
link = link.replace('%20', '+');
link = link.replace('*', '%2A');
link = link.replace('/', '%2F');
link = link.replace('@', '%40');
return link;
}


Thank you so much!

BettyBLS said...

betty again here - just a by the by, here is a before and after screen shot of the effect of my changes to the calendar style view:
http://www.flickr.com/photos/17549214@N03/6153683845/in/photostream/

I also made one UI change in the Calendar style view configuration. I set the Week and Day subheadings to the Time field. Since SP plugs in all items into the 12:00 time slot on day/week displays, the subheading is one way to at least visually express the actual time. It shows up on an item's title bar as well as in the tool tip.

Mike Smith said...

BettyBLS,

You need to blog this project!

Mike

BettyBLS said...

Thanks Mike! I may actually do that at some point. I'm still working out some details though. One improvement I made (at least for my purposes) was to have the task item's Edit form popping up in a modal dialog which is helpful because then, on closing, you are right back on the view you came from (week, day, month, current, previous, next).

a task item's link looks like this now:

[A onclick="modalEdit("/Lists/Task/EditForm.aspx?ID=74";return(false);"
href="javascript:void();">task title)
- go to day view when on a month: (click on [td/>

[tr class="ms-acal-summary-dayrow">
[th title="August 28 - September 03" rowspan="2" date="8/28/2011" evtid="week">
[div class="ms-acal-month-weeksel"/>
[td date="8/28/2011" evtid="day">
[div>[nobr>28[nobr/>[div/>
[td date="8/29/2011" evtid="day">
[div>[nobr>29[nobr/>[div/>
....

So, given that markup will not be available to me on the page to which I am returning, I want to find a way to imitate the action that takes place when clicking on those. I can easily know my starting calendar unit and date before going to the Edit form. So my call back can easily plug in that information. So if I am going back to a day view after editing a task item, I want the callback to say "do whatever would happen were one to click on [td date={current calendar date user is working on} evtid="day">.

Whew. Too many words as they would say here at work ....

Any wise ideas?

Betty

Anonymous said...

Thanks for the code, works great. Had a question. Would it be possible to make the color be dependant on what category a user selected.
What I mean is instead of the user saying I want this entry red, or blue etc.
When they select a category for the type of entry the color is determined for them.

so if they select 'meeting' it would be red, or 'event' it will be blue.
Do you know of way to do this?

Mike Smith said...

Anonymous,


Sure, just change the calculated column's equation:

from:
="<font color='" & Color & "'>" & Title & "</font>"

to something like:

="<font color='" &
if(Category="Meeting","red","black")
& "'>" & Category & "</font>"

Mike

Mike Smith said...

Betty,

> the task item's Edit form popping up in a modal dialog

If I'm understanding your question... the problem with a call back form a modal dialog is that when displaying a page, the SharePoint modal dialog is an IFRAME and JavaScript calls between a page in an IFRAME and the parent page are not allowed by the browser.

Mike

BettyBLS said...

Hi Mike,

Thank you for your answer. Dang it. That throws my plan for a loop. But, just because I want to hang on to some hope, I am going to try to put my question more clearly, just in case my ramblings were too confusing or misleading in my previous post.

I had subsequently started working on some code that I thought was going to work. And from the way I am understanding it, I didn't think the parent page was depending on any communication from the child modal page.

Parent Page: CalendarPage.aspx that has a ListView web part referencing the Task List, calendar view.

Assume I am on a Day calendar view of my task list.

Here is what each task item's link will look like:

[A onclick="modalEdit("/Lists/Task/EditForm.aspx?ID=74";return(false);"
href="javascript:void();"]task title[/A]

And here is modalEdit():

function modalEdit(page) {
var options = {
url: page,
title: 'Edit Task',
allowMaximize: false,
showClose: true,
dialogReturnValueCallback: callBackRefresh,
autoSize: true
};
SP.UI.ModalDialog.showModalDialog(options);
}

this is the Callback that I expected to 'refresh' the task list's Day calendar view when the called modal Edit form was closed. I wanted it to refresh in the same manner as would happen if one clicked on the Day calendar icon in the ribbon so that this view
reflects any changes made during the Edit (different than what I said in my previous post). For example, the edit of a task may have included moving it to another date, so it should no longer show up here.


function callBackRefresh(dialogResult, returnValue) {
$("#Ribbon.Calendar.Calendar.Scope.Day-Large").trigger('click');
}

So .... (fingers crossed) does this make any difference in your answer?

~Betty

Mike Smith said...

Betty,

Sorry, but I have not taken the time to build your example and maybe have missed exactly what you are trying to do. Take a look at these and see if they help:

If you are just wanting a refresh after the dialog is closed then:
http://pacsharepoint.com/search?q=dialogReturnValueCallback

To run code on return:
http://social.technet.microsoft.com/Forums/en-US/sharepoint2010programming/thread/ba06d5e5-8c4c-4bca-95f8-65f40c1b11fa/

Mike

Leon Bryant said...

Awesome, Mike! Thanks for not only sharing the solution but explaining it as you go as well.

Leon in San Antonio

Rich_H said...

Hi Mike, great solution, have it working fine. I have been trying it with overlaid calendars, and can't get the overlaid items to display as colored, the HTML shows instead. As far as I can tell the divs have the same names, so the script ought to get them, but I'm not strong on JS :)

Have you tried overlaid calendars, or any advice on how to overcome issue?

Thanks,

Rich.

Mike Smith said...

Rich and others...

I've had a few requests for making this work with overlaid calendars. I should be able to do it, but which color should win? The color from the base calendar or the color added by the overlay process?

Mike

kraysco said...

Mike,

Thanks for the post, very good stuff!

For those individuals who are seeing the HTML code when they change from the Month view to the Day or Week view, what worked for me was to move the Content Editor Web Part (CEWP) containing the script before the calendar on the page. I initially had the CEWP after the calendar and whenever I changed to Day or Week view the HTML displayed. After moving it before the Calednar, the color coded calendar displays correctly for all views.

Anonymous said...

Much Appreciated!

Anonymous said...

Excellent tip! Thanks for the code, works perfectly.

Anonymous said...

How to do color coding lines in a Sharepoint 2010 SP1 Issue Tracking List based on Issue Status?

Thanks
Moz

MickeyB said...

Thanks Mike for your work and thanks to all who post here. I've followed your instructions, creating a new calendar, columns and view. I added the Java code as directed, and get this error when trying to add a new event to the calendar:

Webpage error details

User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MS-RTC LM 8; .NET4.0C; .NET4.0E; InfoPath.3)
Timestamp: Mon, 14 Nov 2011 22:55:49 UTC


Message: 'SP.UI.ApplicationPages.CalendarNotify' is null or not an object
Line: 759
Char: 3
Code: 0

Did I put the Java Code in the wrong place, or do I have access problems?

Mike Smith said...

MickeyB,

Without seeing your code I can only guess... Just to confirm, you are doing this with SP 2010 and not 2007, right?

The error implies that somewhere in your JavaScript you may have in place of this:

SP.UI.ApplicationPages.CalendarNotify.$4a

something like this:

SP.UI.ApplicationPages.CalendarNotify .$4a
(extra space)

or just this in a line:

SP.UI.ApplicationPages.CalendarNotify

Mike

Darren said...

Has there been any update on the issue of not displaying correctly after choosing Expand All or X more items? It does not seem like this was a problem with earlier versions.

Nikki said...

Hi there.. This post is excellent! I'll be buying that book of yours! Could you help me format the combination of using Categories and the span tag to change both the text and background color... I'm not sure how to do that.

Also how do I have it check multiple categories? Thank you in advance!
Nikki

Mike Smith said...

Nikki,

> format the combination of using Categories and the span tag to change both the text and background color

The use of the "font" tag is actually a bit old school. Today we should be using styles, so you might do something like this:

Create two columns: Color and Background

="<span style='color:" & Color & ";background:" & Background & "'>" & Title & "</span>"

This will create this in the final page:
<span style="color:red;background:yellow">message</span>

> Also how do I have it check multiple categories?

Tell me more... You want the color to be conditional (if x>y...) instead of being set by a value ("red")?

Mike

James312 said...

I have been trying to have a parent site show the colors from 4 different child sites. When an event is created on the parent site the event shows the color, but when a child site is added as an overlay on the parent site we only see: <span style.....

I have tried using the coding above, but the function has not worked. Has anyone been able to make this possible?

Mike Smith said...

James312,

The calendar overlay is a separate and distinct view (asp web page) and does not have your customization. You would to add the code to that page also... but you will then have two things trying to apply color.

Mike

Jason said...

When I hoover over the event item within the SharePoint calendar, the tool tip displays the styling code used within the calculated "CalendarText" column.

How do I change it so that when the user hoovers over the calendar event, the text within the tooltip displays the subject or description column of the calendar event item?

Great solution by the way.

BettyBLS said...

I noticed a few comments/questions about overlays. I found a comment from someone regarding a solution they had found to their calendar overlay issue, so just in case this ends up being relevant for anyone else, see planet_parket post in the msdn forum http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010general/thread/5276ac04-b300-4c64-9f31-a0d689ed3ceb/?prof=required. Here is an extract of the relevant info from the post:

"when using overlays, SharePoint was prefixing the title with the name of the calendar view added as an overlay. For example, I had a calendar view named Open Tickets, so the title was "Open Tickets 12:00 am...". So I [...] looked for the view name, and it worked! Interestingly enough, I only had to specify one of the view names, even though I had multiple overlay calendars added in, and it took care of them all."

shivaji said...

When I click on collapse-all/expand-all in ribbon HTML code is displaying in calendar2010.

Can you please help on this.

Chris said...

Is there any way to make the alternate display hover-over text show the actual title of the event rather than the contents of the Calculated Column? I'm using a small view of the calendar so the text doesn't wrap and mousing over what is visible of the title gives me the tagged title

(i.e. [font color="white"][b]Title of Event[/b][/font]) - couldn't post the actual tags.

Not conducive to user happiness.

Any assistance greatly appreciated!

Confusedofcourse said...

Hi,

I'm on step 6, on Option#2 and i have pasted all JavaScript from Option#1 into SharePoint Designer right under "
// Color coded calendars for"

Am i doing something wrong? I'm not a programmer so any help would be appreciated.

Mike Smith said...

Confusedofcourse,

Make sure that what you copied included <script> and </script>

Are you seeing an error? Is the HTML or script being displayed?

Mike

Anonymous said...

oh my gosh thank you so much. I much prefer the linking to the code in a txt file instead of modifying the html behind the web part. All I wanted to do was remove the quick launch. This was so easy. Love that!

Raja said...

We have used the Color coding for 2007 we have Migrated to SharePoint 2010 now , how make the Calendar work in SharePoint 2010 with visual upgrade.

Mike Smith said...

Raja,

The JavaScript is a bit different for 2007 and 2010. Also see the link at the top of the article about the SP 1 update.

Anonymous said...

Let me try this one more time as my post does not seem to work.
I am using Office 365 with Sharepoint 2010 on line. When I open the view in edit mode I am finding an entry
There does not appear to be an entry .
This entry already has a line . Should I copy your code below this entry?

Mike Smith said...

> Let me try this one more time as my post does not seem to work.

Due to spammers, all posts are moderated and only displayed after I get a chance to review them.


> When I open the view in edit mode I am finding an entry
There does not appear to be an entry .
This entry already has a line .

Can you rephrase this? I'm not sure what you are asking.

BettyBLS said...

Clearing up 12:00 - 12:00 calendar displays (Page 1 of 2)

Just to wrap up my previous posts, I wanted to mention something simple I finally did to get the right time to display!

I created a new DateTime calculated column (DueDate+DueTime) to be used as start-end date in Calendar View. Now Calendar knows the time! (previously, the calendar put everything on 12:00 am because the Due Date, which was used as start-end date in Calendar, was formatted as just a date. So now that the Calendar knows the time, I don't need the modifications in previous versions of script. There is no longer an issue with the 12:00 am time stamp. :-)

I still did use jQuery script, however, to remove the end time from the display because for my Task list there was just a Due Time, not a begin and end.

I also still needed jQuery to link the task item to the Edit form instead of the Display form.

So final script was this:


[script language="javascript" type="text/javascript">
// Created a new column on xRM Task list that concatenates the
// Due Date and Due Time into a single Date/Time field.

// Use the new Date/Time field in the Calendar view configuration as start/end date

// Use jQuery to:

// - change the monthly calendar time range displays (e.g., 3:30 pm - 3:30 pm)
// such that only a single time displays. There is no begin and end date/time
// field in the xRM Task list. Steve will use the Due Date and Due Time to track his activities.
// - Make the same change to tooltips.
// - link to edit form instead of display form. Return automatically to calendar
// the "populateCalendarEventLinkIntercept" technique came from Mike Smith:

// http://techtrainingnotes.blogspot.com/2010/06/sharepoint-2010-color-coded-calendars.html
// this technique handled all calendar view changes (day-week-month; previous/next)
// except the "n more Items" and "collapse" links when more than 3 items are on a month day.
//
// the setTimeout technique was suggested by Marc Anderson.
// it handles the more/collapse scenario

// load our function to the delayed load list
// but do not do this if page is in "Edit" mode


_spBodyOnLoadFunctionNames.push('populateCalendarEventLinkIntercept');

// hook into the existing SharePoint calendar load function
function populateCalendarEventLinkIntercept()
{

if (SP.UI.ApplicationPages.CalendarNotify.$4a) // 20111006 pre-SP1 - Office 365
{
var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4a;
SP.UI.ApplicationPages.CalendarNotify.$4a = function ()
{
OldCalendarNotify();
doModifyCal();
}
}
if (SP.UI.ApplicationPages.CalendarNotify.$4b) // SP2010 SP1
{
var OldCalendarNotify = SP.UI.ApplicationPages.CalendarNotify.$4b;
SP.UI.ApplicationPages.CalendarNotify.$4b = function ()
{
OldCalendarNotify();
doModifyCal();
}
}
// future service pack change may go here!
// if (SP.UI.ApplicationPages.CalendarNotify.???)

}
// }

BettyBLS said...

Clearing up 12:00 - 12:00 calendar displays (Page 2 of 3)

function doModifyCal() {

// get text "Previous Month" or "...Week" or "...Day"
// remove "Previous " from text, leaving only "Month", "Week" or "Day"
var dateUnit = $("#AsynchronousViewDefault_CalendarView a[title^='Previous']").filter(":first").attr("title");
dateUnit=dateUnit.substring(dateUnit.indexOf(" ")+1);

// if there is a more/collapse control (which happens when there are more than three items on month date)
// set its click event to execute this doModifyCal function.
// include a pause to allow for latent data population from separate asynchronous thread
if ($("a.ms-cal-nav").eq(0).length) {
$("div.ms-acal-ctrlitem").eq(0).click(function() {
window.setTimeout(doModifyCal, 0);
});
}

// if there is at least one non-reformatted time display, clean it up
// A dash in the title signifies that this has not yet been reformatted

var str="";
var y=$('div.ms-acal-rootdiv:eq(1) div[title~="-"]').filter(":first");
if(y.length) {
var urlString = urlencode(location.href);
var CalData = $('div.ms-acal-rootdiv').eq(1);
$('div[title]', CalData).each(function() {
str=$(this).attr("title");
str=str.slice(str.search("-")+2); // remove begin time from all link tool tips
$(this).attr("title",str);
});

if(dateUnit=="Month") {
//check for and remove begin time from single-item-per-day times
$("div.ms-acal-time").each(function() {
str=$(this).text();
str=str.slice(str.search("-")+2);
$(this).text(str);
});
}

// additionally, replace the onclick action of each task item's link such that a modal Edit form
// will pop up instead of modal Display form. This involves creating a new function that
// calls SP.UI.ModalDialog methods made available to SP2010 through the EcmaScript Client Object Model
// ref - http://msdn.microsoft.com/en-us/library/ff410259.aspx
//
// do not include "more/collapse" link
//
// For clarification purposes we are going to:
//
// change this:
// [A onclick="EditLink2(this,'WPQ2');return false;"
// href="/Lists/Task/DispForm.aspx?ID=74">task title[/A>
//
// to this:
// [A onclick="modalEdit("/Lists/Task/EditForm.aspx?ID=74";return(false);"
// href="javascript:void();">task title[/A>
//

var Links = $("a:not(.ms-cal-nav)", CalData);
Links.each(function() {
str=$(this).attr("href");
str=str.replace("DispForm","EditForm");
$(this).attr("href","javascript:void();").attr("onclick","modalEdit('" + str + "');return(false);");
});
}
}

BettyBLS said...

Clearing up 12:00 - 12:00 calendar displays (Page 3 of 3)

function callBackRefresh(dialogResult, returnValue) {
var calDetail2 = $("#AsynchronousViewDefault_CalendarView > div.ms-acal-rootdiv > table")
.filter(":first")
.attr("summary");
}

// We are here because someone clicked on a task item link in one of the
// calendar views.
function modalEdit(page) {
var options = {
url: page,
title: 'Edit Task',
allowMaximize: false,
showClose: true,
dialogReturnValueCallback: callBackRefresh,
autoSize: true
};
SP.UI.ModalDialog.showModalDialog(options);
}

function urlencode(link) {
link = encodeURI(link);
link = link.replace('+', '%2B');
link = link.replace('%20', '+');
link = link.replace('*', '%2A');
link = link.replace('/', '%2F');
link = link.replace('@', '%40');
return link;
}

[/script>

bdolla said...

Is there a way to change the background color of the cell/table (the light green on the calendar) rather than the background of the font/text?

Anonymous said...

Betty, do you have a full blog or site for what all you did and the steps to implement it? Something you can send?

BettyBLS said...

No I do not have a blog site I am afraid. And I don't see a way to attach files to these comments. so let's see. Maybe I can put something together and put it on SkyDrive as public. Is this something time sensitive? It might take me awhile...

Arianne said...

Great solution and easy to follow; thanks for the time it took to share. Is there a way to make the new color view work from the home page or just in calendar view? Thanks again!

Mike Smith said...

Arianne,

When the calendar is displayed on the home page it is just a list web part displaying a view, so the same steps will work there when that view is selected in the web part and the JavaScript has been added to the home page.

Mike

Arianne said...

Mike,

Thanks for the quick response. My challenge is finding the right place in the home page to insert the javascript. From the site objects bar in SharePoint Designer I selected site pages>home and found the tag at the bottom, followed by:









If I insert just after the webpart tag however, as in calendar view, I get a warning that the site definitions will change. I'm sensing user error here!

Mike Smith said...

Arianne,

Your code was removed by blog. To paste HTML code you need to type &lt; for each <

> I get a warning that the site definitions will change. I'm sensing user error here!

That is expected, but the message is that the page will be saved as different than the site definition. It will not change the site definition!

Mike

Mike

Harry said...

Mike, BettyBLS,

I have a list with a calendar view. Problem is, when I put the JavaScript on that page in designer, it's not getting read. Suggestions?

thanks for this great post!

Craig St Jean said...

Hey Mike,

I thought I had followed the solution 2 instructions to the letter. But I must be making a very simple mistake and I'm not sure where I am making it. I dont understand where in the process I am defining the colors that are going to be used by each choice I am referencing in the new column. I'm not sure if I'm inserting the Java code properly or in the right place. I'm sort of lost and could use some assistance.

Mike Smith said...

Craig,

The color is simply selected by the user adding the new event.

> 2. Add a new column named "Color" – most likely type will be "Choice" with choices like "Red, Green, Blue, Black", but this could be a lookup or a single line of text.

You could write the formula to pick the color based on one of the other fields. For example, if you had a column named "Meeting Room" you where you wanted Room A events to be in red and all others in blue you might write a formula like this:

=if([Meeting Room]="Room A","<font color='red'>" & Title & "</font>","<font color='blue'>" & Title & "</font>")

Mike

Mike Iskandaryan said...

Hi Mike,

This worked great for me except that the other users are stills seeing the the HTML for "<FONT" .

It looks fine on my screen, i utilized the content editor method and have administrator/full control rights. Any ideas?

Mike Smith said...

Mike,

> This worked great for me except that the other users are stills seeing the the HTML

Did you link the Content Editor Web Part to a file? If so, do your users have at least Read access to that file or library?

Mike

Mike Iskandaryan said...

Thanks Mike, i actually removed everyone else's access from that the file thinking its best for them not even see it. Ive added them back and it is fine now. Thanks!

I was also wondering if there is a way to color the background of the event entry rather than the text?

Thanks

Mike Smith said...

> I was also wondering if there is a way to color the background of the event entry rather than the text?

Yes, see the "Some thoughts on color options…" section of the article. It does not work real well as it does not change the background of the entire row, just the text.

Anonymous said...

Betty,

Any chance that we can download your script in text file. I'm having trouble doing the cut and paste.

Thanks in Advance!

Mike Smith said...

> Any chance that we can download your script in text file.

Problem with getting it copied or is it not copied correctly?

Try using Click, scroll to the end of the code and the Shift-Click to select the code, then right-click.

If it did not paste correctly, everything on one line for example, then try pasting the code into MS Word, and copy and paste from there a Notepad or Designer.

If you bought the book, there is book support site that has this code for download.

Mike

Rick said...

I have the same question that Chris posted on january 23rd- I did not see an answer to it:
------------
Chris said...
Is there any way to make the alternate display hover-over text show the actual title of the event rather than the contents of the Calculated Column? I'm using a small view of the calendar so the text doesn't wrap and mousing over what is visible of the title gives me the tagged title
-------
I have used the ideas+ code here to make a cool color-coded calendar for HR that works off of the "Category" column.

The biggest change I made: The entire width of the box for each line of the entry is has the background color change. The font color change affects the time as well.

Almost all changes were done via javascript- I essentially parsed out the existing innerHTML element into Time, eventType, and Title, then built a brand new innerHTML with a style modification inserted to the DIV- "ms-acal-sdiv"- all other divs were removed, and I inserted a line break into links that need to span more than one line.
The only thing not working well is the hover-over box that appears. That shows my calculated column gibberish.
Thanks
Rick

Blake Reader said...

Hi Mike,

I've been searching through your blog and I also own your book which is becoming my bible for quirky fixes (thank you!). I'm still looking for a smart solution to implement a team Calendar and displaying this a certain way.

Scenario: I manage a team of 20 engineers who work between 2 buildings we own, we are all skilled to carry out the 7 different service functions we offer to our business and we need a centralised way of collating which shift time (we have 4 different shift patterns) each person is on and the particular service function they are covering. Every two weeks engineers switch roles and this can vary from time to time depending on shift cover.

I've been tasked with finding a way to centralise this data but also make it easy to amend (for sickness, holiday etc) on the fly so at any time management can see a real time view of what's happening.

Firstly, I'm no IT developer, I'm picking things up as I go (hence your books are truly a god send) and I'm obviously not thinking about things the right way.

My conclusion so far? Entering in 20 appointments each week either in Outlook (then uploading to Sharepoint using overlay calendars) or entering manually on SP itself is a time consuming task. We currently do this in Excel then copy/paste in to email but we want something more professional.

Is there a way an alternative way to perform this task? Also, by doing any change can it be setup so each engineer is notified via email or all calendar changes?

Any advise or guidance would be much appreciated (I've scoured google and most SP sites but haven't found a solution that fits what we are looking for).

Regards,
Blake

Sudhir Kesharwani said...

Thanks a lot Mark,

We had the color coding in SharePoint 2007 and it stopped workign when we moved to SharePoint 2010.

With your help I was able to get it back to workign again.

Raja said...

Title field in calendar events does not wrap like it did in 2007. Any ideas on how to get the text to wrap?

Anonymous said...

Regarding Wrapping text...
It's not perfect but seems to help wrap the text and then auto set the div height...

.ms-acal-color1 div{clear: both; overflow: auto; white-space: normal;}

.ms-acal-color1 {height:auto !important;}

Where I have an issue is with having more than 3 calendars, I end up with divs setting atop each other.

Indranil Sarkar said...

Hi Mike.
This is not working for Overlay Calendar. When a different calendar is overlaid to the calendar. The event text doesn't show the text background color and is showing the html code.
In calender the Post I have seen you have suggested to include the javascript code in the view of Overlay Calendar also. Can you please help me on how can I change the text color for overlay calendar as well, you probably have the solution for this we believe.

Markus Wehr said...

Sharepoint 2013
anyone adopted this for SP2013?
We want to migrate Color Coded Calendars to 2013

Lei Wang said...

I send my comments about SharePoint 2013 to reply Markus Wehr's question twice but it is not posted.

Mike Smith said...

Lei,
I don't auto-publish any comments until I can review them, especially if they have code or links to other sites. As I now have a catch up day, I'm trying to get through all of the comments.

I have two issues with the link you supplied. One is that the code includes a copyright statement and no comments about acceptable use. The second is that the author did not find a way to trigger their code from list or page updates and instead constantly reruns their JavaScript five times a second!

Do you know if they have an updated article that runs their code only when needed?

Mike

Brian said...

Mike,
I believe I made an error somewhere along the line of using Option 2. I get this error, "Web Part Error: One of the properties of the Web Part has an incorrect format. Microsoft SharePoint Foundation cannot deserialize the Web Part. Check the format of the properties and try again.", when loading after I have made the changes. Is this enough information for you to see what I have done. Thanks.

Mike Smith said...

Brian,

Without seeing your code, I can only guess. The most common issues that would cause that error would be:
- missing or mismatched quotes
- missing or mismatched < or >
- broken key words or tags (part on one line and part on the next)

Mike

Frank Horton said...

A question was asked above about moving this to 2013. Has anyone had any luck doing that?

This worked well for me in 2010 but the same solution doesn't seem to work in 2013.

Vaqar Hyder said...

Hello Everyone,
Well I wont make tall claims but I tried making it work on SP2013. Since Mike made use of

SP.UI.ApplicationPages.CalendarNotify.$4a

so it did not work. I took a different approach and colorized the events.
Please have a look at this blog post. Any comments to optimize this code are most welcome.
http://vaqarhyder.blogspot.de/2014/05/sharepoint-2010-2013-colorizing-event.html


regards

Anonymous said...

Is there anyway to post side by side calendars? For example, the June and July calendars are side by side. Cheers.

Mike Smith said...

> side by side calendars
Sort of.

In a web part page or a home page...
Add two calendar web parts.
Customize the views so one displays June and the other July.

Two problems... manual updates to the views each month, and the calendar views are huge. Do some web searching to find one of the blog articles on how to shrink calendars.

Mike

Note to spammers...

Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.