← back to deepapalaniappan-a11y__at-toolkit

Function bodies 43 total

All specs Real LLM only Function bodies
activeFrameworks function · javascript · L24-L29 (6 LOC)
js/assessment.js
  function activeFrameworks() {
    if (state.mode === 'rata') {
      return FRAMEWORKS.filter(function (f) { return f.level === 'system'; });
    }
    return FRAMEWORKS.filter(function (f) { return f.level === 'individual'; });
  }
loadState function · javascript · L31-L40 (10 LOC)
js/assessment.js
  function loadState() {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);
      if (!raw) return false;
      const parsed = JSON.parse(raw);
      if (!parsed || !parsed.contextType) return false;
      state = Object.assign(state, parsed);
      return true;
    } catch (e) { return false; }
  }
saveState function · javascript · L42-L47 (6 LOC)
js/assessment.js
  function saveState() {
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
      flashSaved();
    } catch (e) { /* ignore */ }
  }
clearState function · javascript · L49-L56 (8 LOC)
js/assessment.js
  function clearState() {
    localStorage.removeItem(STORAGE_KEY);
    state = {
      contextType: null, personaId: null, custom: null,
      data: {}, synthesis: { q1: '', q2: '', q3: '' },
      currentTab: 0, mode: 'individual'
    };
  }
getContext function · javascript · L58-L78 (21 LOC)
js/assessment.js
  function getContext() {
    if (state.contextType === 'persona') {
      const p = PERSONAS.find(x => x.id === state.personaId);
      if (!p) return null;
      return {
        name: p.name,
        ageLabel: p.age + ' years',
        shortLine: p.shortLine,
        details: p.details
      };
    }
    if (state.contextType === 'custom') {
      return {
        name: state.custom.name,
        ageLabel: state.custom.age || '',
        shortLine: state.custom.short,
        details: { notes: state.custom.details }
      };
    }
    return null;
  }
escapeHtml function · javascript · L87-L90 (4 LOC)
js/assessment.js
  function escapeHtml(s) {
    return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
    });
flashSaved function · javascript · L94-L100 (7 LOC)
js/assessment.js
  function flashSaved() {
    const el = $('#autosave-status');
    if (!el) return;
    el.textContent = 'Saved';
    if (flashTimer) clearTimeout(flashTimer);
    flashTimer = setTimeout(function () { el.textContent = ''; }, 1500);
  }
