nice_menus.module in Nice Menus 6.2
Same filename and directory in other branches
Module to enable CSS dropdown and flyout menus.
Maintainer: Addison Berry (add1sun) Originally written by Jake Gordon (jakeg)
File
nice_menus.moduleView source
<?php
/**
* @file
* Module to enable CSS dropdown and flyout menus.
*
* Maintainer: Addison Berry (add1sun)
* Originally written by Jake Gordon (jakeg)
*/
/**
* Implements hook_help().
*/
function nice_menus_help($path, $arg) {
$output = '';
switch ($path) {
case 'admin/settings/modules#description':
$output .= t('Make drop down/flyout CSS menus for site and admin menus.');
break;
case 'admin/settings/nice_menus':
$output .= t('<p>This is a simple module that enables the site to have drop down/flyout CSS menus for site and admin navigation.</p><p>Remember to activate and configure the menu blocks in !link</p>', array(
'!link' => l(t('admin/build/block'), 'admin/build/block'),
));
break;
}
return $output;
}
/**
* Implements hook_form_alter().
*/
function nice_menus_form_alter(&$form, $form_state, $form_id) {
switch ($form_id) {
case 'system_theme_settings':
// This is a global setting, so only insert the field
// on the global settings page.
if (arg(4) && arg(4) != 'global') {
return;
}
// Have to add a custom submit handler since this form doesn't use
// the standard system submit handler.
$form['#submit'][] = 'nice_menus_system_theme_settings_submit';
// Add global theme setting for a custom CSS file.
$form['nice_menus_custom_css'] = array(
'#type' => 'textfield',
'#title' => t('Path to custom Nice menus CSS file'),
'#description' => t('To override the default Nice menus CSS layout, enter the path to your custom CSS file. It should be a relative path from the root of your Drupal install (e.g. sites/all/themes/example/mymenu.css).'),
'#default_value' => variable_get('nice_menus_custom_css', ''),
// Field appears below submit buttons without this -- yucky.
'#weight' => 0,
);
break;
}
}
/**
* Records the Nice menu custom CSS file per theme.
*/
function nice_menus_system_theme_settings_submit($form, &$form_state) {
variable_set('nice_menus_custom_css', $form_state['values']['nice_menus_custom_css']);
}
/**
* Implements hook_menu().
*/
function nice_menus_menu() {
$items['admin/settings/nice_menus'] = array(
'title' => 'Nice menus',
'description' => 'Configure Nice menus.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'nice_menus_admin_settings',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'nice_menus.admin.inc',
);
return $items;
}
/**
* Implements hook_init().
*
* We are adding the JavaScript and CSS here rather than theme_nice_menu
* because when block caching is enabled none of it would get fired
* and the menus are unstyled.
*/
function nice_menus_init() {
// Add Superfish JavaScript, if enabled.
if (variable_get('nice_menus_js', 1) == 1) {
// The script, from http://users.tpg.com.au/j_birch/plugins/superfish.
drupal_add_js(drupal_get_path('module', 'nice_menus') . '/js/superfish.js');
// Add the Superfish options variables.
drupal_add_js(array(
'nice_menus_options' => array(
'delay' => variable_get('nice_menus_sf_delay', 800),
'speed' => variable_get('nice_menus_sf_speed', 1),
'hover_intent' => variable_get('nice_menus_hover_intent', 1),
),
), 'setting');
// Add the bgIframe plugin.
drupal_add_js(drupal_get_path('module', 'nice_menus') . '/js/jquery.bgiframe.min.js');
// Add the HoverIntent plugin.
drupal_add_js(drupal_get_path('module', 'nice_menus') . '/js/jquery.hoverIntent.minified.js');
// The Nice menus implementation.
drupal_add_js(drupal_get_path('module', 'nice_menus') . '/js/nice_menus.js');
}
// Add main CSS functionality.
drupal_add_css(drupal_get_path('module', 'nice_menus') . '/css/nice_menus.css');
// Add custom CSS layout if specified.
if ($custom = variable_get('nice_menus_custom_css', '')) {
drupal_add_css($custom);
}
else {
drupal_add_css(drupal_get_path('module', 'nice_menus') . '/css/nice_menus_default.css');
}
}
/**
* Implements hook_block().
*/
function nice_menus_block($op = 'list', $delta = 0, $edit = array()) {
global $user;
switch ($op) {
case 'list':
for ($i = 1; $i <= variable_get('nice_menus_number', '2'); $i++) {
$blocks[$i]['info'] = variable_get('nice_menus_name_' . $i, 'Nice menu ' . $i) . ' (Nice menu)';
// We have too many things changing per user, per page to cache.
$blocks[$i]['cache'] = BLOCK_NO_CACHE;
}
return $blocks;
case 'configure':
$form['nice_menus_name_' . $delta] = array(
'#type' => 'textfield',
'#title' => t('Menu Name'),
'#default_value' => variable_get('nice_menus_name_' . $delta, 'Nice menu ' . $delta),
);
$form['nice_menus_menu_' . $delta] = array(
'#type' => 'select',
'#title' => t('Menu Parent'),
'#description' => t('The menu parent from which to show a Nice menu.'),
'#default_value' => variable_get('nice_menus_menu_' . $delta, 'navigation:0'),
'#options' => menu_parent_options(menu_get_menus(), 0),
);
$form['nice_menus_depth_' . $delta] = array(
'#type' => 'select',
'#title' => t('Menu Depth'),
'#description' => t('The depth of the menu, i.e. the number of child levels starting with the parent selected above. Leave set to -1 to display all children and use 0 to display no children.'),
'#default_value' => variable_get('nice_menus_depth_' . $delta, -1),
'#options' => drupal_map_assoc(range(-1, 5)),
);
$form['nice_menus_type_' . $delta] = array(
'#type' => 'select',
'#title' => t('Menu Style'),
'#description' => t('right: menu items are listed on top of each other and expand to the right') . '<br />' . t('left: menu items are listed on top of each other and expand to the left') . '<br />' . t('down: menu items are listed side by side and expand down'),
'#default_value' => variable_get('nice_menus_type_' . $delta, 'right'),
'#options' => drupal_map_assoc(array(
'right',
'left',
'down',
)),
);
return $form;
case 'save':
variable_set('nice_menus_name_' . $delta, $edit['nice_menus_name_' . $delta]);
variable_set('nice_menus_menu_' . $delta, $edit['nice_menus_menu_' . $delta]);
variable_set('nice_menus_depth_' . $delta, $edit['nice_menus_depth_' . $delta]);
variable_set('nice_menus_type_' . $delta, $edit['nice_menus_type_' . $delta]);
break;
case 'view':
// Build the Nice menu for the block.
list($menu_name, $mlid) = explode(':', variable_get('nice_menus_menu_' . $delta, 'navigation:0'));
$direction = variable_get('nice_menus_type_' . $delta, 'right');
$depth = variable_get('nice_menus_depth_' . $delta, '-1');
if ($output = theme('nice_menus', $delta, $menu_name, $mlid, $direction, $depth)) {
$block['content'] = $output['content'];
if (variable_get('nice_menus_type_' . $delta, 'right') == 'down') {
$class = 'nice-menu-hide-title';
}
else {
$class = 'nice-menu-show-title';
}
// If we're building the navigation block
// use the same block title logic as menu module.
if ($output['subject'] == t('Navigation') && $user->uid) {
$subject = $user->name;
}
else {
$subject = $output['subject'];
}
$block['subject'] = '<span class="' . $class . '">' . check_plain($subject) . '</span>';
}
else {
$block['content'] = FALSE;
}
return $block;
}
}
/**
* Implements hook_theme().
*/
function nice_menus_theme() {
return array(
'nice_menus_tree' => array(
'arguments' => array(
'menu_name' => NULL,
'mlid' => NULL,
'depth' => -1,
'menu' => NULL,
),
),
'nice_menus_build' => array(
'arguments' => array(
'menu' => NULL,
'depth' => -1,
'trail' => NULL,
),
),
'nice_menus' => array(
'arguments' => array(
'id' => NULL,
'menu_name' => NULL,
'mlid' => NULL,
'direction' => 'right',
'depth' => -1,
'menu' => NULL,
),
),
'nice_menus_primary_links' => array(
'arguments' => array(
'direction' => 'down',
'depth' => -1,
'menu' => NULL,
),
),
'nice_menus_secondary_links' => array(
'arguments' => array(
'direction' => 'down',
'depth' => -1,
'menu' => NULL,
),
),
// Deprecated theme functions that will be removed in 7.x.
'nice_menu_tree' => array(
'arguments' => array(
'menu_name' => NULL,
'mlid' => NULL,
'depth' => -1,
'menu' => NULL,
),
),
'nice_menu_build' => array(
'arguments' => array(
'menu' => NULL,
'depth' => -1,
'trail' => NULL,
),
),
'nice_menu' => array(
'arguments' => array(
'id' => NULL,
'menu_name' => NULL,
'mlid' => NULL,
'direction' => 'right',
'depth' => -1,
'menu' => NULL,
),
),
'nice_menu_primary_links' => array(
'arguments' => array(
'direction' => 'down',
'depth' => -1,
'menu' => NULL,
),
),
);
}
/**
* Builds the active trail from the page's menu data.
*
* @param array $page_menu
* The menu data for a page.
*/
function nice_menus_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, nice_menus_build_page_trail($item['below']));
}
}
return $trail;
}
/**
* Builds the final Nice menu.
*
* @param string $menu_name
* The top-level menu name that contains the menu to use (e.g. navigation
* or primary-links) for Drupal menus. For custom $menus this is just the
* name for menu display.
*
* @param int $mlid
* The menu ID from which to start building the items, i.e. the parent
* of the displayed menu.
*
* @param int $depth
* The number of children levels to display. Use -1 to display all children
* and use 0 to display no children.
*
* @param array $menu
* Optional. A custom menu array to use for theming -- it should have
* the same structure as that returned by menu_tree_all_data().
*
* @return string
* An HTML string of properly nested Nice menu lists.
*/
function theme_nice_menus_tree($menu_name, $mlid = NULL, $depth = -1, $menu = NULL) {
// Load the full menu array.
$menu = isset($menu) ? $menu : menu_tree_all_data($menu_name);
if (isset($menu)) {
$page_menu = menu_tree_page_data($menu_name);
$trail = nice_menus_build_page_trail($page_menu);
unset($page_menu);
}
// Assume depth == 0 by default, overriden if mlid is specified.
// (http://drupal.org/node/1101722).
$parent_depth = 0;
// Allow i18n module to translate strings where available.
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']);
// The depth for our parent item.
$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 sets these ghetto-ass keys in _menu_tree_check_access().
$menu = $menu[50000 + $subitem['weight'] . ' ' . $subitem['title'] . ' ' . $subitem['mlid']]['below'];
}
}
}
else {
// 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('nice_menus_build', $menu, $depth, $trail);
}
return $output;
}
/**
* Helper function that builds the nested lists of a Nice menu.
*
* @param array $menu
* Menu array from which to build the nested lists.
*
* @param int $depth
* The number of children levels to display. Use -1 to display all children
* and use 0 to display no children.
*
* @param array $trail
* An array of parent menu items.
*/
function theme_nice_menus_build($menu, $depth = -1, $trail = NULL) {
$output = '';
// Prepare to count the links so we can mark first, last, odd and even.
$index = 0;
$count = 0;
foreach ($menu as $menu_count) {
if ($menu_count['link']['hidden'] == 0) {
$count++;
}
}
// Get to building the menu.
foreach ($menu as $menu_item) {
$mlid = $menu_item['link']['mlid'];
// Check to see if it is a visible menu item.
if (!isset($menu_item['link']['hidden']) || $menu_item['link']['hidden'] == 0) {
// Check our count and build first, last, odd/even classes.
$index++;
$first_class = $index == 1 ? ' first ' : '';
$oddeven_class = $index % 2 == 0 ? ' even ' : ' odd ';
$last_class = $index == $count ? ' last ' : '';
// Build class name based on menu path
// e.g. to give each menu item individual style.
// Strip funny symbols.
$clean_path = str_replace(array(
'http://',
'www',
'<',
'>',
'&',
'=',
'?',
':',
'.',
), '', $menu_item['link']['href']);
// Convert slashes to dashes.
$clean_path = str_replace('/', '-', $clean_path);
$class = 'menu-path-' . $clean_path;
if ($trail && in_array($mlid, $trail)) {
$class .= ' active-trail';
}
// If it has children build a nice little tree under it.
if (!empty($menu_item['link']['has_children']) && !empty($menu_item['below']) && $depth != 0) {
// Keep passing children into the function 'til we get them all.
$children = theme('nice_menus_build', $menu_item['below'], $depth, $trail);
// Set the class to parent only of children are displayed.
$parent_class = $children && ($menu_item['link']['depth'] <= $depth || $depth == -1) ? 'menuparent ' : '';
$output .= '<li class="menu-' . $mlid . ' ' . $parent_class . $class . $first_class . $oddeven_class . $last_class . '">' . theme('menu_item_link', $menu_item['link']);
// Check our depth parameters.
if ($menu_item['link']['depth'] <= $depth || $depth == -1) {
// Build the child UL only if children are displayed for the user.
if ($children) {
$output .= '<ul>';
$output .= $children;
$output .= "</ul>\n";
}
}
$output .= "</li>\n";
}
else {
$output .= '<li class="menu-' . $mlid . ' ' . $class . $first_class . $oddeven_class . $last_class . '">' . theme('menu_item_link', $menu_item['link']) . '</li>' . "\n";
}
}
}
return $output;
}
/**
* Theme function to allow any menu tree to be themed as a Nice menu.
*
* @param int $id
* The Nice menu ID.
*
* @param string $menu_name
* The top parent menu name from which to build the full menu.
*
* @param int $mlid
* The menu ID from which to build the displayed menu.
*
* @param string $direction
* Optional. The direction the menu expands. Default is 'right'.
*
* @param int $depth
* The number of children levels to display. Use -1 to display all children
* and use 0 to display no children.
*
* @param array $menu
* Optional. A custom menu array to use for theming --
* it should have the same structure as that returned
* by menu_tree_all_data(). Default is the standard menu tree.
*
* @return string
* An HTML string of Nice menu links.
*/
function theme_nice_menus($id, $menu_name, $mlid, $direction = 'right', $depth = -1, $menu = NULL) {
$output = array();
if ($menu_tree = theme('nice_menus_tree', $menu_name, $mlid, $depth, $menu)) {
if ($menu_tree['content']) {
$output['content'] = '<ul class="nice-menu nice-menu-' . $direction . ' nice-menu-' . $menu_name . '" id="nice-menu-' . $id . '">' . $menu_tree['content'] . '</ul>' . "\n";
$output['subject'] = $menu_tree['subject'];
}
}
return $output;
}
/**
* Theme primary links as Nice menus.
*
* @param string $direction
* Optional. The direction the menu expands. Default is 'down'.
*
* @param int $depth
* The number of children levels to display. Use -1 to display all children
* and use 0 to display no children.
*
* @param array $menu
* Optional. A custom menu array to use for theming --
* it should have the same structure as that returned
* by menu_tree_all_data(). Default is the standard menu tree.
*
* @return string
* An HTML string of Nice menu primary links.
*/
function theme_nice_menus_primary_links($direction = 'down', $depth = -1, $menu = NULL) {
$menu_name = variable_get('menu_primary_links_source', 'primary-links');
$output = theme('nice_menus', 0, $menu_name, 0, $direction, $depth, $menu);
return $output['content'];
}
/**
* Theme secondary links as nice menus.
*
* @param string $direction
* Optional. The direction the menu expands. Default is 'down'.
*
* @param int $depth
* The number of children levels to display. Use -1 to display all children
* and use 0 to display no children.
*
* @param array $menu
* Optional. A custom menu array to use for theming --
* it should have the same structure as that returned
* by menu_tree_all_data(). Default is the standard menu tree.
*
* @return string
* An HTML string of nice menu secondary links.
*/
function theme_nice_menus_secondary_links($direction = 'down', $depth = -1, $menu = NULL) {
$menu_name = variable_get('menu_secondary_links_source', 'secondary-links');
$output = theme('nice_menus', 0, $menu_name, 0, $direction, $depth, $menu);
return $output['content'];
}
Functions
Name![]() |
Description |
---|---|
nice_menus_block | Implements hook_block(). |
nice_menus_build_page_trail | Builds the active trail from the page's menu data. |
nice_menus_form_alter | Implements hook_form_alter(). |
nice_menus_help | Implements hook_help(). |
nice_menus_init | Implements hook_init(). |
nice_menus_menu | Implements hook_menu(). |
nice_menus_system_theme_settings_submit | Records the Nice menu custom CSS file per theme. |
nice_menus_theme | Implements hook_theme(). |
theme_nice_menus | Theme function to allow any menu tree to be themed as a Nice menu. |
theme_nice_menus_build | Helper function that builds the nested lists of a Nice menu. |
theme_nice_menus_primary_links | Theme primary links as Nice menus. |
theme_nice_menus_secondary_links | Theme secondary links as nice menus. |
theme_nice_menus_tree | Builds the final Nice menu. |