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.5.57"> 6 7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 8 9<meta name="author" content="Thomas Nagler"> 10<meta name="description" content="Personal Website"> 11 12<title>Thomas Nagler</title> 13<style> 14code{white-space: pre-wrap;} 15span.smallcaps{font-variant: small-caps;} 16div.columns{display: flex; gap: min(4vw, 1.5em);} 17div.column{flex: auto; overflow-x: auto;} 18div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 19ul.task-list{list-style: none;} 20ul.task-list li input[type="checkbox"] { 21 width: 0.8em; 22 margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 23 vertical-align: middle; 24} 25</style> 26 27
28<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 28
28
29<script src="site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 30
30
31<script src="site_libs/quarto-html/quarto.js"></script>
vendor: 1 bytes, line 31
31
32<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 32
32
33<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
33 34<link href="site_libs/quarto-html/tippy.css" rel="stylesheet"> 35<link href="site_libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles"> 36<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark.css" rel="prefetch" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
37<script src="site_libs/bootstrap/bootstrap.min.js"></script>
37 38<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 39<link href="site_libs/bootstrap/bootstrap.min.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light"> 40<link href="site_libs/bootstrap/bootstrap-dark.min.css" rel="prefetch" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark"> 41<link href="site_libs/quarto-contrib/academicons-1.9.2/all.css" rel="stylesheet"> 42<link href="site_libs/quarto-contrib/academicons-1.9.2/size.css" rel="stylesheet">
43<script id="quarto-search-options" type="application/json">{ 44 "language": { 45 "search-no-results-text": "No results", 46 "search-matching-documents-text": "matching documents", 47 "search-copy-link-title": "Copy link to search", 48 "search-hide-matches-text": "Hide additional matches", 49 "search-more-match-text": "more match in this document", 50 "search-more-matches-text": "more matches in this document", 51 "search-clear-button-title": "Clear", 52 "search-text-placeholder": "", 53 "search-detached-cancel-button-title": "Cancel", 54 "search-submit-button-title": "Submit", 55 "search-label": "Search" 56 } 57}</script>
vendor: 1 bytes, line 57
57
58<script async="" src="https://www.googletagmanager.com/gtag/js?id="></script>
58 59
60<script type="text/javascript"> 61 62window.dataLayer = window.dataLayer || []; 63function gtag(){dataLayer.push(arguments);} 64gtag('js', new Date()); 65gtag('config', '', { 'anonymize_ip': true}); 66</script>
66 67 68<!-- 69Load Academicons v1: https://jpswalsh.github.io/academicons/ 70--> 71<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jpswalsh/academicons@1/css/academicons.min.css"> 72 73<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"> 74 75 76<!--- 77The following code are needed to show dimension citation and altmetrics. 78https://api.altmetric.com/embeds.html 79https://badge.dimensions.ai/ 80---> 81
82<script type="text/javascript" src="https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js"></script>
82 83
84<script async="" src="https://badge.dimensions.ai/badge.js" charset="utf-8"></script>
84 85
86<script type="text/javascript" src="//cdn.plu.mx/widget-popup.js"></script>
86 87 88 89<link rel="stylesheet" href="styles.css"> 90<meta property="og:title" content="Thomas Nagler"> 91<meta property="og:description" content="Personal website of Thomas Nagler"> 92<meta property="og:image" content="https://tnagler.com/files/images/avatar2.jpeg"> 93<meta property="og:site_name" content="Thomas Nagler"> 94<meta name="twitter:title" content="Thomas Nagler"> 95<meta name="twitter:description" content="Personal website of Thomas Nagler"> 96<meta name="twitter:image" content="https://tnagler.com/files/images/avatar2.jpeg"> 97<meta name="twitter:card" content="summary_large_image"> 98</head> 99 100<body class="nav-fixed"> 101 102<div id="quarto-search-results"></div> 103 <header id="quarto-header" class="headroom fixed-top"> 104 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 105 <div class="navbar-container container-fluid"> 106 <div class="navbar-brand-container mx-auto"> 107 <a class="navbar-brand" href="./index.html"> 108 <span class="navbar-title">Thomas Nagler</span> 109 </a> 110 </div> 111 <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(); }"> 112 <span class="navbar-toggler-icon"></span> 113</button> 114 <div class="collapse navbar-collapse" id="navbarCollapse"> 115 <ul class="navbar-nav navbar-nav-scroll me-auto"> 116 <li class="nav-item"> 117 <a class="nav-link active" href="./index.html" aria-current="page"> 118<span class="menu-text">About</span></a> 119 </li> 120 <li class="nav-item"> 121 <a class="nav-link" href="./publications.html"> 122<span class="menu-text">Publications</span></a> 123 </li> 124 <li class="nav-item"> 125 <a class="nav-link" href="./software.html"> 126<span class="menu-text">Software</span></a> 127 </li> 128 <li class="nav-item"> 129 <a class="nav-link" href="./teaching.html"> 130<span class="menu-text">Teaching</span></a> 131 </li> 132 <li class="nav-item"> 133 <a class="nav-link" href="./people.html"> 134<span class="menu-text">Team</span></a> 135 </li> 136</ul> 137 </div> <!-- /navcollapse --> 138 <div class="quarto-navbar-tools"> 139 <a href="" class="quarto-color-scheme-toggle quarto-navigation-tool px-1" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a> 140</div> 141 </div> <!-- /container-fluid --> 142 </nav> 143</header> 144<!-- content --> 145<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-full page-navbar"> 146<!-- sidebar --> 147<!-- margin-sidebar --> 148 149<!-- main --> 150<main class="content column-page" id="quarto-document-content"> 151 152 153 154 155<div class="quarto-about-trestles column-page"> 156 <div class="about-entity"> 157 <img src="files/images/avatar2.jpeg" class="about-image 158 rectangle " style="width: 53%;"> 159<header id="title-block-header" class="quarto-title-block default"> 160<div class="quarto-title"> 161<h1 class="title">Thomas Nagler</h1> 162</div> 163<div class="quarto-title-meta column-page"> 164 </div> 165</header> 166 <div class="about-links"> 167 <a href="mailto:[email protected]" class="about-link" rel="" target=""> 168 <i class="bi bi-envelope"></i> 169 <span class="about-link-text"></span> 170 </a> 171 <a href="https://orcid.org/0000-0003-1855-0046" class="about-link" rel="" target="_blank"> 172 <span class="about-link-text"><i class="ai ai-orcid"></i></span> 173 </a> 174 <a href="https://github.com/tnagler" class="about-link" rel="" target="_blank"> 175 <i class="bi bi-github"></i> 176 <span class="about-link-text"></span> 177 </a> 178 <a href="https://scholar.google.com/citations?user=tZR1rZoAAAAJ&hl=en" class="about-link" rel="" target="_blank"> 179 <span class="about-link-text"><i class="ai ai-google-scholar"></i></span> 180 </a> 181</div> 182 </div> 183 <div class="about-contents"><div id="hero-heading"> 184<p>I am Professor at the <a href="https://www.en.statistik.uni-muenchen.de/index.html">Department of Statistics</a>, <a href="https://www.lmu.de/">LMU Munich</a>, and a principal investigator at the <a href="https://mcml.ai/">Munich Center for Machine Learning (MCML)</a>.</p> 185<p>My main research areas are mathematical statistics and machine learning. I develop new methods, derive theoretical guarantees and scalable algorithms, and collaborate with domain experts to solve problems in diverse areas.</p> 186<section id="research-interests" class="level3"> 187<h3 data-anchor-id="research-interests">Research interests</h3> 188<ul> 189<li>Statistical learning methods and theory</li> 190<li>High-dimensional dependence models</li> 191<li>Time series</li> 192<li>Statistical computing</li> 193</ul> 194</section> 195<section id="short-cv" class="level3"> 196<h3 data-anchor-id="short-cv">Short CV</h3> 197<ul> 198<li>2022â: <em>Professor (W2)</em>, Department of Statistics, <a href="https://www.en.statistik.uni-muenchen.de/index.html">LMU Munich</a></li> 199<li>2021â2022: <em>Assistant professor</em>, DIAM, <a href="https://www.tudelft.nl/ewi/over-de-faculteit/afdelingen/applied-mathematics">TU Delft</a></li> 200<li>2019â2021: <em>Assistant professor</em>, Mathematical Institute, <a href="https://www.universiteitleiden.nl/en/science/mathematics">Leiden University</a></li> 201<li>2014â2018: <em>PhD Mathematical Statistics</em>, <a href="https://www.ma.tum.de/en">TU Munich</a></li> 202<li>2012â2014: <em>MSc Mathematical Finance</em>, <a href="https://www.ma.tum.de/en">TU Munich</a></li> 203<li>2009â2012: <em>BSc Mathematics</em>, <a href="https://www.ma.tum.de/en">TU Munich</a></li> 204</ul> 205</section> 206</div></div> 207</div> 208 209<center> 210<hr style="width:100%"> 211</center> 212<section id="office" class="level4"> 213<h4 data-anchor-id="office">Office</h4> 214<p>Room 311 (3rd floor)<br> 215Akademiestr. 7<br> 21680799 Munich, Germany</p> 217 218 219 220</section> 221 222</main> <!-- /main -->
223<script id="quarto-html-after-body" type="application/javascript"> 224window.document.addEventListener("DOMContentLoaded", function (event) { 225 const toggleBodyColorMode = (bsSheetEl) => { 226 const mode = bsSheetEl.getAttribute("data-mode"); 227 const bodyEl = window.document.querySelector("body"); 228 if (mode === "dark") { 229 bodyEl.classList.add("quarto-dark"); 230 bodyEl.classList.remove("quarto-light"); 231 } else { 232 bodyEl.classList.add("quarto-light"); 233 bodyEl.classList.remove("quarto-dark"); 234 } 235 } 236 const toggleBodyColorPrimary = () => { 237 const bsSheetEl = window.document.querySelector("link#quarto-bootstrap"); 238 if (bsSheetEl) { 239 toggleBodyColorMode(bsSheetEl); 240 } 241 } 242 toggleBodyColorPrimary(); 243 const disableStylesheet = (stylesheets) => { 244 for (let i=0; i < stylesheets.length; i++) { 245 const stylesheet = stylesheets[i]; 246 stylesheet.rel = 'prefetch'; 247 } 248 } 249 const enableStylesheet = (stylesheets) => { 250 for (let i=0; i < stylesheets.length; i++) { 251 const stylesheet = stylesheets[i]; 252 stylesheet.rel = 'stylesheet'; 253 } 254 } 255 const manageTransitions = (selector, allowTransitions) => { 256 const els = window.document.querySelectorAll(selector); 257 for (let i=0; i < els.length; i++) { 258 const el = els[i]; 259 if (allowTransitions) { 260 el.classList.remove('notransition'); 261 } else { 262 el.classList.add('notransition'); 263 } 264 } 265 } 266 const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => { 267 const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light'; 268 const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark'; 269 let newTheme = ''; 270 if(darkModeDefault) { 271 newTheme = isAlternate ? baseTheme : alternateTheme; 272 } else { 273 newTheme = isAlternate ? alternateTheme : baseTheme; 274 } 275 const changeGiscusTheme = () => { 276 // From: https://github.com/giscus/giscus/issues/336 277 const sendMessage = (message) => { 278 const iframe = document.querySelector('iframe.giscus-frame'); 279 if (!iframe) return; 280 iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app'); 281 } 282 sendMessage({ 283 setConfig: { 284 theme: newTheme 285 } 286 }); 287 } 288 const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null; 289 if (isGiscussLoaded) { 290 changeGiscusTheme(); 291 } 292 } 293 const toggleColorMode = (alternate) => { 294 // Switch the stylesheets 295 const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate'); 296 manageTransitions('#quarto-margin-sidebar .nav-link', false); 297 if (alternate) { 298 enableStylesheet(alternateStylesheets); 299 for (const sheetNode of alternateStylesheets) { 300 if (sheetNode.id === "quarto-bootstrap") { 301 toggleBodyColorMode(sheetNode); 302 } 303 } 304 } else { 305 disableStylesheet(alternateStylesheets); 306 toggleBodyColorPrimary(); 307 } 308 manageTransitions('#quarto-margin-sidebar .nav-link', true); 309 // Switch the toggles 310 const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle'); 311 for (let i=0; i < toggles.length; i++) { 312 const toggle = toggles[i]; 313 if (toggle) { 314 if (alternate) { 315 toggle.classList.add("alternate"); 316 } else { 317 toggle.classList.remove("alternate"); 318 } 319 } 320 } 321 // Hack to workaround the fact that safari doesn't 322 // properly recolor the scrollbar when toggling (#1455) 323 if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) { 324 manageTransitions("body", false); 325 window.scrollTo(0, 1); 326 setTimeout(() => { 327 window.scrollTo(0, 0); 328 manageTransitions("body", true); 329 }, 40); 330 } 331 } 332 const isFileUrl = () => { 333 return window.location.protocol === 'file:'; 334 } 335 const hasAlternateSentinel = () => { 336 let styleSentinel = getColorSchemeSentinel(); 337 if (styleSentinel !== null) { 338 return styleSentinel === "alternate"; 339 } else { 340 return false;
341 } 342 } 343 const setStyleSentinel = (alternate) => { 344 const value = alternate ? "alternate" : "default"; 345 if (!isFileUrl()) { 346 window.localStorage.setItem("quarto-color-scheme", value); 347 } else { 348 localAlternateSentinel = value; 349 } 350 } 351 const getColorSchemeSentinel = () => { 352 if (!isFileUrl()) { 353 const storageValue = window.localStorage.getItem("quarto-color-scheme"); 354 return storageValue != null ? storageValue : localAlternateSentinel; 355 } else { 356 return localAlternateSentinel; 357 } 358 } 359 const darkModeDefault = false; 360 let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default'; 361 // Dark / light mode switch 362 window.quartoToggleColorScheme = () => { 363 // Read the current dark / light value 364 let toAlternate = !hasAlternateSentinel(); 365 toggleColorMode(toAlternate); 366 setStyleSentinel(toAlternate); 367 toggleGiscusIfUsed(toAlternate, darkModeDefault); 368 }; 369 // Ensure there is a toggle, if there isn't float one in the top right 370 if (window.document.querySelector('.quarto-color-scheme-toggle') === null) { 371 const a = window.document.createElement('a'); 372 a.classList.add('top-right'); 373 a.classList.add('quarto-color-scheme-toggle'); 374 a.href = ""; 375 a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; }; 376 const i = window.document.createElement("i"); 377 i.classList.add('bi'); 378 a.appendChild(i); 379 window.document.body.appendChild(a); 380 } 381 // Switch to dark mode if need be 382 if (hasAlternateSentinel()) { 383 toggleColorMode(true); 384 } else { 385 toggleColorMode(false); 386 } 387 const isCodeAnnotation = (el) => { 388 for (const clz of el.classList) { 389 if (clz.startsWith('code-annotation-')) { 390 return true; 391 } 392 } 393 return false; 394 } 395 const onCopySuccess = function(e) { 396 // button target 397 const button = e.trigger; 398 // don't keep focus 399 button.blur(); 400 // flash "checked" 401 button.classList.add('code-copy-button-checked'); 402 var currentTitle = button.getAttribute("title"); 403 button.setAttribute("title", "Copied!"); 404 let tooltip; 405 if (window.bootstrap) { 406 button.setAttribute("data-bs-toggle", "tooltip"); 407 button.setAttribute("data-bs-placement", "left"); 408 button.setAttribute("data-bs-title", "Copied!"); 409 tooltip = new bootstrap.Tooltip(button, 410 { trigger: "manual", 411 customClass: "code-copy-button-tooltip", 412 offset: [0, -8]}); 413 tooltip.show(); 414 } 415 setTimeout(function() { 416 if (tooltip) { 417 tooltip.hide(); 418 button.removeAttribute("data-bs-title"); 419 button.removeAttribute("data-bs-toggle"); 420 button.removeAttribute("data-bs-placement"); 421 } 422 button.setAttribute("title", currentTitle); 423 button.classList.remove('code-copy-button-checked'); 424 }, 1000); 425 // clear code selection 426 e.clearSelection(); 427 } 428 const getTextToCopy = function(trigger) { 429 const codeEl = trigger.previousElementSibling.cloneNode(true); 430 for (const childEl of codeEl.children) { 431 if (isCodeAnnotation(childEl)) { 432 childEl.remove(); 433 } 434 } 435 return codeEl.innerText; 436 } 437 const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', { 438 text: getTextToCopy 439 }); 440 clipboard.on('success', onCopySuccess); 441 if (window.document.getElementById('quarto-embedded-source-code-modal')) { 442 // For code content inside modals, clipBoardJS needs to be initialized with a container option 443 // TODO: Check when it could be a function (https://github.com/zenorocha/clipboard.js/issues/860) 444 const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', { 445 text: getTextToCopy, 446 container: window.document.getElementById('quarto-embedded-source-code-modal') 447 }); 448 clipboardModal.on('success', onCopySuccess); 449 } 450 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 451 var mailtoRegex = new RegExp(/^mailto:/); 452 var filterRegex = new RegExp("^(?:http:|https:)\/\/drganghe\.github\.io\/custom"); 453 var isInternal = (href) => { 454 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 455 } 456 // Inspect non-navigation links and adorn them if external 457 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)'); 458 for (var i=0; i<links.length; i++) { 459 const link = links[i]; 460 if (!isInternal(link.href)) { 461 // undo the damage that might have been done by quarto-nav.js in the case of 462 // links that we want to consider external 463 if (link.dataset.originalHref !== undefined) { 464 link.href = link.dataset.originalHref; 465 } 466 // target, if specified 467 link.setAttribute("target", "_blank"); 468 if (link.getAttribute("rel") === null) { 469 link.setAttribute("rel", "noopener"); 470 } 471 } 472 } 473 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 474 const config = { 475 allowHTML: true, 476 maxWidth: 500, 477 delay: 100,
478 arrow: false, 479 appendTo: function(el) { 480 return el.parentElement; 481 }, 482 interactive: true, 483 interactiveBorder: 10, 484 theme: 'quarto', 485 placement: 'bottom-start', 486 }; 487 if (contentFn) { 488 config.content = contentFn; 489 } 490 if (onTriggerFn) { 491 config.onTrigger = onTriggerFn; 492 } 493 if (onUntriggerFn) { 494 config.onUntrigger = onUntriggerFn; 495 } 496 window.tippy(el, config); 497 } 498 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 499 for (var i=0; i<noterefs.length; i++) { 500 const ref = noterefs[i]; 501 tippyHover(ref, function() { 502 // use id or data attribute instead here 503 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 504 try { href = new URL(href).hash; } catch {} 505 const id = href.replace(/^#\/?/, ""); 506 const note = window.document.getElementById(id); 507 if (note) { 508 return note.innerHTML; 509 } else { 510 return ""; 511 } 512 }); 513 } 514 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 515 const processXRef = (id, note) => { 516 // Strip column container classes 517 const stripColumnClz = (el) => { 518 el.classList.remove("page-full", "page-columns"); 519 if (el.children) { 520 for (const child of el.children) { 521 stripColumnClz(child); 522 } 523 } 524 } 525 stripColumnClz(note) 526 if (id === null || id.startsWith('sec-')) { 527 // Special case sections, only their first couple elements 528 const container = document.createElement("div"); 529 if (note.children && note.children.length > 2) { 530 container.appendChild(note.children[0].cloneNode(true)); 531 for (let i = 1; i < note.children.length; i++) { 532 const child = note.children[i]; 533 if (child.tagName === "P" && child.innerText === "") { 534 continue; 535 } else { 536 container.appendChild(child.cloneNode(true)); 537 break; 538 } 539 } 540 if (window.Quarto?.typesetMath) { 541 window.Quarto.typesetMath(container); 542 } 543 return container.innerHTML 544 } else { 545 if (window.Quarto?.typesetMath) { 546 window.Quarto.typesetMath(note); 547 } 548 return note.innerHTML; 549 } 550 } else { 551 // Remove any anchor links if they are present 552 const anchorLink = note.querySelector('a.anchorjs-link'); 553 if (anchorLink) { 554 anchorLink.remove(); 555 } 556 if (window.Quarto?.typesetMath) { 557 window.Quarto.typesetMath(note); 558 } 559 // TODO in 1.5, we should make sure this works without a callout special case 560 if (note.classList.contains("callout")) { 561 return note.outerHTML; 562 } else { 563 return note.innerHTML; 564 } 565 } 566 } 567 for (var i=0; i<xrefs.length; i++) { 568 const xref = xrefs[i]; 569 tippyHover(xref, undefined, function(instance) { 570 instance.disable(); 571 let url = xref.getAttribute('href'); 572 let hash = undefined; 573 if (url.startsWith('#')) { 574 hash = url; 575 } else { 576 try { hash = new URL(url).hash; } catch {} 577 } 578 if (hash) { 579 const id = hash.replace(/^#\/?/, ""); 580 const note = window.document.getElementById(id); 581 if (note !== null) { 582 try { 583 const html = processXRef(id, note.cloneNode(true)); 584 instance.setContent(html); 585 } finally { 586 instance.enable(); 587 instance.show(); 588 } 589 } else { 590 // See if we can fetch this 591 fetch(url.split('#')[0]) 592 .then(res => res.text()) 593 .then(html => { 594 const parser = new DOMParser(); 595 const htmlDoc = parser.parseFromString(html, "text/html"); 596 const note = htmlDoc.getElementById(id); 597 if (note !== null) { 598 const html = processXRef(id, note); 599 instance.setContent(html); 600 } 601 }).finally(() => { 602 instance.enable(); 603 instance.show(); 604 }); 605 } 606 } else { 607 // See if we can fetch a full url (with no hash to target)
608 // This is a special case and we should probably do some content thinning / targeting 609 fetch(url) 610 .then(res => res.text()) 611 .then(html => { 612 const parser = new DOMParser(); 613 const htmlDoc = parser.parseFromString(html, "text/html"); 614 const note = htmlDoc.querySelector('main.content'); 615 if (note !== null) { 616 // This should only happen for chapter cross references 617 // (since there is no id in the URL) 618 // remove the first header 619 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 620 note.children[0].remove(); 621 } 622 const html = processXRef(null, note); 623 instance.setContent(html); 624 } 625 }).finally(() => { 626 instance.enable(); 627 instance.show(); 628 }); 629 } 630 }, function(instance) { 631 }); 632 } 633 let selectedAnnoteEl; 634 const selectorForAnnotation = ( cell, annotation) => { 635 let cellAttr = 'data-code-cell="' + cell + '"'; 636 let lineAttr = 'data-code-annotation="' + annotation + '"'; 637 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 638 return selector; 639 } 640 const selectCodeLines = (annoteEl) => { 641 const doc = window.document; 642 const targetCell = annoteEl.getAttribute("data-target-cell"); 643 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 644 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 645 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 646 const lineIds = lines.map((line) => { 647 return targetCell + "-" + line; 648 }) 649 let top = null; 650 let height = null; 651 let parent = null; 652 if (lineIds.length > 0) { 653 //compute the position of the single el (top and bottom and make a div) 654 const el = window.document.getElementById(lineIds[0]); 655 top = el.offsetTop; 656 height = el.offsetHeight; 657 parent = el.parentElement.parentElement; 658 if (lineIds.length > 1) { 659 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 660 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 661 height = bottom - top; 662 } 663 if (top !== null && height !== null && parent !== null) { 664 // cook up a div (if necessary) and position it 665 let div = window.document.getElementById("code-annotation-line-highlight"); 666 if (div === null) { 667 div = window.document.createElement("div"); 668 div.setAttribute("id", "code-annotation-line-highlight"); 669 div.style.position = 'absolute'; 670 parent.appendChild(div); 671 } 672 div.style.top = top - 2 + "px"; 673 div.style.height = height + 4 + "px"; 674 div.style.left = 0; 675 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 676 if (gutterDiv === null) { 677 gutterDiv = window.document.createElement("div"); 678 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 679 gutterDiv.style.position = 'absolute'; 680 const codeCell = window.document.getElementById(targetCell); 681 const gutter = codeCell.querySelector('.code-annotation-gutter'); 682 gutter.appendChild(gutterDiv); 683 } 684 gutterDiv.style.top = top - 2 + "px"; 685 gutterDiv.style.height = height + 4 + "px"; 686 } 687 selectedAnnoteEl = annoteEl; 688 } 689 }; 690 const unselectCodeLines = () => { 691 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 692 elementsIds.forEach((elId) => { 693 const div = window.document.getElementById(elId); 694 if (div) { 695 div.remove(); 696 } 697 }); 698 selectedAnnoteEl = undefined; 699 }; 700 // Handle positioning of the toggle 701 window.addEventListener( 702 "resize", 703 throttle(() => { 704 elRect = undefined; 705 if (selectedAnnoteEl) { 706 selectCodeLines(selectedAnnoteEl); 707 } 708 }, 10) 709 ); 710 function throttle(fn, ms) { 711 let throttle = false;
712 let timer; 713 return (...args) => { 714 if(!throttle) { // first call gets through 715 fn.apply(this, args); 716 throttle = true; 717 } else { // all the others get throttled 718 if(timer) clearTimeout(timer); // cancel #2 719 timer = setTimeout(() => { 720 fn.apply(this, args); 721 timer = throttle = false; 722 }, ms); 723 } 724 }; 725 } 726 // Attach click handler to the DT 727 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 728 for (const annoteDlNode of annoteDls) { 729 annoteDlNode.addEventListener('click', (event) => { 730 const clickedEl = event.target; 731 if (clickedEl !== selectedAnnoteEl) { 732 unselectCodeLines(); 733 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 734 if (activeEl) { 735 activeEl.classList.remove('code-annotation-active'); 736 } 737 selectCodeLines(clickedEl); 738 clickedEl.classList.add('code-annotation-active'); 739 } else { 740 // Unselect the line 741 unselectCodeLines(); 742 clickedEl.classList.remove('code-annotation-active'); 743 } 744 }); 745 } 746 const findCites = (el) => { 747 const parentEl = el.parentElement; 748 if (parentEl) { 749 const cites = parentEl.dataset.cites; 750 if (cites) { 751 return { 752 el, 753 cites: cites.split(' ') 754 }; 755 } else { 756 return findCites(el.parentElement) 757 } 758 } else { 759 return undefined; 760 } 761 }; 762 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 763 for (var i=0; i<bibliorefs.length; i++) { 764 const ref = bibliorefs[i]; 765 const citeInfo = findCites(ref); 766 if (citeInfo) { 767 tippyHover(citeInfo.el, function() { 768 var popup = window.document.createElement('div'); 769 citeInfo.cites.forEach(function(cite) { 770 var citeDiv = window.document.createElement('div'); 771 citeDiv.classList.add('hanging-indent'); 772 citeDiv.classList.add('csl-entry'); 773 var biblioDiv = window.document.getElementById('ref-' + cite); 774 if (biblioDiv) { 775 citeDiv.innerHTML = biblioDiv.innerHTML; 776 } 777 popup.appendChild(citeDiv); 778 }); 779 return popup.innerHTML; 780 }); 781 } 782 } 783}); 784</script>
784 785</div> <!-- /content --> 786<footer class="footer"> 787 <div class="nav-footer"> 788 <div class="nav-footer-left"> 789<a href="http://www.tnagler.com">Thomas Nagler</a> ©
790<script>document.write(new Date().getFullYear())</script>
790 791</div> 792 <div class="nav-footer-center"> 793 794 </div> 795 <div class="nav-footer-right"> 796 797 </div> 798 </div> 799</footer> 800 801 802 803 804</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.