diff --git a/exampleSite/layouts/partials/toc.html b/exampleSite/layouts/partials/toc.html index b941c66081..c4f9a5e527 100644 --- a/exampleSite/layouts/partials/toc.html +++ b/exampleSite/layouts/partials/toc.html @@ -1,5 +1,3 @@ -
-
{{- if eq .Kind "taxonomy" }}
-
\ No newline at end of file +{{- end }} \ No newline at end of file diff --git a/layouts/partials/header.html b/layouts/partials/header.html index c715968a00..fb3d4f041a 100644 --- a/layouts/partials/header.html +++ b/layouts/partials/header.html @@ -67,6 +67,7 @@
+
{{- $hook := "styleclass" }} +
{{- define "breadcrumb" }} diff --git a/layouts/partials/toc-class.html b/layouts/partials/toc-class.html new file mode 100644 index 0000000000..de368cf849 --- /dev/null +++ b/layouts/partials/toc-class.html @@ -0,0 +1,3 @@ +{{- $toc_content := partial "toc.html" . }} +{{- $toc_content = strings.Replace $toc_content "id=\"TableOfContents\"" "class=\"TableOfContents\"" 1 }} +{{- $toc_content | safeHTML }} \ No newline at end of file diff --git a/layouts/partials/toc.html b/layouts/partials/toc.html index 93c41dfb57..0c0fcbef1d 100644 --- a/layouts/partials/toc.html +++ b/layouts/partials/toc.html @@ -1,5 +1,3 @@ -
-
{{- if eq .Kind "taxonomy" }} {{- else }} {{- .TableOfContents }} -{{- end }} -
-
\ No newline at end of file +{{- end }} \ No newline at end of file diff --git a/layouts/partials/topbar-button.html b/layouts/partials/topbar-button.html index 5d02208e78..30bad872de 100644 --- a/layouts/partials/topbar-button.html +++ b/layouts/partials/topbar-button.html @@ -22,13 +22,14 @@ {{- if and $icon (not (findRE ".*?\\bfa-\\w.*?" $icon)) }} {{- $icon = printf "fa-fw fas fa-%s" $icon }} {{- end }} +{{- $content := .content }}
{{- if $isDisabled }} - + {{- else if $isButton }} - + {{- else }} +{{- end }} +{{- if $content }} +
+
+ {{- $content }} +
+
{{- end }}
\ No newline at end of file diff --git a/static/css/ie.css b/static/css/ie.css index 4fe4bb72ee..57134f86b5 100644 --- a/static/css/ie.css +++ b/static/css/ie.css @@ -70,10 +70,10 @@ border-top-right-radius: 0; border-right-width: 0; } - .topbar-left .topbar-button > * { + .topbar-left .topbar-button > .topbar-button-control { border-right: 1px solid rgba( 134, 134, 134, .333 ); } - .topbar-right .topbar-button > * { + .topbar-right .topbar-button > .topbar-button-control { border-left: 1px solid rgba( 134, 134, 134, .333 ); } #body .topbar-sidebar-divider { @@ -85,14 +85,9 @@ html[dir="rtl"] .topbar-next i { transform: scaleX(1); } - .progress { + .topbar-button-flyout { left: 1rem; } - @media screen and (max-width: 48rem) { - .progress { - left: 4.25rem; - } - } @media screen and (max-width: 60rem) { #body { margin-left: 14.375rem; @@ -572,7 +567,7 @@ border-color: rgba( 125, 201, 3, 1 ); /* var(--MENU-HEADER-SEPARATOR-color) */ } - .progress { + .topbar-button-flyout { background-color: rgba( 255, 255, 255, 1 ); /* var(--MAIN-BG-color) */ } diff --git a/static/css/theme.css b/static/css/theme.css index 21f6660adc..425c09cb8d 100644 --- a/static/css/theme.css +++ b/static/css/theme.css @@ -401,9 +401,9 @@ dd { .topbar-breadcrumbs a:hover *, .topbar-breadcrumbs a:active *, .topbar-breadcrumbs a:focus *, -.toc-wrapper a:hover, -.toc-wrapper a:active, -.toc-wrapper a:focus, +.topbar-button-flyout a:hover, +.topbar-button-flyout a:active, +.topbar-button-flyout a:focus, article a:hover, article a:active, article a:focus { @@ -989,15 +989,15 @@ td { position: relative; } -.topbar-button > * { +.topbar-button > .topbar-button-control { display: inline-block; padding-left: 1rem; padding-right: 1rem; } -.topbar-left .topbar-button > * { +.topbar-left .topbar-button > .topbar-button-control { border-inline-end: 1px solid rgba( 134, 134, 134, .333 ); } -.topbar-right .topbar-button > * { +.topbar-right .topbar-button > .topbar-button-control { border-inline-start: 1px solid rgba( 134, 134, 134, .333 ); } @@ -1048,14 +1048,14 @@ html[dir="rtl"] .topbar-next i { } } -.progress { - inset-inline-start: 1rem; - top: 1rem; +.topbar-button-flyout { + top: .75rem; } -@media screen and (max-width: 48rem) { - .progress { - inset-inline-start: 4.25rem; - } +.topbar-left .topbar-button-flyout { + inset-inline-start: 1.5rem; +} +.topbar-right .topbar-button-flyout { + inset-inline-end: 1.5rem; } .topbar-breadcrumbs { @@ -1135,7 +1135,7 @@ html[dir="rtl"] .topbar-next i { margin-inline-start: 14.375rem; overflow: hidden; } - .mobile-support.sidebar-flyout #sidebar-overlay{ + .mobile-support.sidebar-flyout #body-overlay{ background-color: rgba( 134, 134, 134, .5 ); bottom: 0; cursor: pointer; @@ -1360,10 +1360,9 @@ html[dir="rtl"] .expand > .expand-label > i.fa-chevron-right { /* Table of contents */ -.toc-flyout #toc-overlay{ +.topbar-flyout #main-overlay{ bottom: 0; cursor: pointer; - height: calc(100vh - 3rem); left: 0; position: absolute; right: 0; @@ -1371,7 +1370,7 @@ html[dir="rtl"] .expand > .expand-label > i.fa-chevron-right { z-index: 160; } -.progress { +.topbar-button-flyout { border: 0 solid rgba( 134, 134, 134, .166 ); box-shadow: 1px 2px 5px 1px rgba( 134, 134, 134, .2 ); height: 0; @@ -1382,33 +1381,48 @@ html[dir="rtl"] .expand > .expand-label > i.fa-chevron-right { z-index: 180; } -.toc-flyout .progress { +.topbar-button.topbar-flyout .topbar-button-flyout { border-width: 1px; height: auto; opacity: 1; width: auto; } -.progress .toc-wrapper { +.topbar-button-flyout .topbar-button-flyout-wrapper { background-color: rgba( 134, 134, 134, .066 ); } -.progress ul { +.topbar-button-flyout-wrapper { + --ps-rail-hover-color: rgba( 176, 176, 176, .25 ); + max-height: 90vh; + overflow: hidden; + padding: 1rem 1rem; + position: relative; /* PS */ +} + +#TableOfContents, +.TableOfContents { + font-size: .8125rem; +} +#TableOfContents ul, +.TableOfContents ul { list-style: none; margin: 0; padding: 0 1rem; } -#TableOfContents { - --ps-rail-hover-color: rgba( 176, 176, 176, .25 ); - font-size: .8125rem !important; - max-height: 90vh; - overflow: hidden; - padding: 1rem .375rem !important; - position: relative; /* PS */ +#TableOfContents > ul, +.TableOfContents > ul { + padding: 0; } -#TableOfContents > ul > li > a { +#TableOfContents li, +.TableOfContents li { + white-space: nowrap; +} + +#TableOfContents > ul > li > a, +.TableOfContents > ul > li > a { font-weight: 500; } diff --git a/static/css/variant.css b/static/css/variant.css index 41bd1ff030..c7b6821fca 100644 --- a/static/css/variant.css +++ b/static/css/variant.css @@ -318,7 +318,7 @@ pre .copy-to-clipboard-button:hover { border-color: var(--INTERNAL-MENU-HEADER-SEPARATOR-color); } -.progress { +.topbar-button-flyout { background-color: var(--INTERNAL-MAIN-BG-color); } diff --git a/static/js/theme.js b/static/js/theme.js index 2fd1bf274d..c1cbbfa99d 100644 --- a/static/js/theme.js +++ b/static/js/theme.js @@ -34,7 +34,7 @@ var formelements = 'button, datalist, fieldset, input, label, legend, meter, opt // PerfectScrollbar var psc; var psm; -var pst; +var pst = new Map(); var elc = document.querySelector('#body-inner'); function regexEscape( s ){ @@ -709,7 +709,7 @@ function initMenuScrollbar(){ } var elm = document.querySelector('#content-wrapper'); - var elt = document.querySelector('#TableOfContents'); + var elt = document.querySelector('.topbar-button.topbar-flyout .topbar-button-flyout-wrapper'); var autofocus = true; document.addEventListener('keydown', function(event){ @@ -737,10 +737,11 @@ function initMenuScrollbar(){ // if we are showing the sidebar as a flyout we // want to scroll the content-wrapper, otherwise we want // to scroll the body - var nt = document.querySelector('body').matches('.toc-flyout'); + var nt = document.querySelector('body').matches('.topbar-flyout'); var nm = document.querySelector('body').matches('.sidebar-flyout'); if( nt ){ - pst && pst.scrollbarY.focus(); + var psb = pst.get( document.querySelector('.topbar-button.topbar-flyout') ); + psb && psb.scrollbarY.focus(); } else if( nm ){ psm && psm.scrollbarY.focus(); @@ -756,7 +757,15 @@ function initMenuScrollbar(){ // PSC removed for #242 #243 #244 // psc = elc && new PerfectScrollbar('#body-inner'); psm = elm && new PerfectScrollbar('#content-wrapper'); - pst = elt && new PerfectScrollbar('#TableOfContents'); + document.querySelectorAll('.topbar-button .topbar-button-flyout-wrapper').forEach( function( e ){ + var button = getTopbarButtonParent( e ); + if( !button ){ + return; + } + pst.set( button, new PerfectScrollbar( e ) ); + e.addEventListener( 'click', toggleTopbarFlyoutEvent ); + }); + document.addEventListener('keydown', function(){ // if we facked initial scrolling, we want to // remove the focus to not leave visual markers on @@ -764,14 +773,18 @@ function initMenuScrollbar(){ if( autofocus ){ psc && psc.scrollbarY.blur(); psm && psm.scrollbarY.blur(); - pst && pst.scrollbarY.blur(); + pst.forEach( function( psb ){ + psb.scrollbarY.blur(); + }); autofocus = false; } }); // on resize, we have to redraw the scrollbars to let new height // affect their size window.addEventListener('resize', function(){ - pst && setTimeout( function(){ pst.update(); }, 10 ); + pst.forEach( function( psb ){ + setTimeout( function(){ psb.update(); }, 10 ); + }); psm && setTimeout( function(){ psm.update(); }, 10 ); psc && setTimeout( function(){ psc.update(); }, 10 ); }); @@ -784,7 +797,9 @@ function initMenuScrollbar(){ }); // bugfix for PS in RTL mode: the initial scrollbar position is off; // calling update() once, fixes this - pst && setTimeout( function(){ pst.update(); }, 10 ); + pst.forEach( function( psb ){ + setTimeout( function(){ psb.update(); }, 10 ); + }); psm && setTimeout( function(){ psm.update(); }, 10 ); psc && setTimeout( function(){ psc.update(); }, 10 ); @@ -800,27 +815,9 @@ function imageEscapeHandler( event ){ } } -function sidebarEscapeHandler( event ){ - if( event.key == "Escape" ){ - var b = document.querySelector( 'body' ); - b.classList.remove( 'sidebar-flyout' ); - document.removeEventListener( 'keydown', sidebarEscapeHandler ); - documentFocus(); - } -} - -function tocEscapeHandler( event ){ - if( event.key == "Escape" ){ - var b = document.querySelector( 'body' ); - b.classList.remove( 'toc-flyout' ); - document.removeEventListener( 'keydown', tocEscapeHandler ); - documentFocus(); - } -} - -function sidebarShortcutHandler( event ){ +function navShortcutHandler( event ){ if( !event.shiftKey && event.altKey && event.ctrlKey && !event.metaKey && event.which == 78 /* n */ ){ - showNav(); + toggleNav(); } } @@ -832,7 +829,7 @@ function searchShortcutHandler( event ){ function tocShortcutHandler( event ){ if( !event.shiftKey && event.altKey && event.ctrlKey && !event.metaKey && event.which == 84 /* t */ ){ - showToc(); + toggleToc(); } } @@ -856,55 +853,127 @@ function showSearch(){ var b = document.querySelector( 'body' ); if( s == document.activeElement ){ if( b.classList.contains( 'sidebar-flyout' ) ){ - showNav(); + closeNav(); } documentFocus(); } else { if( !b.classList.contains( 'sidebar-flyout' ) ){ - showNav(); + openNav(); } s.focus(); } } -function showNav(){ - if( !document.querySelector( '#sidebar-overlay' ) ){ - // we may not have a flyout - return; - } +function openNav(){ + closeSomeTopbarButtonFlyout(); var b = document.querySelector( 'body' ); - b.classList.toggle( 'sidebar-flyout' ); - if( b.classList.contains( 'sidebar-flyout' ) ){ - b.classList.remove( 'toc-flyout' ); - document.removeEventListener( 'keydown', tocEscapeHandler ); - document.addEventListener( 'keydown', sidebarEscapeHandler ); - } - else{ - document.removeEventListener( 'keydown', sidebarEscapeHandler ); - documentFocus(); + b.classList.add( 'sidebar-flyout' ); + psm && setTimeout( function(){ psm.update(); }, 10 ); + psm && psm.scrollbarY.focus(); + var a = document.querySelector( '#sidebar a' ) + if( a ){ + a.focus(); } } -function showToc(){ - var t = document.querySelector( '.topbar-toc' ); - if( !t ){ - // we may not have a toc - return; - } +function closeNav(){ var b = document.querySelector( 'body' ); - b.classList.toggle( 'toc-flyout' ); - if( b.classList.contains( 'toc-flyout' ) ){ - pst && setTimeout( function(){ pst.update(); }, 10 ); - pst && pst.scrollbarY.focus(); - document.querySelector( '.toc-wrapper ul a' ).focus(); - document.addEventListener( 'keydown', tocEscapeHandler ); + b.classList.remove( 'sidebar-flyout' ); + documentFocus(); +} + +function toggleNav(){ + var b = document.querySelector( 'body' ); + if( b.classList.contains( 'sidebar-flyout' ) ){ + closeNav(); } else{ - document.removeEventListener( 'keydown', tocEscapeHandler ); - documentFocus(); + openNav(); } } +function navEscapeHandler( event ){ + if( event.key == "Escape" ){ + closeNav(); + } +} + +function getTopbarButtonParent( e ){ + var button = e; + while( button && !button.classList.contains( 'topbar-button' ) ){ + button = button.parentElement; + } + return button; +} + +function openTopbarButtonFlyout( button ){ + closeNav(); + var body = document.querySelector( 'body' ); + button.classList.add( 'topbar-flyout' ); + body.classList.add( 'topbar-flyout' ); + var psb = pst.get( button ); + psb && setTimeout( function(){ psb.update(); }, 10 ); + psb && psb.scrollbarY.focus(); + var a = button.querySelector( '.topbar-button-flyout-wrapper a' ); + if( a ){ + a.focus(); + } +} + +function closeTopbarButtonFlyout( button ){ + var body = document.querySelector( 'body' ); + button.classList.remove( 'topbar-flyout' ); + body.classList.remove( 'topbar-flyout' ); + documentFocus(); +} + +function closeSomeTopbarButtonFlyout(){ + var someButton = document.querySelector( '.topbar-button.topbar-flyout' ); + if( someButton ){ + closeTopbarButtonFlyout( someButton ); + }; + return someButton +} + +function toggleTopbarButtonFlyout( button ){ + var someButton = closeSomeTopbarButtonFlyout(); + if( button && button != someButton ){ + openTopbarButtonFlyout( button ); + } +} + +function toggleTopbarFlyout( e ){ + var button = getTopbarButtonParent( e ); + if( !button ){ + return; + } + toggleTopbarButtonFlyout( button ); +} + +function toggleTopbarFlyoutEvent( event ){ + if( event.target.classList.contains( 'topbar-button-flyout' ) + || event.target.classList.contains( 'topbar-button-flyout-wrapper' ) + || event.target.classList.contains( 'ps__rail-x' ) + || event.target.classList.contains( 'ps__rail-y' ) + || event.target.classList.contains( 'ps__thumb-x' ) + || event.target.classList.contains( 'ps__thumb-y' ) + ){ + // the scrollbar was used, don't close flyout + return; + } + toggleTopbarFlyout( event.target ) +} + +function topbarFlyoutEscapeHandler( event ){ + if( event.key == "Escape" ){ + closeSomeTopbarButtonFlyout(); + } +} + +function toggleToc(){ + toggleTopbarButtonFlyout( document.querySelector( '.topbar-toc' ) ); +} + function showEdit(){ var l = document.querySelector( '.topbar-edit a' ); if( l ){ @@ -935,21 +1004,20 @@ function initToc(){ } document.addEventListener( 'keydown', editShortcutHandler ); + document.addEventListener( 'keydown', navShortcutHandler ); document.addEventListener( 'keydown', printShortcutHandler ); - document.addEventListener( 'keydown', sidebarShortcutHandler ); document.addEventListener( 'keydown', searchShortcutHandler ); document.addEventListener( 'keydown', tocShortcutHandler ); + document.addEventListener( 'keydown', navEscapeHandler ); + document.addEventListener( 'keydown', topbarFlyoutEscapeHandler ); - var s = document.querySelector( '#sidebar-overlay' ); - if( s ){ - s.addEventListener( 'click', showNav ); + var b = document.querySelector( '#body-overlay' ); + if( b ){ + b.addEventListener( 'click', closeNav ); } - var o = document.querySelector( '#toc-overlay' ); - var p = document.querySelector( '.progress' ); - if( o && p ){ - // we may not have a toc - o.addEventListener( 'click', showToc ); - p.addEventListener( 'click', showToc ); + var m = document.querySelector( '#main-overlay' ); + if( m ){ + m.addEventListener( 'click', closeSomeTopbarButtonFlyout ); } // finally give initial focus to allow keyboard scrolling in FF @@ -980,10 +1048,7 @@ function initSwipeHandler(){ else if( diffx > 30 ){ startx = null; starty = null; - var b = document.querySelector( 'body' ); - b.classList.remove( 'sidebar-flyout' ); - document.removeEventListener( 'keydown', sidebarEscapeHandler ); - documentFocus(); + closeNav(); } } return false; @@ -994,7 +1059,7 @@ function initSwipeHandler(){ return false; }; - var s = document.querySelector( '#sidebar-overlay' ); + var s = document.querySelector( '#body-overlay' ); s && s.addEventListener("touchstart", handleStartX, false); document.querySelector( '#sidebar' ).addEventListener("touchstart", handleStartX, false); document.querySelectorAll( '#sidebar *' ).forEach( function(e){ e.addEventListener("touchstart", handleStartX); }, false);