Home > database >  Use preg_replace to insert button element between parent anchor and ul dropdown elements in PHP
Use preg_replace to insert button element between parent anchor and ul dropdown elements in PHP

Time:09-21

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="" >
  <a href="https://example.com">Parent Menu Item</a>
  <!-- Add button HTML element here -->
  <ul >
    <!-- Child menu items -->
  </ul>
</li>

Pattern idea:

$pattern = '/<li id="(.*?)" ><a href="(.*?)">(.*?)<\/a><ul >(.*?)<\/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;
}

CodePudding user response:

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="" >
  <a href="https://example.com">Parent Menu Item</a>
  <!-- Add button HTML element here -->
  <ul >
    <!-- 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[@]/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="" >
  <a href="https://example.com">Parent Menu Item</a><button>Your button text</button>
  <!-- Add button HTML element here -->
  <ul >
    <!-- Child menu items -->
  </ul>
</li>

Demo on 3v4l.org

CodePudding user response:

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);
  });
}
  • Related