I have a sidebar menu on a WordPress site that simply outputs all the child pages under that parent. I'm trying to highlight (or hopefully add an arrow) the current child page that is selected. I've run into a wall with my limited PHP experience to figure out how to do that.
Any help would be greatly appreciated. The relevant code is below:
<?php
/* if the current pages has a parent, i.e. we are on a subpage */
if($post->post_parent){
/* $children = wp_list_pages("title_li=&include=".$post->post_parent."&echo=0"); // list the parent page */
$children .= wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0"); // append the list of children pages to the same $children variable
}
/* else if the current page does not have a parent, i.e. this is a top level page */
else {
//$children = wp_list_pages("title_li=&include=".$post->ID."&echo=0"); // include the parent page as well
$children .= wp_list_pages("title_li=&child_of=".$post->ID."&echo=0&"); // form a list of the children of the current page
}
/* if we ended up with any pages from the queries above */
if ($children) { ?>
<ul class="submenu">
<?php echo $children; /*print list of pages*/ ?>
</ul>
<?php } ?>
I'm assuming it would be in the output section, but I simply don't know how to target the current child page that's being browsed and highlight that accordingly.
I had a little fun with this one. And my result might not be exactly what you were looking for, but I think it might be better. In short, the below snippet allows you to easily identify the page hierarchy (parent/children) for the current page. As such, you can then do all sorts of wonderful things to your heart's desire. For the purposes of your specific request, I made the custom function "custom_list_child_pages(...)" return a full list of links from the page hierarchy related to the "current page".
There is tons of logic, all related to the key situations you were trying to tackle. You should be able to identify when you are in a sub-page or parent page, you should be able to call out that little function and modify it to make it do whatever you need it to do with all the relevant players (current, parent [or self if no other], child pages, etc).
Let me know if this helps you and if you get stuck with the code or any other aspects regarding what you are trying to achieve let me know as well and I will see how I can assist you further.
Code:
<?php
//die(var_dump($foo)); // Quickly check a variable value.
function custom_list_child_pages($the_current_page_id, $the_parent_page_id, $child_pages){
$html_page_listing = '';
// Get creative with the parent page.
$the_parent_page = get_page( $the_parent_page_id );
$html_page_listing .= "<h3>" . "<a href='$the_parent_page->guid'>$the_parent_page->post_title</a>" . "</h3>";
// Get creative with the child pages.
$html_page_listing .= "<h3>" . "Child pages:" . "</h3>";
$html_page_listing .= "<ul>";
// Iterate through child pages as desired.
foreach ($child_pages as $key => $page) {
$current_page = get_page_by_title( $page->post_title );
$current_page_id = $page->ID;
if ($current_page_id == $the_current_page_id) {
// Do something great.
$html_page_listing .= "<li> ->" . "<a href='$page->guid'>$page->post_title</a>" . "</li>";
} else {
$html_page_listing .= "<li>" . "<a href='$page->guid'>$page->post_title</a>" . "</li>";
}
}
$html_page_listing .= "</ul>";
return $html_page_listing;
}
global $post; // If outside the loop.
// Set up the objects needed.
$my_wp_query = new WP_Query();
$all_wp_pages = $my_wp_query->query(array('post_type' => 'page', 'posts_per_page' => '-1'));
if ( is_page() && $post->post_parent ) {
// This is a subpage.
$the_current_page_id = $page_id;
$the_parent_page_id = wp_get_post_parent_id( $post_ID );
$the_child_pages = get_page_children( $the_parent_page_id, $all_wp_pages ); // Form a list of the children of the current page.
$the_parent_page_id = wp_get_post_parent_id( $post_ID ); // Include the parent page as well.
$menu = custom_list_child_pages($the_current_page_id, $the_parent_page_id, $the_child_pages); // ~append the list of children pages to the same $children variable
echo $menu; // Print list of pages.
} else {
// This is not a subpage.
$the_current_page_id = $page_id;
$the_parent_page_id = $page_id;
$the_child_pages = get_page_children( $page_id, $all_wp_pages ); // Form a list of the children of the current page.
$the_parent_page_id = $page_id; // Include the parent page as well.
$menu = custom_list_child_pages($the_current_page_id, $the_parent_page_id, $the_child_pages);
echo $menu; // Print list of pages.
}
?>
Regards,
Arty
Related
My company took over the maintenance of a website and I am trying to determine how to properly get both the top-level (parent) links as well as the child links. The code that was being used is:
<div id="monav">
<ul>
<?php
$mobile_menu = menu_navigation_links('menu-mobile-nav');
print theme('links__menu_mobile_nav', array('links' => $mobile_menu));
?>
</ul>
This only spits out the top-level. I have been digging through forums and code trying to find the correct way to get the child links. Can you point me in the right direction oh wise Drupal gurus?
Note: setting the parent link to "Show as expanded" does not work.
I ended up using this code:
In template.php I have
//Render Mobile
function drive_menu_tree__menu_mobile_nav($variables){
return '<ul class="" id="">' . $variables['tree'] . '</ul>';
}
function drive_menu_links__menu_mobile_nav($variables) {
$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";
}
Then I display the menu in page.tpl.php using:
print drupal_render(menu_tree_output(menu_tree_all_data('menu-mobile-nav')));
SOURCE: How to display a menu in a template file?
Update:
The above code was spitting out an error so instead I am doing this.
template.php in the theme_preprocess_page(&$vars) function
//Render main menu
$main_menu_tree = menu_tree(variable_get('menu_main_links_source', 'main-menu'));
$vars['main_menu'] = $main_menu_tree;
Then I am displaying the menu in page.tpl.php using
<div id="monav">
<?php
print render($main_menu);
?>
</div>
To make this menu mobile I added the following jquery
(function ($) {
$(document).ready(function(){
//Mobile Navigation
$('#nav-toggle').click(function(e) {
$('#monav').toggle();
});
$('#monav li.expanded > a').attr("href", "#");
$("#monav li.expanded").click(function() {
$(this).find('.menu').toggle();
});
});
})(jQuery);
Note I had to hide this in my css
#monav ul.menu li.expanded .menu{
display:none;
}
I have taken over a wordpress site built by someone else (londonschoolofsamba.co.uk) and am having difficulties with sub-sub-lists disappearing in the navigation.
If I visit a page that has children, then the navigation displays the parent pages, and the children and grandchildren of that page. If I visit one of the pages that is a child, then the navigation still displays the parent and grandchildren, but if I go to a grandchild page, then the navigation returns to displaying only the parents.
Can anyone help me to get it so that when visiting a grandchild page, that the navigation still shows the children and grandchildren, and not just the parents?
<?php
$this_post = $wp_query->get_queried_object();
$temp = get_post_ancestors($this_post);
if(sizeof($temp) > 0)
{
$this_page_id = $temp[0];
}
else
{
$this_page_id = $this_post->ID;
}
$home_page = get_page_by_title('Home');
$pages = get_pages("sort_column=menu_order&parent=0&exclude=".$home_page->ID);
foreach($pages as $page)
{
$classes = "menu_item";
if($this_page_id == $page->ID)
{
$classes .= " selected_menu";
}
?>
<div class="<?php echo $classes; ?>">
<div class="menu_item_picture">
<?php echo $page->post_title;?>
</div>
<?php
$list = wp_list_pages("title_li=&child_of=".$page->ID."&depth=2&echo=0");
if($this_page_id == $page->ID && strlen($list) >0)
{
?>
<ul>
<?php echo $list;?>
</ul>
<?php
}
?>
</div>
<?php
}
?>
With my very little knowledge of jQuery and PHP, I have almost accomplished an accordion menu where the links display as 'active' when the active page is open, and the slider menu stays open on the correct section when on the active page.
I have added some php to the bottom links. The child links display as active when on the active page. However the parent element does not, and also closes itself.
I'd really appreciate any help!!!
Here's my code as it stands:
<ul id="accordion">
<ul class="parent">
<li>
CMS
<ul class="child">
<li>Intro to CMS</li>
<li>Specific CMS</li>
<li>Installing a CMS</li>
</ul>
</li>
</ul>
<ul class="parent">
<li>
<?php
if ($this_page=="Customising-Google-Forms" || $this_page=="Web-Event-Notes"){
echo "Other";
}else{
echo "Other";
}
?>
<ul class="child">
<?php
if ($this_page=="Customising-Google-Forms"){
echo "<li class=\"current\">Customising-google-forms</li>";
}else{
echo "<li>Customising Google Forms</li>";
}
?>
<?php
if ($this_page=="Web-Event-Notes"){
echo "<li class=\"current\">Web Event Notes</li>";
}else{
echo "<li>Web-Event-Notes</li>";
}
?>
</ul>
</li>
</ul>
<script type="text/javascript">
$(function(){
// hide all links on load
$('ul.child').hide();
// for image
// $("a.slide:first").css("background-image","url('path')");
$('ul.parent a.slide').click(function(){
$('ul.parent a.slide').css("color","#000");
$('ul.parent a.slide').hover(function(){
$(this).css("color","#ef492f");
});
$('ul.parent a.slide').mouseout(function(){
$(this).css("color","#000");
});
$(this).mouseout(function(){
$(this).css("color","#000");
});
$(this).css("color","#000");
// slide all up
$('ul.child').slideUp('slow');
// show the links of current heading
$(this).next().find('a').show();
// slide down current heading
$(this).next().slideDown('fast');
// prevent default action
return false;
});
if($("ul li a").hasClass("current")) {
$(this).closest("ul").slideDown("fast") //open the menu
}
});
</script>
In my opinion the best way to accomplish this is by making a PHP array that contains the links and then build a html menu out of it. In this way PHP can control which of the links will hold the 'current' class based on the url parameters. The last step will be jquery to just grab the '.current' listitem and make it visible. The below may seem like a lot of work, but when you get it, it will be powerful and reusable :)
//Grab the page parameter somehow.. below = example
$page = $_GET['page'];
//Build menu array containing links and subs
$items = Array(
//highest level
'cms' => Array(
'title' => 'CMS',
//Array containing submenu items for cms
'subs' => Array(
'intro-to-cms' => Array('title' => 'Intro to CMS'),
'specific-cms' => Array('title' => 'Specific CMS'),
'installing-a-cms' => Array('title' => 'Installing a CMS')
),
)
);
//Display the menu
echo navlinks($items, $page);
/**
* Recursive function creates a navigation out of an array
* #param type $items
* #return string containing navigationlist
*/
function navlinks($items, $page=false)
{
$html = '<ul>';
foreach ($items AS $uri => $info) {
//Check if the pagename is the same as the link name and set it to current when it is
$html .= '<li'.($info['title'] == $page ? ' class="current"' : '').'>';
echo ' ' . $info['title'] . '';
//If the link has a sub array, recurse this function to build another list in this listitem
if (isset($info['subs']) && is_array($info['subs'])) {
$html .= navlinks($info['subs']);
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
I am building a navigation system on a webpage using PHP, that basically queries data from MySQL database and display as ul, li menu on main menu. But I couldn't figure out how do I make navigation menu selected when user goes to that page. I have one idea but that doesn't make home menu selected by default when user enters that page.
I have also a CSS class written to give that class to the anchor tag if it is that page.
here is my PHP code:
//Query Functions
function queryMenu() {
$query = "SELECT * FROM menu_en";
return $query;
}
// Render Functions
function renderNav() {
$menus = queryMenu();
$queryMenu = mysql_query($menus);
while( $navigation = mysql_fetch_array($queryMenu) ){
if( $navigation['id'] == $_GET['pageId'] ){
echo '<li>
<a href="index.php?pageId="'.$navigation['id'].' class="selected" >'.$navigation['menu_title'].
'</a></li>';
}else{
echo '<li><a href="index.php?pageId="'.$navigation['id'].'>'.$navigation['menu_title'].'</a></li>';
}
}
}
Suggest me a better way to do this, as I want to enhance my skill in PHP. And also please let me know if there is any wrong approach in above code.
If the home page is when $_GET['pageId'] is not set you could check using isset()
if(isset($_GET['pageId'])) {
$page = $_GET['pageId']
} else {
$page = $homePageId; // the ID of the home page.
}
Then you would replace this line:
if( $navigation['id'] == $_GET['pageId'] ){
with this line:
if( $navigation['id'] == $page ){
I think this would work, if i understand you correctly.
I'm using following code to display my 3 level menu:
if(!$post->post_parent){
// will display the subpages of this top level page
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
}else{
// diplays only the subpages of parent level
//$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0");
if($post->ancestors) {
// now you can get the the top ID of this page
// wp is putting the ids DESC, thats why the top level ID is the last one
$ancestors = end($post->ancestors);
$children = wp_list_pages("title_li=&child_of=".$ancestors."&echo=0");
// you will always get the whole subpages list
}
}
if ($children) { ?>
<ul id="submenu">
<?php echo $children; ?>
</ul>
<?php } ?>
It lists pages in side bar, second level then 3rd level too. I would like to include very top level too so i would like to my structure to look as follow:
*A
-a
--a
-b
--b
-c
--c
Where as above code is not listing main page i.e. *A, i hope that make sense and someone will be able to help
Thanks,
I found this code snippet at the wordpress codex site, and I think it's exactly what you're looking for, I've pasted it in for convenience:
<?php
//if the post has a parent
if($post->post_parent){
//collect ancestor pages
$relations = get_post_ancestors($post->ID);
//get child pages
$result = $wpdb->get_results( "SELECT ID FROM wp_posts WHERE post_parent = $post->ID AND post_type='page'" );
if ($result){
foreach($result as $pageID){
array_push($relations, $pageID->ID);
}
}
//add current post to pages
array_push($relations, $post->ID); // <---- THIS IS INCLUDING THE PARENT
//get comma delimited list of children and parents and self
$relations_string = implode(",",$relations);
//use include to list only the collected pages.
$sidelinks = wp_list_pages("title_li=&echo=0&include=".$relations_string);
}else{
// display only main level and children
$sidelinks = wp_list_pages("title_li=&echo=0&depth=2&child_of=".$post->ID);
}
if ($sidelinks) { ?>
<h2><?php the_title() ;?></h2>
<ul>
//links in <li> tags
<?php echo $sidelinks; ?>
</ul>
<?php } ?>
It also has some built-in logic to not display everything if this is a highest-level page. Hope this helps!
<div id="breadcrumbs">
Home
<?php
$parent_id = $post->post_parent;
$breadcrumbs = array();
while ($parent_id) {
$page = get_page($parent_id);
$breadcrumbs[] = ''.get_the_title($page->ID).'';
$parent_id = $page->post_parent;
}
$breadcrumbs = array_reverse($breadcrumbs);
foreach ($breadcrumbs as $crumb) echo ' / '.$crumb;
?>
</div>
<h1><?php the_title(); ?></h1>
credit : Ivovic
from : http://wordpress.org/support/topic/display-page-parent-on-page-with-title?replies=13