Resource Toolbox Generator

Fill in resource details below, then generate HTML to paste directly into a Drupal body field.

Resource Toolbox Generator — InterVarsity (Drupal)

How to use

  1. Click Add Resource for each resource you want to include.
  2. Fill in the fields. Fields marked * are required. Click the card header to collapse/expand it.
  3. Resources are grouped by Category — resources sharing the same category name appear under the same heading in the output. Heading order follows the order resources are listed here.
  4. Use ↑ ↓ to reorder resources. Use to remove one.
  5. Click Generate HTML. Fix any errors shown, then click Copy HTML.
  6. In Drupal, open the overview page, scroll to the Body field, and switch the editor to Source mode. Paste and save.
Alt Text Tips
  • Describe what the image shows — skip "Image of…" or "Picture of…"
  • Keep it under ~125 characters
  • Leave blank if the image is purely decorative, or if the title already fully communicates what it is (e.g. a book cover where the title is the book name)

Resources

0
📄
No resources yet — click Add Resource to begin.

Generate HTML

When all resources are filled in, click Generate. You can re-generate after any edits.

⚠ Fix the following before generating:

Generated HTML — ready to paste into Thinkific


Pasting into Drupal:
  1. Navigate to the overview page and click Edit.
  2. In the Body field toolbar, click the Source button (may appear as </> or Source depending on your editor).
  3. Select all existing content in the source editor and delete it, then paste your copied code.
  4. Click Save.
Text format requirement: The generated HTML includes <style> and <script> tags. Your Body field must use the Full HTML text format — Basic HTML will strip these tags and break the layout and See More behavior. If you don't see a format selector, ask your Drupal admin to confirm your format is set to Full HTML.

         

tag is split to avoid ending the outer script block return `

\t
\t\t

\t
\t
\t\t

All resources referenced from this course will be linked below for your convenience to view and download. Please use/adapt these resources to what works for you in your ministry context.

\t
${listContent}

Back to Top of Toolbox

<` + `script> \t(function() { \t\tconst SELECTOR = "p.description-text, p[data-clamp]"; \t\tconst MAX_LINES = 2; \t\tconst LABEL_MORE = "See more"; \t\tconst LABEL_LESS = "See less"; \t\tconst LINK_CLASS = "see-more-link"; \t\tfunction getLineHeight(el) { \t\t\tconst lh = parseFloat(window.getComputedStyle(el).lineHeight); \t\t\treturn isNaN(lh) ? parseFloat(window.getComputedStyle(el).fontSize) * 1.2 : lh; \t\t} \t\tfunction binarySearchTruncation(p, fullText, link, maxHeight) { \t\t\tlet lo = 0, hi = fullText.length, best = ""; \t\t\tconst textNode = p.firstChild; \t\t\twhile (lo <= hi) { \t\t\t\tconst mid = Math.floor((lo + hi) / 2); \t\t\t\ttextNode.nodeValue = fullText.slice(0, mid) + "\\u2026 "; \t\t\t\tif (p.scrollHeight <= maxHeight) { best = fullText.slice(0, mid); lo = mid + 1; } \t\t\t\telse { hi = mid - 1; } \t\t\t} \t\t\treturn best.slice(0, -3).trim(); \t\t} \t\tfunction setupOne(p) { \t\t\tp.style.display = "block"; \t\t\tp.style.webkitLineClamp = "unset"; \t\t\tp.style.webkitBoxOrient = "unset"; \t\t\tp.style.lineClamp = "unset"; \t\t\tp.style.textOverflow = "clip"; \t\t\tconst fullText = p.textContent.trim(); \t\t\tconst textNode = document.createTextNode(""); \t\t\tconst link = document.createElement("a"); \t\t\tlink.href = "#"; link.className = LINK_CLASS; \t\t\tlink.setAttribute("aria-label", LABEL_MORE); \t\t\tlink.textContent = LABEL_MORE; \t\t\tp.textContent = ""; \t\t\tp.appendChild(textNode); \t\t\tp.appendChild(link); \t\t\tlet expanded = false; \t\t\tfunction render() { \t\t\t\tconst maxHeight = Math.round(getLineHeight(p) * MAX_LINES); \t\t\t\tp.style.maxHeight = "none"; p.style.overflow = "visible"; \t\t\t\ttextNode.nodeValue = fullText; \t\t\t\tif (expanded) { \t\t\t\t\ttextNode.nodeValue = fullText + " "; link.textContent = LABEL_LESS; link.style.display = ""; return; \t\t\t\t} \t\t\t\tif (p.scrollHeight <= maxHeight) { \t\t\t\t\tlink.style.display = "none"; \t\t\t\t} else { \t\t\t\t\tlink.style.display = ""; link.textContent = LABEL_MORE; \t\t\t\t\tp.style.maxHeight = maxHeight + "px"; p.style.overflow = "hidden"; \t\t\t\t\ttextNode.nodeValue = binarySearchTruncation(p, fullText, link, maxHeight) + "\\u2026 "; \t\t\t\t} \t\t\t} \t\t\tlink.addEventListener("click", function(e) { e.preventDefault(); expanded = !expanded; render(); }); \t\t\tnew ResizeObserver(render).observe(p); \t\t\trender(); \t\t} \t\tfunction processAll() { \t\t\tdocument.querySelectorAll(SELECTOR).forEach(function(p) { \t\t\t\tif (!p.querySelector("." + LINK_CLASS)) setupOne(p); \t\t\t}); \t\t} \t\twindow.initSeeMore = processAll; \t\tif (document.readyState === "loading") document.addEventListener("DOMContentLoaded", processAll); \t\telse processAll(); \t})(); <` + `/script>`; } // ───────────────────────────────────────────── // Copy to clipboard // ───────────────────────────────────────────── function copyHTML() { const text = document.getElementById('output-code').textContent; const btn = document.getElementById('copy-btn'); navigator.clipboard.writeText(text).then(() => { btn.textContent = '✓ Copied!'; btn.classList.add('done'); setTimeout(() => { btn.innerHTML = '📋 Copy HTML'; btn.classList.remove('done'); }, 2500); }).catch(() => { // Fallback for browsers without clipboard API const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); btn.textContent = '✓ Copied!'; btn.classList.add('done'); setTimeout(() => { btn.innerHTML = '📋 Copy HTML'; btn.classList.remove('done'); }, 2500); }); } // ───────────────────────────────────────────── // Utilities // ───────────────────────────────────────────── function escHtml(s) { if (!s) return ''; return s.replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"').replace(/'/g,'''); } function escAttr(s) { if (!s) return ''; return s.replace(/&/g,'&').replace(/"/g,'"').replace(//g,'>'); }