JavaScript — Functions & Event Reference

Where JS lives

FileLoadedPurpose
Inline in baseof.html <script>every pageGlobal functions (theme, menu)
static/js/article.jsarticle pages via _default/single.html scripts blockReading progress bar, ToC, copy buttons, image lightbox
static/js/pagefind-search.js/posts/ and /tags/Pagefind search UI
static/js/taxonomy.js/tags/ (after inline POSTS[] data)Tag filter logic + article grid
Inline in certs/single.html {{ block "scripts" }}/certs/*Accordion toggle
static/js/ns.js/posts/linux-namespaces/Namespace explorer (data + render)

baseof.html — global functions

toggleTheme()

function toggleTheme()

Called by: onclick on #themeBtn (desktop) and #themeBtnMob (mobile).

What it does:

  1. Reads the current data-theme attribute from <html>
  2. Switches to the opposite (darklight)
  3. Saves to localStorage.theme
  4. Updates the icon on all #themeBtn, #themeBtnMob buttons

CSS link: document.documentElement.setAttribute('data-theme', next) triggers CSS variables [data-theme="light"].


setLang(lang)

function setLang(lang)
// Example call: setLang('ru')

Called by: onclick on .lang-btn buttons in desktop nav and mobile drawer.

What it does: if the page is bilingual (has <meta id="page-lang">) and the selected language differs from the current one — redirects to the data-lang-pair URL. On non-bilingual pages does nothing.


toggleMobMenu()

function toggleMobMenu()

Called by: onclick on #burgerBtn.

What it does: toggles .open class on three elements simultaneously:

  • #mobDrawer — slides out the drawer
  • #mobOverlay — shows the backdrop
  • #burgerBtn — animates burger into an X

closeMobMenu()

function closeMobMenu()

Called by: onclick on #mobOverlay (clicking the overlay closes the menu).

What it does: removes .open from #mobDrawer, #mobOverlay, #burgerBtn.


applyTheme(theme)

function applyTheme(theme)

Single source of truth for theme state. Called on page load and by toggleTheme().

What it does:

  1. Sets data-theme attribute on <html>
  2. Updates icon on all #themeBtn, #themeBtnMob
  3. Sets aria-pressed on theme buttons

Called at end of <body> as: applyTheme(localStorage.getItem('theme') || 'dark')


article.js — article page functions

Path: static/js/article.js — loaded on all single article pages.

Reading progress bar

Uses #readingBar — a CSS-styled <div id="readingBar"> injected at page load. Width updated on scroll event: scrollY / (scrollHeight - viewportHeight) * 100%.

ToC builder

Finds all h2, h3 inside #articleBody. Only activates if more than 2 headings exist. Inserts links into #tocAside, adds .has-toc to .page at width ≥ 860px, highlights active heading via IntersectionObserver.

Copy buttons

For each <pre> not inside .code-block, wraps it in .code-block and adds a copy button. The {{< code >}} shortcode handles its own copy button separately.

Code toggle

Activated via document.body.dataset.codeToggle === 'true'. Set in the page scripts block when code_toggle: true in frontmatter.


pagefind-search.js — Pagefind search UI

Path: static/js/pagefind-search.js — loaded on /posts/ and /tags/.

Lazy-loads /pagefind/pagefind.js on first keypress. Renders results into #searchResults (CSS-positioned below .search-wrap). Closes on click outside .search-wrap.


taxonomy.js — tag filter logic

Path: static/js/taxonomy.js — loaded on /tags/ after an inline <script> that defines POSTS[] and currentTag.

Reads POSTS[] (Hugo-generated, EN only) and currentTag (current tag slug from Hugo) from the page. Builds the tag grid, filters articles, manages the active pill UI.

Data contract (set inline in tag.html before this script):

const POSTS = [{ url, title, date, tags, tagLabels, summary }, ...];
const currentTag = "linux"; // or "" if on /tags/ root


certs/single.html — accordion

function toggleTopic(btn) {
  const topic = btn.closest('.cert-topic');
  const body  = topic.querySelector('.cert-topic-body');
  if (!body) return;                              // topics without posts don't expand
  const open = topic.classList.toggle('open');
  body.style.maxHeight = open ? body.scrollHeight + 'px' : '0';
}

Animation via max-height: CSS animation max-height: 0 → scrollHeight. scrollHeight = actual content height.

Why not height: auto? CSS cannot animate auto. max-height is the standard workaround.


ns.js — Namespace Explorer

Path: static/js/ns.js
Loaded: only on /posts/linux-namespaces/ via <script src="{{ "js/ns.js" | relURL }}">

Contains:

  • nsData — array of objects with data for all namespaces (name, flag, icon, color, summary, desc…)
  • cheatData — array of commands for the cheatsheet table
  • Render functions: buildNsGrid(), buildNsMap(), buildCheatTable()
  • nsToggleCard(el) — expands/collapses a namespace card
  • IntersectionObserver — progress bar (how many namespaces have been read)
  • buildToc() — builds the table of contents in aside