Dancing with a tambourine, part 2 - tabbed menu in Drupal

Published on February 23, 2009

Dancing with a tambourine, part 2 - tabbed menu in Drupal

    Actually, the continuation of this habratopika , as they say, "at the request of the working people." And before I begin, I bring a bunch of sincere thanks to the habrayuzers who were not lazy to send bug reports and thereby helped to "lick" the result as it should. Let there be no limit to perfection, and I still have to fix a couple of roughnesses - but in any case, better than it was originally. Now I’ll tell you how I pulled all this kitchen onto the menu system in Drupal.

    To begin with - we formulate the problem. We need to:
    1. the menu item became active when selecting the page corresponding to it (well, this is a no brainer, and the corresponding class is automatically hung on the link by Drupal)
    2. each menu item had a unique ID for hanging styles on it
    3. the menu item remained active when selecting any node from this page or when selecting a version for printing (the link to which looks like "page-name-print")
    4. By default, on other pages that are not related to the catalog, the menu item “Apartments” should be active

    Well, to make it all look like this:

    Create a new menu ("Management" - "Site Design" - "Menu"). We push the necessary links into it. We go to "Management" - "Site Design" - "Blocks" and substitute the block with the new menu in some of the visible areas (do not forget to check whether this area is displayed in the template and whether the working divs of the area correspond to those IDs, what are written in the style sheet). We get a “bare” menu, which we will now customize.

    So, since task 1 was solved by Drupal “out of the box” and has already been registered in our style sheet from the previous topic, let's move on to step 2. How to attach unique attributes to each menu item, for example, ID? Very simple - put the Menu Attributes module, turn it on on the module management page, and now, going into editing the menu item, we will see a separate section for adding attributes. In our case, we assign an ID to each link: for the menu item “Apartments” - “apartments”, for “Houses and Cottages” - “houses”, for “Land” - “ground”, and for “Industrial Real Estate” - “ business. " And after this procedure we will see that now the menu, at least on the directory pages (generated using Views, if that) looks like it should.

    Let's go further. Now we need to keep the menu item active in the case of selecting any node from the corresponding section of the catalog, or the version for printing the page. I must say that I have each type of real estate - this is a separate type of node, with the appropriate parameters, therefore. making the binding, I will check exactly the type of node, although in general it can be anything (taxonomy, CCK field ... yes you never know). We climb into the folder of our template and open the template.php file, adding the following lines to it:

    function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
      $class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
      if (!empty($extra_class)) {
        $class .= ' '. $extra_class;
            preg_match("/node\/\d+/", request_uri(), $nid);
    	//я знаю, что это тупой подход, но по крайней мере он работает. а извращения с preg_match - почему-то нет
    	if (!empty($nid[0])) {
    	$nid[0] = ereg_replace("node/", "", $nid[0]);
    	$tmp = node_load($nid[0]);
      if (ereg('apartments',$link) and !(preg_match("/houses|ground|business/", request_uri()) or preg_match("/house|place|for_business/", $tmp->type) )) {$in_active_trail = true;}
        if ( ereg('/houses',$link) and (ereg("/houses", request_uri()) or $tmp->type=='house') ) {$in_active_trail = true;}
        if ( ereg('/ground',$link) and (ereg("/ground", request_uri()) or $tmp->type=='place') ) {$in_active_trail = true;}
        if ( ereg('/business',$link) and (ereg("/business", request_uri()) or $tmp->type=='for_business') ) {$in_active_trail = true;}
      if ($in_active_trail) {
        $class .= ' active-trail ';
      return '<li class="'. $class .'">'. $link . $menu ."</li>\n";

    Wow ... scared? Don’t be afraid. Now I will explain to you what is happening here. The function itself overrides the standard Drupal menu output. Since the global variable $ node is not visible here (FIG knows why, there was no time to understand), the number of the active node, if any, we get from the current URL with a regular expression. And if there is one, we load the parameters of the node.

    Then we check several conditions - just whether the address of the current page is contained in the menu link (this is necessary so that the print versions containing the page name are processed correctly), and if not, then does the type of the current node correspond to the type of real estate. Everything! :)

    I know that this is probably not the most beautiful, fast, scalable, etc. way. But, firstly, this is my first serious project on drupal, and, secondly, they promised me that the structure of the menu and materials will remain unchanged in the future. Although, in principle, if you correctly approach the naming of types of materials and pages so that they all correspond to a certain template, then the same regulars can extrapolate this task to more serious conditions ...