Tuesday, January 22, 2019

Calendar list view SharePoint 2013 customization

As known SharePoint 2013 has a new mechanism for customizing views - Client Side Rendering (CSR). CSR is used for rendering list views, list forms and search results by javascript, but  it has some exclusions. According msdn article  Customize a list view in SharePoint Add-ins using client-side rendering there is no way to load JavaScript files using JSLink  property for Survey or Events lists. Many developers may argue me that JSLink is just mechanism of loading javascript files in SharePoint 2013 and yes, they are right. But if we add our template js file another way (by content editor web part, for example), it will not work! In browser developer console  we can see, that there is no file clienttemplates.js on calendar view page. So, Calendar List View in SharePoint 2013 not support CSR.

In this article, I will show how to make some customizations in calendar list view, such as filter and color events, pass parameters to the new event form (from calendar links), refresh items after new event form closed, change edit form link in calendar.


First of all we have to subscribe to SP.UI.ApplicationPages.Calendar.js file loaded event:
ExecuteOrDelayUntilScriptLoaded(_customCalendar.waitForCalendarToLoad, 'SP.UI.ApplicationPages.Calendar.js');

In waitForCalendarToLoad function we can do some customization:
waitForCalendarToLoad: function () {
    //Pass parameter to new form
    var _$8f_1 = SP.UI.ApplicationPages.CalendarMouseHandler.prototype.$8f_1;
    SP.UI.ApplicationPages.CalendarMouseHandler.prototype.$8f_1 = function ($p0) {
        var $v_0 = $p0.target;
        if (!SP.UI.ApplicationPages.ElementUtility.$M(this.$8_1, $v_0)) {
            return;
        }
        if ($v_0.parentNode.nodeName === 'A') {
            $v_0 = $v_0.parentNode;
        }
        if ($v_0.nodeName === 'A' || $v_0.className.indexOf('ms-acal-vitem') > 0) {
            if (this.$1E_1 && this.$1E_1.$B_1) {
                if (this.$1E_1.$B_1.$4w_1.indexOf('&RoomId') > 0) {
                      this.$1E_1.$B_1.$4w_1 = this.$1E_1.$B_1.$4w_1.substring(0, this.$1E_1.$B_1.$4w_1.indexOf('&RoomId'));
                }
                this.$1E_1.$B_1.$4w_1 = this.$1E_1.$B_1.$4w_1 + '&RoomId=' + _customCalendar.selectedRoomId;
            }
        }
        _$8f_1.call(this, $p0);
    }

    //Refresh items after newitemcreated
    var _$9P_1 = SP.UI.ApplicationPages.CalendarNewFormDialog.prototype.$9P_1;
    SP.UI.ApplicationPages.CalendarNewFormDialog.prototype.$9P_1 = function ($p0, $p1) {
        if ($p0 === 1) {
            var $v_0 = (this.get_events()).getHandler('newitemcreated');
            if ($v_0) {
                  $v_0(this, new Sys.EventArgs());
                  _customCalendar.refreshData();
            }
        }
    }
    //Change edit form
    var _$8g_1 = SP.UI.ApplicationPages.CalendarMouseHandler.prototype.$8g_1;
    SP.UI.ApplicationPages.CalendarMouseHandler.prototype.$8g_1 = function ($p0) {
        if (SP.UI.ApplicationPages.ElementUtility.$M(this.$8_1, $p0.target)) {
             var $v_0 = this.$4U_1($p0);
             var $v_1 = this.$1Z_1;
             if ($v_0.$1j_0 && ($v_0.$1j_0.innerHTML.indexOf("EditForm.aspx") > 0 || $v_0.$1j_0.nextSibling && $v_0.$1j_0.nextSibling.innerHTML && $v_0.$1j_0.nextSibling.innerHTML.indexOf("EditForm.aspx") > 0)) {
                  var div = $v_0.$1j_0 && $v_0.$1j_0;
                  if (div.innerHTML.indexOf("EditForm.aspx") <= 0) {
                        div = div.nextSibling;
                  }
                  id = _customCalendar.getIdFromElement(div);
                  if (id) {
                         var options = {
                            title: "Custom editing",
                            autoSize: true,
                            url: _spPageContextInfo.siteServerRelativeUrl + "/Lists/calendar/EditForm.aspx?ID=" + id,
                            dialogReturnValueCallback: function (dialogResult, returnValue) {
                                       _customCalendar.refreshData();
                            }
                         };
                         SP.UI.ModalDialog.showModalDialog(options);                                               return;
                   }
               }
               while ($v_1 && $v_0.$2E_0) {
                    if ($v_1.$Ai_0($v_0)) {
                           break;
                    }
                    $v_1 = $v_1.$1I_0;
               }
         }
    }
},

