diff --git a/lib/assets/javascripts/_modules/collapsible-navigation.js b/lib/assets/javascripts/_modules/collapsible-navigation.js index 4e4f6426..0d8baad4 100644 --- a/lib/assets/javascripts/_modules/collapsible-navigation.js +++ b/lib/assets/javascripts/_modules/collapsible-navigation.js @@ -57,25 +57,31 @@ $toggleLabel.text(setOpen ? 'Collapse ' + $heading.text() : 'Expand ' + $heading.text()) } + /** + * Returns an absolute pathname to $target by combining it with window.location.href + * @param $target The target whose pathname to return. This may be an anchor with an absolute or relative href. + * @returns {string} The absolute pathname of $target + */ + function getAbsolutePath ($target) { + return new URL($target.attr('href'), window.location.href).pathname + } + function openActiveHeading () { var $activeElement var currentPath = window.location.pathname - var isActiveTrail = '[href*="' + currentPath + '"]' - // Add an exception for the root page, as every href includes / - if (currentPath === '/') { - isActiveTrail = '[href="' + currentPath + window.location.hash + '"]' - } for (var i = $topLevelItems.length - 1; i >= 0; i--) { var $element = $($topLevelItems[i]) var $heading = $element.find('> a') // Check if this item href matches - if ($heading.is(isActiveTrail)) { + if (getAbsolutePath($heading) === currentPath) { $activeElement = $element break } // Otherwise check the children var $children = $element.find('li > a') - var $matchingChildren = $children.filter(isActiveTrail) + var $matchingChildren = $children.filter(function (_) { + return getAbsolutePath($(this)) === currentPath + }) if ($matchingChildren.length) { $activeElement = $element break diff --git a/lib/assets/javascripts/_modules/in-page-navigation.js b/lib/assets/javascripts/_modules/in-page-navigation.js index 8274c876..0848bfb6 100644 --- a/lib/assets/javascripts/_modules/in-page-navigation.js +++ b/lib/assets/javascripts/_modules/in-page-navigation.js @@ -70,13 +70,18 @@ function highlightActiveItemInToc (fragment) { // Navigation items for single page navigation don't necessarily include the path name, but // navigation items for multipage navigation items do include it. This checks for either case. - var $activeTocItem = $tocItems.filter( - '[href="' + window.location.pathname + fragment + '"],[href="' + fragment + '"]' - ) + var $activeTocItem = $tocItems.filter(function (_) { + var url = new URL($(this).attr('href'), window.location.href) + return url.href === window.location.href + }) + // Navigation items with children don't contain fragments in their url // Check to see if any nav items contain just the path name. if (!$activeTocItem.get(0)) { - $activeTocItem = $tocItems.filter('[href="' + window.location.pathname + '"]') + $activeTocItem = $tocItems.filter(function (_) { + var url = new URL($(this).attr('href'), window.location.href) + return url.hash === '' && url.pathname === window.location.pathname + }) } if ($activeTocItem.get(0)) { $tocItems.removeClass('toc-link--in-view') diff --git a/lib/assets/javascripts/_modules/search.js b/lib/assets/javascripts/_modules/search.js index 48f6a0b0..0fa20ecf 100644 --- a/lib/assets/javascripts/_modules/search.js +++ b/lib/assets/javascripts/_modules/search.js @@ -16,7 +16,7 @@ var results var query var maxSearchEntries = 20 - var searchIndexPath + var pathToSiteRoot this.start = function start ($element) { $searchForm = $element.find('form') @@ -26,7 +26,7 @@ $searchResults = $searchResultsWrapper.find('.search-results__content') $searchResultsTitle = $searchResultsWrapper.find('.search-results__title') $searchHelp = $('#search-help') - searchIndexPath = $element.data('searchIndexPath') + pathToSiteRoot = $element.data('pathToSiteRoot') changeSearchAction() changeSearchLabel() @@ -40,7 +40,7 @@ query = s.getQuery() if (query) { $searchInput.val(query) - doSearch(query) + doSearch(query, pathToSiteRoot) doAnalytics() document.title = query + ' - ' + document.title } @@ -51,7 +51,7 @@ this.downloadSearchIndex = function downloadSearchIndex () { updateTitle('Loading search results') $.ajax({ - url: searchIndexPath, + url: pathToSiteRoot + 'search.json', cache: true, method: 'GET', success: function (data) { @@ -67,7 +67,7 @@ // We need JavaScript to do search, so if JS is not available the search // input sends the query string to Google. This JS function changes the // input to instead send it to the search page. - $searchForm.prop('action', '/search') + $searchForm.prop('action', pathToSiteRoot + 'search/index.html') $searchForm.find('input[name="as_sitesearch"]').remove() } @@ -88,10 +88,10 @@ return query } - function doSearch (query) { + function doSearch (query, pathToSiteRoot) { s.search(query, function (r) { results = r - renderResults(query) + renderResults(query, pathToSiteRoot) updateTitle() }) } @@ -140,7 +140,7 @@ callback(getResults(query)) } - function renderResults (query) { + function renderResults (query, pathToSiteRoot) { var output = '' if (results.length === 0) { output += '
Nothing found
' @@ -151,7 +151,9 @@ var content = s.processContent(result.content, query) output += '