<?php
/*
   Calendar tooltips module for Drupal.
   Ronald Baljeu (rjb@xs4all.nl)
   http://linuxpc.info/
*/

/* TODO: hook_uninstall() in order to remove setting variables */

/* Override the theme function template_preprocess_calendar_datebox() in
   modules/calendar/theme/theme.inc.
   See http://www.lullabot.com/articles/overriding-theme-functions-in-modules
   for more info on how to override theme functions in modules.

   Also register our init function for beautytips. We do not use hook_init()
   for this because older versions of beautytips_add_beautytips() called theme()
   which should not be called in hook_init(). In D6 this causes theming issues.
   See: http://drupal.org/node/219910. Workaround found at:
   http://drupal.org/node/599106.
*/
function calendar_tooltips_theme_registry_alter(&$theme_registry) {
  if (!empty($theme_registry['preprocess_calendar_datebox'])) {
    $theme_registry['preprocess_calendar_datebox']['function'] =
      'calendar_tooltips_preprocess_calendar_datebox';
  }
  array_unshift($theme_registry['page']['preprocess functions'],
    'calendar_tooltips_initialize_beautytips');
}

/* Here is the modified theme function which is called for each day
   on the calendar.
*/

/**
 * Create the calendar date box.
 */
function calendar_tooltips_preprocess_calendar_datebox(&$vars) {
  $date = $vars['date'];
  $view = $vars['view'];
  $vars['day'] = intval(substr($date, 8, 2));
  $force_view_url = !empty($view->date_info->block) ? TRUE : FALSE;
  $month_path = calendar_granularity_path($view, 'month');
  $year_path = calendar_granularity_path($view, 'year');
  $day_path = calendar_granularity_path($view, 'day');
  $vars['url'] = str_replace(array($month_path, $year_path), $day_path, date_pager_url($view, NULL, $date, $force_view_url));
  $vars['link'] = !empty($day_path) ? l($vars['day'], $vars['url']) : $vars['day'];
  $vars['granularity'] = $view->date_info->granularity;
  $vars['mini'] = !empty($view->date_info->mini);

  /* The following code has been added. It aggregates event data
     of that day and puts it in an HTML unordered list,
     which is parented in a div element, which, on its turn,
     is placed next to the hyperlink. The div element with the event
     data is hidden by using a "display:none" style.
     The code for telling Beautytips that this is the place to look for
     event data, is in the function
     calendar_tooltips_initialize_beautytips().
  */
  if (!empty($vars['selected'])) {
    $bt_text = "<ul>";
    foreach ($vars['items'][$date] as $time => $results_at_that_time) {
      foreach ($results_at_that_time as $num => $result) {
        $result = (array)$result;
        $bt_text .= "<li>";
        /* The event data shown in the tooltip can be specified in
           the display settings of your calendar view.
           Choose the "Block view" display, and check out
           the "Fields" section.
        */
        foreach ($view->field as $name => $field) {
          if (!$field->options['exclude']) {
            if ($field->options['label'] != "" &&
              ($result['rendered_fields'][$name] != "" ||
              empty($field->options['hide_empty'])))
              $bt_text .= "<div class=\"calendar_tooltips-" . $name .
                "-label\">" . $field->options['label'] .
                ($field->options['element_label_colon'] ? ":" : "") .
                "</div>";
            if ($result['rendered_fields'][$name] != "")
              $bt_text .= "<div class=\"calendar_tooltips-" . $name .
                "-value\">" . $result['rendered_fields'][$name] .
                "</div>";
          }
        }
        $bt_text .= "</li>";
      }
    }
    $bt_text .= "</ul>";
    $bt_text = "<div class=\"calendar_tooltips\" style=\"display:none\">" .
      $bt_text . "</div>";
    if (!empty($day_path))
      $vars['link'] = l($vars['day'], $vars['url']);
    else
      $vars['link'] = '<span>' . $vars['day'] . '</span>';
    $vars['link'] .= $bt_text;
    /*
       The balloon text is appended to the link variable,
       like this: "<a href=...>31</a> <div>balloon text</div>" (see above).
       which makes it difficult for the user to alter the link without
       losing the balloon text. That's why we provide an extra variable with
       the balloon text only. The user may use this to append to
       the new link when overriding calendar-datebox.tpl.php.
    */
    $vars['calendar_tooltips_text'] = $bt_text;
  }
  /* End of additional code. */

  if ($vars['mini']) {
    if (!empty($vars['selected'])) {
      $vars['class'] = 'mini-day-on';
    }
    else {
      $vars['class'] = 'mini-day-off';
    }
  }
  else {
    $vars['class'] = 'day';
  }
}

