PageSourceSearch

https://www.johannesfeldhege.de/index.html

html johannesfeldhege.de collected 2026-10-04 20:15:33 UTC 37,471 bytes, 847 lines download raw bytes

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.9.37">
6
7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
8
9
10<title>Johannes Feldhege, M.Sc. B.A. – Johannes Feldhege</title>
11<style>
12/* Default styles provided by pandoc.
13** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
14*/
15code{white-space: pre-wrap;}
16span.smallcaps{font-variant: small-caps;}
17div.columns{display: flex; gap: min(4vw, 1.5em);}
18div.column{flex: auto; overflow-x: auto;}
19div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
20ul.task-list{list-style: none;}
21ul.task-list li input[type="checkbox"] {
22  width: 0.8em;
23  margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 
24  vertical-align: middle;
25}
26</style>
27
28
29<script src="site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 29
29
30<script src="site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 30
30
31<script src="site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 31
31
32<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 32
32
33<script src="site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 33
33
34<script src="site_libs/quarto-search/quarto-search.js"></script>
34
35<meta name="quarto:offset" content="./">
36<link href="./assets/logo.png" rel="icon" type="image/png">
37<script src="site_libs/cookie-consent/cookie-consent.js"></script>
37
38<link href="site_libs/cookie-consent/cookie-consent.css" rel="stylesheet">
39<script src="site_libs/quarto-html/quarto.js" type="module"></script>
vendor: 1 bytes, line 39
39
40<script src="site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
vendor: 1 bytes, line 40
40
41<script src="site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 41
41
42<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
42
43<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
44<link href="site_libs/quarto-html/quarto-syntax-highlighting-3b5aaf7f86bad49ac49ec71cebff2afb.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
45<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark-8f6e9aadc5ea5a3b74645e22aaa20220.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
46<link href="site_libs/quarto-html/quarto-syntax-highlighting-3b5aaf7f86bad49ac49ec71cebff2afb.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
47<script src="site_libs/bootstrap/bootstrap.min.js"></script>
47
48<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
49<link href="site_libs/bootstrap/bootstrap-016a33c344d85df288a4ca5657a8314d.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
50<link href="site_libs/bootstrap/bootstrap-dark-8dbb7b7b978eae176009dfa8cc82e56a.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
51<link href="site_libs/bootstrap/bootstrap-016a33c344d85df288a4ca5657a8314d.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
52<link href="site_libs/quarto-contrib/fontawesome6-0.1.0/all.css" rel="stylesheet">
53<link href="site_libs/quarto-contrib/fontawesome6-0.1.0/latex-fontsize.css" rel="stylesheet">
54<link href="site_libs/quarto-contrib/academicons-1.9.2/all.css" rel="stylesheet">
55<link href="site_libs/quarto-contrib/academicons-1.9.2/size.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
84<script type="text/javascript" charset="UTF-8">
85document.addEventListener('DOMContentLoaded', function () {
86cookieconsent.run({
87  "notice_banner_type":"headline",
88  "consent_type":"express",
89  "palette":"light",
90  "language":"en",
91  "page_load_consent_levels":["strictly-necessary"],
92  "notice_banner_reject_button_hide":false,
93  "preferences_center_close_button_hide":false,
94  "website_name":""
95  ,
96"language":"en"
97  });
98});
99</script>
99 
100  
101
102
103<meta property="og:title" content="Johannes Feldhege, M.Sc. B.A. – Johannes Feldhege">
104<meta property="og:description" content="Persönliche Webseite von Johannes Feldhege">
105<meta property="og:site_name" content="Johannes Feldhege">
106</head>
107
108<body class="nav-fixed quarto-light">
108<script id="quarto-html-before-body" type="application/javascript">
109    const toggleBodyColorMode = (bsSheetEl) => {
110      const mode = bsSheetEl.getAttribute("data-mode");
111      const bodyEl = window.document.querySelector("body");
112      if (mode === "dark") {
113        bodyEl.classList.add("quarto-dark");
114        bodyEl.classList.remove("quarto-light");
115      } else {
116        bodyEl.classList.add("quarto-light");
117        bodyEl.classList.remove("quarto-dark");
118      }
119    }
120    const toggleBodyColorPrimary = () => {
121      const bsSheetEl = window.document.querySelector("link#quarto-bootstrap:not([rel=disabled-stylesheet])");
122      if (bsSheetEl) {
123        toggleBodyColorMode(bsSheetEl);
124      }
125    }
126    const setColorSchemeToggle = (alternate) => {
127      const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
128      for (let i=0; i < toggles.length; i++) {
129        const toggle = toggles[i];
130        if (toggle) {
131          if (alternate) {
132            toggle.classList.add("alternate");
133          } else {
134            toggle.classList.remove("alternate");
135          }
136        }
137      }
138    };
139    const toggleColorMode = (alternate) => {
140      // Switch the stylesheets
141      const primaryStylesheets = window.document.querySelectorAll('link.quarto-color-scheme:not(.quarto-color-alternate)');
142      const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
143      manageTransitions('#quarto-margin-sidebar .nav-link', false);
144      if (alternate) {
145        // note: dark is layered on light, we don't disable primary!
146        enableStylesheet(alternateStylesheets);
147        for (const sheetNode of alternateStylesheets) {
148          if (sheetNode.id === "quarto-bootstrap") {
149            toggleBodyColorMode(sheetNode);
150          }
151        }
152      } else {
153        disableStylesheet(alternateStylesheets);
154        enableStylesheet(primaryStylesheets)
155        toggleBodyColorPrimary();
156      }
157      manageTransitions('#quarto-margin-sidebar .nav-link', true);
158      // Switch the toggles
159      setColorSchemeToggle(alternate)
160      // Hack to workaround the fact that safari doesn't
161      // properly recolor the scrollbar when toggling (#1455)
162      if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
163        manageTransitions("body", false);
164        window.scrollTo(0, 1);
165        setTimeout(() => {
166          window.scrollTo(0, 0);
167          manageTransitions("body", true);
168        }, 40);
169      }
170    }
171    const disableStylesheet = (stylesheets) => {
172      for (let i=0; i < stylesheets.length; i++) {
173        const stylesheet = stylesheets[i];
174        stylesheet.rel = 'disabled-stylesheet';
175      }
176    }
177    const enableStylesheet = (stylesheets) => {
178      for (let i=0; i < stylesheets.length; i++) {
179        const stylesheet = stylesheets[i];
180        if(stylesheet.rel !== 'stylesheet') { // for Chrome, which will still FOUC without this check
181          stylesheet.rel = 'stylesheet';
182        }
183      }
184    }
185    const manageTransitions = (selector, allowTransitions) => {
186      const els = window.document.querySelectorAll(selector);
187      for (let i=0; i < els.length; i++) {
188        const el = els[i];
189        if (allowTransitions) {
190          el.classList.remove('notransition');
191        } else {
192          el.classList.add('notransition');
193        }
194      }
195    }
196    const isFileUrl = () => {
197      return window.location.protocol === 'file:';
198    }
199    const hasAlternateSentinel = () => {
200      let styleSentinel = getColorSchemeSentinel();
201      if (styleSentinel !== null) {
202        return styleSentinel === "alternate";
203      } else {
204        return false;
205      }
206    }
207    const setStyleSentinel = (alternate) => {
208      const value = alternate ? "alternate" : "default";
209      if (!isFileUrl()) {
210        window.localStorage.setItem("quarto-color-scheme", value);
211      } else {
212        localAlternateSentinel = value;
213      }
214    }
215    const getColorSchemeSentinel = () => {
216      if (!isFileUrl()) {
217        const storageValue = window.localStorage.getItem("quarto-color-scheme");
218        return storageValue != null ? storageValue : localAlternateSentinel;
219      } else {
220        return localAlternateSentinel;
221      }
222    }
223    const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
224      const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
225      const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
226      let newTheme = '';
227      if(authorPrefersDark) {
228        newTheme = isAlternate ? baseTheme : alternateTheme;
229      } else {
230        newTheme = isAlternate ? alternateTheme : baseTheme;
231      }
232      const changeGiscusTheme = () => {
233        // From: https://github.com/giscus/giscus/issues/336
234        const sendMessage = (message) => {
235          const iframe = document.querySelector('iframe.giscus-frame');
236          if (!iframe) return;
237          iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
238        }
239        sendMessage({
240          setConfig: {
241            theme: newTheme
242          }
243        });
244      }
245      const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
246      if (isGiscussLoaded) {
247        changeGiscusTheme();
248      }
249    };
250    const authorPrefersDark = false;
251    const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
252    const darkModeDefault = queryPrefersDark.matches;
253      document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
254      document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
255    let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
256    // Dark / light mode switch
257    window.quartoToggleColorScheme = () => {
258      // Read the current dark / light value
259      let toAlternate = !hasAlternateSentinel();
260      toggleColorMode(toAlternate);
261      setStyleSentinel(toAlternate);
262      toggleGiscusIfUsed(toAlternate, darkModeDefault);
263      window.dispatchEvent(new Event('resize'));
264    };
265    queryPrefersDark.addEventListener("change", e => {
266      if(window.localStorage.getItem("quarto-color-scheme") !== null)
267        return;
268      const alternate = e.matches
269      toggleColorMode(alternate);
270      localAlternateSentinel = e.matches ? 'alternate' : 'default'; // this is used alongside local storage!
271      toggleGiscusIfUsed(alternate, darkModeDefault);
272    });
273    // Switch to dark mode if need be
274    if (hasAlternateSentinel()) {
275      toggleColorMode(true);
276    } else {
277      toggleColorMode(false);
278    }
279  </script>
279
280
281<div id="quarto-search-results"></div>
282  <header id="quarto-header" class="headroom fixed-top">
283    <nav class="navbar navbar-expand-lg " data-bs-theme="dark">
284      <div class="navbar-container container-fluid">
285      <div class="navbar-brand-container mx-auto">
286    <a href="./index.html" class="navbar-brand navbar-brand-logo">
287    <img src="./assets/logo.png" alt="" class="navbar-logo light-content">
288    <img src="./assets/logo.png" alt="" class="navbar-logo dark-content">
289    </a>
290    <a class="navbar-brand" href="./index.html">
291    <span class="navbar-title">Johannes Feldhege</span>
292    </a>
293  </div>
294          <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(); }">
295  <span class="navbar-toggler-icon"></span>
296</button>
297          <div class="collapse navbar-collapse" id="navbarCollapse">
298            <ul class="navbar-nav navbar-nav-scroll ms-auto">
299  <li class="nav-item">
300    <a class="nav-link active" href="./index.html" aria-current="page"> 
301<span class="menu-text">Home</span></a>
302  </li>  
303  <li class="nav-item">
304    <a class="nav-link" href="./publikationen.html"> 
305<span class="menu-text">Publikationen</span></a>
306  </li>  
307  <li class="nav-item">
308    <a class="nav-link" href="./cv.html"> 
309<span class="menu-text">CV</span></a>
310  </li>  
311  <li class="nav-item">
312    <a class="nav-link" href="./impressum.html"> 
313<span class="menu-text">Impressum</span></a>
314  </li>  
315  <li class="nav-item compact">
316    <a class="nav-link" href="https://github.com/jfeldhege/"> <i class="bi bi-github" role="img" aria-label="GitHub Profile">
317</i> 
318<span class="menu-text"></span></a>
319  </li>  
320  <li class="nav-item compact">
321    <a class="nav-link" href="https://www.linkedin.com/in/johannes-feldhege/"> <i class="bi bi-linkedin" role="img" aria-label="Linkedin">
322</i> 
323<span class="menu-text"></span></a>
324  </li>  
325  <li class="nav-item">
326    <a class="nav-link" href="https://scholar.google.com/citations?user=KSmfyO8AAAAJ&amp;hl=de"> 
327<span class="menu-text"><i class="ai  ai-google-scholar" title="" style="color:"></i></span></a>
328  </li>  
329  <li class="nav-item">
330    <a class="nav-link" href="https://www.researchgate.net/profile/Johannes-Feldhege"> 
331<span class="menu-text"><i class="ai  ai-researchgate" title="" style="color:"></i></span></a>
332  </li>  
333</ul>
334          </div> <!-- /navcollapse -->
335            <div class="quarto-navbar-tools">
336  <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>
337</div>
338      </div> <!-- /container-fluid -->
339    </nav>
340</header>
341<!-- content -->
342<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-full page-navbar">
343<!-- sidebar -->
344<!-- margin-sidebar -->
345    
346<!-- main -->
347<div class="quarto-about-trestles column-page">
348  <div class="about-entity">
349    <img src="assets/pfp.jpg" class="about-image
350  rounded " style="width: 20em;">
351<header id="title-block-header" class="quarto-title-block default">
352<div class="quarto-title">
353<h1 class="title">Johannes Feldhege, M.Sc. B.A.</h1>
354</div>
355<div class="quarto-title-meta column-page">
356  </div>
357</header>
358    <div class="about-links">
359  <a href="/cv.html" class="about-link" rel="" target="">
360     <span class="about-link-text"><i class="fa-regular fa-file-pdf" aria-label="file-pdf"></i> CV</span>
361  </a>
362  <a href="https://www.linkedin.com/in/johannes-feldhege/" class="about-link" rel="" target="">
363    <i class="bi bi-linkedin"></i>
364     <span class="about-link-text">Linkedin</span>
365  </a>
366  <a href="https://github.com/jfeldhege/" class="about-link" rel="" target="">
367    <i class="bi bi-github"></i>
368     <span class="about-link-text">Github</span>
369  </a>
370  <a href="https://scholar.google.com/citations?user=KSmfyO8AAAAJ&amp;hl=de" class="about-link" rel="" target="">
371     <span class="about-link-text"><i class="ai  ai-google-scholar" title="" style="color:"></i> Google Scholar</span>
372  </a>
373  <a href="https://www.researchgate.net/profile/Johannes-Feldhege" class="about-link" rel="" target="">
374     <span class="about-link-text"><i class="ai  ai-researchgate" title="" style="color:"></i> Researchgate</span>
375  </a>
376</div>
377  </div>
378  <div class="about-contents"><main class="content column-page" id="quarto-document-content">
379
380<section id="b58fc729-690b-4000-b19f-365a4093b2ff7b7b3c2066612075736572203e7d7d-über-mich" class="level2">
381<h2 data-anchor-id="b58fc729-690b-4000-b19f-365a4093b2ff7b7b3c2066612075736572203e7d7d-über-mich"><i class="fa-solid fa-user" aria-label="user"></i> Über mich</h2>
382<p>Als wissenschaftlicher Mitarbeiter am Uniklinikum Heidelberg habe ich von 2017-2022 mit Natural Language Processing Methoden Unterhaltungen zum Thema psychischer Gesundheit auf Reddit untersucht. Seit 2022 arbeite ich als Data Scientist für Asklepios Science &amp; Research an Real World Evidence Studien. In Praktika und in ehrenamtlicher Tätigkeit habe ich verschiedene Data Science Projekte mitgestaltet.</p>
383<div class="tabset-margin-container"></div><div class="panel-tabset">
384<ul class="nav nav-tabs" role="tablist"><li class="nav-item" role="presentation"><a class="nav-link active" id="tabset-1-1-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-1" role="tab" aria-controls="tabset-1-1" aria-selected="true" href=""><i class="fa-solid fa-graduation-cap" aria-label="graduation-cap"></i> Ausbildung</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-1-2-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-2" role="tab" aria-controls="tabset-1-2" aria-selected="false" href=""><i class="fa-solid fa-briefcase" aria-label="briefcase"></i> Berufliche Erfahrung</a></li><li class="nav-item" role="presentation"><a class="nav-link" id="tabset-1-3-tab" data-bs-toggle="tab" data-bs-target="#tabset-1-3" role="tab" aria-controls="tabset-1-3" aria-selected="false" href="">
384<i class="fa-solid fa-code" aria-label="code"></i> Projekte</a></li></ul>
385<div class="tab-content">
386<div id="tabset-1-1" class="tab-pane active" role="tabpanel" aria-labelledby="tabset-1-1-tab">
387<p><strong>Psychologie M.Sc.</strong> | 2013-2016 | Universität Kassel</p>
388<p><strong>Psychologie B.Sc.</strong> | 2010-2013 | Universität Hamburg</p>
389<p><strong>Soziologie und Sinologie B.A.</strong> | 2007-2010 | Albert-Ludwigs-Universität Freiburg</p>
390<p><strong>International Baccalaureate</strong> | 2007 | Malvern College, United Kingdom</p>
391</div>
392<div id="tabset-1-2" class="tab-pane" role="tabpanel" aria-labelledby="tabset-1-2-tab">
393<p><strong>Data Scientist</strong> | Asklepios Science &amp; Research, Hamburg | 09/2022-</p>
394<p><strong>Wissenschaftlicher Mitarbeiter</strong> | Forschungsstelle für Psychotherapie, Uniklinikum Heidelberg | 2016-2022</p>
395<p><strong>Data Science Praktikant</strong> | Eoda GmbH, Kassel | 2016</p>
396<p><strong>R Tutor</strong> | Universität Kassel | 2014-2015</p>
397<p><strong>Studentische Hilfskraft</strong> | Servicestelle Empirische Forschungsmethoden, Universität Hamburg | 2011–2013</p>
398</div>
399<div id="tabset-1-3" class="tab-pane" role="tabpanel" aria-labelledby="tabset-1-3-tab">
400<p><strong>redditoR</strong>: Ein R Paket für Zugriffe auf die API des sozialen Netzwerks Reddit. <a href="https://github.com/jfeldhege/redditoR">Github</a></p>
401<p><strong>Textanalyse von Call-Dokumentationen zur Erarbeitung von Herausforderungen und Erfolgen in vergangenen Projekten</strong>: Ein Projekt mit projecttogether und CorrelAid.</p>
402<p><strong>Die Platte unter der Lupe: Einflussfaktoren auf die Absatzzahlen einer Mannheimer Suppenküche</strong>: Untersuchung der Absatzzahlen des Lokals Mannheimer Platte und deren saisonale und externe Einflussfaktoren. Ein Projekt mit der Mannheimer Platte und CorrelAid. <a href="http://dx.doi.org/10.31219/osf.io/3zsn6">Projektbericht</a></p>
403<p><strong>Experimente mit Quarto Dashboards, WebR und Shinylive</strong>: <a href="https://www.johannesfeldhege.de/dashboard_lifeexp/">Quarto Dashboard</a>, <a href="http://www.johannesfeldhege.de/webr_test/">WebR Testseite</a>, <a href="http://www.johannesfeldhege.de/shinylive_test/">Shinylive in einem Quarto Dokument</a> und <a href="http://www.johannesfeldhege.de/shinylive_test2/">Eine standalone Shinylive App</a></p>
404<p><strong>openholidaysR</strong>: Ein R Paket für Zugriffe auf die OpenHolidays API, die Datumsangaben für Schul- und Feiertage für eine Reihe von Ländern bereitstellt. Jetzt auch auf Cran: <a href="https://cran.r-project.org/web/packages/openholidaysR/index.html">Link zu Cran</a></p>
405</div>
406</div>
407</div>
408<section id="kontakt" class="level4">
409<h4 data-anchor-id="kontakt">Kontakt:</h4>
410<p><i class="fa-regular fa-envelope" aria-label="envelope"></i> mail [at] johannesfeldhege.de</p>
411
412
413</section>
414</section>
415</main></div>
416</div>
417 <!-- /main -->
418<script id="quarto-html-after-body" type="application/javascript">
419  window.document.addEventListener("DOMContentLoaded", function (event) {
420    // Ensure there is a toggle, if there isn't float one in the top right
421    if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
422      const a = window.document.createElement('a');
423      a.classList.add('top-right');
424      a.classList.add('quarto-color-scheme-toggle');
425      a.href = "";
426      a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
427      const i = window.document.createElement("i");
428      i.classList.add('bi');
429      a.appendChild(i);
430      window.document.body.appendChild(a);
431    }
432    setColorSchemeToggle(hasAlternateSentinel())
433    const isCodeAnnotation = (el) => {
434      for (const clz of el.classList) {
435        if (clz.startsWith('code-annotation-')) {                     
436          return true;
437        }
438      }
439      return false;
440    }
441    const onCopySuccess = function(e) {
442      // button target
443      const button = e.trigger;
444      // don't keep focus
445      button.blur();
446      // flash "checked"
447      button.classList.add('code-copy-button-checked');
448      var currentTitle = button.getAttribute("title");
449      button.setAttribute("title", "Copied!");
450      let tooltip;
451      if (window.bootstrap) {
452        button.setAttribute("data-bs-toggle", "tooltip");
453        button.setAttribute("data-bs-placement", "left");
454        button.setAttribute("data-bs-title", "Copied!");
455        tooltip = new bootstrap.Tooltip(button, 
456          { trigger: "manual", 
457            customClass: "code-copy-button-tooltip",
458            offset: [0, -8]});
459        tooltip.show();    
460      }
461      setTimeout(function() {
462        if (tooltip) {
463          tooltip.hide();
464          button.removeAttribute("data-bs-title");
465          button.removeAttribute("data-bs-toggle");
466          button.removeAttribute("data-bs-placement");
467        }
468        button.setAttribute("title", currentTitle);
469        button.classList.remove('code-copy-button-checked');
470      }, 1000);
471      // clear code selection
472      e.clearSelection();
473    }
474    const getTextToCopy = function(trigger) {
475      const outerScaffold = trigger.parentElement.cloneNode(true);
476      const codeEl = outerScaffold.querySelector('code');
477      for (const childEl of codeEl.children) {
478        if (isCodeAnnotation(childEl)) {
479          childEl.remove();
480        }
481      }
482      return codeEl.innerText;
483    }
484    const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
485      text: getTextToCopy
486    });
487    clipboard.on('success', onCopySuccess);
488    if (window.document.getElementById('quarto-embedded-source-code-modal')) {
489      const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
490        text: getTextToCopy,
491        container: window.document.getElementById('quarto-embedded-source-code-modal')
492      });
493      clipboardModal.on('success', onCopySuccess);
494    }
495      var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
496      var mailtoRegex = new RegExp(/^mailto:/);
497        var filterRegex = new RegExp("^(?:http:|https:)\/\/www\.johannesfeldhege\.de\/custom");
498      var isInternal = (href) => {
499          return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
500      }
501      // Inspect non-navigation links and adorn them if external
502     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)');
503      for (var i=0; i<links.length; i++) {
504        const link = links[i];
505        if (!isInternal(link.href)) {
506          // undo the damage that might have been done by quarto-nav.js in the case of
507          // links that we want to consider external
508          if (link.dataset.originalHref !== undefined) {
509            link.href = link.dataset.originalHref;
510          }
511            // target, if specified
512            link.setAttribute("target", "_blank");
513            if (link.getAttribute("rel") === null) {
514              link.setAttribute("rel", "noopener");
515            }
516        }
517      }
518    function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
519      const config = {
520        allowHTML: true,
521        maxWidth: 500,
522        delay: 100,
523        arrow: false,
524        appendTo: function(el) {
525            return el.parentElement;
526        },
527        interactive: true,
528        interactiveBorder: 10,
529        theme: 'quarto',
530        placement: 'bottom-start',
531      };
532      if (contentFn) {
533        config.content = contentFn;
534      }
535      if (onTriggerFn) {
536        config.onTrigger = onTriggerFn;
537      }
538      if (onUntriggerFn) {
539        config.onUntrigger = onUntriggerFn;
540      }
541      window.tippy(el, config); 
542    }
543    const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
544    for (var i=0; i<noterefs.length; i++) {
545      const ref = noterefs[i];
546      tippyHover(ref, function() {
547        // use id or data attribute instead here
548        let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
549        try { href = new URL(href).hash; } catch {}
550        const id = href.replace(/^#\/?/, "");
551        const note = window.document.getElementById(id);
552        if (note) {
553          return note.innerHTML;
554        } else {
555          return "";
556        }
557      });
558    }
559    const xrefs = window.document.querySelectorAll('a.quarto-xref');
560    const processXRef = (id, note) => {
561      // Strip column container classes
562      const stripColumnClz = (el) => {
563        el.classList.remove("page-full", "page-columns");
564        if (el.children) {
565          for (const child of el.children) {
566            stripColumnClz(child);
567          }
568        }
569      }
570      stripColumnClz(note)
571      if (id === null || id.startsWith('sec-')) {
572        // Special case sections, only their first couple elements
573        const container = document.createElement("div");
574        if (note.children && note.children.length > 2) {
575          container.appendChild(note.children[0].cloneNode(true));
576          for (let i = 1; i < note.children.length; i++) {
577            const child = note.children[i];
578            if (child.tagName === "P" && child.innerText === "") {
579              continue;
580            } else {
581              container.appendChild(child.cloneNode(true));
582              break;
583            }
584          }
585          if (window.Quarto?.typesetMath) {
586            window.Quarto.typesetMath(container);
587          }
588          return container.innerHTML
589        } else {
590          if (window.Quarto?.typesetMath) {
591            window.Quarto.typesetMath(note);
592          }
593          return note.innerHTML;
594        }
595      } else {
596        // Remove any anchor links if they are present
597        const anchorLink = note.querySelector('a.anchorjs-link');
598        if (anchorLink) {
599          anchorLink.remove();
600        }
601        if (window.Quarto?.typesetMath) {
602          window.Quarto.typesetMath(note);
603        }
604        if (note.classList.contains("callout")) {
605          return note.outerHTML;
606        } else {
607          return note.innerHTML;
608        }
609      }
610    }
611    for (var i=0; i<xrefs.length; i++) {
612      const xref = xrefs[i];
613      tippyHover(xref, undefined, function(instance) {
614        instance.disable();
615        let url = xref.getAttribute('href');
616        let hash = undefined; 
617        if (url.startsWith('#')) {
618          hash = url;
619        } else {
620          try { hash = new URL(url).hash; } catch {}
621        }
622        if (hash) {
623          const id = hash.replace(/^#\/?/, "");
624          const note = window.document.getElementById(id);
625          if (note !== null) {
626            try {
627              const html = processXRef(id, note.cloneNode(true));
628              instance.setContent(html);
629            } finally {
630              instance.enable();
631              instance.show();
632            }
633          } else {
634            // See if we can fetch this
635            fetch(url.split('#')[0])
636            .then(res => res.text())
637            .then(html => {
638              const parser = new DOMParser();
639              const htmlDoc = parser.parseFromString(html, "text/html");
640              const note = htmlDoc.getElementById(id);
641              if (note !== null) {
642                const html = processXRef(id, note);
643                instance.setContent(html);
644              } 
645            }).finally(() => {
646              instance.enable();
647              instance.show();
648            });
649          }
650        } else {
651          // See if we can fetch a full url (with no hash to target)
652          // This is a special case and we should probably do some content thinning / targeting
653          fetch(url)
654          .then(res => res.text())
655          .then(html => {
656            const parser = new DOMParser();
657            const htmlDoc = parser.parseFromString(html, "text/html");
658            const note = htmlDoc.querySelector('main.content');
659            if (note !== null) {
660              // This should only happen for chapter cross references
661              // (since there is no id in the URL)
662              // remove the first header
663              if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
664                note.children[0].remove();
665              }
666              const html = processXRef(null, note);
667              instance.setContent(html);
668            } 
669          }).finally(() => {
670            instance.enable();
671            instance.show();
672          });
673        }
674      }, function(instance) {
675      });
676    }
677        let selectedAnnoteEl;
678        const selectorForAnnotation = ( cell, annotation) => {
679          let cellAttr = 'data-code-cell="' + cell + '"';
680          let lineAttr = 'data-code-annotation="' +  annotation + '"';
681          const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
682          return selector;
683        }
684        const selectCodeLines = (annoteEl) => {
685          const doc = window.document;
686          const targetCell = annoteEl.getAttribute("data-target-cell");
687          const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
688          const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
689          const lines = annoteSpan.getAttribute("data-code-lines").split(",");
690          const lineIds = lines.map((line) => {
691            return targetCell + "-" + line;
692          })
693          let top = null;
694          let height = null;
695          let parent = null;
696          if (lineIds.length > 0) {
697              //compute the position of the single el (top and bottom and make a div)
698              const el = window.document.getElementById(lineIds[0]);
699              top = el.offsetTop;
700              height = el.offsetHeight;
701              parent = el.parentElement.parentElement;
702            if (lineIds.length > 1) {
703              const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
704              const bottom = lastEl.offsetTop + lastEl.offsetHeight;
705              height = bottom - top;
706            }
707            if (top !== null && height !== null && parent !== null) {
708              // cook up a div (if necessary) and position it 
709              let div = window.document.getElementById("code-annotation-line-highlight");
710              if (div === null) {
711                div = window.document.createElement("div");
712                div.setAttribute("id", "code-annotation-line-highlight");
713                div.style.position = 'absolute';
714                parent.appendChild(div);
715              }
716              div.style.top = top - 2 + "px";
717              div.style.height = height + 4 + "px";
718              div.style.left = 0;
719              let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
720              if (gutterDiv === null) {
721                gutterDiv = window.document.createElement("div");
722                gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
723                gutterDiv.style.position = 'absolute';
724                const codeCell = window.document.getElementById(targetCell);
725                const gutter = codeCell.querySelector('.code-annotation-gutter');
726                gutter.appendChild(gutterDiv);
727              }
728              gutterDiv.style.top = top - 2 + "px";
729              gutterDiv.style.height = height + 4 + "px";
730            }
731            selectedAnnoteEl = annoteEl;
732          }
733        };
734        const unselectCodeLines = () => {
735          const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
736          elementsIds.forEach((elId) => {
737            const div = window.document.getElementById(elId);
738            if (div) {
739              div.remove();
740            }
741          });
742          selectedAnnoteEl = undefined;
743        };
744          // Handle positioning of the toggle
745      window.addEventListener(
746        "resize",
747        throttle(() => {
748          elRect = undefined;
749          if (selectedAnnoteEl) {
750            selectCodeLines(selectedAnnoteEl);
751          }
752        }, 10)
753      );
754      function throttle(fn, ms) {
755      let throttle = false;
756      let timer;
757        return (...args) => {
758          if(!throttle) { // first call gets through
759              fn.apply(this, args);
760              throttle = true;
761          } else { // all the others get throttled
762              if(timer) clearTimeout(timer); // cancel #2
763              timer = setTimeout(() => {
764                fn.apply(this, args);
765                timer = throttle = false;
766              }, ms);
767          }
768        };
769      }
770        // Attach click handler to the DT
771        const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
772        for (const annoteDlNode of annoteDls) {
773          annoteDlNode.addEventListener('click', (event) => {
774            const clickedEl = event.target;
775            if (clickedEl !== selectedAnnoteEl) {
776              unselectCodeLines();
777              const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
778              if (activeEl) {
779                activeEl.classList.remove('code-annotation-active');
780              }
781              selectCodeLines(clickedEl);
782              clickedEl.classList.add('code-annotation-active');
783            } else {
784              // Unselect the line
785              unselectCodeLines();
786              clickedEl.classList.remove('code-annotation-active');
787            }
788          });
789        }
790    const findCites = (el) => {
791      const parentEl = el.parentElement;
792      if (parentEl) {
793        const cites = parentEl.dataset.cites;
794        if (cites) {
795          return {
796            el,
797            cites: cites.split(' ')
798          };
799        } else {
800          return findCites(el.parentElement)
801        }
802      } else {
803        return undefined;
804      }
805    };
806    var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
807    for (var i=0; i<bibliorefs.length; i++) {
808      const ref = bibliorefs[i];
809      const citeInfo = findCites(ref);
810      if (citeInfo) {
811        tippyHover(citeInfo.el, function() {
812          var popup = window.document.createElement('div');
813          citeInfo.cites.forEach(function(cite) {
814            var citeDiv = window.document.createElement('div');
815            citeDiv.classList.add('hanging-indent');
816            citeDiv.classList.add('csl-entry');
817            var biblioDiv = window.document.getElementById('ref-' + cite);
818            if (biblioDiv) {
819              citeDiv.innerHTML = biblioDiv.innerHTML;
820            }
821            popup.appendChild(citeDiv);
822          });
823          return popup.innerHTML;
824        });
825      }
826    }
827  });
828  </script>
828
829</div> <!-- /content -->
830<footer class="footer">
831  <div class="nav-footer">
832    <div class="nav-footer-left">
833      &nbsp;
834    </div>   
835    <div class="nav-footer-center">
836
837<div class="cookie-consent-footer"><a href="#" id="open_preferences_center">Cookie Preferences</a></div></div>
838    <div class="nav-footer-right">
839<p>Mit <i class="fa-brands fa-r-project" aria-label="r-project"></i> und <a href="https://quarto.org/">Quarto</a> erstellt.<br> Source Code auf <a href="https://github.com/jfeldhege/jfeldhege.github.io"><i class="fa-brands fa-github" aria-label="github"></i> GitHub</a></p>
840</div>
841  </div>
842</footer>
843
844
845
846
847</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.