Hello,
I am using arshaw fullcalendar
v1.5.2 (only month view ) for property booking website , its a great plugin but I stuck in few problem, I have seen similar issues on google code
, but there is nothing clear really. :(, Please help me to solve these problems
Here is working demo
and JS Code
Fetched events data from two different json files below
json_events.php
: this holds booking detail which is booked from front end by user; admin can not change any details of these type of events.
new_charges.php
: this holds special charges events detail ,admin add/update delete the new charges for any future date(s) .
admin can view the details of any event when he click on an event
new_charges.php
a) I want that only one event is allowed for a date(s).
b) Currently if user click on a day on which any booking event or special charges event is there, then it alerts that day is booked, but after that it will show a prompt box to enter event title,
this is occured because I have used both dayClick
and select
methods
How do i stops further propagation if a day already have an event ?
c) suppose a day 15 january (wrapped by fc-day17
div) is booked ( I have applied a class booked
for events ) and now when I go to next month and click on fc-day17
div, it also alert that day is booked whereas there is no booking
by examining the code i found that it still have the class booked
for another months for the same divs
I think there is something missing during eventRender
methods?
does `eventRender()` method is called only once when initialize the calendar
or each time when we go `prev` or `next` month?
d) I have changed background-color for special charges events during rendering events via json file, but when I delte that events, it does not change back the normal background and still say that day is booked.
how do I make default background of a date if I delete the events of that day??
e) how to hide all events related to previous months?
// a) and b)
// We dont need dayClick event, only select
// I think you created calender something like this
// var calendar = $('#calendar').fullCalendar({ ... })
select: function(start, end, allDay) {
//debugger;
var events = calendar.fullCalendar( 'clientEvents' );
for (var i = 0; events.length > i ; i++){
//If we have 1 day event
if((events[i].end == null && (events[i].start.getTime() >= start.getTime() && events[i].start.getTime() <= end.getTime())) ||
// If we have many days event
(events[i].end != null && ((events[i].start.getTime() >= start.getTime() && events[i].start.getTime() <= end.getTime()) ||
(events[i].end.getTime() >= start.getTime() && events[i].start.getTime() <= end.getTime()) ||
(events[i].start.getTime() <= start.getTime() && events[i].end.getTime() >= end.getTime()))
)){
alert("Realy busy!!!");
return;
}
}
// If this time is not busy, for example, we promt to enter Event Title
var title = prompt('Event Title:');
if (title) {
//............Adding event into calendar
}
calendar.fullCalendar('unselect');
},
// c) and d)
// This is invoked when we navigate throw the month callender
eventAfterRender: function(event, element, view ){
$(".booked").removeClass(".booked"); // Remove all booked class from element
var elements = $(".fc-widget-content:not(.fc-other-month)").filter(function(){
//We try to find day number witch corresponds to the event date
return (event.end == null && $(this).find(".fc-day-number").text() == event.start.getDate()) //If we have 1 day event
|| (event.end != null && $(this).find(".fc-day-number").text() >= event.start.getDate() // If we have many day event
&& $(this).find(".fc-day-number").text() <= event.end.getDate())
});
elements.addClass("booked");
// e)
// Hide all events related to previous and next months
// If we event ends in previous month or starts in next we dont show it!
if(
(event.end == null && (view.start.getMonth() != event.start.getMonth())) //If we have 1 day event
|| (event.end != null && (view.start.getMonth() > event.end.getMonth() // If we have many day event
|| view.start.getMonth() < event.start.getMonth()))
){
$(element).hide();
}
}
EDIT This construction
var elements = $(".fc-widget-content:not(.fc-other-month)").filter(function(){
//We try to find day number witch corresponds to the event date
return (event.end == null && $(this).find(".fc-day-number").text() == event.start.getDate()) //If we have 1 day event
|| (event.end != null && $(this).find(".fc-day-number").text() >= event.start.getDate() // If we have many day event
&& $(this).find(".fc-day-number").text() <= event.end.getDate())
});
meansthat we select days of current month (:not(.fc-other-month)
) which satisfy the filter
conditions (return true
) : The days of month equal the days of events
About your code as I said you must remove dayClick event, and your select event is:
select: function (startDate, endDate, allDay, jsEvent) {
// This is my addition //
var events = calendar.fullCalendar( 'clientEvents' );
for (var i = 0; events.length > i ; i++){
//If we have 1 day event
if((events[i].endDate == null && (events[i].start.getTime() >= startDate.getTime() && events[i].start.getTime() <= endDate.getTime())) ||
// If we have many days event
(events[i].endDate != null && ((events[i].start.getTime() >= startDate.getTime() && events[i].start.getTime() <= endDate.getTime()) ||
(events[i].end.getTime() >= startDate.getTime() && events[i].start.getTime() <= endDate.getTime()) ||
(events[i].start.getTime() <= startDate.getTime() && events[i].end.getTime() >= endDate.getTime()))
)){
alert('Sorry this date is already taken');
return;
}
}
// /This is my addition //
console.dir(jsEvent);
if (liveDate > startDate) {
alert('This date has been passed');
return false;
} else {
var title = prompt('New Charges:');
if (title) {
calendar.fullCalendar('renderEvent', {
title: title,
start: startDate,
end: endDate,
allDay: allDay
}, false // make the event "unstick"
);
var startDateString = $.fullCalendar.formatDate(startDate, 'yyyy-MM-dd');
var endDateString = $.fullCalendar.formatDate(endDate, 'yyyy-MM-dd');
$.ajax({
type: 'POST',
url: './new_event.php?action=add',
data: {
startDate: startDateString,
endDate: endDateString,
eventTitle: title,
propID: propID
},
dateType: 'json',
success: function (resp) {
calendar.fullCalendar('refetchEvents');
}
});
} // end of inner if
} // end of else
calendar.fullCalendar('unselect');
},
About viewDisplay
.
Its is fired every time when we go to previous or next month, and it fired after eventAfterRender
. If we use eventAfterRender
and go to month without events we have no effect. The free cells stay booked.
I offer analyse events of current month inviewDisplay
:
function viewCalDisplay(view) {
//...................
// Your code
$(".booked").removeClass("booked"); // Remove all booked class from element
var events = view.calendar.clientEvents(function(event){
//we need only events of current month
return event.start.getMonth() == view.start.getMonth();
} );
for(i = 0; events.length > i; i++){
var event = events[i];
// We need only days of current month. We select <td> of calender table (by class .ui-widget-content)
var elements = $(".ui-widget-content:not(.fc-other-month)").filter(function(){
//We try to find day number witch corresponds to the event date
return (event.end == null && $(this).find(".fc-day-number").text() == event.start.getDate()) //If we have 1 day event
|| (event.end != null && $(this).find(".fc-day-number").text() >= event.start.getDate() // If we have many day event
&& $(this).find(".fc-day-number").text() <= event.end.getDate())
});
elements.addClass("booked"); //Only for this <td>
}
}
a) I want that only one event is allowed for a date(s).
Does this problem get resolved if we resolve the problem B? I mean I think you got it in the dayClick callback, right? alert('Sorry this date is already taken');
b) How do i stops further propagation if a day already have an event ?
Have you tried to return false
in the callbacks? Or can't you just use eventClick
callback? It's more relevant to your needs as far as I can tell.
c) does eventRender()
method is called only once when initialize the calendar
or each time when we go prev
or next
month?
The docs says:
Triggered while an event is being rendered.
So, I suppose it's called each time you go to next and previous month.
e) how to hide all events related to previous months?
I think you could just use eventRender
callback to decide if that event should be rendered or not? (Returning false on this callback will prevent the event from being rendered.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With