I've got problem with my fullcalendar,but only on Mozilla Firefox browser.I want to add 2 events:
First on date 17.07 to 20.07 another on 18.07 to 22.07.
My browser in result show me first event on date 17.07 without end date and second correct result .I don't know why :/ in another browsers (chrome,opera) it's looks better.
$('.calendar').fullCalendar({
header: {
right: '',
center: '',
left: ''
},
firstDay: 1,
buttonIcons: {
prev: 'calendar__prev',
next: 'calendar__next'
},
theme: false,
selectable: true,
selectHelper: true,
editable: false,
events: [
],
viewRender: function (view) {
var calendarDate = $('.calendar').fullCalendar('getDate');
var calendarMonth = calendarDate.month();
//Set data attribute for header. This is used to switch header images using css
$('.calendar .fc-toolbar').attr('data-calendar-month', calendarMonth);
//Set title in page header
$('.content__title--calendar > h1').html(view.title);
},
eventClick: function (event, element) {
$('#edit-event input[value='+event.className+']').prop('checked', true);
$('#edit-event').modal('show');
$('.edit-event__id').val(event.id);
$('.title').val(event.title);
$('.description').val(event.description);
$('.start_date').val(event.start);
$('.stop_date').val(event.stop);
$('.user_full_name').val(event.author);
},
eventRender: function(event, element) {
startDate=event.start.toISOString().substring(0, 10);
stopDate=event.stop.substring(0, 10);
title = event.title + "<br />"+' [ '+startDate+' ]' + ' [ '+stopDate+' ] ';
element.popover({
title: title,
trigger: 'hover',
placement: 'auto',
container: 'body',
html: true
});
}
});
I've got my data from api and editing it on that function.
function getApiData(daysInMonth){
var api_url = $('input[name="apiUrl"]').val();
api_url = api_url+'/api/eventStart='+y+'-'+m+'-'+'01'+'&eventStop='+y+'-'+m+'-'+daysInMonth;
$.getJSON(api_url,function(result){
$.each(result.data,function(key,index){
bg = event_color(index.category_name)
if(index.category_name == "Holiday"){
title = index.category_name+' - '+index.user_name;
endDate=index.event_stop.substring(0, 10);
endTime=index.event_stop.substring(10, 19);
var datePlus1 = endDate.split('-');
datePlus1[2] = Number(datePlus1[2])+1;
if(datePlus1[2] > daysInMonth){
datePlus1[2] = '01';
datePlus1[1] = Number(datePlus1[1])+1;
if(datePlus1[1]<10){
end=datePlus1[0]+'-0'+datePlus1[1]+'-'+datePlus1[2];
}
else{
end=datePlus1[0]+'-'+datePlus1[1]+'-'+datePlus1[2];
}
}
else{
end=datePlus1[0]+'-'+datePlus1[1]+'-'+datePlus1[2];
}
$('.calendar').fullCalendar('renderEvent', {
id: index.id,
title: title,
start: index.event_start,
end: end,
stop: index.event_stop,
description:index.event_description,
author: index.user_full_name,
allDay: true,
className: bg,
}, true);
}
}
}
`
ok I solved the problem. Function must add '0' to value day if days < 10 becouse the date looks like this 2019-11-1 instead 2019-11-01.
Related
This topic follows this one about using fullcalendar :
how to set duration for external events in fullcalendar
Now I'm trying to use the resources.
For now it's just testing so I used the following code:
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
plugins: [ 'resourceTimeGrid' ],
timeZone: 'UTC',
defaultView: 'resourceTimeGridFourDay',
datesAboveResources: true,
header: {
left: 'prev,next',
center: 'title',
right: 'resourceTimeGridDay,resourceTimeGridFourDay'
},
views: {
resourceTimeGridFourDay: {
type: 'resourceTimeGrid',
duration: { days: 4 },
buttonText: '4 days'
}
},
resources: [
{ id: 'a', title: 'Room A' },
{ id: 'b', title: 'Room B' }
],
events: 'https://fullcalendar.io/demo-events.json?with-resources=2'
});
calendar.render();
});
I'm inside a Symfony project.
In terms of Javascript calls I had this :
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/core#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/interaction#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/daygrid#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/timegrid#4.1.0/main.min.js"></script>
So I added these 2 calls:
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-common#4.1.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-timegrid#4.1.0/main.min.js"></script>
All of this was copy / pasted from the demo pages.
Now when I load my page I have this error message and i don't understand why :
Uncaught TypeError: Cannot read property 'addEventListener' of null
It seems the error is triggered here :
// Event Delegation
// ----------------------------------------------------------------------------------------------------------------
function listenBySelector(container, eventType, selector, handler) {
function realHandler(ev) {
var matchedChild = elementClosest(ev.target, selector);
if (matchedChild) {
handler.call(matchedChild, ev, matchedChild);
}
}
container.addEventListener(eventType, realHandler);
return function () {
container.removeEventListener(eventType, realHandler);
};
}
on this part :
container.addEventListener(eventType, realHandler);
What do you think may cause this issue ?
A javascript missinh maybe ?
The error was due to a bad id in the div supposed to contain the calendar...
Everything is actually working fine and I was able to combine dragging events + using resources. The full code is :
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/core#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/interaction#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/daygrid#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/timegrid#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-common#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-daygrid#4.4.0/main.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#fullcalendar/resource-timegrid#4.4.0/main.min.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var Calendar = FullCalendar.Calendar;
var Draggable = FullCalendarInteraction.Draggable;
var calendarEl = document.getElementById('calendar-holder');
var containerEl = document.getElementById('external-events');
// initialize the external events
new Draggable(containerEl, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
var json_event = eventEl.getAttribute("data-event");
var event_array = JSON.parse(json_event);
var event_duration = event_array['duration'];
var event_title = event_array['title'];
var event_color = event_array['color'];
return {
title: event_title, //eventEl.innerText,
duration: event_duration,
backgroundColor: event_color,
};
}
});
var calendar = new FullCalendar.Calendar(calendarEl, {
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'resourceTimeGrid' ],
timeZone: 'UTC',
defaultView: 'resourceTimeGridFourDay',
datesAboveResources: true,
header: {
left: 'prev,next',
center: 'title',
right: 'resourceTimeGridDay,resourceTimeGridFourDay'
},
views: {
resourceTimeGridFourDay: {
type: 'resourceTimeGrid',
duration: { days: 4 },
buttonText: '4 days'
}
},
resources: [
{ id: 'a', title: 'Room A' },
{ id: 'b', title: 'Room B' }
],
events: 'https://fullcalendar.io/demo-events.json?with-resources=2'
});
calendar.render();
});
</script>
Thank you ADyson once again, for taking the time to help me !
Using fullcalendar library, I would like to display the start time for each empty cell on my calendar (empty cells are the one marked with a red cross or red dots in the below screenshot, I modified a bit the aspect of the calendar):
So my expected output is a calendar were timeslots become buttons, when you click you start the process of booking a 30 minutes appointment which would start at the written time (the green slot is an hover effect in the following screenshot):
I can't find any easy way to do it through after reading fullcalendar documentation : https://fullcalendar.io/docs
Subsidiary question, I can't find the way to change the style of the empty cell in the CSS. Can't manage to select the elements through my Chrome console.
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
columnHeaderHtml: function(date) {
if (date.getUTCDay() === 0) {
var date_day = "Lundi";
}
if (date.getUTCDay() === 1) {
var date_day = "Mardi";
}
if (date.getUTCDay() === 2) {
var date_day = "Mercredi";
}
if (date.getUTCDay() === 3) {
var date_day = "Jeudi";
}
if (date.getUTCDay() === 4) {
var date_day = "Vendredi";
}
if (date.getUTCDay() === 5) {
var date_day = "Samedi";
}
if (date.getUTCDay() === 6) {
var date_day = "Dimanche";
}
if(date.getMonth() === 0)
{
var date_month = "Jan";
}
if(date.getMonth() === 1)
{
var date_month = "Fev";
}
if(date.getMonth() === 2)
{
var date_month = "Mar";
}
if(date.getMonth() === 3)
{
var date_month = "Avr";
}
if(date.getMonth() === 4)
{
var date_month = "Mai";
}
if(date.getMonth() === 5)
{
var date_month = "Juin";
}
if(date.getMonth() === 6)
{
var date_month = "Juil";
}
if(date.getMonth() === 7)
{
var date_month = "Août";
}
if(date.getMonth() === 8)
{
var date_month = "Sept";
}
if(date.getMonth() === 9)
{
var date_month = "Oct";
}
if(date.getMonth() === 10)
{
var date_month = "Nov";
}
if(date.getMonth() === 11)
{
var date_month = "Dec";
}
var day_num = date.getDate();
return '<b>'+date_day+'</b><br><small>'+day_num+" "+date_month+"</small>";
},
plugins: [ 'interaction', 'dayGrid', 'list', 'googleCalendar','timeGrid' ],
selectable: true,
defaultView: 'timeGridFourDay',
views: {
timeGridFourDay: {
type: 'timeGrid',
duration: { days: 4 },
buttonText: '4 day'
}
},
slotLabelFormat:{
hour: 'numeric',
minute: '2-digit',
omitZeroMinute: true,
meridiem: 'short'
},
locale:'fr',
header: {
left: 'prev today',
right: 'next'
},
validRange: {
start: '2019-08-05',
end: '2019-09-05'
},
allDaySlot:false,
firstDay:1,
minTime:"08:00:00",
maxTime:"20:00:00",
displayEventTime: true, // don't show the time column in list view
// THIS KEY WON'T WORK IN PRODUCTION!!!
// To make your own Google API key, follow the directions here:
// http://fullcalendar.io/docs/google_calendar/
googleCalendarApiKey: 'AIzaSyAL9K2UqkCVfV0n81mDW0iEpOJSwcklfsY',
// US Holidays
events: 'fr.fr#holiday#group.v.calendar.google.com',
eventClick: function(arg) {
arg.jsEvent.preventDefault() // don't navigate in main tab
console.log(arg);
},
select: function(info) {
console.log(info)
},
loading: function(bool) {
},
eventSources: [
{
googleCalendarId: 'contact#vetorino.com',
className: "gcalEvent"
}],
displayEventEnd:false,
events:[
{ // this object will be "parsed" into an Event Object
start: '2019-08-05 12:30:00', // a property!
end: '2019-08-05 14:00:00', // a property! ** see important note below about 'e6d' **
overlap: true,
backgroundColor:"#F7F7F7",
textColor:"#979797",
classNames:"closed",
}],
contentHeight: "auto",
});
calendar.render();
});
So far as shown in my previous screenshot I just managed to have empty cells, the only cells where you find some information are cells containing events.
As discussed in the comments above, there is no single element in the fullCalendar HTML which represents a specific "cell" or "slot" in the timeGrid view. The grid you can see on screen is actually an illusion created by layering multiple tables on top of each other.
So to meet your requirement for a user to be able to select a 20-minute appointment in a free slot, I can see two main options. The first is what I would normally recommend, using the standard fullCalendar functionality. The second is more like what you are asking for, but I think it over-complicates things.
1) This option simply sets the calendar with a slot duration of 20 minutes, and then has code to stop the user from selecting a longer period of time (they cannot select a shorter period, due to the slotDuration setting. This means that they can click on any empty space once and it will know to create an event of the correct length in that location. The user is not allowed to select any slot where an event already exists. (P.S. I expect in reality you will need to collect more data before adding events, but for the demonstration it adds an event instantly.)
document.addEventListener("DOMContentLoaded", function() {
var Calendar = FullCalendar.Calendar;
var calendarEl = document.getElementById("calendar");
var calendar = new Calendar(calendarEl, {
plugins: ["timeGrid", "interaction"],
header: {
left: "prev,next today",
center: "title",
right: "timeGridFourDay"
},
defaultView: "timeGridFourDay",
views: {
timeGridFourDay: {
type: "timeGrid",
duration: { days: 4 },
buttonText: "4 day"
}
},
slotLabelFormat: {
hour: "numeric",
minute: "2-digit",
omitZeroMinute: true,
meridiem: "short"
},
allDaySlot: false,
firstDay: 1,
minTime: "08:00:00",
maxTime: "20:00:00",
contentHeight: "auto",
slotDuration: "00:20:00",
selectable: true,
select: function(info) {
//console.log(info);
calendar.addEvent({ "title": "Test", start: info.start, end: info.end })
calendar.unselect();
},
selectOverlap: false,
selectAllow: function(selectInfo) {
var stM = moment(selectInfo.start);
var enM = moment(selectInfo.end);
var diff = enM.diff(stM, "minutes");
console.log(diff);
if (diff > 20)
{
return false;
}
return true;
},
events: [
{ "title": "Existing event", "start": "2019-08-08 10:00", "end": "2019-08-08 10:20"},
{ "title": "Existing event", "start": "2019-08-08 13:20", "end": "2019-08-08 13:40"},
]
});
calendar.render();
});
Demo: https://codepen.io/ADyson82/pen/aeqJQg
2) This option is closer to your desired UI (from your 2nd screenshot) but is a bit more complicated to achieve. I also, personally, think it leaves your calendar looking cluttered, and making it harder to see where the free and busy slots are, but ultimately it's up to you how you want to implement it. This works by adding a second event source, containing a list of all currently free slots. These are then used to display the start time of each free slot in the centre of it. They are coloured differently from the existing events (indicating a busy slot), so that it's a bit easier to tell the difference.
Of course, this requires you to use your server-side code to calculate all the currently free slots in your database and use that information to populate the second event source. (In the demo the free slot data is static, but of course that will not work in a real application.)
document.addEventListener("DOMContentLoaded", function() {
var Calendar = FullCalendar.Calendar;
var calendarEl = document.getElementById("calendar");
var calendar = new Calendar(calendarEl, {
plugins: ["timeGrid", "interaction"],
header: {
left: "prev,next today",
center: "title",
right: "timeGridFourDay"
},
defaultView: "timeGridFourDay",
views: {
timeGridFourDay: {
type: "timeGrid",
duration: { days: 4 },
buttonText: "4 day"
}
},
slotLabelFormat: {
hour: "numeric",
minute: "2-digit",
omitZeroMinute: true,
meridiem: "short"
},
allDaySlot: false,
firstDay: 1,
minTime: "08:00:00",
maxTime: "20:00:00",
contentHeight: "auto",
slotDuration: "00:20:00",
displayEventTime: false,
eventClick: function(info) {
if (info.event.extendedProps.type == "free") {
calendar.addEvent({
title: "Test",
start: info.event.start,
end: info.event.end
});
info.event.remove(); //delete the "free slot" event
}
},
eventSources: [
{
id: "busy",
events: [
{
title: "Existing event",
start: "2019-08-08 10:00",
end: "2019-08-08 10:20"
},
{
title: "Existing event",
start: "2019-08-08 13:20",
end: "2019-08-08 13:40"
}
]
},
{
id: "free",
backgroundColor: "green",
events: [
{
title: "08:00",
start: "2019-08-08 08:00",
end: "2019-08-08 08:20",
type: "free"
},
{
title: "08:20",
start: "2019-08-08 08:20",
end: "2019-08-08 08:40",
type: "free"
},
{
title: "08:40",
start: "2019-08-08 08:40",
end: "2019-08-08 09:00",
type: "free"
},
{
title: "09:00",
start: "2019-08-08 09:00",
end: "2019-08-08 09:20",
type: "free"
},
{
title: "09:20",
start: "2019-08-08 09:20",
end: "2019-08-08 09:40",
type: "free"
},
{
title: "09:40",
start: "2019-08-08 09:40",
end: "2019-08-08 10:00",
type: "free"
},
{
title: "10:20",
start: "2019-08-08 10:20",
end: "2019-08-08 10:40",
type: "free"
},
{
title: "10:40",
start: "2019-08-08 10:40",
end: "2019-08-08 11:00",
type: "free"
},
]
}
]
});
calendar.render();
});
For this demo I only created handful of the "free" slots (because it was tedious to create them), but hopefully you can get the idea of how it would start to look with dozens of them all over the calendar. Of course again you can amend the CSS to your requirements.
Demo: https://codepen.io/ADyson82/pen/JgpNEX
(You can of course amend the CSS of this further to make it appear more like your desired look and feel.)
Addendum: Here's the OP's final version, for anyone who is interested in the end product - based on taking the above suggestions into consideration: https://codepen.io/hugo-trial/pen/rXdajv
I want to show on the calendar, that what dates are free dates in the year. For these, i want to set a red background.
My problem is, that with this code, it gives the red background to all the dates.
I am using this in the dayRender event.
var unnep_napok =
[
"2019-01-12",
"2019-01-15"
];
$('#calendar').fullCalendar({
events: valami,
lang: 'hu',
dayClick: function(event) {
$(cell).removeClass('ui-widget-content');
$(cell).addClass('holiday');
$(this).css('background-color', 'green');
},
defaultView: 'month',
contentHeight: 'auto',
slotEventOverlap: false,
eventRender: function(eventObj, $el) {
$el.popover({
title: ' ',
content: eventObj.description,
trigger: 'hover',
placement: 'top',
container: 'body'
});
},
dayRender: function (date, cell) {
for(i = 0; i < unnep_napok.length; i++ )
{
cell.css("background-color", "red");
}
}
});
Update with compare:
dayRender: function (date, cell) {
for(i = 0; i < unnep_napok.length; i++ )
{
if(date == unnep_napok[i] )
{
cell.css("background-color", "red");
}
}
}
Update 2, formatting array elements:
dayRender: function (date, cell)
{
for(i = 0; i < unnep_napok.length; i++ )
{
var datum = unnep_napok[i].moment.format('yyyy-mm-dd');
if(date.getDate() == datum )
{
cell.css("background-color", "red");
}
}
}
Following your update, there are still some problems which could be resolved by reading the documentation (and my earlier comments) more carefully:
1) I didn't give you the literal values to use in the "format" command. Did you read the documentation fully? As you can see, the correct format would be YYYY-MM-DD (big letters not small letters).
2) unnep_napok[i].moment.format ...this is not how you create a momentJS object. I would expect your browser gave an error in the console about this.
3) But anyway 2) is not important really, because as I mentioned in my last comment, it's the date value which you need to format ... your unnep_napok values are already strings!!
4) date.getDate() .. I don't know where you got this from?? MomentJS does not document any such function.
This should work for you:
dayRender: function (date, cell)
{
for(i = 0; i < unnep_napok.length; i++ )
{
if(date.format('YYYY-MM-DD') == unnep_napok[i])
{
cell.css("background-color", "red");
}
}
}
A running example based on ADyson's answer. I have also covered popover example for a quick start.
.popover works this way $(element).popover and doesn't work using element.popover
Running example: https://jsfiddle.net/alifaraze/mr53d7nz/8/
HTML
<div id="calendar"></div>
Script
$(document).ready(function() {
var unnep_napok = [
"2019-01-23",
"2019-01-25"
];
$('#calendar').fullCalendar({
events: [{
id: 1,
title: 'Full Day Event',
start: '2019-01-02',
end: '2019-01-03',
description: 'A full day event description'
},
{
id: 2,
title: 'Whole Week Event',
start: '2019-01-06',
end: '2019-01-10',
description: 'Whole week event description'
}
// more events here
],
eventRender: function(event, element) {
$(element).popover({
title: function() {
return "<B>" + event.title + "</B>";
},
placement: 'auto',
html: true,
trigger: 'click',
animation: 'false',
content: function() {
return "<h4>"+ event.description+"</h4>"
},
container: 'body'
});
},
dayRender: function(date, cell) {
for (i = 0; i < unnep_napok.length; i++) {
if (date.format('YYYY-MM-DD') == unnep_napok[i]) {
cell.css("background-color", "red");
}
}
}
});
})
I'm working in week mode and I want to limit visible time range to the earliest event on the week and the latest event on the week.
I guess the right way to solve the problem is to manually filter events that are visible in current week, find the mininum and maximum time and set them to minTime and maxTime property. The problem is that I don't see weekChanged callback (or something like that) which seems a right place to recalculate minTime and maxTime.
This was a lot more work than I expected, hope it works well enough for you. I'm basically doing what I suggested in the comments above.
Edit:
Changed code to improve performance so we don't have to wait for all of the calendar to render before finding out that we need to start all over again.
Note that to do this more effectively we would either have to implement a new callback because none of the existing ones seem to have clientEvents set already or calculate times from the events beforehand (which could get messy in case of timezones).
http://jsfiddle.net/3E8nk/555/
(function(c) {
var startedViewRender = true;
function greaterTime(first, second) {
//Assuming dates are the same year
if (first.clone().dayOfYear(0).isBefore(second.clone().dayOfYear(0)))
return second;
else
return first;
}
var calendarOptions = {
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaWeek'
},
defaultView: 'agendaWeek',
minTime: '00:00:00',
maxTime: '24:00:00',
defaultDate: '2014-06-12',
defaultTimedEventDuration: '02:00:00',
editable: true,
events: [{
title: 'All Day Event',
start: '2014-06-01'
}, {
title: 'Long Event',
start: '2014-06-07',
end: '2014-06-10'
}, {
id: 999,
title: 'Repeating Event',
start: '2014-06-09T16:00:00'
}, {
id: 999,
title: 'Repeating Event',
start: '2014-06-16T16:00:00'
}, {
title: 'Meeting',
start: '2014-06-12T10:30:00',
end: '2014-06-12T12:30:00'
}, {
title: 'Lunch',
start: '2014-06-12T12:00:00'
}, {
title: 'Birthday Party',
start: '2014-06-13T07:00:00'
}, {
title: 'Click for Google',
url: 'http://google.com/',
start: '2014-06-28'
}],
viewRender: function(view) {
startedViewRender = true;
},
eventRender: function(event, element, view) {
if (!startedViewRender)
return;
else
startedViewRender = false;
if (view.name !== 'agendaWeek') {
console.log('not agendaWeek');
return;
}
var events = c.fullCalendar('clientEvents');
if (events.length === 0) {
console.log('no events at all');
//Set to default times?
return;
}
var visibleAndNotAllDayEvents = events.filter(function(event) {
//end not necessarily defined
var endIsWithin = event.end ? event.end.isWithin(view.start, view.end) : false;
return !event.allDay && (event.start.isWithin(view.start, view.end) || endIsWithin);
});
if (visibleAndNotAllDayEvents.length === 0) {
console.log('no visible not all day events');
//Set to default times?
return;
}
var earliest = visibleAndNotAllDayEvents.reduce(function(previousValue, event) {
return greaterTime(previousValue, event.start).isSame(previousValue) ? event.start : previousValue;
}, moment('23:59:59', 'HH:mm:ss'));
var latest = visibleAndNotAllDayEvents.reduce(function(previousValue, event) {
var end = event.end ? event.end.clone() : event.start.clone().add(moment(calendarOptions.defaultTimedEventDuration, 'HH:mm:ss'));
return greaterTime(previousValue, end);
}, moment('00:00:00', 'HH:mm:ss'));
if (calendarOptions.minTime !== earliest.format('HH:mm:ss') || calendarOptions.maxTime !== latest.format('HH:mm:ss')) {
//Reinitialize the whole thing
var currentDate = c.fullCalendar('getDate');
c.fullCalendar('destroy');
c.fullCalendar($.extend(calendarOptions, {
defaultDate: currentDate,
minTime: earliest.format('HH:mm:ss'),
maxTime: latest.format('HH:mm:ss')
}));
}
}
};
c.fullCalendar(calendarOptions);
})($('#calendar'));
You can do that by using eventAfterAllRender, which is executed after all events have been rendered
eventAfterAllRender: function(view) {
var evts = $("#calendar").fullCalendar( 'clientEvents'),
minTime = moment("2014-01-01 23:59:59").format("HH:mm:ss"),
maxTime = moment("2014-01-01 00:00:00").format("HH:mm:ss"),
currentDate = view.calendar.getDate(),
currentMinTime = view.calendar.options.minTime,
currentMaxTime = view.calendar.options.maxTime;
// lets calculate minTime and maxTime based on the week events
// if this event's minTime is 'before' than the minTime, set this as the minTime
for(var i in evts) {
minTime = timeDiff(minTime, evts[i].start.format("HH:mm:ss"), true);
maxTime = timeDiff(maxTime, evts[i].end.format("HH:mm:ss"), false);
}
// If minTime or maxTime don't match, recreate fullcalendar
// This is a pain in the ass : \
// We have to destroy and apply fullcalendar so this can work.
if (minTime != currentMinTime || maxTime != currentMaxTime) {
$("#calendar").fullCalendar('destroy');
$("#calendar").fullCalendar(
$.extend(fcOpts, {
defaultDate: currentDate,
minTime: minTime,
maxTime: maxTime
})
);
}
}
You will have to have a function to calculate which time is the lattest or earliest:
function timeDiff(time1, time2, getMin) {
var d1 = new Date('2014-01-01 ' + time1),
d2 = new Date('2014-01-01 ' + time2);
if (getMin) {
return d1.getTime(d1) - d2.getTime(d2) < 0 ? time1 : time2;
} else {
return d1.getTime(d1) - d2.getTime(d2) > 0 ? time1 : time2;
}
}
See the following JsFiddle for a working example.
I have am currently using Dojo EnhancedGrid with Pagination, filtering and cell edition.
The problem is that in one page, I need to update another value when a cell is edited. When I update this value, I loose the cell selected so I need to click on the next cell to select it and modify it.
It is so not possible to do Enter / edit / enter / down / enter / edit (Excel like edition).
Here is a part of my code :
var store = new dojo.data.ItemFileWriteStore({'data':data});
var grid = new dojox.grid.EnhancedGrid({
id: 'grid',
store: store,
structure: structure,
columnReordering: true,
autoHeight: true,
autoWidth: true,
initialWidth: '100%',
escapeHTMLInData: false,
plugins: {
pagination: {
pageSizes: ["10", "25", "50", "All"],
description: true,
sizeSwitch: true,
pageStepper: true,
gotoButton: true,
maxPageStep: 4,
position: "bottom"
},
filter : {}
},
onStartEdit: function(inCell, inRowIndex)
{
item = grid.selection.getSelected()[0];
currentVal = item[inCell['field']][0];
},
doApplyCellEdit: function(inValue, inRowIndex, inAttrName) {
if(inValue != currentVal){
[...]
$.ajax(url, data, {
success:function(data, textStatus) {
val = parseInt(data["info"]);
if(!isNaN(val)) {
grid.store.setValue(item, 'info', val);
grid.update();
} else {
grid.store.setValue(item, 'info', 0);
grid.update();
}
}
});
}
}
});
dojo.byId("gridDiv").appendChild(grid.domNode);
grid.startup();
Do you see any solution to handle this ?
I too use an enhanced dojo grid, where I had a similar problem. I used this to reload the data right:
require(["dijit/registry"],function(registry) {
var grid = registry.byId('grid');
grid._lastScrollTop=grid.scrollTop;
grid._refresh();
});
With this you always should get the last row you manipulated, and eventually also the last selected one... .
After many research, I have found the following solution :
$.ajax(url, data, {
success:function(data, textStatus) {
val = parseInt(data["info"]);
if(!isNaN(val)) {
grid.store.setValue(item, 'info', val);
grid.update();
window.setTimeout(function() {
grid.focus.next();
}, 10);
} else {
grid.store.setValue(item, 'info', 0);
grid.update();
window.setTimeout(function() {
grid.focus.next();
}, 10);
}
}
});
The timer is needed because there is a short delay before grid update the thus loosing the focus.