Monday, March 19, 2012

Get the Selected Date/Time within a SharePoint 2010 Calendar using jQuery

The selected date in a SharePoint 2010 calendar may be needed when writing custom solutions. This can be retrieved using JavaScript and jQuery.  First, we need to determine if we are in the month, week, or day scope of the calendar.  There is probably a better way to do this, but the following seems to work:



// make these global
var selectedDate = 'no date selected';
var selectedTime = 'no time selected';


// put the rest of the code in a function
function GetSelectedDate() {

  var dayScope = $('table.ms-acal-detail');
  var weekScope = $('table.ms-acal-detail');
  var monthScope = $('table.ms-acal-month');


  var isDayScope = dayScope.length > 0 ? dayScope.attr('summary').indexOf('Daily') > -1 : false;
  var isWeekScope = weekScope.length > 0 ? weekScope.attr('summary').indexOf('Weekly') > -1 : false;
  var isMonthScope = monthScope.length > 0 ? monthScope.attr('summary').indexOf('Monthly') > -1 : false;


Now lets get the selected element:


var selecteddateelement = $('.ms-acal-vitem');


Now that we know which view we are in, and have the selected element, we can determine the selected date if we are in the monthly scope.


  if(isMonthScope) {
var tditem = selecteddateelement.parent();
var tritem = selecteddateelement.parent().parent();
var prevtr = tritem.prev();
var indx = tritem.children().index(tditem) + 2;
var dttd = prevtr.children(':nth-child(' + indx + ')');
if(selecteddateelement.length > 0) selectedDate = dttd.attr('date');
  }

Next lets handle the weekly  scope .

  else if(isWeekScope) {
var weektritem = selecteddateelement.parent();
var weekdayindx = weektritem.children().index(selecteddateelement) + 1;
var weekselectedhalfhourstarttime = $('[class^=ms-acal-hour]').index(weektritem) / 2;
var weekdttd = $('.ms-acal-week-top').children(':nth-child(' + weekdayindx + ')');
if(weekdttd.length > 0) selectedDate = weekdttd.attr('date');
if(weekselectedhalfhourstarttime >= 0) selectedTime = weekselectedhalfhourstarttime;
  }

And finally the daily  scope .

  else if(isDayScope) {
var verbosedaydate = $('.ms-acal-display').text();
var daydatesplit = verbosedaydate.split(/,| /);
var month = daydatesplit[1];
var dayscopemonth = (new Date()).getMonth() + 1; // default to current month


if(month == "January") dayscopemonth = 1;
else if(month == "February") dayscopemonth = 2;
else if(month == "March") dayscopemonth = 3;
else if(month == "April") dayscopemonth = 4;
else if(month == "May") dayscopemonth = 5;
else if(month == "June") dayscopemonth = 6;
else if(month == "July") dayscopemonth = 7;
else if(month == "August") dayscopemonth = 8;
else if(month == "September") dayscopemonth = 9;
else if(month == "October") dayscopemonth = 10;
else if(month == "November") dayscopemonth = 11;
else if(month == "December") dayscopemonth = 12;


var dayscopeday = daydatesplit[2];
var dayscopeyear = daydatesplit[3];


selectedDate = dayscopemonth + '/' + dayscopeday + '/' + dayscopeyear;


var daytr = selecteddateelement.parent();
var dayselectedhalfhourstarttime = $('[class^=ms-acal-hour]').index(daytr) / 2;
if(dayselectedhalfhourstarttime >= 0) selectedTime = dayselectedhalfhourstarttime;
  }

Now the selectedDate and selectedTime will be populated.  Echo these to the console to see the values:

  console.log("selectedDate:    " + selectedDate); // change this to do something with the date
  console.log("selectedTime:    " + selectedTime); // change this to do something with the time
  // end the function
}

The selectedDate and selectedTime variables should be global variables.  This allows the preceding code to be put into a function, say "GetSelectedDate()" and bound to a click event on the calendar.  The issue with not doing this is if you are trying to call this code from a button or anchor click outside of the calendar, when clicked, first the calendar looses focus, then the ms-acal-vitem class is stripped.  The result is that nothing is selected when the code would run, coming back with "no date selected" every time.  Binding to click would look like this:



$(document).ready(function () {
$('.ms-acal-rootdiv').unbind("click").click(function () {
GetSelectedDate();
});
});



Doing so will set the global variables selectedDate and selectedTime every time a click is made.  Another thing you may want to do is create a function to set these variables to the current date and time.  This could be called first, then the preceding code, resulting in selectedDate and selectedTime always having a date populated.


It seems like a long way to go to get the selected date, and does not handle localization.  I would love to see what others are doing to solve this issue.  I know there are some xslt solutions out there too.


Cheers!

2 comments:

  1. Very nice Post! Thank you for this. It saved me a lot of time!

    Here some more lines to get a timeselection.

    var selecteddateelement = $('.ms-acal-vitem');

    var dayselectedhalfhourstarttime = $('[class^=ms-acal-hour]').index(selecteddateelement.parent())/2;
    var dayselectedhalfhourendtime = ($('[class^=ms-acal-hour]').index(selecteddateelement.last().parent())+1)/2;
    console.log("Start: " + dayselectedhalfhourstarttime)
    console.log("End: " + dayselectedhalfhourendtime)

    ReplyDelete
  2. hi Eugene,
    have u successfully implemented the above solution?

    ReplyDelete