最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Apply minTime and maxTime specific to current week - Stack Overflow

programmeradmin3浏览0评论

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.

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.

Share Improve this question edited Aug 21, 2015 at 17:50 DanielST 14.2k7 gold badges44 silver badges66 bronze badges asked Oct 12, 2014 at 19:24 SiberianGuySiberianGuy 25.3k57 gold badges159 silver badges272 bronze badges 6
  • Look at viewRender. Sounds like you know what to do – Richard Löwenström Commented Oct 12, 2014 at 21:57
  • @RichardHermanson, seems close to what I need. But seems like there is no way to retrieve events for current date-range. – SiberianGuy Commented Oct 13, 2014 at 13:02
  • You could use eventRender for that I guess or you could use getView and then filter clientEvents using the interval start and end. If you go for the latter then maybe this code will help – Richard Löwenström Commented Oct 13, 2014 at 13:10
  • @RichardHermanson, seems like a right thing to do. Could be some problems with timezones though. – SiberianGuy Commented Oct 14, 2014 at 20:13
  • So you want this but dynamically? jsfiddle/3E8nk/542 – Richard Löwenström Commented Oct 14, 2014 at 20:21
 |  Show 1 more ment

2 Answers 2

Reset to default 8 +100

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 ments 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/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./',
            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.

发布评论

评论列表(0)

  1. 暂无评论