admin管理员组文章数量:1287535
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.
I want something like this:
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.
I want something like this:
Share Improve this question asked Aug 20, 2015 at 7:56 sirjaysirjay 1,7664 gold badges34 silver badges54 bronze badges 1- Afaik this is not possible. – Lars Graubner Commented Aug 20, 2015 at 8:05
3 Answers
Reset to default 4I was stuck with that problem too, it is very difficult because the plugin pose 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 overe 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.
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/m5uupf9x/3/
I also faced the same issue and while Alexander's answer is great, i had performance issues with it as it does lot of DOM manipulation. I have about 2000-3000 events per week and became unusable in browsers like Firefox, IE etc. Therefore adapting Alexander's answer and minimizing DOM manipulation came up with following solution.
variables
var itemsOnSlot = {}; // counter to save number of events in same time slot
var maxItemsOnRow = {}; // counter to save max number of events in row
utilize eventRender and eventAfterAllRender callbacks
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;
}
版权声明:本文标题:javascript - Fullcalendar.io: how to display one event per line in agendaWeek then mix all in one? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741239424a2363676.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论