0

I have a node for which there is a menu item. I want this menu item to be disabled except when the user is viewing that node. Can I do this, and if so how?

  • for which Drupal version? – Sk8erPeter Apr 9 '12 at 18:54
  • another question: in which menu is it in? Does it have to be among the "Main menu" links, or it can be in any other menus or blocks? – Sk8erPeter Apr 9 '12 at 19:19
  • Drupal 7. It's in the main menu, which is shown in a Menu Block block and a Nice Menus menu. – tog22 Apr 9 '12 at 20:47
2

I will write a method that you can use by simply editing your theme's template.php file (without having to write your own module), and overriding

functions. YES, that's correct, unfortunately for the correct markup, you have to override all of the above mentioned functions in your own theme, to avoid rendering empty <li> elements in the default main menu, in the Superfish menu or the Site map module's own menu. I will assume you haven't already overridden them.
I tested it, so this code should be working, but please ask if you have any kind of questions.

  1. First, please open your theme's template.php in a text editor of your choice.
  2. Paste the whole code below into the opened template.php.

    /**
     * Should this link be hidden?
     * 
     * @see http://drupal.stackexchange.com/questions/27907/enable-a-nodes-menu-item-when-on-that-node/27922
     * 
     * @param string $link_path The path that should be inspected.
     * @return boolean 
     */
    function YOURTHEMENAME_link_should_be_hidden($link_path) {
    
        // in this example, I let "contact" and "node/9" links only be visible
        // on their own path (so for example, I let "contact" path be visible 
        // in the menu if the user opened "example.com/contact").    
        $your_paths_to_show_in_menu_only_on_their_own_path = array('contact', 'node/9'); // SUBSTITUTE IT with yours - empty cache every time you change that
        $is_link_to_hide = in_array($link_path, $your_paths_to_show_in_menu_only_on_their_own_path);
        if ($is_link_to_hide) {
            $is_current_page_self = ($link_path == $_GET['q']);
            // these links will be visible only on their own paths -
            // BUT here you can define other paths too where they can be visible at!
            // So for example, you want "example.com/node/9" to be visible when visiting its own path
            // AND when visiting "example.com/node/3" OR "example.com/any_other_path".
            // But if you do NOT want any other pages for these links to be visible at, then
            // just leave it empty (like this: array()).
            $link_also_visible_at_paths = array('node/3', 'any_other_path'); // SUBSTITUTE IT with your paths! - empty cache every time you change that
            $element_can_be_visible = $is_current_page_self || (!empty($link_also_visible_at_paths) && in_array($_GET['q'], $link_also_visible_at_paths));
    
            if (!$element_can_be_visible) {
                return TRUE;
            }
        }
        return FALSE;
    }
    
    /**
     * Overriding theme_menu_link()
     * 
     * @see http://api.drupal.org/api/drupal/includes%21menu.inc/function/theme_menu_link/7
     */
    function YOURTHEMENAME_menu_link(array $variables) {
        /**
         * @see http://drupal.stackexchange.com/questions/27907/enable-a-nodes-menu-item-when-on-that-node/27922
         */
        if (YOURTHEMENAME_link_should_be_hidden($variables['element']['#href'])) {
            return '';
        }
    
        $element = $variables['element'];
        $sub_menu = '';
    
        if ($element['#below']) {
            $sub_menu = drupal_render($element['#below']);
        }
        $output = l($element['#title'], $element['#href'], $element['#localized_options']);
        return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
    }
    
    /**
     * Helper function that builds the nested lists of a Superfish menu.
     * @see theme_superfish_build()
     */
    function YOURTHEMENAME_superfish_build($variables) {
    
        $output = array('content' => '');
        $id = $variables['id'];
        $menu = $variables['menu'];
        $depth = $variables['depth'];
        $trail = $variables['trail'];
        // Keep $sfsettings untouched as we need to pass it to the child menus.
        $settings = $sfsettings = $variables['sfsettings'];
        $megamenu = $settings['megamenu'];
        $total_children = $parent_children = $single_children = 0;
        $i = 1;
    
        // Reckon the total number of available menu items.
        foreach ($menu as $menu_item) {
            if (!isset($menu_item['link']['hidden']) || $menu_item['link']['hidden'] == 0) {
                $total_children++;
            }
        }
    
        foreach ($menu as $menu_item) {
    
            $show_children = $megamenu_wrapper = $megamenu_column = $megamenu_content = FALSE;
            $item_class = $link_options = $link_class = array();
            $mlid = $menu_item['link']['mlid'];
    
            /**
             * @see http://drupal.stackexchange.com/questions/27907/enable-a-nodes-menu-item-when-on-that-node/27922
             */
            if (YOURTHEMENAME_link_should_be_hidden($menu_item['link']['link_path'])) {
                continue;
            }
    
            if (!isset($menu_item['link']['hidden']) || $menu_item['link']['hidden'] == 0) {
                $item_class[] = ($trail && in_array($mlid, $trail)) ? 'active-trail' : '';
    
                // Add helper classes to the menu items and hyperlinks.
                $settings['firstlast'] = ($settings['dfirstlast'] == 1 && $total_children == 1) ? 0 : $settings['firstlast'];
                $item_class[] = ($settings['firstlast'] == 1) ? (($i == 1) ? 'first' : (($i == $total_children) ? 'last' : 'middle')) : '';
                $settings['zebra'] = ($settings['dzebra'] == 1 && $total_children == 1) ? 0 : $settings['zebra'];
                $item_class[] = ($settings['zebra'] == 1) ? (($i % 2) ? 'odd' : 'even') : '';
                $item_class[] = ($settings['itemcount'] == 1) ? 'sf-item-' . $i : '';
                $item_class[] = ($settings['itemdepth'] == 1) ? 'sf-depth-' . $menu_item['link']['depth'] : '';
                $link_class[] = ($settings['itemdepth'] == 1) ? 'sf-depth-' . $menu_item['link']['depth'] : '';
                $item_class[] = ($settings['liclass']) ? $settings['liclass'] : '';
                if (strpos($settings['hlclass'], ' ')) {
                    $l = explode(' ', $settings['hlclass']);
                    foreach ($l as $c) {
                        $link_class[] = $c;
                    }
                }
                else {
                    $link_class[] = $settings['hlclass'];
                }
                $i++;
    
                // Add hyperlinks description (title) to their text.
                $show_linkdescription = ($settings['linkdescription'] == 1 && !empty($menu_item['link']['localized_options']['attributes']['title'])) ? TRUE : FALSE;
                if ($show_linkdescription) {
                    if (!empty($settings['hldmenus'])) {
                        $show_linkdescription = (is_array($settings['hldmenus'])) ? ((in_array($mlid, $settings['hldmenus'])) ? TRUE : FALSE) : (($mlid == $settings['hldmenus']) ? TRUE : FALSE);
                    }
                    if (!empty($settings['hldexclude'])) {
                        $show_linkdescription = (is_array($settings['hldexclude'])) ? ((in_array($mlid, $settings['hldexclude'])) ? FALSE : $show_linkdescription) : (($settings['hldexclude'] == $mlid) ? FALSE : $show_linkdescription);
                    }
                    if ($show_linkdescription) {
                        $menu_item['link']['title'] .= '<span class="sf-description">';
                        $menu_item['link']['title'] .= (!empty($menu_item['link']['localized_options']['attributes']['title'])) ? $menu_item['link']['localized_options']['attributes']['title'] : array();
                        $menu_item['link']['title'] .= '</span>';
                        $link_options['html'] = TRUE;
                    }
                }
    
                // Add custom HTML codes around the menu items.
                if ($sfsettings['wrapul'] && strpos($sfsettings['wrapul'], ',') !== FALSE) {
                    $wul = explode(',', $sfsettings['wrapul']);
                    // In case you just wanted to add something after the element.
                    if (drupal_substr($sfsettings['wrapul'], 0) == ',') {
                        array_unshift($wul, '');
                    }
                }
                else {
                    $wul = array();
                }
    
                // Add custom HTML codes around the hyperlinks.
                if ($settings['wraphl'] && strpos($settings['wraphl'], ',') !== FALSE) {
                    $whl = explode(',', $settings['wraphl']);
                    // The same as above
                    if (drupal_substr($settings['wraphl'], 0) == ',') {
                        array_unshift($whl, '');
                    }
                }
                else {
                    $whl = array();
                }
    
                // Add custom HTML codes around the hyperlinks text.
                if ($settings['wraphlt'] && strpos($settings['wraphlt'], ',') !== FALSE) {
                    $whlt = explode(',', $settings['wraphlt']);
                    // The same as above
                    if (drupal_substr($settings['wraphlt'], 0) == ',') {
                        array_unshift($whlt, '');
                    }
                    $menu_item['link']['title'] = $whlt[0] . check_plain($menu_item['link']['title']) . $whlt[1];
                    $link_options['html'] = TRUE;
                }
    
    
                if (!empty($menu_item['link']['has_children']) && !empty($menu_item['below']) && $depth != 0) {
                    // Megamenu is still beta, there is a good chance much of this will be changed.
                    if (!empty($settings['megamenu_exclude'])) {
                        if (is_array($settings['megamenu_exclude'])) {
                            $megamenu = (in_array($mlid, $settings['megamenu_exclude'])) ? 0 : $megamenu;
                        }
                        else {
                            $megamenu = ($settings['megamenu_exclude'] == $mlid) ? 0 : $megamenu;
                        }
                        // Send the result to the sub-menu.
                        $sfsettings['megamenu'] = $megamenu;
                    }
                    if ($megamenu == 1) {
                        $megamenu_wrapper = ($menu_item['link']['depth'] == $settings['megamenu_depth']) ? TRUE : FALSE;
                        $megamenu_column = ($menu_item['link']['depth'] == $settings['megamenu_depth'] + 1) ? TRUE : FALSE;
                        $megamenu_content = ($menu_item['link']['depth'] >= $settings['megamenu_depth'] && $menu_item['link']['depth'] <= $settings['megamenu_levels']) ? TRUE : FALSE;
                    }
                    // Render the sub-menu.
                    $var = array(
                      'id' => $id,
                      'menu' => $menu_item['below'],
                      'depth' => $depth, 'trail' => $trail,
                      'sfsettings' => $sfsettings
                    );
                    $children = theme('superfish_build', $var);
                    // Check to see whether it should be displayed.
                    $show_children = (($menu_item['link']['depth'] <= $depth || $depth == -1) && $children['content']) ? TRUE : FALSE;
                    if ($show_children) {
                        // Add item counter classes.
                        if ($settings['itemcounter']) {
                            $item_class[] = 'sf-total-children-' . $children['total_children'];
                            $item_class[] = 'sf-parent-children-' . $children['parent_children'];
                            $item_class[] = 'sf-single-children-' . $children['single_children'];
                        }
                        // More helper classes.
                        $item_class[] = ($megamenu_column) ? 'sf-megamenu-column' : '';
                        $item_class[] = $link_class[] = 'menuparent';
                    }
                    $parent_children++;
                }
                else {
                    $item_class[] = 'sf-no-children';
                    $single_children++;
                }
    
                $item_class = implode(' ', array_filter($item_class));
    
                if (isset($menu_item['link']['localized_options']['attributes']['class'])) {
                    $link_class_current = $menu_item['link']['localized_options']['attributes']['class'];
                    $link_class = array_merge($link_class_current, array_filter($link_class));
                }
                $menu_item['link']['localized_options']['attributes']['class'] = $link_class;
    
                $link_options['attributes'] = $menu_item['link']['localized_options']['attributes'];
    
                // Render the menu item.
                $output['content'] .= '<li id="menu-' . $mlid . '-' . $id . '"';
                $output['content'] .= ($item_class) ? ' class="' . trim($item_class) . '">' : '>';
                $output['content'] .= ($megamenu_column) ? '<div class="sf-megamenu-column">' : '';
                $output['content'] .= isset($whl[0]) ? $whl[0] : '';
                $output['content'] .= l($menu_item['link']['title'], $menu_item['link']['link_path'], $link_options);
                $output['content'] .= isset($whl[1]) ? $whl[1] : '';
                $output['content'] .= ($megamenu_wrapper) ? '<ul class="sf-megamenu"><li class="sf-megamenu-wrapper ' . $item_class . '">' : '';
                $output['content'] .= ($show_children) ? (isset($wul[0]) ? $wul[0] : '') : '';
                $output['content'] .= ($show_children) ? (($megamenu_content) ? '<ol>' : '<ul>') : '';
                $output['content'] .= ($show_children) ? $children['content'] : '';
                $output['content'] .= ($show_children) ? (($megamenu_content) ? '</ol>' : '</ul>') : '';
                $output['content'] .= ($show_children) ? (isset($wul[1]) ? $wul[1] : '') : '';
                $output['content'] .= ($megamenu_wrapper) ? '</li></ul>' : '';
                $output['content'] .= ($megamenu_column) ? '</div>' : '';
                $output['content'] .= '</li>';
            }
        }
        $output['total_children'] = $total_children;
        $output['parent_children'] = $parent_children;
        $output['single_children'] = $single_children;
        return $output;
    }
    
    /**
     * Overriding theme_site_map_menu_link()
     *
     * @param array $variables
     * @return string 
     */
    function YOURTHEMENAME_site_map_menu_link($variables) {
    
        $element = $variables['element'];
        $sub_menu = '';
    
        /**
         * @see http://drupal.stackexchange.com/questions/27907/enable-a-nodes-menu-item-when-on-that-node/27922
         */
        if (YOURTHEMENAME_link_should_be_hidden($element['#href'])) {
            return '';
        }
    
        if ($element['#below']) {
            $sub_menu = drupal_render($element['#below']);
        }
        $output = l($element['#title'], $element['#href'], $element['#localized_options']);
        return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
    }
    
    /**
     * Returns HTML for a set of links.
     * @see theme_links()
     */
    function YOURTHEMENAME_links($variables) {
        $links = $variables['links'];
        $attributes = $variables['attributes'];
        $heading = $variables['heading'];
        global $language_url;
        $output = '';
    
        if (count($links) > 0) {
            $output = '';
    
            // Treat the heading first if it is present to prepend it to the
            // list of links.
            if (!empty($heading)) {
                if (is_string($heading)) {
                    // Prepare the array that will be used when the passed heading
                    // is a string.
                    $heading = array(
                      'text' => $heading,
                      // Set the default level of the heading.
                      'level' => 'h2',
                    );
                }
                $output .= '<' . $heading['level'];
                if (!empty($heading['class'])) {
                    $output .= drupal_attributes(array('class' => $heading['class']));
                }
                $output .= '>' . check_plain($heading['text']) . '</' . $heading['level'] . '>';
            }
    
            $output .= '<ul' . drupal_attributes($attributes) . '>';
    
            $num_links = count($links);
            $i = 1;
    
            foreach ($links as $key => $link) {
    
                /**
                 * @see http://drupal.stackexchange.com/questions/27907/enable-a-nodes-menu-item-when-on-that-node/27922
                 */
                if (YOURTHEMENAME_link_should_be_hidden($link['href'])) {
                    continue;
                }
    
    
                $class = array($key);
    
                // Add first, last and active classes to the list of links to help out themers.
                if ($i == 1) {
                    $class[] = 'first';
                }
                if ($i == $num_links) {
                    $class[] = 'last';
                }
                if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))
                    && (empty($link['language']) || $link['language']->language == $language_url->language)) {
                    $class[] = 'active';
                }
                $output .= '<li' . drupal_attributes(array('class' => $class)) . '>';
    
                if (isset($link['href'])) {
                    // Pass in $link as $options, they share the same keys.
                    $output .= l($link['title'], $link['href'], $link);
                }
                elseif (!empty($link['title'])) {
                    // Some links are actually not links, but we wrap these in <span> for adding title and class attributes.
                    if (empty($link['html'])) {
                        $link['title'] = check_plain($link['title']);
                    }
                    $span_attributes = '';
                    if (isset($link['attributes'])) {
                        $span_attributes = drupal_attributes($link['attributes']);
                    }
                    $output .= '<span' . $span_attributes . '>' . $link['title'] . '</span>';
                }
    
                $i++;
                $output .= "</li>\n";
            }
    
            $output .= '</ul>';
        }
    
        return $output;
    }
    
    /**
     * Theming links (theme_link())
     * @see http://api.drupal.org/api/drupal/includes!theme.inc/function/theme_link/7
     *
     */
    function YOURTHEMENAME_link($variables) {
        /**
         * @see http://drupal.stackexchange.com/questions/27907/enable-a-nodes-menu-item-when-on-that-node/27922
         */
        if (YOURTHEMENAME_link_should_be_hidden($variables['path'])) {
            return '';
        }
    
        return '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . drupal_attributes($variables['options']['attributes']) . '>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</a>';
    }
    
  3. Substitute YOURTHEMENAME with your own theme's name.

  4. Substitute the values of $your_paths_to_show_in_menu_only_on_their_own_pathand $link_also_visible_at_paths variables in the previous step with your appropriate values. In the previous example, I hide the "contact" AND node/9 pages' menu link by default, and let them only be visible when we are viewing these pages themselves OR when displaying node/3 or any_other_path paths (so in any other cases, I don't see the link to "contact" or node/9).
  5. Save the file.
  6. Clear the cache!

