In this answer, I have shared how to split up wp_nav_menu with custom walker in WordPress. Use following code in your theme’s functions.php file OR in site specific plugin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | class SplitMenuWalker extends Walker_Nav_Menu { private $split_at; private $button; private $count = 0; private $wrappedOutput; private $replaceTarget; private $wrapped = false; private $toSplit = false; public function __construct($split_at = 5, $button = '<a href="#">…</a>') { $this->split_at = $split_at; $this->button = $button; } public function walk($elements, $max_depth) { $args = array_slice(func_get_args(), 2); $output = parent::walk($elements, $max_depth, reset($args)); return $this->toSplit ? $output.'</ul></li>' : $output; } public function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0 ) { $this->count += $depth === 0 ? 1 : 0; parent::start_el($output, $item, $depth, $args, $id); if (($this->count === $this->split_at) && ! $this->wrapped) { // split at number has been reached generate and store wrapped output $this->wrapped = true; $this->replaceTarget = $output; $this->wrappedOutput = $this->wrappedOutput($output); } elseif(($this->count === $this->split_at + 1) && ! $this->toSplit) { // split at number has been exceeded, replace regular with wrapped output $this->toSplit = true; $output = str_replace($this->replaceTarget, $this->wrappedOutput, $output); } } private function wrappedOutput($output) { $dom = new DOMDocument; $dom->loadHTML($output.'</li>'); $lis = $dom->getElementsByTagName('li'); $last = trim(substr($dom->saveHTML($lis->item($lis->length-1)), 0, -5)); // remove last li $wrappedOutput = substr(trim($output), 0, -1 * strlen($last)); $classes = array( 'menu-item', 'menu-item-type-custom', 'menu-item-object-custom', 'menu-item-has-children', 'menu-item-split-wrapper' ); // add wrap li element $wrappedOutput .= '<li class="'.implode(' ', $classes).'">'; // add the "more" link $wrappedOutput .= $this->button; // add the last item wrapped in a submenu and return return $wrappedOutput . '<ul class="sub-menu">'. $last; } } |
The usage is pretty simple:
1 2 3 4 5 6 7 8 9 10 11 | // by default make visible 5 elements wp_nav_menu(array('menu' => 'my_menu', 'walker' => new SplitMenuWalker())); // let's make visible 2 elements wp_nav_menu(array('menu' => 'another_menu', 'walker' => new SplitMenuWalker(2))); // customize the link to click/over to see wrapped items wp_nav_menu(array( 'menu' => 'another_menu', 'walker' => new SplitMenuWalker(5, '<a href="#">more...</a>') )); |
If you like this question & answer and want to contribute, then write your question & answer and email to freewebmentor[@]gmail.com. Your question and answer will appear on FreeWebMentor.com and help other developers.