import 'dart:html' show querySelector, Element, window;
import 'dart:svg' show SvgElement;
// You will see here and there some 'tabindex' attributes added to various HTML
// elements, and I’m sure you will ask "Why? They don’t serve any purpose, do
// they?". Well you are wrong. Webkit has a **terrible** implementation of
// `:focus-within`, and the dropdowns will **not** work unless the parent
// element, in this case a `
` has a `tabindex` attribute set to `0` and its
// first child set to `-1`.
//
// Screw WebKit, and screw Apple for using such a terrible web engine.
// Icons from https://materialdesignicons.com/
final icons = {
'home': SvgElement.svg(
''),
'pages': SvgElement.svg(
''),
'toc': SvgElement.svg(
''),
'share': SvgElement.svg(
''),
'twitter': SvgElement.svg(
''),
'reddit': SvgElement.svg(
''),
'email': SvgElement.svg(
''),
'linkedin': SvgElement.svg(
''),
'facebook': SvgElement.svg(
''),
'theme': SvgElement.svg(
''),
};
// Get the current page’s title
String getPageTitle() => querySelector('title').text;
// Create the home button
Future makeHome() async {
return Element.li()
..classes.add('nav-item')
..insertAdjacentElement(
'afterBegin',
Element.a()
..attributes['href'] = '/'
..append(makeIcon(icons['home'])));
}
// Create a clickable icon
// `t_elem` must be an SVG declared in the above `icons` variable.
Element makeIcon(SvgElement t_elem) {
return t_elem..classes.add('nav-icon');
}
// Create the dropdown sitemap
Future makePages() async {
return Element.li()
..attributes['tabindex'] = '0'
..append(Element.a()
..attributes['tabindex'] = '-1'
..attributes['href'] = 'javascript:void(0)'
..append(makeIcon(icons['pages'])))
..classes.addAll(['nav-item', 'has-dropdown'])
..append(Element.ul()
..attributes['id'] = 'drop-page'
..classes.add('dropdown'));
}
// Create the array of share icons
Future makeShare() async {
// Create a share button
Element makeShareLink(Element t_icon, String t_url) {
return Element.li()
..classes.add('dropdown-item')
..append(Element.a()
..attributes['href'] = t_url
..attributes['target'] = '_blank'
..attributes['rel'] = 'noreferrer'
..append(t_icon));
}
return Element.li()
..classes.addAll(['nav-item', 'has-dropdown'])
..attributes['tabindex'] = '0'
..append(Element.a()
..attributes['href'] = 'javascript:void(0)'
..attributes['tabindex'] = '-1'
..append(makeIcon(icons['share'])))
..append(Element.ul()
..classes.add('dropdown')
..attributes['id'] = 'drop-share'
..append(makeShareLink(
makeIcon(icons['twitter']),
'https://twitter.com/share?text=${getPageTitle()}'
'&url=${window.location.href}'))
..append(makeShareLink(makeIcon(icons['reddit']),
'https://www.reddit.com/submit?title=${getPageTitle()}s&url=${window.location.href}'))
..append(makeShareLink(makeIcon(icons['email']),
'mailto:?subject=${getPageTitle}&body=${window.location.href}'))
..append(makeShareLink(
makeIcon(icons['linkedin']),
'https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}'
'&title=${getPageTitle()}'))
..append(makeShareLink(makeIcon(icons['facebook']),
'https://www.facebook.com/sharer/sharer.php?u=${window.location.href}')));
}
// Create the theme changer
Future makeThemeChanger() async {
Element makeThemeItem(String t_btnId) {
return Element.li()
..classes.add('dropdown-item')
..append(Element.span()
..attributes['id'] = t_btnId
..classes.add('themeBtn'));
}
return Element.li()
..classes.addAll(['nav-item', 'has-dropdown'])
..attributes['tabindex'] = '0'
..append(Element.a()
..attributes['href'] = 'javascript:void(0)'
..attributes['tabindex'] = '-1'
..append(Element.span()
..style.verticalAlign = 'top'
..append(makeIcon(icons['theme']))))
..append(Element.ul()
..classes.add('dropdown')
..attributes['id'] = 'theme-dropdown'
..append(makeThemeItem('lightBtn'))
..append(makeThemeItem('darkBtn'))
..append(makeThemeItem('nordBtn'))
..append(makeThemeItem('blackBtn')));
}
// Create the dropdown table of contents
Future makeToc() async {
return Element.li()
..attributes['id'] = 'toc-drop'
..attributes['tabindex'] = '0'
..classes.addAll(['nav-item', 'has-dropdown'])
..append(Element.a()
..attributes['tabindex'] = '-1'
..attributes['href'] = 'javascript:void(0)'
..append(makeIcon(icons['toc'])));
}
// Add a navbar atop of the HTML body, containing:
// - A back to home button
// - A dropdown sitemap
// - A dropdown table of contents
// - A dropdown array of share icons
// - A theme changer
Future makeNavbar() async {
final navbar_content = Element.ul()..classes.add('navbar-nav');
final home = await makeHome();
final pages = await makePages();
final toc = await makeToc();
final share = await makeShare();
final theme = await makeThemeChanger();
navbar_content
..append(home)
..append(pages)
..append(toc)
..append(share)
..append(theme);
// Navbar content added to navbar
final navbar = Element.nav()
..classes.add('navbar')
..append(navbar_content);
return navbar;
}