Полный календарь — выделение дня на основе выбора события

#jquery #css #fullcalendar

#jquery #css #полный календарь

Вопрос:

В fullcalendar вы можете выбрать событие (которое запускает) функцию eventClick / обратного вызова. Что я хотел бы сделать, так это выделить день события при нажатии на событие (в режиме просмотра месяца).

Например, если событие назначено на 30 октября, и я выбираю событие, я бы хотел, чтобы был выделен цвет фона дня. Это очень похоже на то, как fullcalendar обрабатывает «сегодня», где он выделяет сегодняшний день желтоватым цветом.

Кажется, я не могу понять, как связать класс fc-event или сам объект event с фактическим днем div в календаре. Мое событие 30 октября появляется в следующем div (который является полем 30 октября):

 <div class="fc-sun fc-widget-content fc-day35 fc-first">
  

Как я могу найти этот div (чтобы я мог его выделить) на основе объекта события?

Ответ №1:

Вы можете просто использовать метод выбора в полном календаре.

Например:

 $('#calendar').fullCalendar('select', date);
  

Откуда date берется event.start :

 eventClick: function( event, jsEvent, view ) {
    //pass event.start to select method
}
  

Комментарии:

1. Отличное решение, если событие длится всего один день .

Ответ №2:

Извините, это грубое решение, в основном из памяти, поскольку я не настроен на какие-либо инструменты разработки на этом компьютере.

Надеюсь, это то, что вы ищете!

 //create fullCalendar:
$("#calendar").fullCalendar({
    /* options */

    eventClick: function(event, jsEvent){
        //use the passed-in javascript event to get a jQuery-wrapped reference
        //to the DOM element we clicked on.
        //i can never remember if this is .target, .currentTarget, or .originalTarget
        //... jquery has spoiled me
        var $clickedEvent = $(jsEvent.target);

        //tell the "selectionManager" to find the day this event belongs to,
        //and add the "selected" css class to it
        selectionManager.select($clickedEvent);
    }
});

//define an object that handles the adding-removing of the 'selectedDay' css class
var selectionManager = (function(){
    //i like making private variables :-)
    var $curSelectedDay = null

    //define a "select" method for switching 'selected' state
    return {
        select: function($newEvent) {
            if ($curSelectedDay){
                //if we already had a day chosen, let's get rid of its CSS 'selectedDay' class
                $curSelectedDay.removeClass("selectedDay");
            }
            //find the parent div that has a class matching the pattern 'fc-day', and add the "selectedDay" class to it
            $curSelectedDay = $thisEvent.closest('div[class~="fc-day"]').addClass("selectedDay");
        }       
    };
})();
  

Комментарии:

1. Это не совсем то, что я хотел, но вы указали мне правильное направление своим кодом. Спасибо, что нашли время.

Ответ №3:

Вот немного более простое решение, которое сработало для меня:

 $(".fc-state-highlight").removeClass("fc-state-highlight");
$(jsEvent.currentTarget).addClass("fc-state-highlight");
  

… это происходит внутри вашего обработчика кликов, например:

 $('#eventCalendar').fullCalendar({
    dayClick: function(date, allDay, jsEvent, view) {
        $(".fc-state-highlight").removeClass("fc-state-highlight");
        $(jsEvent.currentTarget).addClass("fc-state-highlight");

    }
});
  

Обратите внимание, что при этом используется dayClick обработчик вместо eventClick обработчика. Я не понимаю, почему это не должно работать eventClick , но я еще не проверял это.

Редактировать:

Использование сопоставимого подхода для eventClick обработчика оказалось более сложным, чем я думал. Проблема в том, что с точки зрения иерархии DOM нет отношения родитель / потомок между содержащим td элементом для «дня» и содержащими div элементами для событий, которые отображаются как происходящие в этот день.

Поэтому мне пришлось написать функцию для поиска правильного td элемента для заданной даты. В итоге я получил что-то вроде:

 function findContainerForDate(date) {
    var firstDayFound = false;
    var lastDayFound = false;
    var calDate = $('#eventCalendar').fullCalendar('getDate');

    var allDates = $('td[class*="fc-day"]')
    for (var index = 0; index < allDates.length; index  ) {
        var container = allDates[index];
        var month = calDate.getMonth();
        var dayNumber = $(container).find(".fc-day-number").html();
        if (dayNumber == 1 amp;amp; ! firstDayFound) {
            firstDayFound = true;
        }
        else if (dayNumber == 1) {
            lastDayFound = true;
        }

        if (! firstDayFound) {
            month--;
        }
        if (lastDayFound) {
            month  ;
        }

        if (month == date.getMonth() amp;amp; dayNumber == date.getDate()) {
            return container;
        }
    }
}
  

… и тогда я мог бы реализовать eventClick так:

 eventClick: function(calEvent, jsEvent, view) {
    var selectedContainer = findContainerForDate(calEvent.start);

    $(".fc-state-highlight").removeClass("fc-state-highlight");
    $(selectedContainer).addClass("fc-state-highlight");
}
  

