【问题标题】:Fullcalendar.io: how to display one event per line in agendaWeek then mix all in one?Fullcalendar.io:如何在议程周中每行显示一个事件,然后将所有事件混合在一起?
【发布时间】:2017-07-20 07:49:05
【问题描述】:

我使用 Fullcalendar.io v2

在我的agendaWeek 模组中,我有事件,所有事件都显示在日广场的一行上。所以,我有更多的事件,然后更细的事件块。

如何每行显示一个事件?就像在month mod 中一样。我有更多的事件,那么我(身高)会更高。也许,很难使用像eventRender 这样的函数,因为如果你检查.fs-event 元素(Web 开发人员工具),你会看到事件块使用position:absolute;top:300px;left:33%...所以我不知道该怎么做。

我想要这样的东西:

【问题讨论】:

  • Afaik 这是不可能的。

标签: javascript jquery css fullcalendar


【解决方案1】:

我也遇到了这个问题,这非常困难,因为插件以一种奇怪的方式组成日历,使用一些表格并使用位置动态定位事件 absolute 并改变 css top 属性。

但是我找到了一个非常有效的通用解决方案。首先,我将向您展示代码,然后我将解释代码的具体作用。

我使用完整日历的选项eventAfterAllRender。这是example working.

我使用moment 来管理时间,我假设 fullCalendar html 元素的 id 是'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'));
  }

代码的工作原理:

首先我找到了所有 tr 元素,它们是我日历的行(请注意,它们包含一个具有自己时间的属性)。

稍后我对每一列进行迭代,并为每一列获取其事件项。每个事件项都是一个 anchor 元素,其中包含一些内部子元素,其中日期作为属性 data-full。

从事件中我窥视它的行应该是什么,如果在该行中有多个项目,则增加事件项目应该位于的位置。我为此使用 margin-top 属性,因为插件不使用或重新调整此属性(不要使用 top 属性)。

在该行中,我设置了一个数据属性来获取具有该行任何列的最大事件数。有了这个,我可以计算该行是否必须增加它的高度。

嗯,这基本上就是代码的作用。如果你有什么问题,请做。

【讨论】:

    【解决方案2】:

    您可以为您的事件添加一个类并尝试使用 CSS 自定义此事件

    作为示例,您可以使用样式

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

    还有这样的事件:

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

    看看这个Fiddle,如果这是你想要实现的目标

    还可以通过一些解决方法使用eventAfterRender 回调来调整特定行的高度。但这不是很安全的解决方案,需要进行一些调整:

    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/

    【讨论】:

    • 嗨!这几乎就是我需要的。我尝试使用 css 代码,但没有结果。问题是如何在表格中使td 更高?正如您在 Fiddle 中看到的那样,一次 2 个事件从 td 区域出现,因为 td 具有固定高度。那么,如何自动高度取决于有多少事件(在一个 td 中)?
    • 我也尝试调整行高,检查我编辑的答案。不可能直接做到这一点
    • 为什么它不起作用?这只是这个解决方案的草案,因为这个库不是这样指定的
    【解决方案3】:

    我也遇到了同样的问题,虽然 Alexander 的回答很好,但我遇到了性能问题,因为它进行了很多 DOM 操作。我每周大约有 2000-3000 个事件,并且在 Firefox、IE 等浏览器中变得无法使用。因此,采用 Alexander 的答案并最小化 DOM 操作提出了以下解决方案。

    变量

    var itemsOnSlot = {};       // counter to save number of events in same time slot 
    var maxItemsOnRow = {};     // counter to save max number of events in row
    

    利用 eventRender 和 eventAfterAllRender 回调

    eventRender: function(event, element, view){
        // for each event, margin top and other css attributes are changed to stack events on top of each other
        if(!(event.start in itemsOnSlot)){          // if itemsOnSlot has no index with current event's start time
            itemsOnSlot[event.start] = 1;           // create index and set count to 1
            $(element).addClass('slot-attributes'); // add css to change the event style
        }else{                                      // if itemsOnSlot already has a index with current event's start time
            itemsOnSlot[event.start] += 1;          // increase counter by 1
            // change margin top to stack events on top of each other and add css to change the event style
            $(element).css('cssText','margin-top:'+(itemsOnSlot[event.start]*18)+'px !important;').addClass('slot-attributes');
        }
    },
    
    eventAfterAllRender: function(view) {
    
        // this loop is run to get the max number of events per row 
        for(var start in itemsOnSlot){          // for all the timeslots with events in them 
            var time = start.substr(16,8);      // extract required time format from index - eg. 14:00:00
            if(!(time in maxItemsOnRow)){       // if maxItemsOnRow has no index with current time
                maxItemsOnRow[time] = itemsOnSlot[start];   // create index and set count to current day's number of events in this time slot
            }else{                              // if maxItemsOnRow already has a index with current time
                if(itemsOnSlot[start] > maxItemsOnRow[time]){   // if current day's number of events in this time slot are greater than existing number
                    maxItemsOnRow[time] = itemsOnSlot[start];   // replace current time's number of slots
                }
            }
        }
    
        // change height of each row using values from maxItemsOnRow
        $('div.fc-slats > table> tbody > tr[data-time]').each(function() {  // for all rows in calendar
            var time = $(this).attr('data-time');   // get time of each row
            if(time in maxItemsOnRow){              // if current row's time is in maxItemsOnRow
                $(this).css('cssText','height:'+(maxItemsOnRow[time]*18)+'px !important;'); // change the height of the row to contain max items in row
            }else{                                  // if current row's time is not in maxItemsOnRow (no events in current time slot)
                $(this).css('cssText','display: none !important;');    // hide timeslot
            }
        });
    
        // repaint the calendar with new dimensions
        $('#calendar').fullCalendar('option', 'aspectRatio', $('#calendar').fullCalendar('option', 'aspectRatio'));
    
        itemsOnSlot = {};     // reset variables
        maxItemsOnRow = {};     // reset variables
    },
    

    CSS

    .slot-attributes {
        left: 4px !important;
        right: 3px !important;
        height: 15px !important;
        margin-right: 0 !important;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多