dhtml_menu.module in DHTML Menu 5
Same filename and directory in other branches
DHTML menus
Allow click expansion of the menu tree via javascript, with graceful degradation.
File
dhtml_menu.moduleView source
<?php
/**
* @file
* DHTML menus
*
* Allow click expansion of the menu tree via javascript, with
* graceful degradation.
*/
/**
* Implementation of hook_menu().
*/
function dhtml_menu_menu($may_cache) {
if ($may_cache) {
$items[] = array(
'path' => 'admin/settings/dhtml_menu',
'title' => t('DHTML Menu'),
'description' => t('Configure jQuery slide effect and Duplicated menu items.'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'dhtml_menu_settings',
),
'access' => user_access('administer menu'),
);
$items[] = array(
'path' => 'admin/settings/dhtml_menu/replace-navigation',
'title' => t('Replace navigation block'),
'callback' => '_dhtml_menu_replace',
'access' => user_access('administer menu'),
'type' => MENU_CALLBACK,
);
return $items;
}
else {
$path = drupal_get_path('module', 'dhtml_menu');
drupal_add_js(array(
'dhtmlMenu' => array(
'useEffects' => variable_get('dhtml_menu_use_effects', 1),
),
), 'setting');
drupal_add_js($path . '/dhtml_menu.js');
}
}
/**
* Implementation of hook_block().
* Basically a copy of menu_block(). We're providing our own version
* of each menu.
*/
function dhtml_menu_block($op = 'list', $delta = 0) {
global $user;
if ($op == 'list') {
$blocks = array();
$root_menus = menu_get_root_menus();
foreach ($root_menus as $mid => $title) {
$blocks[$mid]['info'] = t('DHTML: ') . $title;
}
return $blocks;
}
else {
if ($op == 'view') {
$item = menu_get_item($delta);
if ($user->uid > 0 && check_plain($item['title']) == t('Navigation')) {
$data['subject'] = $user->name;
}
else {
$data['subject'] = check_plain($item['title']);
}
$data['content'] = theme('dhtml_menu_tree', $delta);
return $data;
}
}
}
/**
* DHTML Menu Settings page.
* @ingroup form
*/
function dhtml_menu_settings() {
$form['dhtml_menu_use_effects'] = array(
'#type' => 'checkbox',
'#title' => t('jQuery slide effect'),
'#description' => t('Menu slides when it opens and closes.'),
'#default_value' => variable_get('dhtml_menu_use_effects', 1),
);
// $form['dhtml_menu_bullet'] = array(
// '#type' => 'checkbox',
// '#title' => t('Item bullets'),
// '#description' => t('The menu only collapses/exapand when clicking over the item bullet. WARNING: some themes do not show bullets!'),
// '#default_value' => variable_get('dhtml_menu_bullet', 0)
// );
$form['dhtml_menu_duplicated'] = array(
'#type' => 'textarea',
'#title' => t('Duplicated menu items'),
'#description' => t('You can specify a list of menu items that should be displayed twice: Once as a parent item that expands and collapses the sub-menu and again as its own child item, which points directly to the page (the parent items still links on double-click). Enter one internal path (like "admin") on each line. To specify a custom link text, put it after the path, separated by a space.'),
'#rows' => 4,
'#default_value' => variable_get('dhtml_menu_duplicated', 'admin'),
);
return system_settings_form($form);
}
/**
* Replaces the navigation block in all themes by
* assigning its values to this module's block, then
* disabling the normal block.
*/
function _dhtml_menu_replace() {
// Ensure that the block table is up to date.
_block_rehash();
// Get the navigation blocks of all themes
$res = db_query("SELECT status, weight, region, visibility, pages, title, theme\n FROM {blocks} WHERE module = 'user' AND delta = 1");
while ($row = db_fetch_array($res)) {
$navigation_settings[$row['theme']] = $row;
}
// Enable the equivalent DHTML menu and
// disable the original one
foreach ($navigation_settings as $theme => $row) {
db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s',\n visibility = %d, pages = %d, title = '%s'\n WHERE module = 'dhtml_menu'\n AND delta = 1 AND theme = '%s'", $row);
// relies on $mid of 'Navigation' menu being 1, see dhtml_menu_block('list')
db_query("UPDATE {blocks} SET status = 0, region = ''\n WHERE module = 'user' AND delta = 1 AND theme = '%s'", $theme);
}
drupal_set_message(t('Your navigation block has been replaced with its DHTML equivalent in all currently enabled themes.'), 'status');
// go to block administration
drupal_goto('admin/build/block');
// Its generally not necessary, but for safety, return.
return;
}
/**
* Fetch duplicated menu items - this is a configurable setting.
*/
function _dhtml_get_add_links() {
static $dhtml_menu_duplicated;
if (!isset($dhtml_menu_duplicated)) {
$dhtml_menu_duplicated = array();
$text = variable_get('dhtml_menu_duplicated', 'admin');
$text = preg_split('/\\n/', $text, -1, PREG_SPLIT_NO_EMPTY);
// explode returns array(0 => '') for $text == ''
foreach ($text as $line) {
$line = trim($line);
preg_match('/^([^ ]+)( (.*))?$/', $line, $match);
$dhtml_menu_duplicated[$match[1]] = !empty($match[3]) ? $match[3] : TRUE;
}
}
return $dhtml_menu_duplicated;
}
/**
* Convert menus into DHTML menus
* @param $pid
* Number, parent menu item ID
*/
function dhtml_menu_tree($pid = 1) {
$menu = menu_get_menu();
$output = '';
if (isset($menu['visible'][$pid]) && !empty($menu['visible'][$pid]['children'])) {
foreach ($menu['visible'][$pid]['children'] as $mid) {
$counter = !empty($menu['visible'][$mid]['children']) ? 0 : 1;
$output .= theme('dhtml_menu_item', $mid, theme('dhtml_menu_tree', $mid, false), $counter);
}
}
return $output;
}
/**
* Format each menu item
* @ingroup themable
*/
function theme_dhtml_menu_item($mid, $children = '', $leaf = true) {
static $expanded = null;
$active = $display = '';
if (!is_array($expanded)) {
$expanded = explode(',', $_COOKIE['dhtml_menu']);
}
if ($mid == menu_get_active_nontask_item()) {
$active = ' active';
}
if ($leaf) {
return " <li class=\"leaf{$active}\">" . menu_item_link($mid) . "</li>\n";
}
else {
$menu = menu_get_menu();
$type = isset($menu['visible'][$mid]['type']) ? $menu['visible'][$mid]['type'] : null;
if (menu_in_active_trail($mid) || $type & MENU_EXPANDED || in_array("sub{$mid}", $expanded)) {
$state = 'expanded';
}
else {
$state = 'collapsed';
$display = 'style="display: none;"';
}
$output = "<li class=\"menutitle {$state}\" id=\"menu-sub{$mid}\" >";
$output .= menu_item_link($mid);
$output .= "<div class=\"submenu\" id=\"sub{$mid}\" {$display}>\n";
$output .= "{$children}\n</div>\n";
$output .= "</li>\n";
return $output;
}
}
/**
* Format each menu tree
* @ingroup themable
*/
function theme_dhtml_menu_tree($pid = 1, $toplevel = true) {
if ($tree = dhtml_menu_tree($pid)) {
$add_links = _dhtml_get_add_links();
$menu = menu_get_menu();
if (!empty($add_links[$menu['items'][$pid]['path']])) {
$duplication = menu_get_item($pid);
if ($add_links[$menu['items'][$pid]['path']] !== TRUE) {
$duplication['title'] = $add_links[$menu['items'][$pid]['path']];
}
$tree = "<li class='leaf menu-duplicated'>" . theme('menu_item_link', $duplication, $duplication) . "</li>\n" . $tree;
}
$class = 'menu dhtml_menu';
if (!empty($toplevel)) {
$class .= ' menu-root';
}
return "\n<ul class=\"{$class}\">\n{$tree}\n</ul>\n";
}
}
// panels 2 integration
function dhtml_menu_panels_block_info($module, $delta, &$info) {
$info['icon'] = 'icon_core_block_menu.png';
$info['category'] = array(
t('Menus'),
-2,
);
}
// function dhtml_menu_item_link($item, $link_item) {
// $add_links = _dhtml_get_add_links();
// $title = ($link_item['path'] && $add_links[$link_item['path']] ? $add_links[$link_item['path']] : $item['title']);
// return l($title, $link_item['path'], isset($item['description']) ? array('title' => $item['description']) : array());
// }
Functions
Name![]() |
Description |
---|---|
dhtml_menu_block | Implementation of hook_block(). Basically a copy of menu_block(). We're providing our own version of each menu. |
dhtml_menu_menu | Implementation of hook_menu(). |
dhtml_menu_panels_block_info | |
dhtml_menu_settings | DHTML Menu Settings page. |
dhtml_menu_tree | Convert menus into DHTML menus |
theme_dhtml_menu_item | Format each menu item |
theme_dhtml_menu_tree | Format each menu tree |
_dhtml_get_add_links | Fetch duplicated menu items - this is a configurable setting. |
_dhtml_menu_replace | Replaces the navigation block in all themes by assigning its values to this module's block, then disabling the normal block. |