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;
}
Related
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
I've made a function to hide/view my category menu:
The script:
function toggle(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
</script>
I use it on a p tag like this:
<p onclick="toggle('foos');";>Category</p>
The above works perfectly. When I click on "Category" it shows or hide my div.
However I then made another menu as a list. I want to execute my "toggle" function when you click on one of the "li" from my list.
I've tried to do that with this:
$(".uldropdown").on('click','li',function (){
$("#displaytwo .menu p").click();
});
But when I click on one of the "li" it shows my category menu only for a split second and then it immediately disappears.
So it almost works, but for some reason the div disappears immediately right after the click. I hope someone can tell me whats wrong. Thank you
Edit:
This is my list menu:
echo '<div id="foo">';
echo '<ul id="uldropdown" class="uldropdown">
<ul>';
while($row = mysqli_fetch_array($results)) {
echo '<li class="lidropdown">'.$row['name'].'</li>';
}
echo '</ul>
</ul></div>';
My category menu:
<div class="hejsa" >
<p onclick="toggle('foos');";>Category</p>
<?php
echo '
<div id="foos">';
echo '<ul id="catdropdown" class="catdropdown">
<ul>';
while($row = mysqli_fetch_array($resultcats)) {
echo '<li class="catdropdown" onclick="location.reload()"; ">'.$row['category'].'</li>';
}
echo '</ul>
</ul></div></div>';
I did not add some of the SQL parts, just to keep it as simple as possible.
In WordPress i'm currently using Yoast's SEO Plugin to display breadcrumbs for my pages and posts, which is working fine when visiting a specific page.
Here is the function i'm using to display the breadcrumbs inside of my WordPress templates:
<?php if ( function_exists('yoast_breadcrumb') ) {
yoast_breadcrumb('<p id="breadcrumbs">','</p>');
} ?>
For example when browsing to Team Members which is a child of About Us I get:
Home > About Us > Team Members
However i'd like to be able to display the same breadcrumbs (for the individual pages and posts) inside the search results loop.
So far what displays when searching for Members is:
Your Search Results:
Team Members
Home > Search > Members
Members Area
Home > Search > Members
But I don't want breadcrumbs for the Search Results page, I want them for the individual pages and posts that are displayed as a result of searching for a keyword.
For example Imagine I searched again for Members I would like displayed the below:
Your Search Results:
Team Members
Home > About Us > Team Members
Members Area
Home > Members Area
I'm not fussed if this is or isn't integrated with the SEO plugin, however thus far it's the best solution I found to display breadcrumbs in WordPress!
Also incase abody requires it, here is my search.php file: http://pastebin.com/0qjb2954
Try this. That's my own working snippet that shows breadcrumbs inside search loop.
/*Begin Loop */
<?php
echo '<div class="b-search_result_list__item_breadcrumbs breadcrumbs">';
$current_type = get_post_type();
if ($current_type == 'page') {
$parents = get_post_ancestors(get_the_ID());
if($parents){
for($i=count($parents)-1;$i>=0;$i--){
echo '<span typeof="v:Breadcrumb">';
echo '<a rel="v:url" property="v:title" title="'.get_the_title($parents[$i]).'" href="'.get_permalink($parents[$i]).'">'.get_the_title($parents[$i]).'</a>';
echo '</span>';
}
}else{
echo '<span typeof="v:Breadcrumb">';
echo '<a rel="v:url" property="v:title" title="'.get_bloginfo('name').'" href="'.get_bloginfo('url').'">'.get_bloginfo('name').'</a>';
echo '</span>';
}
echo '<span typeof="v:Breadcrumb">';
echo '<span property="v:title">'.get_the_title().'</span>';
echo '</span>';
}else{
$current_obj = get_post_type_object($current_type);
echo '<span typeof="v:Breadcrumb">';
echo '<a rel="v:url" property="v:title" title="'.get_bloginfo('name').'" href="'.get_bloginfo('url').'">'.get_bloginfo('name').'</a>';
echo '</span>';
echo '<span typeof="v:Breadcrumb">';
echo '<a rel="v:url" property="v:title" title="'.$current_obj->labels->name.'" href="'.get_post_type_archive_link( $current_type ).'">'.$current_obj->labels->name.'</a>';
echo '</span>';
$current_taxonomies = get_object_taxonomies($current_type);
if($current_taxonomies){
$current_terms = get_the_terms(get_the_ID(), $current_taxonomies[0]);
if($current_terms){
$current_term = array_shift($current_terms);
echo '<span typeof="v:Breadcrumb">';
echo '<a rel="v:url" property="v:title" title="'.$current_term->name.'" href="'.get_term_link($current_term).'">'.$current_term->name.'</a>';
echo '</span>';
/*
var_dump($current_obj->labels->name); // Archive name
var_dump(get_post_type_archive_link( $current_type )); // Archive link
var_dump($current_term->name); // Term name
var_dump(get_term_link($current_term)); // Term link
var_dump(get_permalink()); // Post link
*/
}
}
echo '<span typeof="v:Breadcrumb">';
echo '<span property="v:title">'.get_the_title().'</span>';
echo '</span>';
}
echo '</div>';
?>
/*End Loop*/
try adding this line of code above the yoast breadcrumb function in your search.php file:
WPSEO_Breadcrumbs::$instance = NULL;
This would be line 22 I believe, and also make sure to use the Yoast breadcrumb function from your question, not the new breadcrumb() function that's there now.
Please let me know if this works!
Full explanation:
The Yoast plugin breadcrumbs functionality is build on the page load, based on the current page as the child. To make it load the right child and parents, you'd need to reset it before you run the function. There is no built-in reset function, however setting the static $instance to NULL should cause the plugin to re-generate its data based on the current global post object which is set while you're looping.
Building upon Yavor's answer I found a way. Been banging my head about it for hours. You can place the backup and restore otuside of the loop though. Here it is:
global $wp_query;
//backup
$old_singular_value = $wp_query->is_singular;
//change
$wp_query->is_singular = true;
//reset
WPSEO_Breadcrumbs::$instance = NULL;
//breadcrumbs
if (function_exists('yoast_breadcrumb')){
yoast_breadcrumb('<p id="breadcrumbs">','</p>');
}
//restore
$wp_query->is_singular = $old_singular_value;
It fakes the query to make it singular so the newly-refreshed breadcrumbs thinks that this is not the search page but a single post or page or whatever you are displaying as your search results.
Using a plugin to generate breadcrumbs is not really necessary. Here's a simple PHP function you can add to your functions.php file:
function breadcrumbs() {
global $post;
echo "<ul id='breadcrumbs'>";
if (!is_home()) {
echo '<li>Home</li>';
if (is_category() || is_single()) {
echo "<li>" . the_category(' </li><li> ');
if (is_single()) {
echo "</li><li>" . the_title() . "</li>";
}
} elseif (is_page()) {
if($post->post_parent){
foreach ( get_post_ancestors( $post->ID ) as $ancestor ) {
echo '<li>' . get_the_title($ancestor) . '</li>' . get_the_title();
}
} else {
echo "<li>" . get_the_title() . "</li>";
}
}
} elseif (is_tag()) {
single_tag_title();
} elseif (is_day()) {
echo "<li>Archive for " . the_time('F jS, Y') . "</li>";
} elseif (is_month()) {
echo "<li>Archive for " . the_time('F, Y') . "</li>";
} elseif (is_year()) {
echo "<li>Archive for " . the_time('Y') . "</li>";
} elseif (is_author()) {
echo "<li>Author Archive</li>";
} elseif (isset($_GET['paged']) && !empty($_GET['paged'])) {
echo "<li>Blog Archives</li>";
} elseif (is_search()) {
echo "<li>Search Results for" . the_search_query() . "</li>";
}
echo "</ul>";
}
along with some CSS to style it, customize as you desire
#breadcrumbs {
list-style:none;
margin:5px 0;
overflow:hidden;
}
#breadcrumbs li{
float:left;
}
#breadcrumbs li+li:before {
content: '| ';
padding:0 4px;
}
You can then implement those breadcrumbs on any page you like, including your searchpage.php file or whichever file you use to display search results with this call
<?php breadcrumbs(); ?>
The search pages have a conditional function that can be used. You could always apply that to loading the breadcrumbs. Here is an example:
if ( ! is_search() ) {
if ( function_exists('yoast_breadcrumb') ) {
yoast_breadcrumb('<p id="breadcrumbs">','</p>');
}
}
It depends where you are loading the breadcrumbs as well, but this should typically work unless your theme is very unique.
Ok the background on this is as follows:
1. I want the joomla menu nav to switch from its default classes to my custom classes and add an tag for the pages active menu item (if neccessary)
The default classes in the default.php file is this
<ul class="nav menu<?php echo $class_sfx;?>"<?php
$tag = '';
if ($params->get('tag_id') != null)
{
$tag = $params->get('tag_id') . '';
echo ' id="' . $tag . '"';
}
?>>
<?php
foreach ($list as $i => &$item)
{
$class = 'item-' . $item->id;
if ($item->id == $active_id)
{
$class .= ' current';
}
if (in_array($item->id, $path))
{
$class .= ' active';
}
elseif ($item->type == 'alias')
{
$aliasToId = $item->params->get('aliasoptions');
if (count($path) > 0 && $aliasToId == $path[count($path) - 1])
{
$class .= ' active';
}
elseif (in_array($aliasToId, $path))
{
$class .= ' alias-parent-active';
}
}
if ($item->type == 'separator')
{
$class .= ' divider';
}
if ($item->deeper)
{
$class .= ' deeper';
}
if ($item->parent)
{
$class .= ' parent';
}
if (!empty($class))
{
$class = ' class="' . trim($class) . '"';
}
echo '<li' . $class . '>';
// Render the menu item.
switch ($item->type) :
case 'separator':
case 'url':
case 'component':
case 'heading':
require JModuleHelper::getLayoutPath('mod_menu', 'default_' . $item->type);
break;
default:
require JModuleHelper::getLayoutPath('mod_menu', 'default_url');
break;
endswitch;
// The next item is deeper.
if ($item->deeper)
{
echo '<ul class="nav-child unstyled small">';
}
elseif ($item->shallower)
{
// The next item is shallower.
echo '</li>';
echo str_repeat('</ul></li>', $item->level_diff);
}
else
{
// The next item is on the same level.
echo '</li>';
}
}
?></ul>
the output via browser is this
<ul class="nav menu">
<li class="item-101 current active">Home</li></ul>
the output I would like it to be is this...
<ul class="title-area">
<li class="name">
<h1>My Site</h1>
</li>
</ul>
My brute intution would tell me to change the nav to title-area but I am unsure of how to incorporate "name" into the li structure.
Moreover, I am assuming the tag is only for the page that is active or present at the moment... This would be nice to incorporate as well... as my foundation css structure has the line height already assigned to that structure of html.
help is appreciated.
Ok after testing I have figured out the proper answer. Now this solution is in general and should work well for any menu and dropdown menu structure within Joomla's default menu system.
I have complete this solution with Foundation 5 menu setup (later I will try a different menu system but the idea should be the same).
For the menu module go to the default.php located here: /modules/mod_menu/tmpl
The default setting has a class structure of nav menu as such:
<ul class="nav menu<?php echo $class_sfx;?>"<?php
$tag = '';
Change the class to be what you need the class structure to be. if you are 100% circumventing the Joomla css (bootstrap) file structure then you can change it... or if not you can just add a class name(s) that you need.
here is what mine changed to:
<ul class="right nav menu<?php echo $class_sfx;?>"<?php
$tag = '';
Now if you are following your new menu system's class structure (Foundation) you might need to designate a class for <li and for the sub menu items i.e. for a dropdown menu.
***Keep in mind that for Joomla's menu structure within PHP it pulls the item number and if it is the current page it will auto mark it as auto (automatically)... so no need to add that in except for the class you are adding. Edit* Adding the class "has-dropdown" should be for the parent
so on this line (the before):
if ($item->parent)
{
$class .= ' parent';
}
Change it to this (the after):
if ($item->parent)
{
$class .= ' has-dropdown parent';
}
As well the sub child items need to change.
So on this line (the before):
// The next item is deeper.
if ($item->deeper)
{
echo '<ul class="nav-child unstyled small">';
}
Change it to this (the after):
// The next item is deeper.
if ($item->deeper)
{
echo '<ul class="dropdown nav-child unstyled small">';
}
I think it would be great to add a plug-in that can mod the backend menu setup to include class to add to or change for <ul and <li for both menu and sub menu child items.
Hopefully this helps someone... I will add more later.
*I have one error I am getting with this and the Foundation menu I am using. The first child will show but if that child has a child menu item it won't show... So there's that fix still needed.
*remember to change the setting: Show Sub-menu Items to "yes"
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;
}