Ответ №4:

 eventRender: function (event, element, view) {          
        // like that
        var dateString = $.fullCalendar.formatDate(event.start, 'yyyy-MM-dd');
        view.element.find('.fc-day[data-date="'   dateString   '"]').css('background-color', '#FAA732');

        // or that
        var cell = view.dateToCell(event.start);
        view.element.find('tr:eq('   (cell.row   1)   ') td:eq('   cell.col   ')').css('background-color', '#FAA732');
    }
  

Есть ли лучшее решение?

Ответ №5:

Мой взгляд на функцию поиска aroth

      // based on the given event date return the full calendar day jquery object (<td ...>)
     // matching day and month
     //
     // assumptions:
     //  - the event date is if for the same year as the current viewable month
     //  - the fc-day* TD's are in chronological order
     //  - the fc-day* TD's not for the current month have a class of fc-other-month
     //
    findFullCalendarDayForClickedEvent : function( eventDate ) {

        var foundDay;

        var $theCalendar = $( '#myCalendar' );

        var currentDate = $theCalendar.fullCalendar( 'getDate' );
        var fullCalendarDayContainers = $theCalendar.find( 'td[class*="fc-day"]' );

        for( var i = 0; i < fullCalendarDayContainers.length; i   ) {

            var $currentContainer = $( fullCalendarDayContainers[ i ] );

            var dayNumber = $currentContainer.find( '.fc-day-number' ).html();

            // first find the matching day
            if ( eventDate.getDate() == dayNumber ) {

                // now month check, if our current container has fc-other-month
                // then the event month and the current month needs to mismatch,
                // otherwise container is missing fc-other-month then the event
                // month and current month need to match
                if( $currentContainer.hasClass( 'fc-other-month' ) ) {

                    if( eventDate.getMonth() != currentDate.getMonth() ) {
                        foundDay = $currentContainer;
                        break;
                    }
                }
                else {
                    if ( eventDate.getMonth() == currentDate.getMonth() ) {
                        foundDay = $currentContainer;
                        break;
                    }
                }
            }
        }

        return foundDay;
    }
  

Ответ №6:

Благодаря ответу Фитца Агарда о существовании метода выбора полного календаря, вот версия, которая работает даже для многодневных событий.

В основном он пытается найти день, в который находятся координаты щелчка мыши, затем он передает свою дату методу выбора полного календаря.

 function findClickedDay(e) {
 var days = $('#calendar .fc-day');
  for(var i = 0 ; i < days.length ; i  ) {
      var day = $(days[i]);
      var mouseX = e.pageX;
      var mouseY = e.pageY;
      var offset = day.offset();
      var width  = day.width();
      var height = day.height();

      if (    mouseX > offset.left amp;amp; mouseX < offset.left width 
           amp;amp; mouseY > offset.top  amp;amp; mouseY < offset.top height )
         return day;
  }
}

function myDayClick(date) { ... } // Optional

$('#calendar').fullCalendar({
  dayClick: function(date) { myDayClick(date); }, // Optional
  eventClick: function(event, jsEvent, view) {
    clickedDay = findClickedDay(jsEvent);
    var date = new Date(clickedDay.data('date'));
    $('#calendar').fullCalendar('select', date);
    myDayClick(date); // Optional
  }
});
  

Редактировать:

Я только что понял, что метод выбора полного календаря не запускает обратный вызов dayClick. Итак, если вы установили обратный вызов dayClick, вы должны обернуть его в функцию (называемую здесь myDayClick ) и вызвать ее в обратном вызове eventClick . Если у вас нет обратного вызова dayClick, вы можете удалить необязательные части.

Ответ №7:

Не уверен, помогает ли это, но я обнаружил, что это работает довольно хорошо, подобно решению kayz1…

             $("[data-date='"   $.datepicker.formatDate('yy-mm-dd', new Date(calEvent.start))   "']").addClass("fc-state-highlight");
  

Ответ №8:

Так много ответов. Небольшие исследования дают мне более понятный код: fullcalendar v2.1.1

  onDayClick = function( date, jsEvent, view ){
    var cell = view.dateToCell(date);
    var el = view.dayGrid.getCellDayEl(cell);
    var $clickedEvent = $(el);
    $clickedEvent.addClass("SelectedDay");
};
  

Ответ №9:

Если вы обновитесь до fullcalendar версии v2 или выше, это очень просто:

 $('#calendar').fullCalendar({
    eventClick: function(calEvent, jsEvent, view) {
        // change the border color just for fun
        $(this).css('border-color', 'red');
    }
});
  

Вот ссылка для eventClick.

Комментарии:

1. Посмотрите на вопрос OP: что я хотел бы сделать, это выделить ДЕНЬ события при нажатии на событие. Ваш ответ выделяет СОБЫТИЕ, а не ДЕНЬ