0

I am building a simple website with a number of pages, each of which is grouped.

Let's say my website has roughly 20 pages, grouped into 5 categories. So I want my navbar to display the 5 categories, and each category, on rollover, displays the pages created under it.

Now since I am creating my pages as pages and not posts, I understand that "categories" are not available. So I am creating them as sub-pages. And I am creating each "category" as a page.

My problem: I only created these "pages" for the purpose of grouping the "sub-pages" in the navbar. But none of these "pages" are actual pages, so I don't want any of them to be clickable. What I want is if someone clicks on the "page" itself in the navbar, they should be taken to the first sub-page of that category (or page).

I would be grateful for any solutions.

(Side note: This seems like an extremely common situation, and yet, after hunting around for quite a while, I see nothing addressing the issue. I'm a web programmer with over a decade experience, but a relative newbie to wp, and I find this kind of situation repeating itself over and over.)

1
  • Set the custom link URL to #, and then put all other pages as sub-pages.
    – Jane
    Commented Jan 19 at 15:17

5 Answers 5

2

I would use the built in Wordpress Menu Manager (Appearance -> Menus) to create my menu structure.

For each of the 'dummy' parent pages you can just use a second link to that pages first child page, and rename it to read however you want.

So if your structure is:

-Parent A

  • Child A

  • Child B

  • Child C

And you want to make it so that clicking on Parent A will take people to the Child A page, just insert a link to Child A as your top-level page, and then rename it to read "Parent A".

Once you have this structure created how you like it, you can use WP_Nav_Menu (http://codex.wordpress.org/Function_Reference/wp_nav_menu) to display the menu in your header.

If on your interior pages you need to show only the child pages of the current section, you can use a plugin I wrote called WP Nav Plus to set your starting depth and only show the children pages (https://mattkeys.me/products/wp-nav-plus/).

I hope this helps.

2
  • Matt, please see the response I posted below and give me your reaction to it, so that I can decide whether to accept your answer. Thank you.
    – oyvey
    Commented May 21, 2013 at 14:01
  • This is very close to what I meant, and serves about the same purpose. Where you used a 'custom' menu item, you could have also just added the same page (the first child) to the menu twice, setting one of them as the parent and the second one as the first child. You can then rename the 'parent' link to be named more appropriately
    – Matt Keys
    Commented May 23, 2013 at 22:15
1

I upvoted @MattKey's answer because the back-end configurable menu system is a good way to deal with things like this, and also keeps the menus editable from the back-end.

However... that answer does not directly answer the question of how you would do this based on the page structure alone. The answer I came up with is a custom Walker for wp_list_pages.

class No_Top_Link_Walker extends Walker_Page {
  static $parent = false;

  function start_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent%s<ul class='children'>\n";
  }

  function start_el( &$output, $page, $depth, $args, $current_page = 0 ) {
    if ( $depth ) {
      $indent = str_repeat("\t", $depth);
    } else {
      $indent = '';
    }

    extract($args, EXTR_SKIP);
    $css_class = array('page_item', 'page-item-'.$page->ID);
    if ( !empty($current_page) ) {
      $_current_page = get_post( $current_page );
    if ( in_array( $page->ID, $_current_page->ancestors ) )
      $css_class[] = 'current_page_ancestor';
    if ( $page->ID == $current_page )
      $css_class[] = 'current_page_item';
    elseif ( $_current_page && $page->ID == $_current_page->post_parent )
      $css_class[] = 'current_page_parent';
    } elseif ( $page->ID == get_option('page_for_posts') ) {
      $css_class[] = 'current_page_parent';
    }

    $css_class = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page ) );

    $href = (0 === $depth && $args['has_children']) ? '%s' : get_permalink($page->ID);

    $tli = '';
    if (false !== static::$parent) {
      $tli = sprintf(static::$parent,get_permalink($page->ID));
      static::$parent = false;
    }

    $output = sprintf($output,$tli);

    $li = $indent . '<li class="' . $css_class . '"><a href="' . $href . '">' . $link_before . apply_filters( 'the_title', $page->post_title, $page->ID ) . $link_after . '</a>';

    if ( !empty($show_date) ) {
      if ( 'modified' == $show_date )
    $time = $page->post_modified;
      else
    $time = $page->post_date;

      $li .= " " . mysql2date($date_format, $time);
    }

    if (0 === $depth && $args['has_children']) {
      static::$parent = $li;
    } else {
      $output .= $li;
    }
  }

  function end_el( &$output, $page, $depth = 0, $args = array() ) {
    if (false === static::$parent) {
      $output .= "</li>\n";
    }
  }

}
$args = array(
  'walker' => new No_Top_Link_Walker,
  'title_li' => 'Pages'
);
echo '<ul>';
wp_list_pages($args);     
echo '</ul>';

