Adding sections or headings to WordPress Menus – Making use of the walker_nav_menu_start_el filter

The WordPress menu builder makes it easy to add nested menu item links to a named menu, and display it in pre-defined theme location. However, as of writing in Jan 2019, there’s not an easy or built-in way to add menu sections or section headers. Here’s my solution:

The Design

Example visual to be recreated as a WordPress menu
Example visual to be recreated as a WordPress menu

The adjacent image shows the design that I’ve been asked to translate to a WordPress native menu. The orange items are page links. The white items are section headers and should not be active in any way. They are simply visual cues to aid navigation.

The Challenge

‘Out of the box’ WordPress doesn’t provide a place for menu section headers like ‘Services’ and ‘Products’ to be entered. It is possible to add them based on a menu item’s class or ID using the CSS ‘content’ property, or an absolutely positioned image, but this is tacky and hard-coded, so site owners and admins can’t easily change the menu section headers without a developer type person or some Additional CSS hackery.

We need to find a way of adding section headers that uses the WordPress menu builder and remains editable.

Hidden Options

In many WordPress admin screens there is a Screen Options link/tab/button, usually at the top right. The options available depend on the item being edited. In the Menu Builder, there are several ‘Advanced menu properties’ available, and the one we want is ‘Description’.

Description setting in Screen Options area
Description can be enabled under the ‘Screen Options’ tab in the edit screen.

Once ‘Description’ is selected, a new field will be available when editing a menu item. For our example design we want a section header called ‘Services’ to appear before the ‘Investigative Consulting’ menu item, so “Services” is entered into the description, and the menu us saved/published.

Description field in menu builder
Entering the desired section name in the newly activated Description field in the menu builder

The section head is now part of the menu object but without further theme modification, it won’t appear anywhere.

Theme Mods

Next we want to modify the WordPress theme to allow our description to show in the menu as a section header. To do this we’ll be editing the theme functions.php file.

Many articles aimed at modifying WordPress menu output suggest using a custom ‘walker’ class . This would work, but it’s overkill for what we’re doing. The walker_nav_menu class applies a filter called walker_nav_menu_start_el and that’s what we’re going to use instead.

The Code

The walker_nav_menu_start_el filter can edit each menu item’s “starting output” i.e. the menu link element (<a ... > </a> etc) and any ‘before’ and ‘after’ attributes which have been set when the menu is called. For a discussion of menu attributes, see the wp_nav_menu article.

By adding the following code to the functions.php file of the active theme a span containing the menu item’s Description is placed before the menu link when the menu is rendered:

// somewhere in the theme's functions.php file

function mqf_menu_descriptions( $item_output, $item, $depth, $args ){
    if ($depth == 0 && $item->description) {
        $item_output = '<span class="menu-item-description">' . $item->description . '</span>'.$item_output;
    }
    return $item_output;
}

add_filter( 'walker_nav_menu_start_el', 'mqf_menu_descriptions', 10, 4);

The if statement checks that the menu item is a top-level item with $depth == 0 and also that a description is set.

If this filter should only effect menus in certain locations, i.e. ‘primary’, then the if statement might look like this:

