1<!DOCTYPE html> 2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head> 3 4<meta charset="utf-8"> 5<meta name="generator" content="quarto-1.10.18"> 6 7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 8 9 10<title>Dashboards â hubverse</title> 11<style> 12/* Default styles provided by pandoc. 13** See https://pandoc.org/MANUAL.html#variables-for-html for config info. 14*/ 15span.smallcaps{font-variant: small-caps;} 16div.columns{display: flex; gap: 1.5em;} 17div.column{flex: auto;} 18@media screen { 19div.columns{gap: min(4vw, 1.5em);} 20div.column{overflow-x: auto;} 21} 22div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 23ul.task-list{list-style: none;} 24ul.task-list li input[type="checkbox"] { 25 width: 0.8em; 26 margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 27 vertical-align: middle; 28} 29</style> 30 31
32<script src="../site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 32
32
33<script src="../site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 33
33
34<script src="../site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 34
34
35<script src="../site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 35
35
36<script src="../site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 36
36
37<script src="../site_libs/quarto-search/quarto-search.js"></script>
37 38<meta name="quarto:offset" content="../"> 39<link href="..//brand/logo/logo.png" rel="icon" type="image/png">
40<script src="../site_libs/quarto-html/quarto.js" type="module"></script>
vendor: 1 bytes, line 40
40
41<script src="../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
vendor: 1 bytes, line 41
41
42<script src="../site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 42
42
43<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
vendor: 1 bytes, line 43
43
44<script src="../site_libs/quarto-html/anchor.min.js"></script>
44 45<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet"> 46<link href="../site_libs/quarto-html/quarto-syntax-highlighting-64a204ab8560d761af7679ceaba22944.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles"> 47<link href="../site_libs/quarto-html/quarto-syntax-highlighting-dark-b85bc7c33db8c58e0ec93c3465666fed.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles"> 48<link href="../site_libs/quarto-html/quarto-syntax-highlighting-64a204ab8560d761af7679ceaba22944.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
49<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
49 50<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 51<link href="../site_libs/bootstrap/bootstrap-faa19e120cee703ce4399906c6e9bee7.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light"> 52<link href="../site_libs/bootstrap/bootstrap-dark-faa19e120cee703ce4399906c6e9bee7.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="light"> 53<link href="../site_libs/bootstrap/bootstrap-faa19e120cee703ce4399906c6e9bee7.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light"> 54<link href="../site_libs/quarto-contrib/fontawesome6-6.7.2/all.min.css" rel="stylesheet"> 55<link href="../site_libs/quarto-contrib/fontawesome6-6.7.2/latex-fontsize.css" rel="stylesheet">
56<script id="quarto-search-options" type="application/json">{ 57 "location": "navbar", 58 "copy-button": false, 59 "collapse-after": 3, 60 "panel-placement": "end", 61 "type": "overlay", 62 "limit": 50, 63 "keyboard-shortcut": [ 64 "f", 65 "/", 66 "s" 67 ], 68 "show-item-context": false, 69 "language": { 70 "search-no-results-text": "No results", 71 "search-matching-documents-text": "matching documents", 72 "search-copy-link-title": "Copy link to search", 73 "search-hide-matches-text": "Hide additional matches", 74 "search-more-match-text": "more match in this document", 75 "search-more-matches-text": "more matches in this document", 76 "search-clear-button-title": "Clear", 77 "search-text-placeholder": "", 78 "search-detached-cancel-button-title": "Cancel", 79 "search-submit-button-title": "Submit", 80 "search-label": "Search" 81 } 82}</script>
82 83<!-- Privacy-friendly analytics by Plausible -->
84<script async="" src="https://plausible.io/js/pa-Qtr0-pdxejuvymNBgYMIj.js"></script>
vendor: 1 bytes, line 84
84
85<script> 86 window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}}; 87 plausible.init() 88</script>
88 89 90 91<link rel="stylesheet" href="../styles.css"> 92</head> 93 94<body class="nav-fixed quarto-light"> 95 96<div id="quarto-search-results"></div> 97 <header id="quarto-header" class="headroom fixed-top"> 98 <div id="quarto-announcement" data-announcement-id="8501bbe9620e8dff98c7b235d38034d7" class="alert alert-info hidden"><i class="bi bi-baloon quarto-announcement-icon"></i><div class="quarto-announcement-content"> 99<p>Welcome to the hubverse. Discover <a href="../community/index.html">our community</a>, get involved, or reach out to share your feedback.</p> 100</div><i class="bi bi-x-lg quarto-announcement-action"></i></div> 101 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 102 <div class="navbar-container container-fluid"> 103 <div class="navbar-brand-container mx-auto"> 104 <a href="../index.html" class="navbar-brand navbar-brand-logo"> 105 <img src="../brand/logo/logo.png" alt="" class="navbar-logo light-content"> 106 <img src="../brand/logo/logo.png" alt="" class="navbar-logo dark-content"> 107 </a> 108 <a class="navbar-brand" href="../index.html"> 109 <span class="navbar-title">hubverse</span> 110 </a> 111 </div> 112 <div id="quarto-search" class="" title="Search"></div> 113 <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }"> 114 <span class="navbar-toggler-icon"></span> 115</button> 116 <div class="collapse navbar-collapse" id="navbarCollapse"> 117 <ul class="navbar-nav navbar-nav-scroll ms-auto"> 118 <li class="nav-item"> 119 <a class="nav-link" href="../index.html"> 120<span class="menu-text">Home</span></a> 121 </li> 122 <li class="nav-item dropdown "> 123 <a class="nav-link dropdown-toggle" href="#" id="nav-menu-get-started" role="link" data-bs-toggle="dropdown" aria-expanded="false"> 124 <span class="menu-text"><strong>Get started</strong></span> 125 </a> 126 <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-get-started"> 127 <li> 128 <a class="dropdown-item" href="../quickstart/index.html"><i class="bi bi-question-circle" role="img"> 129</i> 130 <span class="dropdown-text">What is a modeling hub?</span></a> 131 </li> 132 <li> 133 <a class="dropdown-item" href="../quickstart/create.html"><i class="bi bi-diagram-3" role="img"> 134</i> 135 <span class="dropdown-text">Create a hub</span></a> 136 </li> 137 <li> 138 <a class="dropdown-item" href="../quickstart/submit.html"><i class="bi bi-file-earmark-arrow-up" role="img"> 139</i> 140 <span class="dropdown-text">Submit model output</span></a> 141 </li> 142 <li> 143 <a class="dropdown-item" href="../quickstart/analyze.html"><i class="bi bi-graph-up" role="img"> 144</i> 145 <span class="dropdown-text">Analyze data</span></a> 146 </li> 147 <li> 148 <a class="dropdown-item" href="../quickstart/develop.html"><i class="bi bi-braces" role="img"> 149</i> 150 <span class="dropdown-text">Develop software</span></a> 151 </li> 152 <li><hr class="dropdown-divider"></li> 153 <li> 154 <a class="dropdown-item" href="../quickstart/support-consulting.html"><i class="bi bi-headset" role="img"> 155</i> 156 <span class="dropdown-text">Consulting support</span></a> 157 </li> 158 </ul> 159 </li> 160 <li class="nav-item dropdown "> 161 <a class="nav-link dropdown-toggle" href="#" id="nav-menu-tools" role="link" data-bs-toggle="dropdown" aria-expanded="false"> 162 <span class="menu-text">Tools</span> 163 </a> 164 <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-tools"> 165 <li> 166 <a class="dropdown-item" href="../tools/data.html"><i class="bi bi-compass" role="img"> 167</i> 168 <span class="dropdown-text">Data standards</span></a> 169 </li> 170 <li> 171 <a class="dropdown-item" href="../tools/software.html"><i class="bi bi-tools" role="img"> 172</i> 173 <span class="dropdown-text">Software</span></a> 174 </li> 175 <li> 176 <a class="dropdown-item" href="../tools/dashboards.html"><i class="bi bi-speedometer" role="img"> 177</i> 178 <span class="dropdown-text">Dashboards</span></a> 179 </li> 180 </ul> 181 </li> 182 <li class="nav-item dropdown "> 183 <a class="nav-link dropdown-toggle" href="#" id="nav-menu-community" role="link" data-bs-toggle="dropdown" aria-expanded="false"> 184 <span class="menu-text">Community</span> 185 </a> 186 <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-community"> 187 <li> 188 <a class="dropdown-item" href="../community/index.html"> 189 <span class="dropdown-text"><i class="fa-solid fa-people-line" aria-label="people-line"></i> Community</span></a> 190 </li> 191 <li> 192 <a class="dropdown-item" href="../community/hubs.html"> 193 <span class="dropdown-text"><i class="fa-solid fa-list" aria-label="list"></i> List of hubs</span></a> 194 </li> 195 <li> 196 <a class="dropdown-item" href="../community/contributors.html"> 197 <span class="dropdown-text"><i class="fa-solid fa-pencil" aria-label="pencil"></i> Contributors</span></a> 198 </li> 199 <li> 200 <a class="dropdown-item" href="../contact.html"> 201 <span class="dropdown-text"><i class="fa-solid fa-address-card" aria-label="address-card"></i> Contact</span></a> 202 </li> 203 <li><hr class="dropdown-divider"></li> 204 <li> 205 <a class="dropdown-item" href="../about.html"><i class="bi bi-info-circle-fill" role="img"> 206</i> 207 <span class="dropdown-text">
207About the hubverse</span></a> 208 </li> 209 </ul> 210 </li> 211 <li class="nav-item dropdown "> 212 <a class="nav-link dropdown-toggle" href="#" id="nav-menu-resources" role="link" data-bs-toggle="dropdown" aria-expanded="false"> 213 <span class="menu-text">Resources</span> 214 </a> 215 <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-resources"> 216 <li> 217 <a class="dropdown-item" href="../terminology.html"><i class="bi bi-book" role="img"> 218</i> 219 <span class="dropdown-text">Terminology</span></a> 220 </li> 221 <li> 222 <a class="dropdown-item" href="https://docs.hubverse.io/"> 223 <span class="dropdown-text"><i class="fa-solid fa-book" aria-label="book"></i> Documentation <i class="fa-solid fa-arrow-up-right-from-square" aria-label="arrow-up-right-from-square"></i></span></a> 224 </li> 225 <li> 226 <a class="dropdown-item" href="../funding.html"> 227 <span class="dropdown-text"><i class="fa-solid fa-coins" aria-label="coins"></i> Funding</span></a> 228 </li> 229 <li> 230 <a class="dropdown-item" href="../researchtalks.html"> 231 <span class="dropdown-text"><i class="fa-solid fa-user-graduate" aria-label="user-graduate"></i> Research & talks</span></a> 232 </li> 233 <li> 234 <a class="dropdown-item" href="../trainings.html"> 235 <span class="dropdown-text"><i class="fa-solid fa-laptop-code" aria-label="laptop-code"></i> Trainings</span></a> 236 </li> 237 <li> 238 <a class="dropdown-item" href="../cite.html"> 239 <span class="dropdown-text"><i class="fa-solid fa-quote-left" aria-label="quote-left"></i> How to cite</span></a> 240 </li> 241 <li> 242 <a class="dropdown-item" href="../CONTRIBUTING.html"><i class="bi bi-github" role="img"> 243</i> 244 <span class="dropdown-text">Contributing to the site</span></a> 245 </li> 246 <li><hr class="dropdown-divider"></li> 247 <li> 248 <a class="dropdown-item" href="../quickstart/support-consulting.html"><i class="bi bi-headset" role="img"> 249</i> 250 <span class="dropdown-text">Consulting support</span></a> 251 </li> 252 </ul> 253 </li> 254 <li class="nav-item compact"> 255 <a class="nav-link" href="https://github.com/hubverse-org"> <i class="bi bi-github" role="img" aria-label="hubverse GitHub organization"> 256</i> 257<span class="menu-text"></span></a> 258 </li> 259</ul> 260 </div> <!-- /navcollapse --> 261 <div class="quarto-navbar-tools"> 262</div> 263 </div> <!-- /container-fluid --> 264 </nav> 265</header> 266<!-- content --> 267<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar"> 268<!-- sidebar --> 269<!-- margin-sidebar --> 270 <div id="quarto-margin-sidebar" class="sidebar margin-sidebar"> 271 <nav id="TOC" role="doc-toc" class="toc-active"> 272 <h2 id="toc-title">On this page</h2> 273 274 <ul> 275 <li><a href="#introduction" id="toc-introduction" class="nav-link active" data-scroll-target="#introduction">Introduction</a></li> 276 <li><a href="#examples" id="toc-examples" class="nav-link" data-scroll-target="#examples">Examples</a></li> 277 </ul> 278<div class="toc-actions"><ul><li><a href="https://github.com/hubverse-org/hubverse-site/edit/main/tools/dashboards.qmd" class="toc-action"><i class="bi bi-github"></i>Edit this page</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/blob/main/tools/dashboards.qmd" class="toc-action"><i class="bi empty"></i>View source</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/issues/new" class="toc-action"><i class="bi empty"></i>Report an issue</a></li></ul></div></nav> 279 </div> 280<!-- main --> 281<main class="content" id="quarto-document-content">
282<script> 283 const path = window.location.pathname; 284 const isDev = window.location.hostname === "localhost"; 285 286 // Use console.log for debugging: 287 // console.log("ð docs-redirect script loaded"); 288 // console.log("ð§ Current path:", path); 289 290 const redirects = { 291 "overview/history.html": "https://hubverse.io/about.html#history", 292 "overview/contributors.html": "https://hubverse.io/community/contributors.html", 293 "overview/contribute.html": "https://hubverse.io/community/", 294 "overview/who-we-are.html": "https://hubverse.io/about.html", 295 "overview/scope.html": "https://hubverse.io/about.html#scope", 296 "overview/support-consulting.html": "https://hubverse.io/quickstart/support-consulting.html", 297 "overview/data-storage.html": "https://docs.hubverse.io/en/latest/user-guide/data-storage.html", 298 "user-guide/presentations.html": "https://hubverse.io/researchtalks.html" 299 }; 300 301 const versionedPathRegex = /^\/en\/(\d+\.\d+\.\d+|latest|stable)\//; 302 const isVersionedPath = versionedPathRegex.test(path); 303 const isLatestOrStable = path.startsWith("/en/latest") || path.startsWith("/en/stable"); 304 305 let redirected = false; 306 307 if (isDev || isVersionedPath) { 308 if (isLatestOrStable) { 309 for (const [key, url] of Object.entries(redirects)) { 310 if (path.includes(key)) { 311 // console.log("ð Redirecting to:", url); 312 window.location.href = url; 313 redirected = true; 314 break; 315 } 316 } 317 } 318 } 319 320 if (!redirected && isVersionedPath) { 321 const fallback = "https://docs.hubverse.io" + path; 322 // console.log("ð Redirecting to fallback docs:", fallback); 323 window.location.href = fallback; 324 } 325</script>
325 326 327 328<header id="title-block-header" class="quarto-title-block default"> 329<div class="quarto-title"> 330<h1 class="title"><i class="bi bi-speedometer"></i> Dashboards</h1> 331</div> 332 333 334 335<div class="quarto-title-meta"> 336 337 338 339 340 </div> 341 342 343 344</header> 345 346 347<section id="introduction" class="level2"> 348<h2 class="anchored" data-anchor-id="introduction">Introduction</h2> 349<div class="callout callout-style-default callout-note callout-titled"> 350<div class="callout-header d-flex align-content-center"> 351<div class="callout-icon-container"> 352<i class="callout-icon"></i> 353</div> 354<div class="callout-title-container flex-fill"> 355Note 356</div> 357</div> 358<div class="callout-body-container callout-body"> 359<p>The current iteration of the dashboard is intended for modelers and hub administrators, who are more likely to be familiar with modeling exercise and evaluation methods.</p> 360<p>This is not yet intended for use by decision-makers as there is more information here than they may want or need.</p> 361</div> 362</div> 363<p>The hubverse dashboard is an experimental landing page and plug-and-play visualization for hub data. Each dashboard is an independent repository for any given hub.</p> 364<div id="fig-dashboards" class="quarto-layout-panel"> 365<figure class="quarto-float quarto-float-fig figure"> 366<div aria-describedby="fig-dashboards-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca"> 367<div class="quarto-layout-row"> 368<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: flex-start;"> 369<div class="quarto-figure quarto-figure-center"> 370<figure class="figure"> 371<p><img src="../includes/img/dashboard-forecast.png" class="img-fluid figure-img"></p> 372<figcaption>forecasts</figcaption> 373</figure> 374</div> 375</div> 376<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: flex-start;"> 377<div class="quarto-figure quarto-figure-center"> 378<figure class="figure"> 379<p><img src="../includes/img/dashboard-eval-heat.png" class="img-fluid figure-img"></p> 380<figcaption>evaluations</figcaption> 381</figure> 382</div> 383</div> 384</div> 385</div> 386<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-dashboards-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca"> 387Figure 1: Forecast and Evaluation dashboards for the FluSight forecast hub. 388</figcaption> 389</figure> 390</div> 391<p><a href="https://docs.hubverse.io/en/latest/user-guide/dashboards.html" class="btn btn-outline-dark ms-auto"><i class="fa-solid fa-book" aria-label="book"></i> Get started with dashboards</a></p> 392</section> 393<section id="examples" class="level2"> 394<h2 class="anchored" data-anchor-id="examples">Examples</h2> 395<p>Some examples of dashboards are:</p> 396<table class="caption-top table"> 397<thead> 398<tr class="header"> 399<th>Hub</th> 400<th>Dashboard</th> 401</tr> 402</thead> 403<tbody> 404<tr class="odd"> 405<td><a href="https://github.com/reichlab/flu-metrocast">flu-metrocast</a></td> 406<td><a href="https://reichlab.io/metrocast-dashboard" class="uri">https://reichlab.io/metrocast-dashboard</a></td> 407</tr> 408<tr class="even"> 409<td><a href="https://github.com/cdcepi/FluSight-Forecast-hub">FluSight-forecast-hub</a></td> 410<td><a href="https://reichlab.io/flusight-dashboard" class="uri">https://reichlab.io/flusight-dashboard</a></td> 411</tr> 412<tr class="odd"> 413<td><a href="https://github.com/CDCgov/covid19-forecast-hub">COVID-19 Forecast Hub</a></td> 414<td><a href="https://reichlab.io/covidhub-dashboard" class="uri">https://reichlab.io/covidhub-dashboard</a></td> 415</tr> 416<tr class="even"> 417<td><a href="https://github.com/reichlab/variant-nowcast-hub">variant-nowcast-hub</a></td> 418<td><a href="https://reichlab.io/variant-nowcast-hub-dashboard" class="uri">https://reichlab.io/variant-nowcast-hub-dashboard</a></td> 419</tr> 420</tbody> 421</table> 422<div class="page-nav"> 423<div class="prev-page"> 424<p><a href="../tools/software.html" class="prev-arrow">â¹</a></p> 425<p><a href="../tools/software.html" class="prev-label">Previous</a></p> 426<p><a href="../tools/software.html" class="prev-title"><strong>Software</strong></a></p> 427</div> 428<div class="next-page"> 429<p><a href="../community/index.html" class="next-label">Next</a></p> 430<p><a href="../community/index.html" class="next-arrow">âº</a></p> 431<p><a href="../community/index.html" class="next-title"><strong>Community</strong></a></p> 432</div> 433</div> 434 435 436</section> 437 438</main> <!-- /main -->
439<script id="quarto-html-after-body" type="application/javascript"> 440 window.document.addEventListener("DOMContentLoaded", function (event) { 441 const icon = "î§"; 442 const anchorJS = new window.AnchorJS(); 443 anchorJS.options = { 444 placement: 'right', 445 icon: icon 446 }; 447 anchorJS.add('.anchored'); 448 const isCodeAnnotation = (el) => { 449 for (const clz of el.classList) { 450 if (clz.startsWith('code-annotation-')) { 451 return true; 452 } 453 } 454 return false; 455 } 456 const onCopySuccess = function(e) { 457 // button target 458 const button = e.trigger; 459 // don't keep focus 460 button.blur(); 461 // flash "checked" 462 button.classList.add('code-copy-button-checked'); 463 var currentTitle = button.getAttribute("title"); 464 button.setAttribute("title", "Copied!"); 465 let tooltip; 466 if (window.bootstrap) { 467 button.setAttribute("data-bs-toggle", "tooltip"); 468 button.setAttribute("data-bs-placement", "left"); 469 button.setAttribute("data-bs-title", "Copied!"); 470 tooltip = new bootstrap.Tooltip(button, 471 { trigger: "manual", 472 customClass: "code-copy-button-tooltip", 473 offset: [0, -8]}); 474 tooltip.show(); 475 } 476 setTimeout(function() { 477 if (tooltip) { 478 tooltip.hide(); 479 button.removeAttribute("data-bs-title"); 480 button.removeAttribute("data-bs-toggle"); 481 button.removeAttribute("data-bs-placement"); 482 } 483 button.setAttribute("title", currentTitle); 484 button.classList.remove('code-copy-button-checked'); 485 }, 1000); 486 // clear code selection 487 e.clearSelection(); 488 } 489 const getTextToCopy = function(trigger) { 490 const outerScaffold = trigger.parentElement.cloneNode(true); 491 const codeEl = outerScaffold.querySelector('code'); 492 for (const childEl of codeEl.children) { 493 if (isCodeAnnotation(childEl)) { 494 childEl.remove(); 495 } 496 } 497 return codeEl.innerText; 498 } 499 const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', { 500 text: getTextToCopy 501 }); 502 clipboard.on('success', onCopySuccess); 503 if (window.document.getElementById('quarto-embedded-source-code-modal')) { 504 const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', { 505 text: getTextToCopy, 506 container: window.document.getElementById('quarto-embedded-source-code-modal') 507 }); 508 clipboardModal.on('success', onCopySuccess); 509 } 510 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 511 var mailtoRegex = new RegExp(/^mailto:/); 512 var filterRegex = new RegExp("https:\/\/hubverse\.io"); 513 var isInternal = (href) => { 514 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 515 } 516 // Inspect non-navigation links and adorn them if external 517 var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)'); 518 for (var i=0; i<links.length; i++) { 519 const link = links[i]; 520 if (!isInternal(link.href)) { 521 // undo the damage that might have been done by quarto-nav.js in the case of 522 // links that we want to consider external 523 if (link.dataset.originalHref !== undefined) { 524 link.href = link.dataset.originalHref; 525 } 526 // default icon 527 link.classList.add("external"); 528 } 529 } 530 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 531 const config = { 532 allowHTML: true, 533 maxWidth: 500, 534 delay: 100, 535 arrow: false, 536 appendTo: function(el) { 537 return el.parentElement; 538 }, 539 interactive: true, 540 interactiveBorder: 10, 541 theme: 'quarto', 542 placement: 'bottom-start', 543 }; 544 if (contentFn) { 545 config.content = contentFn; 546 } 547 if (onTriggerFn) { 548 config.onTrigger = onTriggerFn; 549 } 550 if (onUntriggerFn) { 551 config.onUntrigger = onUntriggerFn; 552 } 553 window.tippy(el, config); 554 } 555 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 556 for (var i=0; i<noterefs.length; i++) { 557 const ref = noterefs[i]; 558 tippyHover(ref, function() { 559 // use id or data attribute instead here 560 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 561 try { href = new URL(href).hash; } catch {} 562 const id = href.replace(/^#\/?/, ""); 563 const note = window.document.getElementById(id); 564 if (note) { 565 return note.innerHTML; 566 } else { 567 return ""; 568 } 569 }); 570 } 571 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 572 const processXRef = (id, note) => { 573 // Strip column container classes 574 const stripColumnClz = (el) => { 575 el.classList.remove("page-full", "page-columns"); 576 if (el.children) { 577 for (const child of el.children) {
578 stripColumnClz(child); 579 } 580 } 581 } 582 stripColumnClz(note) 583 if (id === null || id.startsWith('sec-')) { 584 // Special case sections, only their first couple elements 585 const container = document.createElement("div"); 586 if (note.children && note.children.length > 2) { 587 container.appendChild(note.children[0].cloneNode(true)); 588 for (let i = 1; i < note.children.length; i++) { 589 const child = note.children[i]; 590 if (child.tagName === "P" && child.innerText === "") { 591 continue; 592 } else { 593 container.appendChild(child.cloneNode(true)); 594 break; 595 } 596 } 597 if (window.Quarto?.typesetMath) { 598 window.Quarto.typesetMath(container); 599 } 600 return container.innerHTML 601 } else { 602 if (window.Quarto?.typesetMath) { 603 window.Quarto.typesetMath(note); 604 } 605 return note.innerHTML; 606 } 607 } else { 608 // Remove any anchor links if they are present 609 const anchorLink = note.querySelector('a.anchorjs-link'); 610 if (anchorLink) { 611 anchorLink.remove(); 612 } 613 if (window.Quarto?.typesetMath) { 614 window.Quarto.typesetMath(note); 615 } 616 if (note.classList.contains("callout")) { 617 return note.outerHTML; 618 } else { 619 return note.innerHTML; 620 } 621 } 622 } 623 for (var i=0; i<xrefs.length; i++) { 624 const xref = xrefs[i]; 625 tippyHover(xref, undefined, function(instance) { 626 instance.disable(); 627 let url = xref.getAttribute('href'); 628 let hash = undefined; 629 if (url.startsWith('#')) { 630 hash = url; 631 } else { 632 try { hash = new URL(url).hash; } catch {} 633 } 634 if (hash) { 635 const id = hash.replace(/^#\/?/, ""); 636 const note = window.document.getElementById(id); 637 if (note !== null) { 638 try { 639 const html = processXRef(id, note.cloneNode(true)); 640 instance.setContent(html); 641 } finally { 642 instance.enable(); 643 instance.show(); 644 } 645 } else { 646 // See if we can fetch this 647 fetch(url.split('#')[0]) 648 .then(res => res.text()) 649 .then(html => { 650 const parser = new DOMParser(); 651 const htmlDoc = parser.parseFromString(html, "text/html"); 652 const note = htmlDoc.getElementById(id); 653 if (note !== null) { 654 const html = processXRef(id, note); 655 instance.setContent(html); 656 } 657 }).finally(() => { 658 instance.enable(); 659 instance.show(); 660 }); 661 } 662 } else { 663 // See if we can fetch a full url (with no hash to target) 664 // This is a special case and we should probably do some content thinning / targeting 665 fetch(url) 666 .then(res => res.text()) 667 .then(html => { 668 const parser = new DOMParser(); 669 const htmlDoc = parser.parseFromString(html, "text/html"); 670 const note = htmlDoc.querySelector('main.content'); 671 if (note !== null) { 672 // This should only happen for chapter cross references 673 // (since there is no id in the URL) 674 // remove the first header 675 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 676 note.children[0].remove(); 677 } 678 const html = processXRef(null, note); 679 instance.setContent(html); 680 } 681 }).finally(() => { 682 instance.enable(); 683 instance.show(); 684 }); 685 } 686 }, function(instance) { 687 }); 688 } 689 let selectedAnnoteEl; 690 const selectorForAnnotation = ( cell, annotation) => { 691 let cellAttr = 'data-code-cell="' + cell + '"'; 692 let lineAttr = 'data-code-annotation="' + annotation + '"'; 693 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 694 return selector; 695 } 696 const selectCodeLines = (annoteEl) => { 697 const doc = window.document; 698 const targetCell = annoteEl.getAttribute("data-target-cell"); 699 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 700 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 701 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 702 const lineIds = lines.map((line) => { 703 return targetCell + "-" + line; 704 }) 705 let top = null; 706 let height = null; 707 let parent = null; 708 if (lineIds.length > 0) { 709 //compute the position of the single el (top and bottom and make a div) 710 const el = window.document.getElementById(lineIds[0]); 711 top = el.offsetTop; 712 height = el.offsetHeight; 713 parent = el.parentElement.parentElement; 714 if (lineIds.length > 1) { 715 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 716 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 717 height = bottom - top; 718 } 719 if (top !== null && height !== null && parent !== null) { 720 // cook up a div (if necessary) and position it 721 let div = window.document.getElementById("code-annotation-line-highlight"); 722 if (div === null) { 723 div = window.document.createElement("div"); 724 div.setAttribute("id", "code-annotation-line-highlight"); 725 div.style.position = 'absolute'; 726 parent.appendChild(div); 727 } 728 div.style.top = top - 2 + "px"; 729 div.style.height = height + 4 + "px"; 730 div.style.left = 0; 731 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 732 if (gutterDiv === null) { 733 gutterDiv = window.document.createElement("div"); 734 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 735 gutterDiv.style.position = 'absolute'; 736 const codeCell = window.document.getElementById(targetCell); 737 const gutter = codeCell.querySelector('.code-annotation-gutter'); 738 gutter.appendChild(gutterDiv); 739 } 740 gutterDiv.style.top = top - 2 + "px"; 741 gutterDiv.style.height = height + 4 + "px"; 742 } 743 selectedAnnoteEl = annoteEl; 744 } 745 }; 746 const unselectCodeLines = () => { 747 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 748 elementsIds.forEach((elId) => { 749 const div = window.document.getElementById(elId); 750 if (div) { 751 div.remove(); 752 } 753 }); 754 selectedAnnoteEl = undefined; 755 }; 756 // Handle positioning of the toggle 757 window.addEventListener( 758 "resize", 759 throttle(() => { 760 elRect = undefined; 761 if (selectedAnnoteEl) { 762 selectCodeLines(selectedAnnoteEl); 763 } 764 }, 10) 765 ); 766 function throttle(fn, ms) { 767 let throttle = false;
768 let timer; 769 return (...args) => { 770 if(!throttle) { // first call gets through 771 fn.apply(this, args); 772 throttle = true; 773 } else { // all the others get throttled 774 if(timer) clearTimeout(timer); // cancel #2 775 timer = setTimeout(() => { 776 fn.apply(this, args); 777 timer = throttle = false; 778 }, ms); 779 } 780 }; 781 } 782 // Attach click handler to the DT 783 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 784 for (const annoteDlNode of annoteDls) { 785 annoteDlNode.addEventListener('click', (event) => { 786 const clickedEl = event.target; 787 if (clickedEl !== selectedAnnoteEl) { 788 unselectCodeLines(); 789 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 790 if (activeEl) { 791 activeEl.classList.remove('code-annotation-active'); 792 } 793 selectCodeLines(clickedEl); 794 clickedEl.classList.add('code-annotation-active'); 795 } else { 796 // Unselect the line 797 unselectCodeLines(); 798 clickedEl.classList.remove('code-annotation-active'); 799 } 800 }); 801 } 802 const findCites = (el) => { 803 const parentEl = el.parentElement; 804 if (parentEl) { 805 const cites = parentEl.dataset.cites; 806 if (cites) { 807 return { 808 el, 809 cites: cites.split(' ') 810 }; 811 } else { 812 return findCites(el.parentElement) 813 } 814 } else { 815 return undefined; 816 } 817 }; 818 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 819 for (var i=0; i<bibliorefs.length; i++) { 820 const ref = bibliorefs[i]; 821 const citeInfo = findCites(ref); 822 if (citeInfo) { 823 tippyHover(citeInfo.el, function() { 824 var popup = window.document.createElement('div'); 825 citeInfo.cites.forEach(function(cite) { 826 var citeDiv = window.document.createElement('div'); 827 citeDiv.classList.add('hanging-indent'); 828 citeDiv.classList.add('csl-entry'); 829 var biblioDiv = window.document.getElementById('ref-' + cite); 830 if (biblioDiv) { 831 citeDiv.innerHTML = biblioDiv.innerHTML; 832 } 833 popup.appendChild(citeDiv); 834 }); 835 return popup.innerHTML; 836 }); 837 } 838 } 839 }); 840 </script>
840 841</div> <!-- /content --> 842<footer class="footer"> 843 <div class="nav-footer"> 844 <div class="nav-footer-left"> 845 <ul class="footer-items list-unstyled"> 846 <li class="nav-item"> 847 <i class="bi bi-c-circle" role="img"> 848</i> 849 Copyright 2025, Collaborative Modelling Consortium 850 </li> 851</ul> 852 </div> 853 <div class="nav-footer-center"> 854 855 <div class="toc-actions d-sm-block d-md-none"><ul><li><a href="https://github.com/hubverse-org/hubverse-site/edit/main/tools/dashboards.qmd" class="toc-action"><i class="bi bi-github"></i>Edit this page</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/blob/main/tools/dashboards.qmd" class="toc-action"><i class="bi empty"></i>View source</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/issues/new" class="toc-action"><i class="bi empty"></i>Report an issue</a></li></ul></div></div> 856 <div class="nav-footer-right"> 857 <ul class="footer-items list-unstyled"> 858 <li class="nav-item"> 859 <a class="nav-link" href="../funding.html"> 860<p><i class="fa-solid fa-coins" aria-label="coins"></i> Funding supporting the hubverse</p> 861</a> 862 </li> 863 <li class="nav-item"> 864 <a class="nav-link" href="../contact.html"> 865<p><i class="fa-solid fa-address-card" aria-label="address-card"></i> Contact</p> 866</a> 867 </li> 868 <li class="nav-item"> 869 <a class="nav-link" href="../about.html"> 870<p><i class="bi bi-info-circle-fill"></i> About the hubverse</p> 871</a> 872 </li> 873</ul> 874 </div> 875 </div> 876</footer> 877 878 879 880 881</body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.