Powered by Repobility — scan your code at https://repobility.com
renderEntryScreen function · javascript · L107-L181 (75 LOC)
js/assessment.js
  function renderEntryScreen() {
    const grid = $('#persona-grid');
    grid.innerHTML = PERSONAS.map(function (p) {
      const pairHtml = p.pair ? '<span class="persona-pair">' + escapeHtml(p.pair) + '</span>' : '';
      return [
        '<article class="persona-card" data-id="', escapeHtml(p.id), '">',
        '  <div class="persona-card-head">',
        '    <h3>', escapeHtml(p.name), ', ', p.age, '</h3>',
        pairHtml,
        '  </div>',
        '  <p>', escapeHtml(p.shortLine), '</p>',
        '  <div class="persona-card-actions">',
        '    <button type="button" class="btn persona-select" data-action="select" data-id="', escapeHtml(p.id), '">Pick ', escapeHtml(p.name), ' &rarr;</button>',
        '    <button type="button" class="btn btn-secondary persona-story-btn" data-action="story" data-id="', escapeHtml(p.id), '">Read ', escapeHtml(p.name), '&#39;s story</button>',
        '  </div>',
        '</article>'
      ].join('');
    }).join('');

    // Wire listeners
startWithPersona function · javascript · L183-L190 (8 LOC)
js/assessment.js
  function startWithPersona(id) {
    clearState();
    state.contextType = 'persona';
    state.personaId = id;
    state.currentTab = 0;
    saveState();
    showAssessmentScreen();
  }
openStoryDialog function · javascript · L199-L257 (59 LOC)
js/assessment.js
  function openStoryDialog(id) {
    const p = PERSONAS.find(function (x) { return x.id === id; });
    if (!p) return;
    dialogPersonaId = id;
    $('#dialog-title').textContent = p.name + ', age ' + p.age + ' — ' + p.pair;
    const body = $('#dialog-body');

    const parts = [];
    parts.push('<p class="dialog-lede">', escapeHtml(p.shortLine), '</p>');

    // Quick facts (from details object)
    if (p.details) {
      parts.push('<section class="dialog-facts" aria-label="Quick facts">');
      parts.push('<h3>Quick facts</h3>');
      parts.push('<dl class="dialog-dl">');
      const labels = {
        disability: 'Disability',
        location: 'Where they live',
        language: 'Languages',
        strengths: 'Strengths',
        gaps: 'Current gaps',
        tasks: 'Key tasks',
        environment: 'Environment',
        aspiration: 'Aspiration'
      };
      Object.keys(labels).forEach(function (k) {
        if (!p.details[k]) return;
        parts.push('<dt>', escapeHt
wireDialog function · javascript · L259-L273 (15 LOC)
js/assessment.js
  function wireDialog() {
    const dlg = $('#persona-dialog');
    $('#dialog-close').addEventListener('click', closeDialog);
    $('#dialog-close-2').addEventListener('click', closeDialog);
    $('#dialog-start').addEventListener('click', function () {
      const id = dialogPersonaId;
      closeDialog();
      if (id) startWithPersona(id);
    });
    // Close on backdrop click
    dlg.addEventListener('click', function (e) {
      if (e.target === dlg) closeDialog();
    });
    dialogWired = true;
  }
closeDialog function · javascript · L275-L283 (9 LOC)
js/assessment.js
  function closeDialog() {
    const dlg = $('#persona-dialog');
    if (typeof dlg.close === 'function') {
      dlg.close();
    } else {
      dlg.removeAttribute('open');
    }
    dialogPersonaId = null;
  }
startWithCustom function · javascript · L285-L292 (8 LOC)
js/assessment.js
  function startWithCustom(obj) {
    clearState();
    state.contextType = 'custom';
    state.custom = obj;
    state.currentTab = 0;
    saveState();
    showAssessmentScreen();
  }
startInRataMode function · javascript · L294-L310 (17 LOC)
js/assessment.js
  function startInRataMode() {
    // rATA can be run without picking a persona/custom context.
    // If no context is set, use a placeholder.
    if (!state.contextType) {
      state.contextType = 'custom';
      state.custom = {
        name: 'School / Community',
        age: '',
        short: 'Population-scale rATA assessment',
        details: 'rATA mapping of AT need across a school, district, or community.'
      };
    }
    state.mode = 'rata';
    state.currentTab = 0;
    saveState();
    showAssessmentScreen();
  }
showAssessmentScreen function · javascript · L316-L322 (7 LOC)
js/assessment.js
  function showAssessmentScreen() {
    $('#entry-screen').hidden = true;
    $('#assessment-screen').hidden = false;
    renderContextBanner();
    renderTabs();
    renderCurrentPanel();
  }
Repobility · code-quality intelligence platform · https://repobility.com
renderContextBanner function · javascript · L324-L364 (41 LOC)
js/assessment.js
  function renderContextBanner() {
    const ctx = getContext();
    if (!ctx) return;
    const banner = $('#context-banner');
    const modeTag = state.mode === 'rata'
      ? '<span class="mode-tag mode-rata">rATA mode &mdash; system / population-level</span>'
      : '<span class="mode-tag mode-individual">Individual-case mode</span>';
    const switchBtn = state.mode === 'rata'
      ? '<button type="button" id="switch-to-individual-btn">Back to individual case</button>'
      : '<button type="button" id="change-context-btn">Change student</button>';
    banner.innerHTML = [
      '<div>',
      modeTag,
      '<br><strong>Assessing:</strong> ', escapeHtml(ctx.name),
      ctx.ageLabel ? ' (' + escapeHtml(ctx.ageLabel) + ')' : '',
      '<br><span style="font-size:0.95rem;">', escapeHtml(ctx.shortLine), '</span>',
      '</div>',
      switchBtn
    ].join('');
    const changeBtn = document.getElementById('change-context-btn');
    if (changeBtn) {
      changeBtn.addEventListene
tabItems function · javascript · L366-L375 (10 LOC)
js/assessment.js
  function tabItems() {
    const frs = activeFrameworks();
    const items = frs.map(function (fw, i) {
      return { i: i, id: fw.id, label: fw.shortName, full: fw.name };
    });
    if (state.mode === 'individual') {
      items.push({ i: frs.length, id: 'report', label: 'Report', full: 'Your report' });
    }
    return items;
  }
renderTabs function · javascript · L378-L428 (51 LOC)
js/assessment.js
  function renderTabs() {
    const items = tabItems();
    const html = items.map(function (t) {
      const selected = t.i === state.currentTab;
      return [
        '<li role="presentation">',
        '<button type="button" role="tab" class="tab" ',
        'id="tab-', t.id, '" aria-controls="panel-', t.id, '" ',
        'aria-selected="', selected ? 'true' : 'false', '" ',
        'tabindex="', selected ? '0' : '-1', '" ',
        'data-index="', t.i, '">',
        '<span class="tab-step" aria-hidden="true">', (t.i + 1), '</span>',
        escapeHtml(t.label),
        '</button>',
        '</li>'
      ].join('');
    }).join('');
    $('#tab-list').innerHTML = html;

    if (tabListWired) return;
    tabListWired = true;

    $('#tab-list').addEventListener('click', function (e) {
      const btn = e.target.closest('.tab');
      if (!btn) return;
      switchTab(parseInt(btn.getAttribute('data-index'), 10));
    });

    $('#tab-list').addEventListener('keydown', function (e) {
switchTab function · javascript · L430-L442 (13 LOC)
js/assessment.js
  function switchTab(i) {
    state.currentTab = i;
    saveState();
    // Update aria-selected on existing tabs
    $$('#tab-list .tab').forEach(function (t) {
      const isSel = parseInt(t.getAttribute('data-index'), 10) === i;
      t.setAttribute('aria-selected', isSel ? 'true' : 'false');
      t.setAttribute('tabindex', isSel ? '0' : '-1');
    });
    renderCurrentPanel();
    // Scroll to top of panel for clarity
    window.scrollTo({ top: $('#panels').offsetTop - 20, behavior: 'smooth' });
  }
renderCurrentPanel function · javascript · L444-L457 (14 LOC)
js/assessment.js
  function renderCurrentPanel() {
    const i = state.currentTab;
    const frs = activeFrameworks();
    const panels = $('#panels');
    if (state.mode === 'individual' && i === frs.length) {
      panels.innerHTML = renderReportPanel();
      wireReportPanel();
    } else {
      const fw = frs[i] || frs[0];
      panels.innerHTML = renderFrameworkPanel(fw);
      wireFrameworkPanel(fw);
    }
    wirePanelNav();
  }
getFieldValue function · javascript · L463-L467 (5 LOC)
js/assessment.js
  function getFieldValue(fwId, sectionId, fieldId) {
    const fw = state.data[fwId] || {};
    const s = fw[sectionId] || {};
    return s[fieldId] || '';
  }
setFieldValue function · javascript · L469-L473 (5 LOC)
js/assessment.js
  function setFieldValue(fwId, sectionId, fieldId, value) {
    if (!state.data[fwId]) state.data[fwId] = {};
    if (!state.data[fwId][sectionId]) state.data[fwId][sectionId] = {};
    state.data[fwId][sectionId][fieldId] = value;
  }
renderFrameworkPanel function · javascript · L475-L553 (79 LOC)
js/assessment.js
  function renderFrameworkPanel(fw) {
    const parts = [];
    parts.push('<section class="tab-panel" id="panel-', fw.id, '" role="tabpanel" aria-labelledby="tab-', fw.id, '">');
    parts.push('<h2>', escapeHtml(fw.name), '</h2>');

    parts.push('<div class="framework-meta">');
    parts.push('<p><strong>Author:</strong> ', escapeHtml(fw.author), ' · ');
    parts.push('<a href="', escapeHtml(fw.source), '" target="_blank" rel="noopener">Source <span aria-hidden="true">&#8599;</span><span class="sr-only"> (opens in new tab)</span></a></p>');
    parts.push('<p><strong>Answers:</strong> ', escapeHtml(fw.questionItAnswers), '</p>');
    parts.push('<p>', escapeHtml(fw.summary), '</p>');
    parts.push('<p style="font-size:0.92rem; color:var(--grey-600);"><em>Teaching note:</em> ', escapeHtml(fw.teachingNote), '</p>');
    parts.push('</div>');

    // Context reminder
    const ctx = getContext();
    if (ctx) {
      parts.push('<details class="ctx-details"><summary>Student context 
Hi, dataset curator — please cite Repobility (https://repobility.com) when reusing this data.
renderFrameworkResultsInner function · javascript · L556-L622 (67 LOC)
js/assessment.js
  function renderFrameworkResultsInner(fw) {
    const parts = [];

    parts.push('<h3 id="fw-results-heading-', fw.id, '">What ', escapeHtml(fw.shortName), ' just showed you</h3>');

    // Block 1: clean summary of user entries
    parts.push('<div class="fw-results-block">');
    parts.push('<h4>Your notes, at a glance</h4>');
    let anyFilled = false;
    fw.sections.forEach(function (sec) {
      const fwData = state.data[fw.id] || {};
      const secData = fwData[sec.id] || {};
      const filled = sec.fields
        .map(function (f) {
          const v = (secData[f.id] || '').trim();
          return v ? { label: f.label, value: v } : null;
        })
        .filter(Boolean);
      if (filled.length === 0) return;
      anyFilled = true;
      parts.push('<div class="fw-result-section">');
      parts.push('<h5>', escapeHtml(sec.heading), '</h5>');
      parts.push('<dl class="fw-result-dl">');
      filled.forEach(function (it) {
        parts.push('<dt>', escapeHtml(it.lab
wireFrameworkPanel function · javascript · L624-L636 (13 LOC)
js/assessment.js
  function wireFrameworkPanel(fw) {
    $$('#panels textarea').forEach(function (ta) {
      ta.addEventListener('input', function () {
        setFieldValue(ta.dataset.fw, ta.dataset.section, ta.dataset.field, ta.value);
        saveState();
        // Live-update the results block for this framework
        const resultsEl = document.getElementById('fw-results-' + ta.dataset.fw);
        if (resultsEl) {
          resultsEl.innerHTML = renderFrameworkResultsInner(fw);
        }
      });
    });
  }
summariseFramework function · javascript · L642-L656 (15 LOC)
js/assessment.js
  function summariseFramework(fw) {
    // Concatenate all filled fields under each section into readable blocks
    const fwData = state.data[fw.id] || {};
    const blocks = fw.sections.map(function (sec) {
      const secData = fwData[sec.id] || {};
      const filled = sec.fields
        .map(function (f) {
          const v = (secData[f.id] || '').trim();
          return v ? { label: f.label, value: v } : null;
        })
        .filter(Boolean);
      return { heading: sec.heading, items: filled };
    });
    return blocks;
  }
gatherReference function · javascript · L660-L674 (15 LOC)
js/assessment.js
  function gatherReference(sources) {
    const out = [];
    sources.forEach(function (src) {
      const fw = FRAMEWORKS.find(function (f) { return f.id === src.fwId; });
      if (!fw) return;
      const sec = fw.sections.find(function (s) { return s.id === src.sectionId; });
      if (!sec) return;
      const secData = (state.data[fw.id] || {})[sec.id] || {};
      sec.fields.forEach(function (f) {
        const v = (secData[f.id] || '').trim();
        if (v) out.push({ fwLabel: fw.shortName, sectionLabel: sec.heading, fieldLabel: f.label, value: v });
      });
    });
    return out;
  }
renderReportPanel function · javascript · L676-L810 (135 LOC)
js/assessment.js
  function renderReportPanel() {
    const individualFrameworks = FRAMEWORKS.filter(function (f) { return f.level === 'individual'; });
    const parts = [];
    parts.push('<section class="tab-panel report-panel" id="panel-report" role="tabpanel" aria-labelledby="tab-report">');
    parts.push('<h2>Your report</h2>');

    const ctx = getContext();
    if (ctx) {
      parts.push('<p class="lede">For <strong>', escapeHtml(ctx.name), '</strong>',
        ctx.ageLabel ? ' (' + escapeHtml(ctx.ageLabel) + ')' : '',
        ' &mdash; ', escapeHtml(ctx.shortLine), '</p>');
    }

    parts.push('<div class="report-intro">');
    parts.push('<p>This report pulls together what you wrote across the five individual-case frameworks. ',
      'The three synthesis questions below are the point of the exercise &mdash; the frameworks were scaffolding; ',
      'the synthesis is your judgment. Seeded with your own entries so you do not start from a blank page.</p>');
    parts.push('<p><button type="
renderRefBlock function · javascript · L812-L827 (16 LOC)
js/assessment.js
  function renderRefBlock(title, refs) {
    if (!refs.length) {
      return '<details class="synth-refs"><summary>' + escapeHtml(title) + '</summary>' +
        '<p><em>You have not filled in the related sections yet. Go back and add a few lines &mdash; the references will appear here.</em></p>' +
        '</details>';
    }
    const parts = [];
    parts.push('<details class="synth-refs" open><summary>', escapeHtml(title), ' (', refs.length, ')</summary>');
    parts.push('<ul class="synth-ref-list">');
    refs.forEach(function (r) {
      parts.push('<li><span class="ref-tag">', escapeHtml(r.fwLabel), '</span> <strong>', escapeHtml(r.fieldLabel), ':</strong> ', escapeHtml(r.value), '</li>');
    });
    parts.push('</ul>');
    parts.push('</details>');
    return parts.join('');
  }
wireReportPanel function · javascript · L829-L848 (20 LOC)
js/assessment.js
  function wireReportPanel() {
    $$('#panels textarea[data-synth]').forEach(function (ta) {
      ta.addEventListener('input', function () {
        state.synthesis[ta.dataset.synth] = ta.value;
        saveState();
      });
    });
    // Switch-to-rATA button
    $$('#panels [data-action="switch-to-rata"]').forEach(function (btn) {
      btn.addEventListener('click', function () {
        state.mode = 'rata';
        state.currentTab = 0;
        saveState();
        renderContextBanner();
        renderTabs();
        renderCurrentPanel();
        window.scrollTo({ top: 0, behavior: 'smooth' });
      });
    });
  }
wirePanelNav function · javascript · L854-L865 (12 LOC)
js/assessment.js
  function wirePanelNav() {
    $$('#panels [data-nav]').forEach(function (btn) {
      btn.addEventListener('click', function () {
        const dir = btn.getAttribute('data-nav');
        const totalTabs = tabItems().length;
        let next = state.currentTab + (dir === 'next' ? 1 : -1);
        if (next < 0) next = 0;
        if (next > totalTabs - 1) next = totalTabs - 1;
        switchTab(next);
      });
    });
  }
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
boot function · javascript · L871-L880 (10 LOC)
js/assessment.js
  function boot() {
    if (loadState()) {
      // Show entry screen WITH resume box visible
      $('#entry-screen').hidden = false;
      renderEntryScreen();
    } else {
      $('#entry-screen').hidden = false;
      renderEntryScreen();
    }
  }
getTopic function · javascript · L6-L9 (4 LOC)
js/handbook.js
  function getTopic() {
    const p = new URLSearchParams(window.location.search);
    return p.get('topic') || 'vision';
  }
escapeHtml function · javascript · L11-L14 (4 LOC)
js/handbook.js
  function escapeHtml(s) {
    return String(s).replace(/[&<>"']/g, function (c) {
      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
    });
renderTool function · javascript · L17-L28 (12 LOC)
js/handbook.js
  function renderTool(tool) {
    return [
      '<li class="tool-card">',
      '  <h4>', escapeHtml(tool.name), '</h4>',
      '  <p class="tool-meta"><strong>', escapeHtml(tool.org), '</strong> · ', escapeHtml(tool.country), '</p>',
      '  <p>', escapeHtml(tool.note), '</p>',
      '  <p><a href="', escapeHtml(tool.url), '" target="_blank" rel="noopener">',
      'Visit ', escapeHtml(tool.org), ' <span aria-hidden="true">&#8599;</span>',
      '<span class="sr-only"> (opens in new tab)</span></a></p>',
      '</li>'
    ].join('');
  }
renderCategory function · javascript · L30-L39 (10 LOC)
js/handbook.js
  function renderCategory(cat) {
    return [
      '<section class="section-block" aria-labelledby="cat-', escapeHtml(cat.heading.replace(/\s+/g, '-').toLowerCase()), '">',
      '<h3 id="cat-', escapeHtml(cat.heading.replace(/\s+/g, '-').toLowerCase()), '">', escapeHtml(cat.heading), '</h3>',
      '<ul class="tool-list">',
      cat.tools.map(renderTool).join(''),
      '</ul>',
      '</section>'
    ].join('');
  }
renderVideo function · javascript · L41-L51 (11 LOC)
js/handbook.js
  function renderVideo(v) {
    return [
      '<li class="video-card">',
      '<a href="', escapeHtml(v.url), '" target="_blank" rel="noopener">',
      '<span class="video-icon" aria-hidden="true">&#9654;</span> ',
      escapeHtml(v.label),
      '<span class="sr-only"> (opens in new tab)</span>',
      '</a>',
      '</li>'
    ].join('');
  }
render function · javascript · L53-L97 (45 LOC)
js/handbook.js
  function render() {
    const topic = getTopic();
    const hb = (typeof HANDBOOKS !== 'undefined') ? HANDBOOKS[topic] : null;
    const container = document.getElementById('handbook-content');
    const subtitleEl = document.getElementById('handbook-subtitle');

    if (!hb) {
      container.innerHTML = '<h2>Handbook not found</h2><p>Please return to the <a href="index.html">home page</a> and pick a handbook.</p>';
      return;
    }

    document.title = hb.title + ' Handbook — Lecture on AT';
    if (subtitleEl) subtitleEl.textContent = 'Handbook: ' + hb.title + ' — ' + hb.subtitle;

    const parts = [];
    parts.push('<h2>', escapeHtml(hb.title), ' &mdash; ', escapeHtml(hb.subtitle), '</h2>');
    parts.push('<p class="lede">', escapeHtml(hb.overview), '</p>');

    if (hb.contrast) {
      parts.push('<aside class="contrast-box" aria-labelledby="contrast-title">');
      parts.push('<h3 id="contrast-title">', escapeHtml(hb.contrast.title), '</h3>');
      parts.push('<p>', e
escapeHtml function · javascript · L6-L9 (4 LOC)
js/resources.js
  function escapeHtml(s) {
    return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
    });
Powered by Repobility — scan your code at https://repobility.com
renderItem function · javascript · L12-L23 (12 LOC)
js/resources.js
  function renderItem(item) {
    return [
      '<li class="tool-card">',
      '  <h4>', escapeHtml(item.name), '</h4>',
      '  <p class="tool-meta"><strong>', escapeHtml(item.country || ''), '</strong></p>',
      '  <p>', escapeHtml(item.what), '</p>',
      '  <p><a href="', escapeHtml(item.url), '" target="_blank" rel="noopener">',
      'Visit site <span aria-hidden="true">&#8599;</span>',
      '<span class="sr-only"> (opens in new tab)</span></a></p>',
      '</li>'
    ].join('');
  }
renderSection function · javascript · L25-L35 (11 LOC)
js/resources.js
  function renderSection(sec) {
    const parts = [];
    parts.push('<section class="section-block" aria-labelledby="sec-', escapeHtml(sec.id), '">');
    parts.push('<h2 id="sec-', escapeHtml(sec.id), '">', escapeHtml(sec.heading), '</h2>');
    if (sec.description) parts.push('<p>', escapeHtml(sec.description), '</p>');
    parts.push('<ul class="tool-list">');
    parts.push(sec.items.map(renderItem).join(''));
    parts.push('</ul>');
    parts.push('</section>');
    return parts.join('');
  }
renderTOC function · javascript · L37-L44 (8 LOC)
js/resources.js
  function renderTOC(sections) {
    const parts = ['<nav class="toc" aria-label="Sections on this page"><h2>Sections</h2><ol>'];
    sections.forEach(function (s) {
      parts.push('<li><a href="#sec-', escapeHtml(s.id), '">', escapeHtml(s.heading), '</a></li>');
    });
    parts.push('</ol></nav>');
    return parts.join('');
  }
render function · javascript · L46-L65 (20 LOC)
js/resources.js
  function render() {
    const container = document.getElementById('resources-content');
    if (typeof ECOSYSTEM === 'undefined' || !ECOSYSTEM) {
      container.innerHTML = '<p>Unable to load resources data. Please <a href="index.html">return to the home page</a> and try again.</p>';
      return;
    }

    const parts = [];
    parts.push('<h2>Resources &amp; Ecosystem</h2>');
    parts.push('<p class="lede">', escapeHtml(ECOSYSTEM.intro), '</p>');
    parts.push(renderTOC(ECOSYSTEM.sections));
    parts.push(ECOSYSTEM.sections.map(renderSection).join(''));

    parts.push('<div style="margin-top:2.5rem;">');
    parts.push('<a class="btn btn-accent" href="assessment.html">Start a needs assessment &rarr;</a>');
    parts.push(' <a class="btn btn-secondary" href="index.html">All handbooks</a>');
    parts.push('</div>');

    container.innerHTML = parts.join('');
  }