SharePoint 2010: Color Coded Calendars!

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

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:

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.

How do you add HTML?

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

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

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.

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…

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

Open SharePoint Designer 2010 and open your site

In the Navigation pane and in the Site Object section click Master Pages

Click your master page (most likely “v4.master”) and if asked, check it out

In Customization section click “Edit file”

Scroll to the bottom of the file and just before the </body> tag add the script below

Setup the Calendar

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)

Add a new column named "CalendarText"

Column Type is Calculated

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

Data type returned = single line of text

Modify the existing view, or create a new view such as "Color Calendar"

Change the field used for the Month View Title AND Day View Title AND Week View Title to "CalendarText"

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.

Open Windows Notepad and add the script below

Save the file with a name like “CalendarColorScript.txt”

Upload the text file to your library (Shared Documents in this example)

Go to the document library where you uploaded the script file, right-click the file name and select Properties

Copy the URL to the file and click OK

Display your calendar and select the view you modified earlier

Click Site Actions and then Edit Page

Click “Add a Web Part” and select the Content Editor web part

In the new web part’s dropdown menu click “Edit Web Part”

Paste in the URL to the script file you copied in step 2

Click OK

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.

Go to the calendar in the browser and create a new view (maybe "Calendar - No Links")

Open your site in SharePoint Designer 2010

Click Lists and Libraries in the Site Objects pane

Click your calendar list and click the new view

In the ribbon click the "Advanced Mode" link (so you can edit the entire page)

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>

Add the JavaScript from below

Save your changes in SharePoint Designer

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:

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

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.

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.

87 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.

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:

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

// 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

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.

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/>

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">.

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?

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.

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.

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.

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?

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.

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:

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

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?

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.

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."

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

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!

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?

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

// 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

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...

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.

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!

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.

> 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:

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.ThanksRick

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).

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.

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,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.

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)

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