Reputation: 875
So I am using a cool little function to render a search bar in my menu. Check it out here:
function add_search_to_wp_menu ( $items, $args ) {
if( 'main-menu' === $args -> theme_location ) {
$items .= '<li class="menu-item menu-item-search">';
$items .= '<form method="get" class="menu-search-form" action="' . get_bloginfo('home') . '/"><p><input class="text_input" type="text" value="Enter Text & Click to Search" name="s" id="s" onfocus="if (this.value == \'Enter Text & Click to Search\') {this.value = \'\';}" onblur="if (this.value == \'\') {this.value = \'Enter Text & Click to Search\';}" /><input type="submit" class="my-wp-search" id="searchsubmit" value="search" /></p></form>';
$items .= '</li>';
}
return $items;
}
add_filter('wp_nav_menu_items','add_search_to_wp_menu',10,2);
I didn't make it - but its doing the job.
So the only problem is that it is appearing at the top level:
<ul>
<li>Normal Item</li>
<li>OH LOOOK THE SEATCHBAR APPEARS HERE</li>
</ul>
The problem is that I need it to appear a few more steps down in the menu, ie - here:
<ul>
<li>
Normal Item
<ul>
<li>
I want THE SEARCH to appear here
</li>
<ul>
</li>
</ul>
Not only that, I want it to appear after the last <ul><li><ul><li>
in the menu...
IE, if I had a list of 3 normal items with their own sub items, it would look like this once injected:
<ul>
<li>
Normal Item1
</li>
<li>
Normal Item2
</li>
<li>
Normal Item3
</li>
<li>
Normal Item
<ul>
<li>
I want THE SEARCH to appear here
</li>
<ul>
</li>
</ul>
Hopefully that makes sense. Thanks for the help!
Upvotes: 0
Views: 313
Reputation: 14959
A quick and dirty hack. It will (maybe, needs tuning) works but you have to fiddle with the code and the codex (reference on the bottom of the answer) or you will not make it another time.
function add_search_to_wp_menu_item ( $items, $args ) {
$search_form = '<ul><li class="menu-item menu-item-search">'
. '<form method="get......./form>' // FILL IT WITH YOUR HTML
.'</li></ul></li>';
if( 'main-menu' === $args -> theme_location ) {
$items = preg_replace('/<\/li>\s*$/',$search_form,trim($items));
}
return $items;
}
add_filter('wp_nav_menu_items','add_search_to_wp_menu_item',10,2);
It SHOULD work as I don't know the content of the $item parameter.
If I guess right, stated the correctness of the legacy function, it is a string containing a list of li (without enclosing ul) and then I inject an ul into the last one (if the filter is processing the main-menu element of the page).
References:
Addendum
What '/<\/li>\s*$/'
is?
It is a regular expression (see an easy tutorial on them], it is not limited to php as it is present in several languages.
It is a language per se, to be precise.
preg_replace
leverage on regular expression to let you perform some advanced string manipulation. That regex tell to the engine to find the last tag in the string the one just before the string's end it doesn't matter if there are spaces, tabs or newlines (but just this set of chars) before the ending of the string.
I will dissect the code hoping it will shed some light on it.
/
are the regex enclosure, the real regex is <\/li>\s*$
/
into your string you need to escape it with a \
. The engine will not think that it marks the end of the regex.*
is a quantity modifier, it change the meanings of the previous character stating that it can be repeated a number of times there are several of them. Ours say 0 or more.When the engine find in your string a chunk of characters that fit the description you give him then there is a match and that part of the string will be changed with the second parameter given to preg_replace.
I've just scratched the surface of this topic, and it is up to you to choose to go deeper or not.
The tutorial I linked (you need to read all the 3 parts) is a good point of start.
Upvotes: 1