| // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:js_interop'; |
| |
| import 'package:web/web.dart'; |
| |
| import 'search.dart' show ElementExtension; |
| |
| /// Initialize the sidebar contents and sidenav toggle handlers. |
| void init() { |
| _initializeContents(); |
| _initializeToggles(); |
| } |
| |
| void _initializeToggles() { |
| final leftNavToggle = document.getElementById('sidenav-left-toggle'); |
| final leftDrawer = document.querySelector('.sidebar-offcanvas-left'); |
| final overlayElement = document.getElementById('overlay-under-drawer'); |
| |
| final toggleDrawerAndOverlay = (Event _) { |
| leftDrawer?.classList.toggle('active'); |
| overlayElement?.classList.toggle('active'); |
| }.toJS; |
| |
| overlayElement?.addEventListener('click', toggleDrawerAndOverlay); |
| leftNavToggle?.addEventListener('click', toggleDrawerAndOverlay); |
| } |
| |
| void _initializeContents() { |
| final body = document.body; |
| if (body == null) { |
| return; |
| } |
| |
| final dataUsingBaseHref = body.getAttribute('data-using-base-href'); |
| if (dataUsingBaseHref == null) { |
| // This should never happen. |
| assert(false, '"data-using-base-href" attribute on "body" is null.'); |
| return; |
| } |
| |
| final String baseHref; |
| if (dataUsingBaseHref != 'true') { |
| final dataBaseHref = body.getAttribute('data-base-href'); |
| if (dataBaseHref == null) { |
| return; |
| } |
| baseHref = dataBaseHref; |
| } else { |
| baseHref = ''; |
| } |
| |
| final mainContent = document.getElementById('dartdoc-main-content'); |
| if (mainContent == null) { |
| return; |
| } |
| |
| final aboveSidebarPath = mainContent.getAttribute('data-above-sidebar'); |
| final leftSidebar = document.getElementById('dartdoc-sidebar-left-content'); |
| _loadSidebar(baseHref, aboveSidebarPath, leftSidebar); |
| |
| final belowSidebarPath = mainContent.getAttribute('data-below-sidebar'); |
| final rightSidebar = document.getElementById('dartdoc-sidebar-right'); |
| _loadSidebar(baseHref, belowSidebarPath, rightSidebar); |
| } |
| |
| void _loadSidebar( |
| String baseHref, |
| String? sidebarPath, |
| Element? sidebarElement, |
| ) { |
| if (sidebarPath == null || sidebarPath.isEmpty || sidebarElement == null) { |
| return; |
| } |
| |
| window.fetch('$baseHref$sidebarPath'.toJS).toDart.then((fetchResponse) async { |
| if (fetchResponse.status != HttpStatus.ok) { |
| final errorAnchor = HTMLAnchorElement() |
| ..href = 'https://dart.dev/tools/dart-doc#troubleshoot' |
| ..text = 'Failed to load sidebar. ' |
| 'Visit dart.dev for help troubleshooting.'; |
| sidebarElement.appendChild(errorAnchor); |
| return; |
| } |
| |
| final responseText = (await fetchResponse.text().toDart).toDart; |
| final sidebarContent = HTMLDivElement()..innerHtml = responseText; |
| |
| _updateLinks(baseHref, sidebarContent); |
| sidebarElement.appendChild(sidebarContent); |
| }); |
| } |
| |
| /// Recurses down a DOM tree to adjust the links in a newly loaded sidebar |
| /// if "base href" is not being used. |
| void _updateLinks(String baseHref, Node node) { |
| if (node.isA<HTMLAnchorElement>()) { |
| final hrefValue = |
| (node as HTMLAnchorElement).attributes.getNamedItem('href')?.value; |
| if (hrefValue == null) { |
| return; |
| } |
| final href = Uri.tryParse(hrefValue); |
| if (href != null && !href.isAbsolute) { |
| node.href = '$baseHref$hrefValue'; |
| } |
| } |
| |
| final children = node.childNodes; |
| for (var childIndex = 0; childIndex < children.length; childIndex += 1) { |
| if (children.item(childIndex) case final child?) { |
| _updateLinks(baseHref, child); |
| } |
| } |
| } |