Fullcalendar.io: how to display one event per line in agendaWeek then mix all in one?

后端 未结 3 575
别跟我提以往
别跟我提以往 2021-01-05 09:50

I use Fullcalendar.io v2

In my agendaWeek mod I have events and all of them are displayed on one line in day square. So, more events I have, then thiner

3条回答
  •  梦谈多话
    2021-01-05 10:21

    I was stuck with that problem too, it is very difficult because the plugin compose the calendar in an odd way, using some tables and locating the events with dynamically with a position absolute and varying the css top property.

    However i found a generic solution that works very good. First i will show you the code, and them i will explain what exactly the code does.

    I use the option eventAfterAllRender of the fullCalendar. This is an example working.

    I use moment for manage time and i assume the id of the fullCalendar html element is 'Calendar'.

    eventAfterAllRender: function() {
    
        // define static values, use this values to vary the event item height
        var defaultItemHeight = 25;
        var defaultEventItemHeight = 18;
        // ...
    
        // find all rows and define a function to select one row with an specific time
        var rows = [];
        $('div.fc-slats > table > tbody > tr[data-time]').each(function() {
          rows.push($(this));
        });
        var rowIndex = 0;
        var getRowElement = function(time) {
          while (rowIndex < rows.length && moment(rows[rowIndex].attr('data-time'), ['HH:mm:ss']) <= time) {
            rowIndex++;
          }
          var selectedIndex = rowIndex - 1;
          return selectedIndex >= 0 ? rows[selectedIndex] : null;
        };
    
        // reorder events items position and increment row height when is necessary
        $('div.fc-content-col > div.fc-event-container').each(function() {  // for-each week column
          var accumulator = 0;
          var previousRowElement = null;
    
          $(this).find('> a.fc-time-grid-event.fc-v-event.fc-event.fc-start.fc-end').each(function() {  // for-each event on week column
            // select the current event time and its row
            var currentEventTime = moment($(this).find('> div.fc-content > div.fc-time').attr('data-full'), ['h:mm A']);
            var currentEventRowElement = getRowElement(currentEventTime);
    
            // the current row has to more than one item
            if (currentEventRowElement === previousRowElement) {
              accumulator++;
    
              // move down the event (with margin-top prop. IT HAS TO BE THAT PROPERTY TO AVOID CONFLICTS WITH FullCalendar BEHAVIOR)
              $(this).css('margin-top', '+=' + (accumulator * defaultItemHeight).toString() + 'px');
    
              // increse the heigth of current row if it overcome its current max-items
              var maxItemsOnRow = currentEventRowElement.attr('data-max-items') || 1;
              if (accumulator >= maxItemsOnRow) {
                currentEventRowElement.attr('data-max-items', accumulator + 1);
                currentEventRowElement.css('height', '+=' + defaultItemHeight.toString() + 'px');
              }
            } else {
              // reset count
              rowIndex = 0;
              accumulator = 0;
            }
    
            // set default styles for event item and update previosRow
            $(this).css('left', '0');
            $(this).css('right', '7px');
            $(this).css('height', defaultEventItemHeight.toString() + 'px');
            $(this).css('margin-right', '0');
            previousRowElement = currentEventRowElement;
          });
        });
    
        // this is used for re-paint the calendar
        $('#calendar').fullCalendar('option', 'aspectRatio', $('#calendar').fullCalendar('option', 'aspectRatio'));
      }
    

    How the code works:

    First i found all tr elements that are the rows of my calendar (note that they contains an attribute with its owns time).

    Later I iterate for each column and get, for each one, its events items. Each event item is an anchor element with some inner child with the date as an attribute data-full.

    From the event i peek what should be its row, and in that row if there are more than one item, then increase the position where the event item should be located. I use for that the margin-top property because this property is not used or readjust by the plugin (don't use top property).

    In the row i set a data attribute to take the max amount of events that has any column of that row. With that, i can calculate if the row must be increase its height or not.

    Well, this is basically what the codes does. If you have some question please do-it.

提交回复
热议问题