The walker extends Walker_Page and replaces several methods. The code above is essentially a copy of that walker's methods except where where I had make changes, not counting some trivial formatting and syntax changes.

The walker doesn't know what the child URL is until it gets there so I saved the markup for the top level menus without children and inserted them before beginning the markup for the child.

I have tested it a bit during development and it appears to work and validator.w3.org gives it a "green". However, no promises. I just made it up.

0

Here is the code for menu with sub-menu from pages and child pages.

<ul>
<?php 
$parents = array();
$args = array(
                'post_type' => 'page',
                'parent' => -1,
                'number' => '',
             );
$pages = get_pages($args);
foreach( $pages as $page){
    $childs = get_pages('child_of='.$page->ID);
    if( count( $childs ) > 0 ){
        echo '<li><a href="#">' . $page->post_title . '</a>';

        if( count( $childs ) > 0 ){
            echo '<ul>';
            foreach( $childs as $child ){
                echo '<li><a href="' . get_permalink($child->ID) . '">' . $child->post_title . '</a></li>';
            }
            echo '</ul>';
        }
    }
}
?>
</ul>

Now, check this code for pure CSS menu and sub menu and customize it to your needs.

0

In response to Matt, here is what I've done:

  1. I delete all of the pages that I had created just for the sake of grouping the sub-pages.
  2. All of the pages that were sub-pages are now regular pages, not sub-pages.
  3. I created a new menu.
  4. For each menu group, I created a custom link, and assigned as its url the url of what will be its first child.
  5. Within the menu, I created a hierarchy of these custom links and their respective children.

Matt, is this what you meant? It seems to suit my needs.

Actually, I believe it is a bit simpler than your solution, in that I don't need to edit WP_Nav_Menu or WP_Nav_Plus.

The main disadvantage that I can see is that every time the first child of a group changes, I will need to manually change the url of its parent custom link. (Perhaps this is an advantage in your solution? For me, the advantage that I don't need to edit any php outweighs this disadvantage.)

Not too bad, but it seems to me that there ought to be a way to not have to create a custom menu to accomplish this. Perhaps what I'm saying is that there should be a feature called "Page Category" that would automatically accomplish this. I'm sure I'm the first person to make such a suggestion!

(I understand that I'm supposed to enter this as a comment to Matt's comment, but it wouldn't let me due to the length of my post.)

0

AS I browsing the net regarding nav menu styles i stumbled across this thread, as I trying to understand this scenario.... "Let's say my website has roughly 20 pages, grouped into 5 categories. So I want my navbar to display the 5 categories, and each category, on rollover, displays the pages created under it." and "he only created these "pages" for the purpose of grouping the "sub-pages" in the navbar. But none of these "pages" are actual pages, so I don't want any of them to be clickable. What I want is if someone clicks on the "page" itself in the navbar, they should be taken to the first sub-page of that category (or page).

My simplest answer I can think of is... since you made the pages for the purpose of grouping them, I suggest is to make a link menu to group them instead, then put the actual sub page as the sub menu.

To do this login to your wordpress site then go to appearance, then menu. On menu items choose custom link then on the Link text Put the Category Title you want then on the URL just put a hashtag (#) on it to make it unclickable, then drag the custom link to your menu. Do the same for the rest of the 4 categories you want. then on the menu items go to pages then select the actual pages created under this category then drag it to your main nav menu under this custom link as a sub menu page.

I hope this helps.

Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.