So the final code should look similar to this: http://pastebin.com/PzQFhykn.

BUT in your exact case, you would like to hide node/425, so your code should look like this: http://pastebin.com/DKi5aSyq

Ask if something isn't quite clear.

|improve this answer|||||
  • First off, thanks for your exemplary reply. I've implemented your pastebin.com/a6FTdKt7 code for this node cea-gwwc-alex1.philosofiles.com/our-pledge/… . It works in the menu block in the left sidebar, but not the dropdown menu at the top (in this case, you'll see it under 'the pledge' > 'trying out giving' even when not on this node). This dropdown is generated by the Superfish module, not Nice Menus (really sorry I gave the wrong module!) Any pointers? – tog22 Apr 12 '12 at 16:13
  • 1
    @tog22: yes, you are absolutely right, this didn't work in all cases. But please see my updated answer, I totally rewrote my whole post and the code, so the previous one (the whole overriding of the mentioned function!) can be ignored/deleted from your template.php! Please read the post once again and see the updated pastebin links, mainly the last one! Thanks! – Sk8erPeter Apr 13 '12 at 17:58
  • (1) First off, massive thanks again; this is helping with (I think) a very good cause, givingwhatwecan.org . If you're willing to help more on such Drupal issues, please do email me at webmaster@ [that URL] :) (2) answer works in hiding node's menu items when not on that node (albeit with a slight graphical glitch in Superfish menus), which is effectively what I asked so I've accepted it; (3) $link_also_visible_on_paths will help resolve another question I have, for which see (1), or subscribe to drupal.stackexchange.com/feeds/user/4012 – tog22 Apr 14 '12 at 8:59
  • 1
    @tog22: OK, I see, you're right, I'm sorry, I hope I'll have some time tomorrow evening to inspect the code and find out the solution. – Sk8erPeter May 21 '12 at 15:40
  • 1
    @tog22: I'm glad I could help. Yes, I tried a lot of different ways, spent a lot of time with it, but unfortunately I didn't find an easier solution, because Superfish uses a different solution than the core menu-rendering, so I could only solve it with such a lot of codes. – Sk8erPeter Jun 9 '12 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.