Feb 8th, 2013
Here's an example of how to theme a book navigation menu. This example creates a theme function that can be used to output the book outline in any place. There is an example in this module that create a panels pane.
First, in jeffy_book/jeffy_book.info:
name = Jeffy Book description = Extends the book module core = 7.x version = 7.x-1.0 dependencies[] = book
Next, in jeffy_book/jeffy.module:
/** * @file * Extends the book module. */ /** * Implements hook_theme(); */ function jeffy_book_theme($existing, $type, $theme, $path) { return array( 'jeffy_book_nav' => array( 'variables' => array('book' => FALSE), ), 'jeffy_book_menu_link' => array( 'render element' => 'element', ), 'jeffy_book_menu_tree' => array( 'render element' => 'tree', ), ); } /** * Preprocess jeffy book navigation pane */ function theme_jeffy_book_nav(array $variables) { $book = $variables['book']; $menu = _jeffy_book_menu_tree($book['menu_name']); $menu['#theme_wrappers'][0] = 'jeffy_book_menu_tree'; return drupal_render($menu); } /** * Returns HTML for a wrapper for a book menu sub-tree. * * @see theme_menu_tree() */ function theme_jeffy_book_menu_tree(array $variables) { return '<ol>' . $variables['tree']['#children'] . '</ol>'; } /** * Returns HTML for a book menu link and submenu. * * @see theme_menu_link() */ function theme_jeffy_book_menu_link(array $variables) { $element = $variables['element']; $sub_menu = ''; $current_path = current_path(); if ($element['#below']) { $sub_menu = drupal_render($element['#below']); } if ($current_path === $element['#href']) { $output = '<mark>' . check_plain($element['#title']) . '</mark>'; } else { $output = l($element['#title'], $element['#href'], $element['#localized_options']); } return '<li>' . $output . $sub_menu . "</li>\n"; } /** * Renders a book menu tree * * @see menu_tree() */ function _jeffy_book_menu_tree($menu_name) { $menu_output = &drupal_static(__FUNCTION__, array()); if (!isset($menu_output[$menu_name])) { $tree = menu_build_tree($menu_name); $key = key($tree); $tree = array_merge($tree, $tree[$key]['below']); $tree[$key]['below'] = array(); $tree[$key]['link']['has_children'] = 0; $menu = menu_tree_output($tree); array_walk_recursive($menu, 'jeffy_book_menu_link_theme_override'); $menu_output[$menu_name] = $menu; } return $menu_output[$menu_name]; } /** * Changes theme properties for links * * Used in _jeffy_book_menu_tree() with array_walk_recursive() */ function jeffy_book_menu_link_theme_override(&$item, $key) { if ($key === '#theme') { $item = 'jeffy_book_menu_link'; } } /** * Implements hook_ctools_plugin_directory(). * * @see ctools.api.php * @see ctools_plugin_example.module */ function jeffy_book_ctools_plugin_directory($module, $plugin) { if ($module == 'ctools' && !empty($plugin)) { return "plugins/$plugin"; } }
Finally, in jeffy_book/plugins/content_types/jeffy_book_navigation.inc:
/** * @file * * Ctools content type (panel pane) * @see ctools_plugin_example.module */ $plugin = array( 'title' => t('Book Navigation'), 'description' => t('Navigation for book pages'), 'single' => TRUE, 'content_types' => array('jeffy_book_navigation'), 'render callback' => 'jeffy_book_navigation_pane_render', 'defaults' => array(), 'category' => array(t('Jeffy'), -9), ); /** * Renders a ctools content type (panel pane) */ function jeffy_book_navigation_pane_render($subtype, $conf, $context = NULL) { $node = menu_get_object(); $block = new stdClass(); if (property_exists($node, 'book')) { $block->content = theme('jeffy_book_nav', array('book' => $node->book)); } return $block; }