понедельник, 7 сентября 2015 г.

Форматирование календаря с помощью JS + REST

Сегодня я расскажу, как можно произвести форматирование в представлении Календарь стандартного списка. В интернете можно найти решения, когда создается вычисляемое поле, в него подается значение из нескольких полей элемента. В представлении выводится вычисляемое поле, а дальше с помощью JS происходит форматирование и скрытие лишней информации. В целом решение не плохое, но мне не особо понравилось, и я решил пойти по другому пути…

Берем представление списка «Календарь» пробегаем по всем ссылкам на в календаре и формируем массив ссылок.


Далее из ссылок получаем Id элементов и делаем запрос к списку. В итоге получаем любые поля из списка и можем с ними работать.
К примеру, можно применить форматирование.


function  getColor(login)
{
 var color;
 login = login.replace("i:0#.w|domain\\","");
 switch(login){
  case "Kaplin Vladimir" : color = "red"; break;
  case "P Michael" : color = "green"; break;
  case "F Pavel" : color = "rgba(254, 164, 0, 1)"; break;

  default: color = "rgb(78, 142, 227)"
  
 }
 return color;
}

function postRender()
{
 data = jQuery("a[href*='.aspx?ID=']");
 //обработка ссылок на элементы
 var arrayID = [] 
 for (var i=0; i <  data.length; i++)
 { 
  var str = data[i].toString();
  var start = str.indexOf('?ID=');
  var end = str.indexOf('"',start);
  if (end == -1){
   var id = str.slice(start+4);
  }
  else{
   var id = str.slice(start+4, end+1);
  }
 
  arrayID.push("Id eq " + id);
 } 
 //работа с объектами элементов
 if (arrayID.length > 0)
 {
  var getItems = getListItem(arrayID.join(" or "));
  getItems.done(function (data, status, xhr) {   
   var items = data.d.results; 
   for(var i=0; i < items.length; i++ )
   {   
    var url = String.format("a[href*='.aspx?ID={0}']", items[i].ID)
    if(items[i].Editor.Title)
    {
     console.log(items[i].Editor.Title)
     var color = getColor(items[i].Editor.Title)
     jQuery(url).closest(".ms-acal-item").css("background-color", color)      
    };    
   }
  })
  getItems.fail(onError)
 }
}
function onError(error) {
    console.log(error.responseText);
}


function getListItem(itemId) { 
 var listTitle = "Заявки"  // название списка
 var webUrl = _spPageContextInfo.webAbsoluteUrl;
 var selectFields = ["Id","Title","Editor/Id","Editor/Title"]; // получаемые поля
 var expandFields = ["Editor/Id","Editor/Title"]; // поля подстановки 
 var listItemUri = webUrl + "/_api/web/lists/GetByTitle('"+ listTitle + "')/Items?$filter=" + itemId+ "&$select="+selectFields.join()+"&$expand="+expandFields.join();
 request = jQuery.ajax({
      url: listItemUri,
      type: "GET",
      headers: { "accept": "application/json;odata=verbose" }
     }); 
 request.done(function (data){console.log('данные REST полученны, объектов - ' + data.d.results.length );});  
 request.fail(function (){console.log('Ошибка при вылнении запроса REST')}); 
 return request;       
}


/* =======================================================================
блок для вызова функции обработки при изменении представления месяц - день 
======================================================================*/ 
 function onCalendarGridsRendered(){
    setTimeout(function () { 
        postRender()
    }, 100);
}

function onCalendarResized(){
    setTimeout(function () { 
        //Add your functionality here
  postRender()
    }, 100);
}

SP.SOD.executeOrDelayUntilScriptLoaded(function () {

    //Week or Day Calendar View
    SP.UI.ApplicationPages.DetailCalendarView.prototype.renderGrids_Old = 
        SP.UI.ApplicationPages.DetailCalendarView.prototype.renderGrids;
    SP.UI.ApplicationPages.DetailCalendarView.prototype.renderGrids = 
        function SP_UI_ApplicationPages_DetailCalendarView$renderGrids($p0) {
        this.renderGrids_Old($p0);

        onCalendarGridsRendered();
    };
    
    //Month Calendar View
    SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids_Old = 
        SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids;
    SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids = 
        function SP_UI_ApplicationPages_SummaryCalendarView$renderGrids($p0) {
        this.renderGrids_Old($p0);

        onCalendarGridsRendered();
    };

    //Resize Calendar
    SP.UI.ApplicationPages.CalendarStateHandler.prototype.parentResized_Old = 
        SP.UI.ApplicationPages.CalendarStateHandler.prototype.parentResized;
    SP.UI.ApplicationPages.CalendarStateHandler.prototype.parentResized = 
        function SP_UI_ApplicationPages_CalendarStateHandler$parentResized() {
        this.parentResized_Old();

        onCalendarResized();
    };
}, "SP.UI.ApplicationPages.Calendar.js"); 

Можно пойти дальше, т.к. мы можем получить любые данные из элемента, то и можем с ними работать. вот пример фильтрации элементов в календаре.
Да, решение не столь красивое, но можно реализовать используя штатные вещи.