diff --git a/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php b/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php index 28ad2c04451158ac0b9ea891cca328c47ada2597..78a09a563a5b67755a994edbe53fe3e2bdfdad0a 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php +++ b/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php @@ -204,16 +204,15 @@ public static function setLinkActiveClass($html_markup, $current_path, $is_front } // The query parameters of an active link are equal to the current // parameters. - if ($add_active) { - if ($query) { - if (!$node->hasAttribute('data-drupal-link-query') || $node->getAttribute('data-drupal-link-query') !== Json::encode($query)) { - $add_active = FALSE; - } - } - else { - if ($node->hasAttribute('data-drupal-link-query')) { - $add_active = FALSE; - } + if ($add_active && $node->hasAttribute('data-drupal-link-query')) { + $query_match = empty(array_filter( + Json::decode($node->getAttribute('data-drupal-link-query')), + fn ($value, $key) => $value !== ($query[$key] ?? NULL), + ARRAY_FILTER_USE_BOTH + )); + + if (!$query_match) { + $add_active = FALSE; } } diff --git a/core/misc/active-link.js b/core/misc/active-link.js index 464e9a4044f0af4b7391edccd9ec48a623bfbe45..45fdcc25458f8ded715cae702c33a7a4f92e0c4e 100644 --- a/core/misc/active-link.js +++ b/core/misc/active-link.js @@ -22,14 +22,10 @@ attach(context) { // Start by finding all potentially active links. const path = drupalSettings.path; - const queryString = JSON.stringify(path.currentQuery); - const querySelector = queryString - ? `[data-drupal-link-query="${CSS.escape(queryString)}"]` - : ':not([data-drupal-link-query])'; + path.currentQuery = path.currentQuery ?? []; const originalSelectors = [ `[data-drupal-link-system-path="${CSS.escape(path.currentPath)}"]`, ]; - let selectors; // If this is the front page, we have to check for the <front> path as // well. @@ -38,7 +34,7 @@ } // Add language filtering. - selectors = [].concat( + const selectors = [].concat( // Links without any hreflang attributes (most of them). originalSelectors.map((selector) => `${selector}:not([hreflang])`), // Links with hreflang equals to the current language. @@ -47,16 +43,21 @@ ), ); - // Add query string selector for pagers, exposed filters. - selectors = selectors.map((current) => current + querySelector); - // Query the DOM. - const activeLinks = context.querySelectorAll(selectors.join(',')); - const il = activeLinks.length; - for (let i = 0; i < il; i++) { - activeLinks[i].classList.add('is-active'); - activeLinks[i].setAttribute('aria-current', 'page'); - } + context.querySelectorAll(selectors.join(',')).forEach(function (link) { + // Check if the link does not contain query parameters that + // don't match the current query. + const queryMatch = + !link.hasAttribute('data-drupal-link-query') || + !Object.entries( + JSON.parse(link.getAttribute('data-drupal-link-query')), + ).find(([key, value]) => value !== (path.currentQuery[key] || null)); + + if (queryMatch) { + link.classList.add('is-active'); + link.setAttribute('aria-current', 'page'); + } + }); }, detach(context, settings, trigger) { if (trigger === 'unload') {