To filter and color items we have to override onItemsSucceed handler in SP.UI.ApplicationPages.CalendarStateHandler.prototype:
//Subscribe to the event of loading calendar items
var _onItemsSucceed = SP.UI.ApplicationPages.CalendarStateHandler.prototype.onItemsSucceed;
SP.UI.ApplicationPages.CalendarStateHandler.prototype.onItemsSucceed = function ($p0, $p1) {
     var rootThis = this;
     //filter returned items by comparing with _customCalendar.roomEvents collection
     if (_customCalendar.rommEvents && _customCalendar.rommEvents.length > 0) {
           var new$p0 = $.grep($p0, function (value) {
              var event = _customCalendar.getEventById(value.$11_0);
              if (event) {
                  return true;
              }
              else {
                 return false;
              }
           });
           $.each(new$p0, function (i, el) {
              if (el.$N_0 && el.$N_0.formUrl) {
                 el.$N_0.formUrl = el.$N_0.formUrl.replaceAll('DispForm', 'EditForm');
              }
           });
           _onItemsSucceed.call(this, new$p0, $p1);
           //Customize event template
           _customCalendar.colourCalendar();
     }
     else {
           _onItemsSucceed.call(rootThis, [], $p1);
     }
};

coloreCalendar and refreshData functions example:
colourCalendar: function () {
    var eventsContainers = $('.ms-acal-item');
    if (eventsContainers.length) {
        $.each(eventsContainers, function (i, el) {
            var box = $(el);
            var link = box.find('a');
            if (link.length) {
                 var event = _customCalendar.getEvent(link[0]);
                 if (event) {
                      var color = _mbCore.calendar.getStatusColor(event.Status);
                      if (color) {
                            box.css('background-color', color);
                            box.find('div').css('color', 'black');
                            box.find('a').attr('style', 'color:black !important;');
                       }
                       if (event.Description) {
                            box.attr('title', event.Description);
                       }
                  }
            }
        });
    }
},
refreshData: function () {
    _customCalendar.selectedRoomId = _customCalendar.$filter.val();
    $('#roomH').val(_customCalendar.selectedRoomId);
    var a = $('#AsynchronousViewDefault_CalendarView').find('a[id*="WPQ"]');
    if (a.length > 0) {
        var id = a[0].id;
        var fs = id.indexOf('_');
        if (fs > 0) {
             id = a[0].id.substring(0, fs);
        }
        _customCalendar.loadRoomEvents().then(function (data) {
             _customCalendar.rommEvents = _mbCore.ConverWCFDates(data);
              SP.UI.ApplicationPages.CalendarInstanceRepository.$w[id].refreshItems();
        });
    }
},





4 comments:

  1. Sir, this is amazing work! I don't know how to dissected that obfuscated SharePoint "API" to develop this.

    ReplyDelete
  2. Calendar list view SharePoint 2013 customization

    Great post FOR sharepoint developers...!

    Keep sharing..

    SharePoint Web Development

    SharePoint Development Services

    ReplyDelete
  3. Very interesting article.For more informative blog just visit
    We Sharepoint developer services provide start at $2100 per month.

    ReplyDelete
  4. Great Blog!
    Thanks for sharing this excellent blog
    Great post FOR sharepoint developers...!

    Keep sharing..

    Sharepoint Development Services
    Sharepoint Developer

    ReplyDelete