Scrolling doesn't open tocify menu items
- [x] I confirm that I have read and attempted the tips in the Troubleshooting Guide.
What happened? I'm using the latest version of Scribe and when scrolling through the api docs, the tocify menu doesn't automatically highlight the current page or open submenus.
Scrolling works in the demo on https://demo.scribe.knuckles.wtf/ but that is running a much older version. I think it broke when we upgraded from 3.16 to 3.21.
My environment:
- PHP version (from
php -v): 8.0.14 - Framework (Laravel/Lumen): Laravel
- Laravel/Lumen version (from
composer show laravel/frameworkorcomposer show laravel/lumen-framework): 8.76.1 - Scribe version (from
composer show knuckleswtf/scribe): 3.23.0
My Scribe config (minus the comments):
[
"theme" => "default",
"title" => "API Documentation",
"description" => "",
"base_url" => null,
"routes" => [
[
"match" => [
"domains" => [
"*",
],
"prefixes" => [
"api/*",
],
"versions" => [
"v1",
],
],
"include" => [],
"exclude" => [],
"apply" => [
"headers" => [
"Content-Type" => "application/json",
"Accept" => "application/json",
],
"response_calls" => [
"methods" => [],
"config" => [
"app.env" => "documentation",
],
"queryParams" => [],
"bodyParams" => [],
"fileParams" => [],
"cookies" => [],
],
],
],
],
"type" => "laravel",
"static" => [
"output_path" => "public/docs",
],
"laravel" => [
"add_routes" => false,
"docs_url" => "/api-documentation",
"middleware" => [],
],
"try_it_out" => [
"enabled" => false,
"base_url" => null,
"use_csrf" => false,
"csrf_url" => "/sanctum/csrf-cookie",
],
"auth" => [
"enabled" => true,
"default" => true,
"in" => "bearer",
"name" => "key",
"use_value" => null,
"placeholder" => "{API_TOKEN}",
"extra_info" => "",
],
"intro_text" => """
This documentation provides all the information you need to work with our API.\n
\n
<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).\n
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>
""",
"example_languages" => [
"bash",
"javascript",
"python",
"php",
],
"postman" => [
"enabled" => true,
"overrides" => [],
],
"openapi" => [
"enabled" => true,
"overrides" => [],
],
"default_group" => "Endpoints",
"logo" => false,
"faker_seed" => null,
"strategies" => [
"metadata" => [
"Knuckles\Scribe\Extracting\Strategies\Metadata\GetFromDocBlocks",
],
"urlParameters" => [
"Knuckles\Scribe\Extracting\Strategies\UrlParameters\GetFromLaravelAPI",
"Knuckles\Scribe\Extracting\Strategies\UrlParameters\GetFromLumenAPI",
],
"queryParameters" => [
"Knuckles\Scribe\Extracting\Strategies\QueryParameters\GetFromFormRequest",
"Knuckles\Scribe\Extracting\Strategies\QueryParameters\GetFromInlineValidator",
"Knuckles\Scribe\Extracting\Strategies\QueryParameters\GetFromQueryParamTag",
"App\Http\Api\Docs\Strategies\AddFilterParam",
"App\Http\Api\Docs\Strategies\AddSortParam",
"App\Http\Api\Docs\Strategies\AddIncludeParam",
],
"headers" => [
"Knuckles\Scribe\Extracting\Strategies\Headers\GetFromRouteRules",
"Knuckles\Scribe\Extracting\Strategies\Headers\GetFromHeaderTag",
],
"bodyParameters" => [
"Knuckles\Scribe\Extracting\Strategies\BodyParameters\GetFromFormRequest",
"Knuckles\Scribe\Extracting\Strategies\BodyParameters\GetFromInlineValidator",
"Knuckles\Scribe\Extracting\Strategies\BodyParameters\GetFromBodyParamTag",
],
"responses" => [
"Knuckles\Scribe\Extracting\Strategies\Responses\UseTransformerTags",
"Knuckles\Scribe\Extracting\Strategies\Responses\UseResponseTag",
"Knuckles\Scribe\Extracting\Strategies\Responses\UseResponseFileTag",
"Knuckles\Scribe\Extracting\Strategies\Responses\UseApiResourceTags",
"Knuckles\Scribe\Extracting\Strategies\Responses\ResponseCalls",
"App\Http\Api\Docs\Strategies\AddExampleResponses",
"App\Http\Api\Docs\Strategies\AddPaginatedExampleResponses",
],
"responseFields" => [
"Knuckles\Scribe\Extracting\Strategies\ResponseFields\GetFromResponseFieldTag",
],
],
"fractal" => [
"serializer" => null,
],
"routeMatcher" => "Knuckles\Scribe\Matching\RouteMatcher",
"database_connections_to_transact" => [
"mysql",
"mysql",
],
]
Additional info:
@bjhijmans @shalvah its ref to #395 Probably, it doesn't need.
No, that issue was solved. This is a known missing feature caused by a refactor/improvement we made to the sidebar. See https://github.com/knuckleswtf/scribe/pull/377.
In the grand scheme of things, It's a nice-to-have, so I prioritised more important fixes. PRs are welcome.
More details:
https://github.com/knuckleswtf/scribe/pull/354 did a refactor of the sidebar to improve its performance and fix some longstanding issues. Unforunately, it introduced a few bugs, notably https://github.com/knuckleswtf/scribe/issues/374, which I fixed in https://github.com/knuckleswtf/scribe/pull/376.
But I had to remove the scroll-tracking feature in https://github.com/knuckleswtf/scribe/commit/8c66bfd3db75df2514411e9ecd3da93372d74d68, because it wasn't working properly and causing https://github.com/knuckleswtf/scribe/issues/395. We need to find a way to redo it.
I managed to get this working correctly using a snip from here with little modification
const divs = document.querySelectorAll('.tocify-wrapper div[id]');
document.addEventListener('scroll', (e) => {
divs.forEach(items => {
const rect = items.getBoundingClientRect();
if (rect.top > 0 && rect.top < 150) {
const location = window.location.toString().split('#')[0];
history.replaceState(null, null, location + '#' + items.id);
hashChange()
}
});
});
Hope it helps
The code added by shopisaur works for me. Can someone please add it to the next release?
I tried the https://github.com/knuckleswtf/scribe/issues/422#issuecomment-1083593968 , in v4... and the scroll doesn't work...
I used the following in the latest version of scribe v4 based on what @shopisaur posted:
const divs = document.querySelectorAll('.content h1[id], .content h2[id]');
document.addEventListener('scroll', (e) => {
divs.forEach(item => {
const rect = item.getBoundingClientRect();
if (rect.top > 0 && rect.top < 150) {
const location = window.location.toString().split('#')[0];
history.replaceState(null, null, location + '#' + item.id);
dispatchEvent(new Event('hashchange'));
}
});
});
Nice, that seems to work. I could never figure that out myself, dealing with bounding boxes and whatnot. The UI part of web dev is not my forte 😅 . Can you PR this so we can finally close this issue? @bjhijmans