<?php // $Id: superfish.module,v 1.2 2010/02/15 13:38:03 mehrpadin Exp $

/**
 * @file
 *  Module to deply jQuery Superfish plugin.
 *
 * A special thanks goes to Jake Gordon (jakeg)
 * and Addison Berry (add1sun) since some parts of
 * this file is written by them.
 */

/**
 * Implementation of hook_menu().
 */
function superfish_menu() {
  $items['admin/settings/superfish'] = array(
    'title' => 'Superfish',
    'description' => 'Configure Superfish Menus',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('superfish_menu_settings'),
    'access arguments' => array('administer site configuration'),
    'file' => 'superfish.admin.inc'
  );
  return $items;
}

/**
 * Implementation of hook_help().
 */
function superfish_help($path, $arg) {
  $output = '';
  switch ($path) {
  case 'admin/settings/modules#description':
    $output .= t('Superfish adds jQuery Superfish plugin to your menus.');
    break;
  case 'admin/settings/superfish':
    $output .= t('<p>Block-specific Superfish settings could be found at !link</p>', array('!link' => l('admin/build/block', 'admin/build/block')));
    break;
  }
  return $output;
}

/**
 * Implementation of hook_block().
 */
function superfish_block($op = 'list', $delta = 0, $edit = array()) {
  global $user;

  switch ($op) {
    case 'list' :
      $number = variable_get('superfish_number', 2);
      $number++;
      for ($i = 1; $i <= $number; $i++) {
        $blocks[$i]['info'] = variable_get('superfish_name_'. $i, 'Superfish '. $i) .' (Superfish)';
        $blocks[$i]['cache'] = BLOCK_NO_CACHE;
      }
      return $blocks;
    break;

  case 'configure' :
    $form['superfish_name_'. $delta] = array(
      '#type' => 'textfield',
      '#title' => t('Menu Name'),
      '#default_value' => variable_get('superfish_name_'. $delta, 'Superfish '. $delta),
    );
    $form['sf-settings'] = array(
      '#type' => 'fieldset',
      '#title' => t('Superfish settings'),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );
    $form['sf-settings']['superfish_menu_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Menu Parent'),
      '#description' => t('The menu you want to be displayed using Superfish.'),
      '#default_value' => variable_get('superfish_menu_'. $delta, 'navigation:0'),
      '#options' => menu_parent_options(menu_get_menus(), 0),
    );
    $form['sf-settings']['superfish_depth_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Menu Depth'),
      '#description' => t('The number of child levels starting with the parent selected above. -1 means all of them, 0 means none of them.'),
      '#default_value' => variable_get('superfish_depth_'. $delta, -1),
      '#options' => drupal_map_assoc(range(-1, 5)),
    );
    $form['sf-settings']['superfish_type_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Menu Type'),
      '#description' => t('There are 3 types of Superfish menus.<br /><b>Horizontal</b> which drops down.<br /><b>Vertical</b> which drops right.<br /><b>NavBar</b> which is a tab-based menu.'),
      '#default_value' => variable_get('superfish_type_'. $delta, 'Horizontal'),
      '#options' => array(
        'horizontal' => t('Horizontal'),
        'vertical' => t('Vertical'),
        'navbar' => t('NavBar')),
    );
    $form['sf-settings']['superfish_style_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Menu Style'),
      '#default_value' => variable_get('superfish_style_'. $delta, 'default'),
      '#description' => t('Superfish modules has five different colour schemes in addition to the default purplish Superfish menu theme.'),
      '#options' => array(
        'default' => t('Default'),
        'blue' => t('Blue'),
        'coffee' => t('Coffee'),
        'light-blue' => t('Light blue'),
        'pomegranate' => t('Pomegranate'),
        'space' => t('Space [Blue]'),
        'space-orange' => t('Space [Orange]'),
        'space-teal' => t('Space [Teal]'),
        'spring' => t('Spring'),
        'white' => t('White')),
    );
    $form['sf-settings']['superfish_fade_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Fade effect'),
      '#default_value' => variable_get('superfish_fade_'. $delta, 'true'),
      '#options' => array(
        'true' => t('Yes'),
        'false' => t('No')),
    );
    $form['sf-settings']['superfish_slide_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Slide-in effect'),
      '#default_value' => variable_get('superfish_slide_'. $delta, 'true'),
      '#options' => array(
        'true' => t('Yes'),
        'false' => t('No')),
    );
    $form['sf-settings']['superfish_delay_'. $delta] = array(
      '#type' => 'textfield',
      '#title' => t('Mouse delay'),
      '#description' => t('The delay in <b>milliseconds</b> that the mouse can remain outside a sub-menu without it closing.'),
      '#default_value' => variable_get('superfish_delay_'. $delta, 1000),
      '#size' => 10,
    );
    $form['sf-settings']['superfish_speed_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Animation Speed'),
      '#default_value' => variable_get('superfish_speed_'. $delta, 'normal'),
      '#options' => array(
        'slow' => t('Slow'),
        'normal' => t('Normal'),
        'fast' => t('Fast')),
    );
    $form['sf-settings']['superfish_shadow_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Drop shadows'),
      '#default_value' => variable_get('superfish_shadow_'. $delta, 'true'),
      '#options' => array(
        'true' => t('Yes'),
        'false' => t('No')),
    );
    $form['sf-settings']['superfish_arrow_'. $delta] = array(
      '#type' => 'select',
      '#title' => t('Auto-arrows'),
      '#description' => t('Automatically adds an arrow to each parent menu item.'),
      '#default_value' => variable_get('superfish_arrow_'. $delta, 'false'),
      '#options' => array(
        'true' => t('Yes'),
        'false' => t('No')),
    );
    $form['sf-settings']['sf-settings-supersubs'] = array(
      '#type' => 'fieldset',
      '#title' => t('Supersubs options'),
      '#description' => t('<b>Supersubs</b> makes it possible to define custom widths for your menus. (Recommended)'),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );
    $form['sf-settings']['sf-settings-supersubs']['superfish_supersubs_'. $delta] = array(
      '#type' => 'checkbox',
      '#title' => t('Enable Supersubs'),
      '#default_value' => variable_get('superfish_supersubs_'. $delta, 1),
    );
    $form['sf-settings']['sf-settings-supersubs']['superfish_minwidth_'. $delta] = array(
      '#type' => 'textfield',
      '#title' => t('Minimum width'),
      '#description' => t('Minimum width of sub-menus in <b>em</b> units. '),
      '#default_value' => variable_get('superfish_minwidth_'. $delta, '12'),
      '#size' => 20,
    );
    $form['sf-settings']['sf-settings-supersubs']['superfish_maxwidth_'. $delta] = array(
      '#type' => 'textfield',
      '#title' => t('Maximum width'),
      '#description' => t('Maximum width of sub-menus in <b>em</b> units. '),
      '#default_value' => variable_get('superfish_maxwidth_'. $delta, '27'),
      '#size' => 20,
    );
    return $form;
  break;

  case 'save' :
    variable_set('superfish_name_'. $delta, $edit['superfish_name_'. $delta]);
    variable_set('superfish_menu_'. $delta, $edit['superfish_menu_'. $delta]);
    variable_set('superfish_depth_'. $delta, $edit['superfish_depth_'. $delta]);
    variable_set('superfish_type_'. $delta, $edit['superfish_type_'. $delta]);
    variable_set('superfish_style_'. $delta, $edit['superfish_style_'. $delta]);
    variable_set('superfish_fade_'. $delta, $edit['superfish_fade_'. $delta]);
    variable_set('superfish_slide_'. $delta, $edit['superfish_slide_'. $delta]);
    variable_set('superfish_delay_'. $delta, $edit['superfish_delay_'. $delta]);
    variable_set('superfish_speed_'. $delta, $edit['superfish_speed_'. $delta]);
    variable_set('superfish_shadow_'. $delta, $edit['superfish_shadow_'. $delta]);
    variable_set('superfish_arrow_'. $delta, $edit['superfish_arrow_'. $delta]);
    variable_set('superfish_supersubs_'. $delta, $edit['superfish_supersubs_'. $delta]);
    variable_set('superfish_minwidth_'. $delta, $edit['superfish_minwidth_'. $delta]);
    variable_set('superfish_maxwidth_'. $delta, $edit['superfish_maxwidth_'. $delta]);
  break;

  case 'view' :
    list($menu_name, $mlid) = explode(':', variable_get('superfish_menu_'. $delta, 'navigation:0'));
    $depth = variable_get('superfish_depth_'. $delta, '-1');
    $type = variable_get('superfish_type_'. $delta, 'horizontal');
    $style = variable_get('superfish_style_'. $delta, 'default');
    $fade = variable_get('superfish_fade_'. $delta, 'true');
    $slide = variable_get('superfish_slide_'. $delta, 'true');
    $delay = variable_get('superfish_delay_'. $delta, 1000);
    $speed = variable_get('superfish_speed_'. $delta, 'normal');
    $shadow = variable_get('superfish_shadow_'. $delta, 'true');
    $arrow = variable_get('superfish_arrow_'. $delta, 'false');
    $supersubs = variable_get('superfish_supersubs_'. $delta, 1);

    global $language;
    if ($language->direction == 1) {
      $type .= ' rtl';
    }

    if ($style != 'default') {
        drupal_add_css(drupal_get_path('module', 'superfish') .'/css/extra/'. $style .'.css');
    }

    // SuperSubs enabled? get the max\min widths and prepare the Javascript code
    if ($supersubs == 1) {
      $minwidth = variable_get('superfish_minwidth_'. $delta, '12');
      $maxwidth = variable_get('superfish_maxwidth_'. $delta, '27');
      $supersubs_javascript = "jQuery('ul#superfish-$delta').supersubs({\n minWidth: $minwidth,\n maxWidth: $maxwidth,\n extraWidth: 1\n});\n";
    }

    // Checking for any jQuery .animate(); stuffs
    if ($fade == 'true' || $slide == 'true') {
      $animation = "animation: {";
      if ($fade == 'true') {
        $animation .= "opacity:'show'";
      }
      if ($fade == 'true' && $slide == 'true') {
        $animation .= ',';
      }
      if ($slide == 'true') {
        $animation .= "height:'show'";
      }
      $animation .= "},";
    }

    // And finally assembling our js code
    $javascript = "jQuery(function(){\n $supersubs_javascript jQuery('ul#superfish-$delta').superfish({\n pathClass: 'active',\n delay: $delay,\n $animation\n speed: '$speed',\n autoArrows: $arrow,\n dropShadows: $shadow\n}).find('ul').bgIframe({opacity:false});\n});";

    drupal_add_js($javascript, 'inline');

    if ($output = theme('superfish', $delta, $menu_name, $mlid, $type, $style, $depth)) {
      $block['content'] = $output['content'];
      $block['subject'] = check_plain($subject);
    }
    else {
      $block['content'] = FALSE;
    }
    return $block;
  break;
  }
}

