Arshaw fullcalendar: несколько вопросов

Hello,
Я использую arshaw fullcalendar v1.5.2 (только месяц) для сайта бронирования недвижимости, его отличный плагин, но я застрял в нескольких проблемах, Я видел подобные проблемы на google code, но на самом деле ничего не ясно.:(, Пожалуйста, помогите мне решить эти проблемы.

Вот working demo и JS Code

Что я сделал до сих пор

  • Полученные данные о событиях из двух разных json файлов ниже

    • json_events.php: здесь хранится подробная информация о бронировании, которая забронирована пользователем с лицевой стороны; Администратор не может изменять какие-либо сведения об этих типах событий.

    • new_charges.php: в нем содержатся специальные сведения о событиях, admin добавить/обновить удаление новых платежей за любую будущую дату (даты).

  • admin может просматривать информацию о любом событии, когда он нажимает на событие

  • admin может добавлять/редактировать и удалять новые события в календаре для будущих дат или диапазона дат, которые будут сохранены на new_charges.php

вот мои проблемы

a) I want that only one event is allowed for a date(s).

b) В настоящее время, если пользователь нажимает в тот день, когда происходит какое-либо мероприятие по бронированию или мероприятие с особыми зарядами, он предупреждает, что этот день забронирован, , но, после чего появится окно подсказки для ввода названия события,

Это происходит потому, что я использовал методы dayClick и select

How do i stops further propagation if a day already have an event ?

c) предположим, что за 15 января (завернутый fc-day17 div) забронирован (я применил класс booked для событий), и теперь, когда я перехожу в следующий месяц и нажимаю fc-day17 div, он также предупреждает, что день забронирован, тогда как нет бронирования  изучив код, я обнаружил, что он еще имеет класс booked в течение еще нескольких месяцев для тех же divs

Я думаю, что что-то не хватает во время eventRender методов?

does `eventRender()`  method is called only once when initialize the calendar 
or each time when we go `prev` or `next` month?

d). Я изменил фоновый цвет для событий специальных зарядов во время событий рендеринга через json файл, но когда я делют эти события, он не изменяет нормальный фон и все еще говорит, что день забронированы.

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?

Ответ 1

// 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 Эта конструкция

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())
});

означает, что мы выбираем дни текущего месяца (:not(.fc-other-month)), которые удовлетворяют условиям filter (return true): дни месяц равен дням событий

О вашем коде, как я уже сказал, вы должны удалить событие dayClick, и ваше событие select:

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');
},

О viewDisplay. Его запускают каждый раз, когда мы идем в предыдущий или следующий месяц, и он запускается после eventAfterRender. Если мы используем eventAfterRender и переходим на месяц без событий, мы не имеем никакого эффекта. Свободные ячейки остаются забронированными. Я предлагаю проанализировать события текущего месяца в viewDisplay:

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> 
            }
}

Ответ 2

a) Я хочу, чтобы на дату было разрешено только одно событие.

Устранена ли эта проблема, если мы разрешим проблему B? Я имею в виду, я думаю, что вы получили его в callClick дня, не так ли? alert('Sorry this date is already taken');

b) Как остановить дальнейшее распространение, если в день уже есть событие?

Вы пытались выполнить return false в обратных вызовах? Или вы не можете использовать обратный вызов eventClick? Насколько мне известно, это более актуально для ваших нужд.

c) метод eventRender() вызывается только один раз при инициализации календаря или каждый раз, когда мы идем prev или next month?

docs говорит:

Запускается, пока выполняется событие.

Итак, я предполагаю, что он называется каждый раз, когда вы переходите к следующему и предыдущему месяцам.

e) как скрыть все события, связанные с предыдущими месяцами?

Я думаю, вы могли бы просто использовать обратный вызов eventRender, чтобы решить, нужно ли это событие отображать или нет? (Возврат false при этом обратном вызове предотвратит отображение события.)