if ('primary' == $args->theme_location && $depth == 0 && $item->description) {

The Output

description output before the menu item but unstyled Now that the filter is added, when the menu is viewed it should output the description that’s been set immediately before the menu item. In the example we started with it appears as white text (see the adjacent image).

In order to style it up a bit, the following CSS improves things:

.section_description {
    display: block;
    text-transform: uppercase;
    font-size: 1.4rem;
    padding: 0.6rem 0 0.4rem;
    color: rgb(240, 240, 240);
}

The final result with some more section headers and menu items added is shown here:

Finished menu showing styled section headers
Finished menu showing styled section headers.

Hope that’s helped someone. If you have questions, corrections or criticisms please leave a comment below. Or just let me know what you thought with a click/tap on a thumb: Nope, not helpful...Yep, more useful than not! (No Ratings Yet)
Loading...

Stop WordPress installing new bundled themes and plugins when the core is upgraded.

Problem: Every time WordPress updates to a newer major version it tries to install the newest default Theme too, i.e. WP5.0 arrived with the theme Twenty Nineteen.

In many – maybe MOST cases – we aren’t going to want this to happen on an existing WordPress installation, especially if you are already using a custom theme.

Solution: Thankfully there’s a config value to stop this happening. The value is:

define('CORE_UPGRADE_SKIP_NEW_BUNDLED', true);

…and if you add this line to your `wp-config.php` file (usually found in the root of your site) it will skip new bundles items when the core is upgraded, as the name suggests.

Please let me know if this post was useful with a click, be honest 🙂
Nope, not helpful...Yep, more useful than not! - -1 thumb, 1 overall.
Loading...

Updated for 1.2 & 1.3: Adding category depth tag to Shopp

Problem: I needed to display sub categories of a category in category.php but only one level deep. Using:

<?php if(shopp('category','hascategories')): ?>
  <?php while(shopp('category','subcategories')): ?>
    //display stuff
  <?php endwhile; ?>
<?php endif; ?>

…displays all subcast AND their subcats. Continue reading “Updated for 1.2 & 1.3: Adding category depth tag to Shopp”

Remove ‘ul’ and ‘li’ tags from WordPress menus while retaining all the classes

Problem:
I need to output a WordPress nav menu as a series of anchors surrounded by spans, within one nav element. Manipulating the args passed to wp_nav_menu() function will allow the <ul> element to be removed, and passing the output through ‘striptags’ can remove the <li> elements, but I end up losing all the link ancestry classes.

Solution:
If a ‘Walker’ class is used, the output from wp_nav_menu() can be controlled totally. Here’s an example that removes the list elements, adds a span around each item link, and adds the possibility of a separator string between each menu item.

Add to your theme / header / etc: Continue reading “Remove ‘ul’ and ‘li’ tags from WordPress menus while retaining all the classes”

Custom Ordering Shopp (wordpress plugin) products in just one category

Problem: I’ve developed a site using the Shopp ecommerce WordPress Plugin and product ordering is set to ‘Price – Low to High’ at the Client’s request. Splendid. But now – for one category only – he want’s the Products to be give a custom order. In the Shopp presentation settings, ‘Product Order’ is set site-wide.

Solution: I created a custom template for the category in question, then in that template loaded the specific category with the ‘order’ option set to ‘custom’. Here are some steps.

1) Create the category specific template in the ‘Shopp’ theme templates directory in your WordPress theme. In my case the file was called category-truss.php as ‘truss’ is the slug of the category, and it’s a copy of my main category.php template file.

2) At the top of category-truss.php add the API function shopp(‘storefront.category’) like so:

<?php shopp('storefront','category','slug=truss&load=true&order=custom'); ?>
// load=true is needed to stop the functioning spitting out the category directly.
// slug is whatever your category's slug is. See the docs for more 'order' options.

3) In the Shopp Admin area, edit the category you want to custom order, then use the ‘Arrange Products’ button/link. Then drag the products into the order you want and test.

It might be that there’s an easier or better way to do this, if so please let me know in the comments!

Please let me know if this tiny snippet was useful, just one click!
Nope, not helpful...Yep, more useful than not! - +1 thumb, 1 overall.
Loading...

Exclude a WordPress Post Category across the whole site… but not custom queries.