/**
 * Implementation of hook_init().
  */
function superfish_init() {
  if (variable_get('superfish_hid', 1) == 1) {
    drupal_add_js(drupal_get_path('module', 'superfish') .'/js/jquery.hoverIntent.minified.js');
  }
  drupal_add_js(drupal_get_path('module', 'superfish') .'/js/jquery.bgiframe.min.js');
  drupal_add_js(drupal_get_path('module', 'superfish') .'/js/superfish.js');
  drupal_add_js(drupal_get_path('module', 'superfish') .'/js/supersubs.js');

  // Adding CSS
  drupal_add_css(drupal_get_path('module', 'superfish') .'/css/superfish.css');
  drupal_add_css(drupal_get_path('module', 'superfish') .'/css/superfish-vertical.css');
  drupal_add_css(drupal_get_path('module', 'superfish') .'/css/superfish-navbar.css');
}

/**
 * Implementation of hook_theme().
 */
function superfish_theme() {
  return array(
    'superfish_tree' => array(
        'arguments' => array('id' => NULL, 'menu_name' => NULL, 'mlid' => NULL, 'depth' => -1, 'menu' => NULL),
      ),
    'superfish_build' => array(
        'arguments' => array('id' => NULL, 'menu' => NULL, 'depth' => -1, 'trail' => NULL),
      ),
    'superfish' => array(
      'arguments' => array('id' => NULL, 'menu_name' => NULL, 'mlid' => NULL, 'type' => 'horizontal', 'style' => 'Blue', 'depth' => -1, 'menu' => NULL),
    )
  );
}

