FullCalendar Event Hover with title, body, event date and URL

Created on 24 March 2025, 3 months ago

I have a drupal event calendar, When I click on an event it shows event details in a new page, How to show event details in a popup when a hover on the event

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Feature request
Status

Active

Version

3.0

Component

Code

Created by

🇮🇳India maheshv Bangalore

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @maheshv
  • 🇮🇳India nitesh624 Ranchi, India
  • 🇺🇸United States jennypanighetti

    I'm looking for this functionality as well. It is in the Fullcalendar JS library, but is it in this module?

  • 🇮🇳India nitesh624 Ranchi, India

    I don't think this module have this feature. Even if we try to add if try to implement through custom approach. Looks like html tags are getting stripped off in the view.

  • 🇮🇳India nitesh624 Ranchi, India

    I think hovering feature is a must have feature show show title and description When we hover onto a title. Suppose if title is two long (Suppose 7-10 words ) then it will only show few 3-4 words only on calendar. There is no way to read the complete title.

  • 🇮🇳India nitesh624 Ranchi, India

    So Now I am able to get this functionality working and below is the code snippet I had to write to get this working

    function custom_calendar_preprocess_views_view__fullcalendar(array &$variables): void {
      if (isset($variables['rows']['#attached']['drupalSettings']['fullcalendar']['js-view-dom-id-' . $variables['dom_id']]['options']['eventSources'])) {
        $events = $variables['rows']['#attached']['drupalSettings']['fullcalendar']['js-view-dom-id-' . $variables['dom_id']]['options']['eventSources'][0];
        // Update the events to include descriptions from nodes.
        $events = array_map(function ($event) {
          // Load the node by ID and set the description from body field.
          $node = \Drupal::entityTypeManager()->getStorage('node')->load($event['id']);
          if ($node instanceof NodeInterface && $node->hasField('body') && !$node->get('body')->isEmpty()) {
            $description = $node->body->value;
            // Trim the description to 160 chars.
            $event['description'] = mb_substr(strip_tags($description), 0, 160);
          }
          else {
            $event['description'] = '';
          }
          return $event;
        }, $events);
        // Update the events in the drupalSettings.
        $variables['rows']['#attached']['drupalSettings']['fullcalendar']['js-view-dom-id-' . $variables['dom_id']]['options']['eventSources'][0] = $events;
      }
    }
    

    and below is the js file content

    (function eventTooltip(Drupal, drupalSettings, once, tippy, FullCalendar) {
      Drupal.behaviors.calendarTooltip = {
        attach(context) {
          // Resets the "once" behavior for .fullcalendar--wrapper
          once.remove('fullCalendarBuild', '.fullcalendar--wrapper', context);
          once('fullCalendarBuild', '.fullcalendar--wrapper', context).forEach(
            (calendarEl) => {
              const domId = calendarEl.id;
              if (drupalSettings.fullcalendar.hasOwnProperty(domId)) {
                const settings = drupalSettings.fullcalendar[domId];
                const calendarOptions = settings.options;
                  calendarOptions.eventDidMount = function addTooltip(info) {
                    // Format the date as "MMM d" (e.g., "Jan 1")
                    const formattedDate = info.event.start.toLocaleDateString(undefined, { month: 'long', day: 'numeric' });
                    // Custom tooltip logic
                    tippy(info.el, {
                      content: `<div class="event-tooltip-title">${info.event.title}</div><div class="event-tooltip-date">${formattedDate}</div><div class="event-tooltip-description">${info.event.extendedProps.description}</div>`,
                      allowHTML: true,
                    });
                  };
                // Render the calendar as usual
                const calendar = new FullCalendar.Calendar(calendarEl, calendarOptions);
                calendar.render();
              }
            }
          );
        }
      };
    })(Drupal, drupalSettings, once, window.tippy, window.FullCalendar);
    
  • 🇮🇳India nitesh624 Ranchi, India

    I am not able to find any way to reuse the existing calendar object and add the callback function before rendering.

  • 🇺🇸United States mortona2k Seattle

    Is the code in here helpful? https://www.drupal.org/project/fullcalendar/issues/3527506 Extensible javascript FullCalendar object. Active

  • 🇮🇳India nitesh624 Ranchi, India

    yes that option I already tried. but I could not see anything to check if calendar is already rendered or not

  • 🇨🇦Canada mandclu

    Providing some form of tooltip display option is definitely a priority for this module. There seem to be quite a few examples online (including on FullCalendar.io) that show using Tippy.js, but it doesn't look like that library's repo has seen any updates in over 3 years and has now been marked as read only, which doesn't give me confidence. Floating UI looks to be actively maintained which makes it look like a better candidate.

    As to how this could be configured for Drupal, I would favour allowing a site builder to choose a view mode that would be used to render the content that would appear within the tooltip. That should allow virtually limitless customization options (including the use of custom templates, if desired) but does have the potential drawback that a misconfiguration (for example, choosing view mode that hasn't been set up for a content type) could cause full nodes to be rendered for the tooltip displays, causing the view render to be huge.

  • 🇮🇳India nitesh624 Ranchi, India

    Yes this could be the good option

  • 🇺🇸United States erutan

    There's built in functionality in fullcalendar that does this already that might be worth looking at vs recreating with a third party solution:

    https://fullcalendar.io/docs/event-popover

    https://www.drupal.org/project/fullcalendar/issues/3491161 Allow opening of events in a modal dialog Active appears to be a dupe of this issue.

  • 🇨🇦Canada mandclu

    The event popover seems designed to handle the use case of there being too many events to be shown within the calendar cell. While very useful, that seems different from what is being discussed here. I do agree that Allow opening of events in a modal dialog Active is a duplicate, so thank you for closing that.

    One thing from that issue to bring here is the potential approach of just using Drupal's AJAX API. I'm not 100% sure that simply adding the markup work, but it's definitely worth a try. A big advantage of that approach would be not having to worry about additional rendering or markup in the page.

    That said, there are potential advantages to something more customizable that design specifically to show an embedded view of the event information within the calendar. But if it works, the AJAX API version could be a good first step with low overhead.

  • 🇺🇸United States erutan

    I've been using (abusing?) the ajax API on a project to load form modes and whatnot into a model and having a ?destination= redirect back to the page the view on for doing larger content edits on the fly. I have it in views rewrites as well as templates. :)

    <a href="/storage/{{ id }}/edit/?display=FOO&destination=/BAR" class="use-ajax" data-dialog-type="dialog">✍️</a>

    This could simply be documented somewhere.

    fullcalendar_view iirc has an option where you check a box and then the last field in the view will get loaded in a modal. With rewrites and custom text fields this is a nice workable option.

  • 🇨🇦Canada mandclu

    Yeah the existing JS in this module leverages those properties already for the feature that double-clicking on a time slot or date opens a form to create a new event, and I can verify that it's very convenient. The challenge is that passing it into FullCalendar is not as straightforward. The class is no problem but data attributes aren't as well documented. I think adding it within extendedProps might work.

Production build 0.71.5 2024