Problem: On my latest project there’s a WordPress post category that only ever displays in a sidebar. I never want it to display in a ‘main’ loop posts on an archive page (whether it be the blog home, date archives, author archive etc etc. Until now I’ve been using ‘query_posts()’ and doing something like this in the main templates like home.php and index.php:

<?php $catObj = get_category_by_slug('my-cat-slug');
query_posts( 'cat=-'.$catObj->term_id );
if ( have_posts() ) :
	while ( have_posts() ) : the_post(); ?>
		<!-- Show stuff init! -->
	<?php endwhile;
endif;?>

This works… but I have to do it everywhere the loop is used, and when you dig into WordPress Templates that’s a lot of places.

Solution: There’s always a way to do something globaly in WordPress using Filters, Actions, or Classes in your theme’s functions.php file (or a plugin even). In this case we can use the ‘pre_get_posts’ action in functions.php to exclude the category for all main queries: Continue reading “Exclude a WordPress Post Category across the whole site… but not custom queries.”

How to use wp_get_attachment_image_src() properly…

Problem: No matter WHAT I do, wp_get_attachment_image_src() is NOT working. I JUST want the featured image source of this $post->ID.

Solution: Yes is probably is working… but stupidly I’m trying to pass it the POST ID and not the ATTACHMENT ID like I should be. The Attachment ID can be found with the get_post_thumbnail_id() function, and then passed like this:

1
2
$thisimg = wp_get_attachment_image_src(get_post_thumbnail_id($arr->ID),full);
print_r($thisimg); //shows the Array of bits you need.

Duh… me.

Please let me know if this post was useful with a click, be honest 🙂
Nope, not helpful...Yep, more useful than not! (No Ratings Yet)
Loading...

Zurb Foundation Tooltips for and WordPress thumbnails

Problem: I wanted to use Foundation 4’s tooltips on some WordPress post thumbnail (featured) images, but wasn’t sure how to add the necessary data attribute and classes.

Solution: It turns out after some playing about that an array of attributes can be passed to the WordPress ‘get_the_post_thumbnail()‘ function. Firstly we need to add the class ‘has-tip’ (and any extra positioning classes like ‘tip-top’ if that’s where we want the tooltip to appear – see the Foundation Docs link at the top). We then need to add the data attribute ‘data-tooltip’. An example of how to do this is in the following code where I pull out a value from an Advanced Custom Field, and display a list of images with tooltips:

1
2
3
4
5
6
7
8
$icons = get_field('accom_spec_icons');
if ($icons && !is_wp_error($icons)) {
	echo '<ul class="small-block-grid-4">';
	foreach($icons as $icon) {
		echo '<li>',get_the_post_thumbnail($icon->ID,'box-thumb',array('title'=>trim(strip_tags($icon->post_title)),'class'=>'has-tip tip-top','data-tooltip'=>'')),'</li>';
	}
	echo '</ul>';
}

It’s important to add the ‘data-tooltip’ attribute with a value of ”, otherwise it wont be inserted into the generated image tag correctly.

Removing
tags around WordPress Shortcodes while retaining wpautop() changes.

Problem:
I’m building something using Drew Morris’ Foundation 4 Theme for WordPress (http://fwp.drewsymo.com/) and it allows shortcodes like [row] and [column] to be used, so that content can be aligned to the grid.

The problem is, when those shortcodes are used with any sort of line break after them, wpautop() plays havoc with the markup. I could just disable wpauto() with `remove_filter( ‘the_content’, ‘wpautop’ );` but I want it to effect all other content.

Solution:
Wordpress 3.6 has an nice new tag called has_shortcode() which can be used along with some RegEx and preg_replace() to replace the offending <br /> tags. Here’s my first version… it can be improved but it’s working pretty well so far!

add_filter ('the_content', 'cleangridshortcodes');
function cleangridshortcodes($content) {
  if(has_shortcode($content,'row') || has_shortcode($content,'column')) {
    $patterns = array("/([row])
/","/([column(.*)])
/","/([/column])
/"); $replacements = array('$1','$1','$1'); $content = preg_replace($patterns, $replacements, $content); } return $content; }

Accessing selected payment type in Shopp Summary.php (Checkout and Order Confirmation page)

Problem: Someone on the Shopp Helpdesk asked how they could display the payment type that a customer had just selected, on the following Order Confirmation page. They were using multiple ‘Offline Payment’ type options, and presumably they needed the customer to be able to visually confirm what they’d selected. As far as I can see, there’s no template tag provided for this.

Solution: All sorts can be pulled from the ShoppShopping() object directly. In this case the following worked:

1
<?php echo ShoppShopping()--->data->Order->Billing->cardtype; ?>

Bonus: To display the same info in reciept.php, the following can be used:

1
<?php echo shopp('purchase','cardtype','return=1'); ?>