/**
 * Builds the active trail from the page's menu data.
 */
function superfish_build_page_trail($page_menu) {
  $trail = array();
  foreach ($page_menu as $item) {
    if ($item['link']['in_active_trail']) {
      $trail[] = $item['link']['mlid'];
    }
    if ($item['below']) {
      $trail = array_merge($trail, superfish_build_page_trail($item['below']));
    }
  }
  return $trail;
}

/**
 * Builds the final Superfish.
 */
function theme_superfish_tree($id, $menu_name, $mlid = NULL, $depth = -1, $menu = NULL) {
  $menu = isset($menu) ? $menu : menu_tree_all_data($menu_name);
  if (isset($menu)) {
    $page_menu = menu_tree_page_data($menu_name);
    $trail = superfish_build_page_trail($page_menu);
    unset($page_menu);
  }

  if (module_exists('i18nmenu')) {
    i18nmenu_localize_tree($menu);
  }

  // For custom $menus and menus built all the way from the top-level we
  // don't need to "create" the specific sub-menu and we need to get the title
  // from the $menu_name since there is no "parent item" array.

  // Create the specific menu if we have a mlid.
  if (!empty($mlid)) {
    // Load the parent menu item.
    $item = menu_link_load($mlid);
    $title = check_plain($item['title']);
    $parent_depth = $item['depth'];

    // Narrow down the full menu to the specific sub-tree we need.
    for ($p = 1; $p < 10; $p++) {
      if ($sub_mlid = $item["p$p"]) {
      $subitem = menu_link_load($sub_mlid);
      $menu = $menu[(50000 + $subitem['weight']) .' '. $subitem['title'] .' '. $subitem['mlid']]['below'];
      }
    }
  }
  else {
    // Otherwise just set a title and move on.
    // Get the title from the DB since we don't have it in the $menu.
    $result = db_result(db_query("SELECT title FROM {menu_custom} WHERE menu_name = '%s'", $menu_name));
    $title = check_plain($result);
  }

  $output['content'] = '';
  $output['subject'] = $title;

  if ($menu) {
    // Set the total menu depth counting from this parent if we need it.
    $depth =  ($depth > 0) ? ($parent_depth + $depth) : $depth;
    $output['content'] .= theme('superfish_build', $id, $menu, $depth, $trail);
  }
  return $output;
}

