views:

70

answers:

1

I want to display events in the jQuery UI Datepicker. I want the days that have events to be styled differently from days that don't have events, and I want to display a custom tooltip with the event details when hovering dates with events.

The solution to the question "jQuery UI Datepicker with jQuery tipsy" gets very close, but doesn't work with the Datepicker configuration I use. I use the "showOtherMonths" option, and it throws the date link calculation off.

The event data is available at http://mydomain.com/events.json

Mockup of what I want:

Datepicker with events

This is the code I use for creating the Datepicker:

$('#dateDiv').datepicker({
    altField: '#dateInput',
    altFormat: 'yy-mm-dd',
    dateFormat: 'yy-mm-dd',
    firstDay: '1',
    showOtherMonths: 'true',
});

I'm not concerned about the CSS part of the solution at this time, just the javascript part. How do I make my custom tooltip appear when hovering the dates with events attached to them? And how do I attach the events (calendar events, not javascript/DOM events ;) )?

A: 

This is not a very elegant solution, but it does seem to work. Can someone please come up with something better?

EDIT: Here's a jsFiddle with the code running: http://jsfiddle.net/Tobbe/JrkSN/3/

EDIT2: It works until I click on a date, then all the events disappears because the beforeShowDay callback isn't called in that case. How do I work around that?

getEvents();

$(function() {
    $('#dateDiv').datepicker({
        altField: '#dateInput',
        altFormat: 'yy-mm-dd',
        dateFormat: 'yy-mm-dd',
        firstDay: '1',
        showOtherMonths: 'true',
        beforeShowDay: beforeShowDay,
        onChangeMonthYear: getEvents
    });
});

var enqueuedDates = [];
var tryCounter = 0;
var events = [];

function getEvents() {
    events = [];
    enqueuedDates = [];
    $.getJSON('events.json', function(json) {
        events = json;
    });
}

function beforeShowDay(date) {
    enqueuedDates.push(new Date(date));

    if (enqueuedDates.length == 35) {
        processEnqueuedDates();
    }

    return [true, '', ''];
}

function processEnqueuedDates() {
    if (!events || events.length === 0) {
        tryCounter++;
        if (tryCounter < 100) {
            setTimeout(processEnqueuedDates, 10);
        } else {
            tryCounter = 0;
        }

        return;
    }

    tryCounter = 0;

    for (var i = 0; i < enqueuedDates.length; ++i) {
        var event = getEvent(events, enqueuedDates[i]);

        if (event) {
            var theDateCells = $('#dateDiv .ui-datepicker-calendar td');
            var hideTimeoutID;
            theDateCells.eq(i).addClass('eventPlanned').
                bind('mouseenter', function(eventText) {
                    return function() {
                        if (hideTimeoutID) {
                            clearTimeout(hideTimeoutID);
                            hideTimeoutID = null;
                        }

                        var popup = $('#eventPopup');
                        if (popup.size() == 0) {
                            popup = $('<div></div>').attr('id', 'eventPopup');
                            $('body').append(popup);
                        }

                        var pos = $(this).offset();

                        popup.html('<p>' + eventText + '</p>').
                            css('left', pos.left + 5 + 'px').
                            css('top', (pos.top - popup.height() - 2) + 'px').
                            bind('mouseenter', function() {
                                clearTimeout(hideTimeoutID);
                                hideTimeoutID = null;
                            }).
                            bind('mouseleave', function() {
                                $(this).hide();
                            }).
                            show();
                    }
                }(event.text)).
                bind('mouseleave', function(eventObject) {
                    hideTimeoutID = setTimeout(function() {
                        $('#eventPopup').hide();
                    }, 200);
                });
        }
    }
}

function getEvent(events, date) {
    return events.filter(function(event, index, arr) {
        return date - $.datepicker.parseDate('yy-mm-dd', event.date) === 0;
    })[0];
}
Tobbe