Jscti
Jscti

Reputation: 14440

Fullcalendar (v2.x) Getting day-cell from an eventClick?

I'm struggling to retrieve the day clicked when clicking on a multi-days (period) event (eventClick).

Whe clicking on the background cell, it's easy :

function dayClick(date, jsEvent, view) {         

   //todo: store related day
   $scope.selectedDay = date;
}

But when clicking on an event (which is on a period of days), I can't retrieve which day exactly the user was on. (I need to perform a different action depending on the background day) :

function alertEventOnClick(event, jsEvent, view) {

            // "event" stores only start and end date without any reference to the current day
            // "jsEvent" retrieve the "td" element but fullcalendar HTML structure is complex and it's impossible to go-up to find the day-cell
            // $scope.selectedDay = ??
        };

I tried playing with "selectable" but "eventClick" JS Event doesn't propagate, and doesn't "select" the day

Thanks

Upvotes: 3

Views: 2647

Answers (5)

blair dowis
blair dowis

Reputation: 21

I updated Dane Iracleous's solution slightly to make it work with 1. click on multi-day events when there is more than one on the same day. and 2. this works in month/week/day views.

Using visibility/z-index solved my issue of the 'all day' container shrinking temporarily when the event layer was hidden.

getClickedDate(event) {
   //used to get specific date clicked on multiple day event
   let topLayer = $(event.el).closest(".fc-row");
   let eventLayer = topLayer.find(".fc-content-skeleton");
   let initialZIndex = $(eventLayer).css('z-index')

   $(eventLayer).css({ 'visibility': 'hidden', 'z-index': '-1'});

   let dayElement = $(document.elementFromPoint(event.jsEvent.pageX - window.pageXOffset, event.jsEvent.pageY - window.pageYOffset));

   $(eventLayer).css({ 'visibility': 'visible', 'z-index': initialZIndex });

   let clickedDate = dayElement.attr("data-date");
   console.log('clicked date', clickedDate)
   return clickedDate;
}

Upvotes: 0

Dane Iracleous
Dane Iracleous

Reputation: 1759

Here is slicedtoad's solution modified to work with v4 of fullcalendar and also taking into account the window's current scroll position:

     eventClick: function(ev) {
        var topLayer = $(ev.el).closest(".fc-row");
        var eventLayer = topLayer.find(".fc-content-skeleton");
        eventLayer.hide();
        var dayElement = $(document.elementFromPoint(ev.jsEvent.pageX - window.pageXOffset, ev.jsEvent.pageY - window.pageYOffset));
        eventLayer.show();
        var current_day = dayElement.attr("data-date");
        console.log(current_day);
     }

Upvotes: 0

jmm
jmm

Reputation: 1

Here is my solution:

eventClick: function(event, jsEvent, view) {
    var day=$(this).closest('.'+(view.type=='month'?'fc-row':'fc-time-grid')).find('.fc-bg td:eq('+$(this).closest('td').index()+')').data('date');
    console.log(day);
}

Upvotes: 0

DanielST
DanielST

Reputation: 14133

If you don't need to catch event clicks at all, you can just add a class to all events with pointer-events: none;

JSFiddle Demo

eventRender: function (event, element) {
    $(element).addClass('clickThrough');
},

IE8

Bleh. There is a hacky method to simulate pointer-events: none; on IE8 but while trying to implement it I found a simpler way to achieve the goal. (The simulated pointer-events hack is described here.)

To get the date at the cursor:

  • Hide the event table
  • Get element under cursor
  • Show the event table

JSFiddle Demo

eventClick: function (calEvent, jsEvent, view) {
    var topLayer = $(jsEvent.currentTarget).closest("tbody");
    topLayer.hide(); //hide the entire event layer (makes it work with multiple events)
    var dayElement = document.elementFromPoint(jsEvent.pageX, jsEvent.pageY); //get the element under the cursor (should be a day cell)
    topLayer.show();
    alert($(dayElement).data("date"));
}

Better IE8 workaround

(this doesn't seem to work)

So it turns out that anchor tags have a better pointer-events: none; workaround. https://stackoverflow.com/a/18118092/728393

You simply add the attribute disabled="disabled" to the <a> and it can be clicked through.

JSFiddle Demo

eventRender: function (event, element) {
    $(element).addClass('clickThrough').attr("disabled","disabled"); //disabled attribute is a IE workaround for pointer-events
},

Upvotes: 3

Jscti
Jscti

Reputation: 14440

So I finally found a quick(&dirty ?) solution relying on parsing close DOM Table elements.

From eventClick js event, I can retrieve the currentTarget clicked and go back in the table headers : the first row contains thead headers definition containing cell date mapping.

$scope.alertEventOnClick = function(event, jsEvent, view) {

    var columnIndex = $(jsEvent.currentTarget).parent('td').get(0).cellIndex + 1;
    var parentTable = $(jsEvent.currentTarget).closest('table');
    var dateString = $('thead td:nth-child('+ columnIndex +')', parentTable).attr('data-date');

    $scope.selectedDay = moment(dateString);
};

edit: solution OK for 1 event by day. but KO for more than one event by day ...

Another solution can be to determine x/y position of the clicked cell (by counting div/td childs) and map it with view.coordMap.grid.cellDates[position]

Upvotes: 1

Related Questions