Skip to content

Instantly share code, notes, and snippets.

@bob-moore
Last active June 6, 2016 16:58
Show Gist options
  • Save bob-moore/58a2ecf68024580dc17d5c07131a30ac to your computer and use it in GitHub Desktop.
Save bob-moore/58a2ecf68024580dc17d5c07131a30ac to your computer and use it in GitHub Desktop.
Related Navigation in Wordpress
Purpose: Display navigation of a pages siblings and children.
1. Children / Grandchildren of SIBLING top level pages are hidden (visually)
2. All top level pages are visible, and the navigation down to 1 level below the current page
2. Items are not expandable, the purpose is not to provide a full navigation menu, instead the goal is to provide links Nth levels up, and 1 level down the navigational tree.
In this way, as pages are added / removed from the site, they are automatically represented in the related navigation tree.
Example when the current page is a top level page with children
===============================================================
- Top Level Page
- Current Top Level Page
- Current Page Child
- Current Page Child
- Current Page Child
- Top Level Page
- Top Level Page
Example when the current page is a second level (child) page with children
==========================================================================
- Top Level Page
- Current Page Parent
- Current Page
- Current Page Child
- Current Page Child
- Current Page Sibling
- Current Page Sibling
- Top Level Page
- Top Level Page
<?php
/*******************************************************************************
* PLUGIN NAME: Page Navigation Widget
* URI PLUGIN URI: http://www.midwestfamilymarketing.com
* DESCRIPTION: Display page menu
* VERSION: 1.0.0
* AUTHOR: Midwest Digital Marketing Team
* AUTHOR URI: http://www.midwestfamilymarketing.com
******************************************************************************/
class Page_Navigation_Widget extends WP_Widget {
public $widget_id_base;
public $widget_name;
public $widget_options;
/**
* Constructor, initialize the widget
* @param $id_base, $name, $widget_options, $control_options ( ALL optional )
* @since 1.0.0
*/
public function __construct() {
$this->widget_id_base = 'page_navigation';
$this->widget_name = 'Page Navigation';
$this->widget_options = array(
'classname' => 'page_navigation_widget',
'description' => 'Display Page Navigation'
);
parent::__construct( $this->widget_id_base, $this->widget_name, $this->widget_options );
} // end __construct
/**
* Create back end form for specifying image and content
* @param $instance
* @see https://codex.wordpress.org/Function_Reference/wp_parse_args
* @since 1.0.0
*/
public function form( $instance ) {
// define our default values
$defaults = array(
'title' => null,
'name' => null,
);
// merge instance with default values
$instance = wp_parse_args( (array)$instance, $defaults );
// include our form markup
include plugin_dir_path( __FILE__ ) . 'widget_form.php';
} // end form()
/**
* Update form values
* @param $new_instance, $old_instance
* @since 1.0.0
*/
public function update( $new_instance, $old_instance ) {
// initially set instance = old_instance, and replace individual values as we validate them
$instance = $old_instance;
// escape and set new values
$instance['title'] = sanitize_text_field( $new_instance['title'] );
$instance['name'] = sanitize_text_field( $new_instance['name'] );
return $instance;
} // end update()
/**
* Output widget on the front end
* @param $args, $instance
* @since 1.0.0
*/
public function widget( $args, $instance ) {
// Extract the widget arguments ( before_widget, after_widget, description, etc )
extract( $args );
// Instantiate $heading to avoid errors
$heading = '';
// Append before / after title elements if title is not blank
if( !empty( $instance['name'] ) ) {
$heading .= $args['before_title'];
$heading .= apply_filters( 'widget_title', $instance['name'], $instance, $this->id_base );
$heading .= $args['after_title'];
}
// Display the markup before the widget (as defined in functions.php)
echo $before_widget;
// Echo the title
if( !empty( $instance['name'] ) ) {
echo $heading;
}
$menu = wp_list_pages( array( 'title_li' => '', 'show_home' => false, 'sort_column' => 'menu_order', 'exclude' => get_option( 'page_on_front' ), 'echo' => false ) );
$output = '<nav id="sidebar-navigation" class="navigation-menu" role="navigation" itemscope itemtype="https://schema.org/SiteNavigationElement">';
$output .= '<ul class="related-pages">';
$output .= apply_filters( 'schema_site_navigation', $menu );
$output .= '</ul></nav>';
echo $output;
// Display the markup after the widget (as defined in functions.php)
echo $after_widget;
} // end widget()
} // end class
/*
* Register widget
*/
if( !function_exists( 'register_page_navigation_widget' ) ) {
function register_page_navigation_widget() {
register_widget( 'Page_Navigation_Widget' );
}
add_action( 'widgets_init', 'page_navigation_widget' );
}
/*
* Insert schema.org markup into navigation
* @see https://schema.org/SiteNavigationElement
*/
if( !function_exists( 'schema_site_navigation_filter' ) ) {
function schema_site_navigation_filter( $menu ) {
// Add itemprop to LI elements
$menu = str_replace( '<li', '<li itemprop="name"', $menu );
// Add itemprop to A elements
$menu = str_replace( '<a', '<a itemprop="url"', $menu );
// Return the modified menu
return $menu;
}
add_filter( 'schema_site_navigation', 'schema_site_navigation_filter', 1, 999 );
}
.related-pages {
list-style-type: none;
padding: 0;
margin: 0;
border-left: 4px solid #f1f1f1;
li {
position: relative;
&.current_page_item {
overflow: visible;
> a, > a:link {
font-weight: 600;
}
}
&.top-level-page {
> a, > a:link, > a:hover, > a:focus {
font-size: 1.3em;
&:before {
content: '';
display: none;
}
}
}
}
a, a:link {
display: block;
font-size: .9em;
padding: 0 20px;
line-height: 30px;
text-decoration: none;
transition: text-indent .25s linear;
&:hover, &:focus {
font-weight: 400;
text-indent: 5px;
}
}
ul.children, ul.submenu {
margin-left: 24px;
border-left: 4px solid #f1f1f1;
}
ul.children {
li {
display: none;
}
}
li.current_page_ancestor, li.current_page_parent, li.current_page_item {
> ul.children > li {
display: block;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment