Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 event blocks.

How can I show one event per line? Like in month mod. And more events I have, then higher day block will me (height). Perhaps, it is hard to use functions like eventRender, because if you inspect .fs-event element (web developer tool), you will see event block uses position:absolute;top:300px;left:33%... so I don't know what to do.

enter image description here

I want something like this: enter image description here

like image 408
sirjay Avatar asked Aug 20 '15 07:08

sirjay


People also ask

How do I create a dynamic event in FullCalendar?

although it is not specified on the fullcalender site, it is necessary to assign a value to the "allday" parameter to be able to add new events dynamically. If you set this value to "false", it will not add the event to the AllDay row. If you do "true" it will add to the AllDay row. Save this answer.

How do I set events in FullCalendar?

Here is an example of how to specify an array of events: var calendar = new Calendar(calendarEl, { events: [ { title : 'event1', start : '2010-01-01' }, { title : 'event2', start : '2010-01-05', end : '2010-01-07' }, { title : 'event3', start : '2010-01-09T12:30:00', allDay : false // will make the time show } ] });

How do I select multiple dates in FullCalendar?

Detect when the user clicks on dates or times. Give the user the ability to select multiple dates or time slots with their mouse or touch device. Allows a user to highlight multiple days or timeslots by clicking and dragging.


2 Answers

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.enter image description here

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.

like image 197
Alexander Leyva Caro Avatar answered Sep 28 '22 01:09

Alexander Leyva Caro


You can add a class to your events and try to customize this events with CSS

As an example you can use style

.test {
    width: 100%;
    height: auto;
    position: relative !important;
    left: 0% !important;
    margin-right: 0% !important;
}

and event like this:

{
    title: 'Lunch',
    start: '2014-06-09T10:30:00',
    className: 'test'
},

Look on this Fiddle if this is what you want to achieve

Also with a little bit workaround you can use eventAfterRender callback to adjust height of specific row. But this is not very safe solution and it requires some tuning:

eventAfterRender: function( event, element, view ) { 
    var row = $(".fc-slats tr:contains('"+ moment(event.start).format('ha') + "')");
    if (moment(event.start).format('mm') != '00')
    {
        row = row.next();
    }
    row.height(element.height()+row.height());
}

https://jsfiddle.net/m5uupf9x/3/

like image 44
suvroc Avatar answered Sep 28 '22 01:09

suvroc