Removing / displaying child categories in the menu

Today we will solve a dreary and annoying task that took out the brain for several days - in the Drupal category menu, the main categories are displayed in blocks if they have subcategories - in the main block, another block with links to child categories is added, so when the page loads, we display in the source code all categories with subcategories.

The SEO did not like this and the task was set in the style of "make it like on a socket", i.e. when loading the page, display only the list of main categories, hovering over one of them would load the list of child categories of this category.

The approximate structure of the output categories was as follows

<div class="category-menu clearfix">
    <div class="category-menu-parent catas_1">
        <a href="link"><span>Anchor main category</span></a>
        <div class="category-menu-children" id="catas_1">
            <div class="category-menu-children-title"><span>Header subcategory</span></div>
            <a href="link" >Anchor subcategory</a>
            <a href="link" >Anchor subcategory</a>
            <a href="link" >Anchor subcategory</a>
        </div>
    </div>
    <div class="category-menu-parent catas_2">
        <a href="link"><span>Anchor main category</span></a>
        <div class="category-menu-children" id="catas_2">
            <div class="category-menu-children-title"><span>Header subcategory</span></div>
            <a href="link" >Anchor subcategory</a>
            <a href="link" >Anchor subcategory</a>
        </div>
    </div>
    <div class="category-menu-parent catas_3">
        <a href="link"><span>Anchor main category</span></a>
    </div>
    <div class="category-menu-parent catas_3">
        <a href="link"><span>Anchor main category</span></a>
    </div>
    <div class="category-menu-parent catas_4">
        <a href="link"><span>Anchor main category</span></a>
        <div class="category-menu-children" id="catas_4">
            <div class="category-menu-children-title"><span>Header subcategory</span></div>
            <a href="link" >Anchor subcategory</a>
            <a href="link" >Anchor subcategory</a>
            <a href="link" >Anchor subcategory</a>
        </div>
    </div>
</div>

In order to solve this problem, an additional class "catas_" with a counter was initially added for blocks of the main categories, the text of the same class was duplicated in the ID of the block of subcategories of this category. Thus, we had a unique binding of the class of the main category with the class of the block of its subcategories.

The case for the script

var catachild = $('.category-menu-children').detach();
$('.category-menu-parent').hover(function() {
	var classname = $(this)[0].className.split(' ')[1];
	catachild.appendTo($(this));
	catachild.remove("div[id!=" + classname + "]");
});

In the first line, we pass the list of all subcategory blocks to the catachild variable and they are initially removed from our page. Further, when hovering over the block of the main category, we get the second, unique, class of the main category in the classname variable. On the 4th line, we dump the list of all subcategory blocks into the current, hovered category block, and on the last line, we delete all subcategory blocks whose id is not equal to our unique class of the main, hovered category.


It turned out that the option above does not fit the word "completely", because. in the source code, through Ctrl U, there were links of all subcategories on the page anyway. Below we’ll add another option, this time with unloading links from the created view page.

We create a view with an unformatted list, with taxonomy terms of the categories we need, with a filter for the presence of a parent (value !=null), in the fields we display the hidden name of the category (text), a link to the category (also text), the parent of the term (identifier) ​​and visible custom text in which we will display a link with the name, address of our subcategory and with the class in which we will display the parent's ID (for further filtering).

Now we themize the view and its fields in order to get rid of unnecessary code. First, create a file views-view-unformatted--list_all_subcategoryss.html.twig in our theme folder with templates, where list_all_subcategoryss is the machine name of our view, with the following content

<div id="subcatas">
    {% for row in rows %}
        {{- row.content -}}
    {% endfor %}
</div>

And then we create a template file views-view-fields--list_all_subcategoryss.html.twig with the content

{% for field in fields -%}
      {{ field.content }}
{%- endfor %}

In this way, we will significantly reduce the amount of extra code that will be passed to our menus.

And then we have a script running

$.post("podcategorys", function(data){
	var mainDiv = $("a", data);
	$('.category-menu-parent').hover(function() {
		var idparent = $(this).attr('id');
		mainDiv.appendTo($(".subcat_list", this));
		mainDiv.remove("a[class!=" + idparent + "]");
	});
}, "html");

In the first line, we indicate the URL of our view page with a list of subcategory links. In the second line, we pass links from this page to the object. Next comes the hover handler for the block of the main menu category, which should contain the id of this category, which we receive in line 4 into a variable. In line 5 we upload the list of subcategory links to the folder of the current (hovered) category and in the next line we delete all links that do not have the class of our parent. Thus, only links that are linked to the parent's ID remain.

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
The comment language code.