From 870ffc83ed542e3c5369811650dc30148633e1d4 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Fri, 27 Mar 2026 15:08:01 -0500 Subject: [PATCH 1/3] Fix JS errors in doxygen navtree Fixes anchor links in some browsers and restores the navtree alongside the Table of Contents for several pages --- docs/doxygen/hdf5_navtree_hacks.js | 688 ++++++++++++++++++++++------- 1 file changed, 536 insertions(+), 152 deletions(-) diff --git a/docs/doxygen/hdf5_navtree_hacks.js b/docs/doxygen/hdf5_navtree_hacks.js index 804701f7f6f..31d396c0c40 100644 --- a/docs/doxygen/hdf5_navtree_hacks.js +++ b/docs/doxygen/hdf5_navtree_hacks.js @@ -1,3 +1,524 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +var global_navtree_object; + +// THG - Moved to wider scope +const ARROW_RIGHT = '►'; +const ARROW_DOWN = '▼'; + +// Modified to save the root node into global_navtree_object +function initNavTree(toroot,relpath) { + let navTreeSubIndices = []; + const NAVPATH_COOKIE_NAME = ''+'navpath'; + + const getData = function(varName) { + const i = varName.lastIndexOf('/'); + const n = i>=0 ? varName.substring(i+1) : varName; + return eval(n.replace(/-/g,'_')); + } + + const stripPath2 = function(uri) { + const i = uri.lastIndexOf('/'); + const s = uri.substring(i+1); + const m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; + } + + const hashValue = function() { + return $(location).attr('hash').substring(1).replace(/[^\w-]/g,''); + } + + const hashUrl = function() { + return '#'+hashValue(); + } + + const pathName = function() { + return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;()]/g, ''); + } + + const deleteLink = function() { + Cookie.eraseSetting(NAVPATH_COOKIE_NAME); + } + + const cachedLink = function() { + return Cookie.readSetting(NAVPATH_COOKIE_NAME,''); + } + + const getScript = function(scriptName,func) { + const head = document.getElementsByTagName("head")[0]; + const script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = func; + script.src = scriptName+'.js'; + head.appendChild(script); + } + + let animationInProgress = false; + + const gotoAnchor = function(anchor,aname) { + let pos, docContent = $('#doc-content'); + let ancParent = $(anchor.parent()); + if (ancParent.hasClass('memItemLeft') || ancParent.hasClass('memtitle') || + ancParent.hasClass('fieldname') || ancParent.hasClass('fieldtype') || + ancParent.is(':header')) { + pos = ancParent.offset().top; + } else if (anchor.position()) { + pos = anchor.offset().top; + } + if (pos) { + const dcOffset = docContent.offset().top; + const dcHeight = docContent.height(); + const dcScrHeight = docContent[0].scrollHeight + const dcScrTop = docContent.scrollTop(); + let dist = Math.abs(Math.min(pos-dcOffset,dcScrHeight-dcHeight-dcScrTop)); + animationInProgress = true; + docContent.animate({ + scrollTop: pos + dcScrTop - dcOffset + },Math.max(50,Math.min(500,dist)),function() { + animationInProgress=false; + if (anchor.parent().attr('class')=='memItemLeft') { + let rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); + glowEffect(rows.children(),300); // member without details + } else if (anchor.parent().attr('class')=='fieldname') { + glowEffect(anchor.parent().parent(),1000); // enum value + } else if (anchor.parent().attr('class')=='fieldtype') { + glowEffect(anchor.parent().parent(),1000); // struct field + } else if (anchor.parent().is(":header")) { + glowEffect(anchor.parent(),1000); // section header + } else { + glowEffect(anchor.next(),1000); // normal member + } + }); + } + } + + const showRoot = function() { + const headerHeight = $("#top").height(); + const footerHeight = $("#nav-path").height(); + const windowHeight = $(window).height() - headerHeight - footerHeight; + (function() { // retry until we can scroll to the selected item + try { + const navtree=$('#nav-tree'); + navtree.scrollTo('#selected',100,{offset:-windowHeight/2}); + } catch (err) { + setTimeout(arguments.callee, 0); + } + })(); + } + + const glowEffect = function(n,duration) { + n.addClass('glow').delay(duration).queue(function(next) { + $(this).removeClass('glow');next(); + }); + } + + const highlightAnchor = function() { + const aname = hashUrl(); + const anchor = $(aname); + gotoAnchor(anchor,aname); + } + + // THG - Overloaded to automatically expand the selected node + const selectAndHighlight = function(hash,n) { + let a; + if (hash) { + const link=stripPath(pathName())+':'+hash.substring(1); + a=$('.item a[class$="'+link+'"]'); + } + if (a && a.length) { + a.parent().parent().addClass('selected'); + a.parent().parent().attr('id','selected'); + highlightAnchor(); + } else if (n) { + $(n.itemDiv).addClass('selected'); + $(n.itemDiv).attr('id','selected'); + } + let topOffset=5; + if ($('#nav-tree-contents .item:first').hasClass('selected')) { + topOffset+=25; + } + $('#nav-sync').css('top',topOffset+'px'); + expandNode(global_navtree_object, n, true, true); // <- THG - we added this line + showRoot(); + } + + const showNode = function(o, node, index, hash) { + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + showNode(o,node,index,hash); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).css({'display':'block'}); + node.plus_img.innerHTML = ARROW_DOWN; + node.expanded = true; + const n = node.children[o.breadcrumbs[index]]; + if (index+11 ? '#'+parts[1].replace(/[^\w-]/g,'') : ''; + } + if (hash.match(/^#l\d+$/)) { + const anchor=$('a[name='+hash.substring(1)+']'); + glowEffect(anchor.parent(),1000); // line number + hash=''; // strip line number anchors + } + const url=root+hash; + let i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function() { + navTreeSubIndices[i] = eval('NAVTREEINDEX'+i); + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + }); + } + } + + const showSyncOff = function(n,relpath) { + n.html(''); + } + + const showSyncOn = function(n,relpath) { + n.html(''); + } + + const o = { + toroot : toroot, + node : { + childrenData : NAVTREE, + children : [], + childrenUL : document.createElement("ul"), + getChildrenUL : function() { return this.childrenUL }, + li : document.getElementById("nav-tree-contents"), + depth : 0, + relpath : relpath, + expanded : false, + isLast : true, + plus_img : document.createElement("img"), + }, + }; + o.node.li.appendChild(o.node.childrenUL); + // THG - Modified + // o.node.plus_img.className = 'arrow'; + // o.node.plus_img.innerHTML = ARROW_RIGHT; + o.node.plus_img.src = relpath+"ftv2pnode.png"; + o.node.plus_img.width = 16; + o.node.plus_img.height = 22; + + global_navtree_object = o; // <- THG - we added this line + + const navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.removeClass('sync'); + } else { + showSyncOn(navSync,relpath); + } + + navSync.click(() => { + const navSync = $('#nav-sync'); + if (navSync.hasClass('sync')) { + navSync.removeClass('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.addClass('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } + }); + + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + + $(window).bind('hashchange', () => { + if (!animationInProgress) { + if (window.location.hash && window.location.hash.length>1) { + let a; + if ($(location).attr('hash')) { + const clslink=stripPath(pathName())+':'+hashValue(); + a=$('.item a[class$="'+clslink.replace(/ storeLink(link); + } + } else if (childrenData != null) { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + return node; +} + +// THG - Moved to wider scope +const removeToInsertLater = function(element) { + const parentNode = element.parentNode; + const nextSibling = element.nextSibling; + parentNode.removeChild(element); + return function() { + if (nextSibling) { + parentNode.insertBefore(element, nextSibling); + } else { + parentNode.appendChild(element); + } + }; +} + +// THG - Moved to wider scope and modified to remove links to sections/subsections +const getNode = function(o, po) { + const insertFunction = removeToInsertLater(po.li); + po.childrenVisited = true; + const l = po.childrenData.length-1; + for (let i in po.childrenData) { + const nodeData = po.childrenData[i]; + if ((!nodeData[1]) || (nodeData[1].indexOf('#') == -1)) // <- THG - added this line + po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2], i==l); + } + insertFunction(); +} + +// THG - moved to wider scope +const expandNode = function(o, node, imm, setFocus) { + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + expandNode(o, node, imm, setFocus); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).slideDown("fast"); + node.plus_img.innerHTML = ARROW_DOWN; + node.expanded = true; + if (setFocus) { + $(node.expandToggle).focus(); + } + } + } +} +/* @license-end */ + +// return false if the node has no children at all, or has only section/subsection children +function checkChildrenData(node) { + if (!(typeof(node.childrenData)==='string')) { + for (var i in node.childrenData) { + var url = node.childrenData[i][1]; + if (url.indexOf("#")==-1) + return true; + } + return false; + } + return (node.childrenData); +} // generate a table of contents in the side-nav based on the h1/h2 tags of the current page. function generate_autotoc() { @@ -47,22 +568,7 @@ function generate_autotoc() { } } - -var global_navtree_object; - -// Overloaded to remove links to sections/subsections -function getNode(o, po) -{ - po.childrenVisited = true; - var l = po.childrenData.length-1; - for (var i in po.childrenData) { - var nodeData = po.childrenData[i]; - if((!nodeData[1]) || (nodeData[1].indexOf('#')==-1)) // <- we added this line - po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2], i==l); - } -} - -// Overloaded to adjust the size of the navtree wrt the toc +// Adjust the size of the navtree wrt the toc function resizeHeight() { var header = $("#top"); @@ -74,162 +580,39 @@ function resizeHeight() var headerHeight = header.outerHeight(); var footerHeight = footer.outerHeight(); - var tocHeight = toc.height(); var windowHeight = $(window).height() - headerHeight - footerHeight; + content.css({height:windowHeight + "px"}); - navtree.css({height:(windowHeight-tocHeight) + "px"}); sidenav.css({height:windowHeight + "px"}); -} -// Overloaded to save the root node into global_navtree_object -function initNavTree(toroot,relpath) -{ - var o = new Object(); - global_navtree_object = o; // <- we added this line - o.toroot = toroot; - o.node = new Object(); - o.node.li = document.getElementById("nav-tree-contents"); - o.node.childrenData = NAVTREE; - o.node.children = new Array(); - o.node.childrenUL = document.createElement("ul"); - o.node.getChildrenUL = function() { return o.node.childrenUL; }; - o.node.li.appendChild(o.node.childrenUL); - o.node.depth = 0; - o.node.relpath = relpath; - o.node.expanded = false; - o.node.isLast = true; - o.node.plus_img = document.createElement("img"); - o.node.plus_img.src = relpath+"ftv2pnode.png"; - o.node.plus_img.width = 16; - o.node.plus_img.height = 22; - - if (localStorageSupported()) { - var navSync = $('#nav-sync'); - if (cachedLink()) { - showSyncOff(navSync,relpath); - navSync.removeClass('sync'); - } else { - showSyncOn(navSync,relpath); - } - navSync.click(function(){ toggleSyncButton(relpath); }); - } - - navTo(o,toroot,window.location.hash,relpath); - - $(window).bind('hashchange', function(){ - if (window.location.hash && window.location.hash.length>1){ - var a; - if ($(location).attr('hash')){ - var clslink=stripPath($(location).attr('pathname'))+':'+ - $(location).attr('hash').substring(1); - a=$('.item a[class$="'+clslink+'"]'); - } - if (a==null || !$(a).parent().parent().hasClass('selected')){ - $('.item').removeClass('selected'); - $('.item').removeAttr('id'); - } - var link=stripPath2($(location).attr('pathname')); - navTo(o,link,$(location).attr('hash'),relpath); - } else if (!animationInProgress) { - $('#doc-content').scrollTop(0); - $('.item').removeClass('selected'); - $('.item').removeAttr('id'); - navTo(o,toroot,window.location.hash,relpath); - } - }) - - $(window).on("load", showRoot); -} - -// return false if the node has no children at all, or has only section/subsection children -function checkChildrenData(node) { - if (!(typeof(node.childrenData)==='string')) { - for (var i in node.childrenData) { - var url = node.childrenData[i][1]; - if(url.indexOf("#")==-1) - return true; - } - return false; - } - return (node.childrenData); -} - -// Modified to: -// 1 - remove the root node -// 2 - remove the section/subsection children -function createIndent(o,domNode,node,level) -{ - var level=-2; // <- we replaced level=-1 by level=-2 - var n = node; - while (n.parentNode) { level++; n=n.parentNode; } - if (checkChildrenData(node)) { // <- we modified this line to use checkChildrenData(node) instead of node.childrenData - var imgNode = document.createElement("span"); - imgNode.className = 'arrow'; - imgNode.style.paddingLeft=(16*level).toString()+'px'; - imgNode.innerHTML=arrowRight; - node.plus_img = imgNode; - node.expandToggle = document.createElement("a"); - node.expandToggle.href = "javascript:void(0)"; - node.expandToggle.onclick = function() { - if (node.expanded) { - $(node.getChildrenUL()).slideUp("fast"); - node.plus_img.innerHTML=arrowRight; - node.expanded = false; - } else { - expandNode(o, node, false, false); - } - } - node.expandToggle.appendChild(imgNode); - domNode.appendChild(node.expandToggle); + // Each item in the nav tree is currently 30px. This may change, but + // this knowledge is needed to get a reasonable size for the TOC. + if (NAVTREE) { + var navtree_item_height = 30; + var navtree_root = NAVTREE[0]; + var navtree_items = navtree_root[1].length; + var navtree_height = navtree_items * navtree_item_height + 10; // Add 10px for comfortable separation between nav-tree and TOC + navtree.css({height:navtree_height + "px"}); } else { - var span = document.createElement("span"); - span.className = 'arrow'; - span.style.width = 16*(level+1)+'px'; - span.innerHTML = ' '; - domNode.appendChild(span); + var tocHeight = toc.height(); + if (tocHeight < windowHeight) + navtree.css({height:(windowHeight-tocHeight) + "px"}); } } -// Overloaded to automatically expand the selected node -function selectAndHighlight(hash,n) -{ - var a; - if (hash) { - var link=stripPath($(location).attr('pathname'))+':'+hash.substring(1); - a=$('.item a[class$="'+link+'"]'); - } - if (a && a.length) { - a.parent().parent().addClass('selected'); - a.parent().parent().attr('id','selected'); - highlightAnchor(); - } else if (n) { - $(n.itemDiv).addClass('selected'); - $(n.itemDiv).attr('id','selected'); - } - if ($('#nav-tree-contents .item:first').hasClass('selected')) { - $('#nav-sync').css('top','30px'); - } else { - $('#nav-sync').css('top','5px'); - } - expandNode(global_navtree_object, n, true, true); // <- we added this line - showRoot(); -} - - $(document).ready(function() { generate_autotoc(); (function (){ // wait until the first "selected" element has been created try { - // this line will trigger an exception if there is no #selected element, i.e., before the tree structure is complete. document.getElementById("selected").className = "item selected"; // ok, the default tree has been created, we can keep going... // expand the "Chapters" node - if(window.location.href.indexOf('unsupported')==-1) + if (window.location.href.indexOf('unsupported')==-1) expandNode(global_navtree_object, global_navtree_object.node.children[0].children[2], true, true); else expandNode(global_navtree_object, global_navtree_object.node.children[0].children[1], true, true); @@ -237,6 +620,7 @@ $(document).ready(function() { // Hide the root node "HDF5" $(document.getElementsByClassName('index.html')[0]).parent().parent().css({display:"none"}); + resizeHeight(); } catch (err) { setTimeout(arguments.callee, 10); } From 182d02bca7fbe237b151aebfcd4ec0b9c34e4d20 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Tue, 7 Apr 2026 15:37:30 -0500 Subject: [PATCH 2/3] Remove the doxygen navtree hacks file --- docs/doxygen/CMakeLists.txt | 2 +- docs/doxygen/hdf5_header.html | 1 - docs/doxygen/hdf5_navtree_hacks.js | 630 ----------------------------- docs/doxygen/hdf5doxy.css | 88 +--- 4 files changed, 5 insertions(+), 716 deletions(-) delete mode 100644 docs/doxygen/hdf5_navtree_hacks.js diff --git a/docs/doxygen/CMakeLists.txt b/docs/doxygen/CMakeLists.txt index 413be945b47..5ebb1b04b65 100644 --- a/docs/doxygen/CMakeLists.txt +++ b/docs/doxygen/CMakeLists.txt @@ -25,7 +25,7 @@ if (DOXYGEN_FOUND) set (DOXYGEN_HTML_HEADER ${HDF5_DOXYGEN_DIR}/hdf5_header.html) set (DOXYGEN_HTML_FOOTER ${HDF5_DOXYGEN_DIR}/hdf5_footer.html) set (DOXYGEN_HTML_EXTRA_STYLESHEET "${HDF5_DOXYGEN_DIR}/hdf5doxy.css ${HDF5_DOXYGEN_DIR}/doxygen-awesome.css") - set (DOXYGEN_HTML_EXTRA_FILES "${HDF5_DOXYGEN_DIR}/hdf5_navtree_hacks.js ${HDF5_DOXYGEN_DIR}/doxygen-awesome-tabs.js") + set (DOXYGEN_HTML_EXTRA_FILES "${HDF5_DOXYGEN_DIR}/doxygen-awesome-tabs.js") set (DOXYGEN_TAG_FILE ${HDF5_BINARY_DIR}/hdf5.tag) set (DOXYGEN_SERVER_BASED_SEARCH NO) set (DOXYGEN_EXTERNAL_SEARCH NO) diff --git a/docs/doxygen/hdf5_header.html b/docs/doxygen/hdf5_header.html index 724b4155b83..440e804f0d1 100644 --- a/docs/doxygen/hdf5_header.html +++ b/docs/doxygen/hdf5_header.html @@ -21,7 +21,6 @@ $extrastylesheet -
Help us improve by taking our short survey: https://www.hdfgroup.org/website-survey/
diff --git a/docs/doxygen/hdf5_navtree_hacks.js b/docs/doxygen/hdf5_navtree_hacks.js deleted file mode 100644 index 31d396c0c40..00000000000 --- a/docs/doxygen/hdf5_navtree_hacks.js +++ /dev/null @@ -1,630 +0,0 @@ -/* - @licstart The following is the entire license notice for the JavaScript code in this file. - - The MIT License (MIT) - - Copyright (C) 1997-2020 by Dimitri van Heesch - - Permission is hereby granted, free of charge, to any person obtaining a copy of this software - and associated documentation files (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, publish, distribute, - sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - @licend The above is the entire license notice for the JavaScript code in this file - */ - -var global_navtree_object; - -// THG - Moved to wider scope -const ARROW_RIGHT = '►'; -const ARROW_DOWN = '▼'; - -// Modified to save the root node into global_navtree_object -function initNavTree(toroot,relpath) { - let navTreeSubIndices = []; - const NAVPATH_COOKIE_NAME = ''+'navpath'; - - const getData = function(varName) { - const i = varName.lastIndexOf('/'); - const n = i>=0 ? varName.substring(i+1) : varName; - return eval(n.replace(/-/g,'_')); - } - - const stripPath2 = function(uri) { - const i = uri.lastIndexOf('/'); - const s = uri.substring(i+1); - const m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); - return m ? uri.substring(i-6) : s; - } - - const hashValue = function() { - return $(location).attr('hash').substring(1).replace(/[^\w-]/g,''); - } - - const hashUrl = function() { - return '#'+hashValue(); - } - - const pathName = function() { - return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;()]/g, ''); - } - - const deleteLink = function() { - Cookie.eraseSetting(NAVPATH_COOKIE_NAME); - } - - const cachedLink = function() { - return Cookie.readSetting(NAVPATH_COOKIE_NAME,''); - } - - const getScript = function(scriptName,func) { - const head = document.getElementsByTagName("head")[0]; - const script = document.createElement('script'); - script.id = scriptName; - script.type = 'text/javascript'; - script.onload = func; - script.src = scriptName+'.js'; - head.appendChild(script); - } - - let animationInProgress = false; - - const gotoAnchor = function(anchor,aname) { - let pos, docContent = $('#doc-content'); - let ancParent = $(anchor.parent()); - if (ancParent.hasClass('memItemLeft') || ancParent.hasClass('memtitle') || - ancParent.hasClass('fieldname') || ancParent.hasClass('fieldtype') || - ancParent.is(':header')) { - pos = ancParent.offset().top; - } else if (anchor.position()) { - pos = anchor.offset().top; - } - if (pos) { - const dcOffset = docContent.offset().top; - const dcHeight = docContent.height(); - const dcScrHeight = docContent[0].scrollHeight - const dcScrTop = docContent.scrollTop(); - let dist = Math.abs(Math.min(pos-dcOffset,dcScrHeight-dcHeight-dcScrTop)); - animationInProgress = true; - docContent.animate({ - scrollTop: pos + dcScrTop - dcOffset - },Math.max(50,Math.min(500,dist)),function() { - animationInProgress=false; - if (anchor.parent().attr('class')=='memItemLeft') { - let rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); - glowEffect(rows.children(),300); // member without details - } else if (anchor.parent().attr('class')=='fieldname') { - glowEffect(anchor.parent().parent(),1000); // enum value - } else if (anchor.parent().attr('class')=='fieldtype') { - glowEffect(anchor.parent().parent(),1000); // struct field - } else if (anchor.parent().is(":header")) { - glowEffect(anchor.parent(),1000); // section header - } else { - glowEffect(anchor.next(),1000); // normal member - } - }); - } - } - - const showRoot = function() { - const headerHeight = $("#top").height(); - const footerHeight = $("#nav-path").height(); - const windowHeight = $(window).height() - headerHeight - footerHeight; - (function() { // retry until we can scroll to the selected item - try { - const navtree=$('#nav-tree'); - navtree.scrollTo('#selected',100,{offset:-windowHeight/2}); - } catch (err) { - setTimeout(arguments.callee, 0); - } - })(); - } - - const glowEffect = function(n,duration) { - n.addClass('glow').delay(duration).queue(function(next) { - $(this).removeClass('glow');next(); - }); - } - - const highlightAnchor = function() { - const aname = hashUrl(); - const anchor = $(aname); - gotoAnchor(anchor,aname); - } - - // THG - Overloaded to automatically expand the selected node - const selectAndHighlight = function(hash,n) { - let a; - if (hash) { - const link=stripPath(pathName())+':'+hash.substring(1); - a=$('.item a[class$="'+link+'"]'); - } - if (a && a.length) { - a.parent().parent().addClass('selected'); - a.parent().parent().attr('id','selected'); - highlightAnchor(); - } else if (n) { - $(n.itemDiv).addClass('selected'); - $(n.itemDiv).attr('id','selected'); - } - let topOffset=5; - if ($('#nav-tree-contents .item:first').hasClass('selected')) { - topOffset+=25; - } - $('#nav-sync').css('top',topOffset+'px'); - expandNode(global_navtree_object, n, true, true); // <- THG - we added this line - showRoot(); - } - - const showNode = function(o, node, index, hash) { - if (node && node.childrenData) { - if (typeof(node.childrenData)==='string') { - const varName = node.childrenData; - getScript(node.relpath+varName,function() { - node.childrenData = getData(varName); - showNode(o,node,index,hash); - }); - } else { - if (!node.childrenVisited) { - getNode(o, node); - } - $(node.getChildrenUL()).css({'display':'block'}); - node.plus_img.innerHTML = ARROW_DOWN; - node.expanded = true; - const n = node.children[o.breadcrumbs[index]]; - if (index+11 ? '#'+parts[1].replace(/[^\w-]/g,'') : ''; - } - if (hash.match(/^#l\d+$/)) { - const anchor=$('a[name='+hash.substring(1)+']'); - glowEffect(anchor.parent(),1000); // line number - hash=''; // strip line number anchors - } - const url=root+hash; - let i=-1; - while (NAVTREEINDEX[i+1]<=url) i++; - if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index - if (navTreeSubIndices[i]) { - gotoNode(o,i,root,hash,relpath) - } else { - getScript(relpath+'navtreeindex'+i,function() { - navTreeSubIndices[i] = eval('NAVTREEINDEX'+i); - if (navTreeSubIndices[i]) { - gotoNode(o,i,root,hash,relpath); - } - }); - } - } - - const showSyncOff = function(n,relpath) { - n.html(''); - } - - const showSyncOn = function(n,relpath) { - n.html(''); - } - - const o = { - toroot : toroot, - node : { - childrenData : NAVTREE, - children : [], - childrenUL : document.createElement("ul"), - getChildrenUL : function() { return this.childrenUL }, - li : document.getElementById("nav-tree-contents"), - depth : 0, - relpath : relpath, - expanded : false, - isLast : true, - plus_img : document.createElement("img"), - }, - }; - o.node.li.appendChild(o.node.childrenUL); - // THG - Modified - // o.node.plus_img.className = 'arrow'; - // o.node.plus_img.innerHTML = ARROW_RIGHT; - o.node.plus_img.src = relpath+"ftv2pnode.png"; - o.node.plus_img.width = 16; - o.node.plus_img.height = 22; - - global_navtree_object = o; // <- THG - we added this line - - const navSync = $('#nav-sync'); - if (cachedLink()) { - showSyncOff(navSync,relpath); - navSync.removeClass('sync'); - } else { - showSyncOn(navSync,relpath); - } - - navSync.click(() => { - const navSync = $('#nav-sync'); - if (navSync.hasClass('sync')) { - navSync.removeClass('sync'); - showSyncOff(navSync,relpath); - storeLink(stripPath2(pathName())+hashUrl()); - } else { - navSync.addClass('sync'); - showSyncOn(navSync,relpath); - deleteLink(); - } - }); - - navTo(o,toroot,hashUrl(),relpath); - showRoot(); - - $(window).bind('hashchange', () => { - if (!animationInProgress) { - if (window.location.hash && window.location.hash.length>1) { - let a; - if ($(location).attr('hash')) { - const clslink=stripPath(pathName())+':'+hashValue(); - a=$('.item a[class$="'+clslink.replace(/ storeLink(link); - } - } else if (childrenData != null) { - a.className = "nolink"; - a.href = "javascript:void(0)"; - a.onclick = node.expandToggle.onclick; - } - return node; -} - -// THG - Moved to wider scope -const removeToInsertLater = function(element) { - const parentNode = element.parentNode; - const nextSibling = element.nextSibling; - parentNode.removeChild(element); - return function() { - if (nextSibling) { - parentNode.insertBefore(element, nextSibling); - } else { - parentNode.appendChild(element); - } - }; -} - -// THG - Moved to wider scope and modified to remove links to sections/subsections -const getNode = function(o, po) { - const insertFunction = removeToInsertLater(po.li); - po.childrenVisited = true; - const l = po.childrenData.length-1; - for (let i in po.childrenData) { - const nodeData = po.childrenData[i]; - if ((!nodeData[1]) || (nodeData[1].indexOf('#') == -1)) // <- THG - added this line - po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2], i==l); - } - insertFunction(); -} - -// THG - moved to wider scope -const expandNode = function(o, node, imm, setFocus) { - if (node.childrenData && !node.expanded) { - if (typeof(node.childrenData)==='string') { - const varName = node.childrenData; - getScript(node.relpath+varName,function() { - node.childrenData = getData(varName); - expandNode(o, node, imm, setFocus); - }); - } else { - if (!node.childrenVisited) { - getNode(o, node); - } - $(node.getChildrenUL()).slideDown("fast"); - node.plus_img.innerHTML = ARROW_DOWN; - node.expanded = true; - if (setFocus) { - $(node.expandToggle).focus(); - } - } - } -} -/* @license-end */ - -// return false if the node has no children at all, or has only section/subsection children -function checkChildrenData(node) { - if (!(typeof(node.childrenData)==='string')) { - for (var i in node.childrenData) { - var url = node.childrenData[i][1]; - if (url.indexOf("#")==-1) - return true; - } - return false; - } - return (node.childrenData); -} - -// generate a table of contents in the side-nav based on the h1/h2 tags of the current page. -function generate_autotoc() { - var headers = $("h1, h2"); - if(headers.length > 1) { - var toc = $("#side-nav").append(''); - toc = $("#nav-toc"); - var footer = $("#nav-path"); - var footerHeight = footer.height(); - toc = toc.append('
    '); - toc = toc.find('ul'); - var indices = new Array(); - indices[0] = 0; - indices[1] = 0; - - var h1counts = $("h1").length; - headers.each(function(i) { - var current = $(this); - var levelTag = current[0].tagName.charAt(1); - if(h1counts==0) - levelTag--; - var cur_id = current.attr("id"); - - indices[levelTag-1]+=1; - var prefix = indices[0]; - if (levelTag >1) { - prefix+="."+indices[1]; - } - - // Uncomment to add number prefixes - // current.html(prefix + " " + current.html()); - for(var l = levelTag; l < 2; ++l){ - indices[l] = 0; - } - - if(cur_id == undefined) { - current.attr('id', 'title' + i); - current.addClass('anchor'); - toc.append("
  • " + current.text() + "
  • "); - } else { - toc.append("
  • " + current.text() + "
  • "); - } - }); - resizeHeight(); - } -} - -// Adjust the size of the navtree wrt the toc -function resizeHeight() -{ - var header = $("#top"); - var sidenav = $("#side-nav"); - var content = $("#doc-content"); - var navtree = $("#nav-tree"); - var footer = $("#nav-path"); - var toc = $("#nav-toc"); - - var headerHeight = header.outerHeight(); - var footerHeight = footer.outerHeight(); - var windowHeight = $(window).height() - headerHeight - footerHeight; - - content.css({height:windowHeight + "px"}); - sidenav.css({height:windowHeight + "px"}); - - // Each item in the nav tree is currently 30px. This may change, but - // this knowledge is needed to get a reasonable size for the TOC. - if (NAVTREE) { - var navtree_item_height = 30; - var navtree_root = NAVTREE[0]; - var navtree_items = navtree_root[1].length; - var navtree_height = navtree_items * navtree_item_height + 10; // Add 10px for comfortable separation between nav-tree and TOC - navtree.css({height:navtree_height + "px"}); - } else { - var tocHeight = toc.height(); - if (tocHeight < windowHeight) - navtree.css({height:(windowHeight-tocHeight) + "px"}); - } -} - -$(document).ready(function() { - - generate_autotoc(); - - (function (){ // wait until the first "selected" element has been created - try { - // this line will trigger an exception if there is no #selected element, i.e., before the tree structure is complete. - document.getElementById("selected").className = "item selected"; - - // ok, the default tree has been created, we can keep going... - - // expand the "Chapters" node - if (window.location.href.indexOf('unsupported')==-1) - expandNode(global_navtree_object, global_navtree_object.node.children[0].children[2], true, true); - else - expandNode(global_navtree_object, global_navtree_object.node.children[0].children[1], true, true); - - // Hide the root node "HDF5" - $(document.getElementsByClassName('index.html')[0]).parent().parent().css({display:"none"}); - - resizeHeight(); - } catch (err) { - setTimeout(arguments.callee, 10); - } - })(); - - $(window).on("load", resizeHeight); -}); diff --git a/docs/doxygen/hdf5doxy.css b/docs/doxygen/hdf5doxy.css index 52d72077ebb..3b09c82e8f2 100644 --- a/docs/doxygen/hdf5doxy.css +++ b/docs/doxygen/hdf5doxy.css @@ -1,29 +1,11 @@ /**** Table of content in the side-nav ****/ /* - * Collapse the navigation tree to zero height instead of removing it from the layout. - * This allows the Doxygen scripts to correctly calculate the side-panel's width - * and apply the proper 'margin-left' to the main content, preventing overlap. + * Completely hide the side-nav panel. It is only included so that a + * page outline panel can be generated. */ -#nav-tree { - height: 0; - overflow: hidden; - padding: 0; - margin: 0; - border: none; -} - -/* Make sure the side panel itself allows overflow */ #side-nav { - overflow: visible; /* Don't clip the TOC */ - width: 245px; /* Set initial width (default is usually around 250px) */ - min-width: 200px; /* Prevent it from getting too small */ -} - -/* Ensure main content and header never go behind the side panel */ -#doc-content, -#top { - margin-left: 255px !important; /* 245px sidebar + 10px gap */ + display: none } /* Only reset margin on smaller screens */ @@ -38,7 +20,7 @@ @media screen and (min-width: 1200px) { #doc-content, #top { - margin-left: 260px !important; /* Slightly wider gap for large screens */ + margin-left: 10px !important; /* Slightly wider gap for large screens */ } } @@ -135,64 +117,6 @@ body { font-size: 0.9em !important; /* Smaller font size */ height: 24px !important; /* Match the container height */ } - - /* Make sure the side nav stays fixed position */ - #side-nav { - position: fixed !important; - left: 0 !important; - top: 0 !important; - height: 100vh !important; - z-index: 100 !important; - } -} - -/* Style the TOC to fill the entire side panel with proper scrolling */ -div.toc { - margin: 0; - padding: 1em 0 0 0; - width: 100%; - height: calc(100vh - 2em); /* Fixed height to enable proper scrolling */ - float: none; - position: relative; - border-radius: 0px; - border-style: none; - overflow: auto; /* Both horizontal and vertical scrolling */ - box-sizing: border-box; -} - -div.toc h3 { - margin-left: 0.5em; - margin-bottom: 0.2em; -} - -/* Make sure nested lists also scroll properly */ -div.toc ul { - margin: 0.2em 0 0.4em 0.5em; - width: max-content; /* Allow content to determine width */ - min-width: 100%; -} - -/* Ensure the TOC root container can expand */ -div.toc > ul { - width: max-content; - min-width: 100%; -} - -/* Ensure TOC entries don't wrap and enable horizontal scrolling */ -div.toc li a { - white-space: nowrap; - display: inline-block; /* Changed from block to inline-block */ - width: auto; /* Let content determine width */ - min-width: 100%; /* Ensure it takes at least full container width */ -} - -/* - * Prevent long TOC entries from wrapping. - * This keeps each entry on a single line and makes the panel - * horizontally scrollable if an entry is too wide. - */ -#side-nav div.toc li a { - white-space: nowrap; } span.cpp11,span.cpp14,span.cpp17 { @@ -233,10 +157,6 @@ td.width20em p.endtd { /* Style external links -- nav-tree is different */ -#nav-tree .label a { - padding:2px 16px 2px 2px; -} - a { outline: none; text-decoration: none; From 87036dadd9d9d3ebe534f59eff22c1cd33bf027d Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Mon, 22 Jun 2026 15:07:44 -0500 Subject: [PATCH 3/3] Update CSS for page-nav panel and hidden footer --- docs/doxygen/CMakeLists.txt | 2 +- docs/doxygen/hdf5_header.html | 1 - docs/doxygen/hdf5doxy.css | 16 ++++++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/doxygen/CMakeLists.txt b/docs/doxygen/CMakeLists.txt index 5ebb1b04b65..7c6c5bd0cb0 100644 --- a/docs/doxygen/CMakeLists.txt +++ b/docs/doxygen/CMakeLists.txt @@ -24,7 +24,7 @@ if (DOXYGEN_FOUND) set (DOXYGEN_LAYOUT_FILE ${HDF5_DOXYGEN_DIR}/hdf5doxy_layout.xml) set (DOXYGEN_HTML_HEADER ${HDF5_DOXYGEN_DIR}/hdf5_header.html) set (DOXYGEN_HTML_FOOTER ${HDF5_DOXYGEN_DIR}/hdf5_footer.html) - set (DOXYGEN_HTML_EXTRA_STYLESHEET "${HDF5_DOXYGEN_DIR}/hdf5doxy.css ${HDF5_DOXYGEN_DIR}/doxygen-awesome.css") + set (DOXYGEN_HTML_EXTRA_STYLESHEET "${HDF5_DOXYGEN_DIR}/doxygen-awesome.css ${HDF5_DOXYGEN_DIR}/hdf5doxy.css") set (DOXYGEN_HTML_EXTRA_FILES "${HDF5_DOXYGEN_DIR}/doxygen-awesome-tabs.js") set (DOXYGEN_TAG_FILE ${HDF5_BINARY_DIR}/hdf5.tag) set (DOXYGEN_SERVER_BASED_SEARCH NO) diff --git a/docs/doxygen/hdf5_header.html b/docs/doxygen/hdf5_header.html index 440e804f0d1..1eec617561b 100644 --- a/docs/doxygen/hdf5_header.html +++ b/docs/doxygen/hdf5_header.html @@ -20,7 +20,6 @@ $mathjax $extrastylesheet -
    Help us improve by taking our short survey: https://www.hdfgroup.org/website-survey/
    diff --git a/docs/doxygen/hdf5doxy.css b/docs/doxygen/hdf5doxy.css index 3b09c82e8f2..3ab7fdc870a 100644 --- a/docs/doxygen/hdf5doxy.css +++ b/docs/doxygen/hdf5doxy.css @@ -5,7 +5,15 @@ * page outline panel can be generated. */ #side-nav { - display: none + display: none; +} + +/* + * Align the page navigation panel to the right hand side + */ +#page-nav { + margin-left: auto; + margin-right: 0; } /* Only reset margin on smaller screens */ @@ -31,7 +39,7 @@ body { /* Additional specificity - target the content container directly */ #doc-content > div { - margin-left: 0; /* Reset any inherited margins */ + margin-left: auto; /* Reset any inherited margins */ padding-left: 0; /* Reset any inherited padding */ } @@ -207,3 +215,7 @@ div[style*="background:#FFDDDD"] a:hover { .dynheader:hover { text-decoration: underline; } + +/* Hide footer and surrounding lines/space */ +li.footer { display: none; } +div.navpath { display: none; }