/* This function will be called at the beginning of each page request.
   It is used to setup Beautytips. The "cssSelect" below is a CSS
   selector that selects every date containing events on the calendar.
   The "contentSelector" is jQuery code which specifies the HTML code
   of the hyperlink's first sibling (in our case the div element)
   as the tooltip's content.
   The rest of the code is for telling Beautytips when to close the tooltip.
*/
function calendar_tooltips_initialize_beautytips() {
  $bt_options['calendar-tooltips'] = array(
    "cssSelect" =>
      ".calendar-calendar .mini-day-on a, .calendar-calendar .day a, " .
        ".calendar-calendar .mini-day-on span, .calendar-calendar .day span",
    "contentSelector" => '$(this).next().html()'
  );
  switch (variable_get("calendar_tooltips_whentoclose", "mouseout")) {
    case "click":
      $bt_options['calendar-tooltips']['trigger'] =
        array(0 => "mouseover", 1 => "click");
      break;
    case "timeout":
      /* The trigger is "hoverIntent" by default so we don't have to
         set it like above. We only need to change its timeout.
      */
      $bt_options['calendar-tooltips']['hoverIntentOpts'] =
        array(
          "timeout" =>
            variable_get('calendar_tooltips_close_delay', 3000),
          "interval" => 0);
      /* bug workaround needed to use the built-in hoverIntent plugin:
         see http://drupal.org/node/502318
      */
      drupal_add_js(drupal_get_path('module', 'beautytips') .
        '/other_libs/jquery.hoverIntent.minified.js');
      break;
    case "mouseout":
    default:
      $bt_options['calendar-tooltips']['trigger'] =
        array(0 => "mouseover", 1 => "mouseout");
  }
  beautytips_add_beautytips($bt_options);
}

/* Here are the module settings of this module. More info on the form API:
      http://api.drupal.org/api/drupal/developer--topics--forms_api.html/6
*/
function calendar_tooltips_admin() {
  $form = array();
  $form['calendar_tooltips_whentoclose'] = array(
    '#type' => 'radios',
    '#title' => t('Close tooltip when'),
    '#default_value' =>
       variable_get('calendar_tooltips_whentoclose', "mouseout"),
    '#options' => array(
       'click' => t('the user clicks outside the tooltip (click to close)'),
       'mouseout' => t('the cursor moves away from the date'),
       'timeout' => t('the cursor is kept away from the date ' .
          'during a certain amount of time (timeout)'))
  );
  $form['calendar_tooltips_close_delay'] = array(
    '#type' => 'textfield',
    '#title' => t('Time in milliseconds to wait before closing the tooltip'),
    '#default_value' =>
       variable_get('calendar_tooltips_close_delay', 3000),
    '#size' => 5,
    '#maxlength' => 5,
    '#description' => t('This field only has effect when the timeout option' .
       ' (last option from above) is selected')
  );
  return system_settings_form($form);
}

/* Register the module settings page above.
   See also Drupal's module creation tutorial at:
   http://drupal.org/node/206761 .
*/
function calendar_tooltips_menu() {
  $items = array();
  $items['admin/config/user-interface/calendar_tooltips'] = array(
    'title' => 'Calendar tooltips',
    'description' => 'Settings of calendar tooltips',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('calendar_tooltips_admin'),
    'access arguments' => array('administer site configuration')
  );
  return $items;
}