/**
 * Helper function that builds the nested lists of a Superfish menu.
 */
function theme_superfish_build($id, $menu, $depth = -1, $trail = NULL) {
  $output = '';
  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    if ($menu_item['link']['hidden'] == 0) {
      if ($trail && in_array($mlid, $trail)) {
        $class = ' active-trail';
      }
      if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) {
        $children = theme('superfish_build', $id, $menu_item['below'], $depth, $trail);
        $parent_class = $children ? 'menuparent ' : '';
        $output .= '<li id="menu-'. $mlid .'-'. $id .'"';
        if (!empty($parent_class) || !empty($class)) {
          $output .= ' class="'. $parent_class . $class .'"';
        }
        $output .= '>'. theme('menu_item_link', $menu_item['link']);
        if ($menu_item['link']['depth'] <= $depth || $depth == -1) {
          if ($children) {
            $output .= "<ul>\n $children \n</ul>\n";
          }
        }
        $output .= "</li>\n";
      }
      else {
        $output .= '<li id="menu-'. $mlid .'-'. $id .'"';
        if (!empty($class)) {
          $output .= ' class="'. $class .'"';
        }
        $output .= '>'. theme('menu_item_link', $menu_item['link']) .'</li>'."\n";
      }
    }
  }
  return $output;
}

/**
 * Theme function to allow any menu tree to be themed as a Superfish menu.
 */
function theme_superfish($id, $menu_name, $mlid, $type = 'horizontal', $style = 'Blue', $depth = -1, $menu = NULL) {
  $output = array();
  if ($menu_tree = theme('superfish_tree', $id, $menu_name, $mlid, $depth, $menu)) {
    if ($menu_tree['content']) {
      $output['content'] = '<ul class="sf-menu sf-'. $type .' sf-style-'. $style .'" id="superfish-'. $id .'">'. $menu_tree['content'] .'</ul>'."\n";
      $output['subject'] = $menu_tree['subject'];
    }
  }
  return $output;
}