skip to Main Content

I have the following lines of HTML that I am needing to use preg_replace or a similar function to add a button element that can be used for JavaScript events.

<li id="" class="menu-item-has-children">
  <a href="https://example.com">Parent Menu Item</a>
  <!-- Add button HTML element here -->
  <ul class="sub-menu">
    <!-- Child menu items -->
  </ul>
</li>

Pattern idea:

$pattern = '/<li id="(.*?)" class="menu-item-has-children"><a href="(.*?)">(.*?)</a><ul class="(.*?)">(.*?)</ul></li>/s';

Only li elements that have the menu-item-has-children class should be used.

I have used the following WordPress filter function to find and replace anchor elements that do not have a href attribute, but have been unable to modify it to successfully add a button element between the anchor elements and sub-menu unordered lists.

add_filter( 'wp_nav_menu_items', 'themename_filter_empty_anchor_items', 10, 2 );
function themename_filter_empty_anchor_items( $items, $args ) {
  if( $args->theme_location == 'want-to-navigation') {
    $pattern = '/<a>(.*?)</a>/s';
    $replacement = '<button aria-expanded="false" data-submenu-toggle="">$1<svg role="img" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><title>Expand submenu navigation icon</title><path d="m432 256c0 17.69-14.33 32.01-32 32.01h-144v144c0 17.69-14.33 31.99-32 31.99s-32-14.3-32-31.99v-144h-144c-17.67 0-32-14.32-32-32.01s14.33-31.99 32-31.99h144v-144c0-17.69 14.33-32.01 32-32.01s32 14.32 32 32.01v144h144c17.7-.01 32 14.29 32 31.99z"/></svg></button>';
    $items = preg_replace( $pattern, $replacement, $items );
  }
  return $items;
}

2

Answers


  1. Chosen as BEST ANSWER

    I followed CBroe's suggestion and utilized JavaScript to insert the button elements between the a and ul elements.

    The code below details what I implemented. A matchMedia method was used to target the code at screens smaller than 1169 pixels.

    const mediaQuery = window.matchMedia('(max-width: 1169px)');
    if (mediaQuery.matches) {
      let links = document.querySelectorAll("#global-navigation .menu-item-has-children > a");
      links.forEach(function (link) {
        let linkExpander = document.createElement("button");
        linkExpander.setAttribute("aria-expanded", "false");
        linkExpander.setAttribute("data-submenu-toggle", "");
        let svg = `<svg role="img" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><title>Expand submenu navigation icon</title><path d="m432 256c0 17.69-14.33 32.01-32 32.01h-144v144c0 17.69-14.33 31.99-32 31.99s-32-14.3-32-31.99v-144h-144c-17.67 0-32-14.32-32-32.01s14.33-31.99 32-31.99h144v-144c0-17.69 14.33-32.01 32-32.01s32 14.32 32 32.01v144h144c17.7-.01 32 14.29 32 31.99z"></path></svg>`;
        linkExpander.insertAdjacentHTML("beforeend", svg);
        link.after(linkExpander);
      });
    }
    

  2. You could use DOMDocument in conjunction with DOMXPath to load your HTML, find the appropriate a element and then append a button after it:

    $html = <<<EOD
    <li id="" class="menu-item-has-children">
      <a href="https://example.com">Parent Menu Item</a>
      <!-- Add button HTML element here -->
      <ul class="sub-menu">
        <!-- Child menu items -->
      </ul>
    </li>
    EOD;
    
    $doc = new DOMDocument();
    $doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    $xpath = new DOMXPath($doc);
    foreach ($xpath->query('//li[@class="menu-item-has-children"]/a') as $a) {
        $button = $doc->createElement('button', 'Your button text');
        // modify button as required
        // ...
        // add to document
        $a->parentNode->insertBefore($button, $a->nextSibling);
    }
    echo $doc->saveHTML();
    

    Output:

    <li id="" class="menu-item-has-children">
      <a href="https://example.com">Parent Menu Item</a><button>Your button text</button>
      <!-- Add button HTML element here -->
      <ul class="sub-menu">
        <!-- Child menu items -->
      </ul>
    </li>
    

    Demo on 3v4l.org

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search