Handle Clicks On Calendar Items In SharePoint 2010 With JavaScript

In some scenarios, you might want to add extended client behavior to a Calendar View in SharePoint 2010. The client-side API of the Calendar View ist not of a great help in every case here. especially, it does not provide an event or hook to catch clicks on calendar items. 

Fortunately, JavaScript itself is powerful enough to allow us injecting such hooks by ourselves. The trick is just to override the API function SP.UI.ApplicationPages.CalendarContainerFactory.create. We just need to wait until the calendar API is loaded and call a function provided by us:

ExecuteOrDelayUntilScriptLoaded(
    MyCalendarHook, 
    "SP.UI.ApplicationPages.Calendar.js");

Be sure to place this call so that the function MyCalendarHook is called before any other calendar-related functions, especially to any other calls to ExecuteOrDelayUntilScriptLoaded with “SP.UI.ApplicationPages.Calendar.js”. In this function, we override SP.UI.ApplicationPages.CalendarContainerFactory.create with whatever code we need. For example:

function MyCalendarHook() {     
    var _patchCalendar = function() {        
        $('.ms-acal-rootdiv .ms-acal-item').click(function () {
            var itemId = $('a', $(this)).attr('href').split('?ID=')[1];
            alert('Item with ID ' + itemId + ' was clicked!');
        });
    };
    
    var _onItemsSucceed = SP.UI.ApplicationPages.CalendarStateHandler.prototype.onItemsSucceed;
    SP.UI.ApplicationPages.CalendarStateHandler.prototype.onItemsSucceed = function($p0, $p1) {
        _onItemsSucceed.call(this, $p0, $p1);
        _patchCalendar();
    };
}

In the code above, we override a function that is called whenever calendar items are loaded (onItemsSucceed). Inside our own onItemsSucceed, we call the original onItemsSucceed to make sure that all calendar functionality is as it used to be. After that, we patch the calendar: find each calendar item (i.e. appointment) and add an onClick event handler. Inside the handler, we can do whatever we want. Note that we’re using jQuery in the example above for simplicity, but you’ll need make sure that jQuery is referenced (or use plain JavaScript instead).

Where to put this?

To show where the scripts from above can be included, below is the header element from the master file V4.master I used. The only changes made to this file are the two script-includes between the “BEGIN DEMO” and “END DEMO” comments. The file patchcalendar.js contains exactly the two script blocks from above. Nevermind the jQuery version – this should work with any version.

<head runat="server">
  <meta http-equiv="X-UA-Compatible" content="IE=8"/>
  <meta name="GENERATOR" content="Microsoft SharePoint"/>
  <meta name="progid" content="SharePoint.WebPartPage.Document"/>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <meta http-equiv="Expires" content="0"/>
  <SharePoint:RobotsMetaTag runat="server"/>
  <title id="onetidTitle"><asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/></title>
  <SharePoint:CssLink runat="server" Version="4"/>
  <SharePoint:Theme runat="server"/>
  <SharePoint:ULSClientConfig runat="server"/>
  <script type="text/javascript">
  var _fV4UI = true;
  </script>
  <SharePoint:ScriptLink language="javascript" name="core.js" OnDemand="true" runat="server"/>
  <SharePoint:CustomJSUrl runat="server"/>
  <SharePoint:SoapDiscoveryLink runat="server"/>
  <asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server"/>
  <SharePoint:DelegateControl runat="server" ControlId="AdditionalPageHead" AllowMultipleControls="true"/>
  <SharePoint:SPShortcutIcon runat="server" IconUrl="/_layouts/images/favicon.ico"/>
  <asp:ContentPlaceHolder id="PlaceHolderBodyAreaClass" runat="server"/>
  <!-- BEGIN DEMO -->
  <script type="text/javascript" src="/_layouts/js/jquery-1.6.1.js"></script>
  <script type="text/javascript" src="/_layouts/js/patchcalendar.js"></script>
  <!-- END DEMO -->
  <asp:ContentPlaceHolder id="PlaceHolderTitleAreaClass" runat="server"/>
  <SharePoint:SPPageManager runat="server"/>
  <SharePoint:SPHelpPageComponent Visible="false" runat="server"/>
</head>

You see, even if some product’s API does not allow us to do everything we like, the power of JavaScript does 🙂

Advertisements

12 thoughts on “Handle Clicks On Calendar Items In SharePoint 2010 With JavaScript

  1. Question for you. I have a great javascript calendar that goes in-sync w/ the sharepoint calendar webpart. however, I need to disable the click event and add my own. Meaning, in the month view, if somebody clicks on the day, it switches to the day view. I would like it to never switch, just to stay on the month view,but add my own click event (which runs my custom script). any help is appreciated. thanks,

    • Please see Matt’s comments below. He removed the original click event handler of the calendar items using this code:

      $(‘a’, ‘.ms-acal-rootdiv .ms-acal-item’).attr(‘onclick’, ”).unbind(‘click’);

      It must be placed inside the _patchCalendar function from above. You could try to modify the jQuery selector to capture the day header elements and maybe you get rid of the original event handler.

  2. Thanks for the example. This only seems to work on the initial load of the page. When the user clicks the forward or backward buttons for the next month, they get the old behavior. Any thoughts on how to make the script fire every time?

    • Matt, I have updated the code in this post. We don’t override “CalendarContainerFactory.create” anymore, but “SP.UI.ApplicationPages.CalendarStateHandler.onItemsSucceed” instead. This should take care of the problem.

      • Good stuff!!! I hadn’t thought of that, but it makes sense to tie in to the client object model’s asynchronous success call.

      • Overriding the onItemsSucceed works very well. FYI, I got rid of the calendar launching in to the modal page by removing the click event from the interior anchor tag.

        $(‘a’, ‘.ms-acal-rootdiv .ms-acal-item’).attr(‘onclick’, ”).unbind(‘click’);

        I then used your code to deploy my own code in the click event you created above.
        Very good work here! Thank you very much!

      • Thank you for the hint on how to remove the original click event. I tried using unbind() on the anchor element, but haven’t thought of also removing the onclick attribute. In fact, I might add a blog post on this one (unless, of course, there’s a blog post from you, because then I’ll link it).

  3. Thanks Alot. I just used it and worked perfectly. I had to change arrows images on the calendar navigation and also had to remove “Today Is” from footer of the calendar in calendar view. Hope you blog more useful tricks like this 🙂

  4. Thank you very much!
    I just search a couple of sites and tried around 5 different solutions, but yours is the first and only that works on all occasions, even after switching the months of the calendar.

  5. Thanks for the article! This is exactly what I needed to color code my calendar the way I want.

    There was a blog series on http://blog.pathtosharepoint.com/ that used text to html javascript to color code columns. This is the type of code needed to make those parts work on MOSS 2013 calendars. The old MOSS 2007 Planet Wilson calendar could have used this to make it work on MOSS 2013, as well.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s