Changes for page Alder Support Center scripts
Last modified by wiki admin on 2026/08/26 01:04
From version 1.1
edited by wiki admin
on 2026/08/24 21:04
on 2026/08/24 21:04
Change comment:
There is no comment for this version
To version 5.1
edited by wiki admin
on 2026/08/24 22:13
on 2026/08/24 22:13
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
-
Objects (0 modified, 1 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -1,1 +1,1 @@ 1 -Article accordion for the customer-facing design. Edit the object, not this text.1 +Article accordion. Edit the object, not this text.
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,0 +1,135 @@ 1 +/* =========================================================================== 2 + Alder Support Center - article accordion 3 + Goes in an XWiki.JavaScriptExtension object on AlderTheme.Scripts (alder wiki). 4 + 5 + Turns each top-level H2 inside #xwikicontent into a collapsible section, so a 6 + long omnibus article becomes a short list of section titles. No article needs 7 + editing: the sections come from headings the content already has. 8 + 9 + Deliberate behaviours, all reversible by disabling this object: 10 + * Sections open independently. Opening one does not close another. 11 + * The first section starts open, so the page never looks empty. 12 + * Fewer than two H2s: nothing happens, the article renders normally. 13 + * Edit/preview modes are skipped, or authors would be editing generated 14 + markup. 15 + * A link to a heading inside a collapsed section opens that section and 16 + scrolls to it, including on first load and on later hash changes. 17 + =========================================================================== */ 18 +(function () { 19 + 'use strict'; 20 + 21 + var MIN_SECTIONS = 2; 22 + 23 + function ready(fn) { 24 + if (document.readyState === 'loading') { 25 + document.addEventListener('DOMContentLoaded', fn); 26 + } else { 27 + fn(); 28 + } 29 + } 30 + 31 + function chevron() { 32 + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); 33 + svg.setAttribute('class', 'alder-chev'); 34 + svg.setAttribute('viewBox', '0 0 24 24'); 35 + var path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); 36 + path.setAttribute('d', 'M6 9l6 6 6-6'); 37 + svg.appendChild(path); 38 + return svg; 39 + } 40 + 41 + function build() { 42 + var body = document.body; 43 + if (!body || body.className.indexOf('viewbody') === -1) { 44 + return; // edit, preview, or anything that is not a rendered page 45 + } 46 + var content = document.getElementById('xwikicontent'); 47 + if (!content) { return; } 48 + 49 + // Only top-level headings. An h2 nested inside a table or a macro box is 50 + // part of that structure and must not be torn out of it. 51 + var headings = []; 52 + for (var i = 0; i < content.children.length; i++) { 53 + if (content.children[i].tagName === 'H2') { headings.push(content.children[i]); } 54 + } 55 + if (headings.length < MIN_SECTIONS) { return; } 56 + 57 + var made = []; 58 + headings.forEach(function (h2, index) { 59 + var details = document.createElement('details'); 60 + details.className = 'alder-sec'; 61 + if (index === 0) { details.open = true; } 62 + 63 + var summary = document.createElement('summary'); 64 + var title = document.createElement('span'); 65 + title.className = 'alder-sec-title'; 66 + title.textContent = (h2.textContent || '').trim(); 67 + summary.appendChild(title); 68 + summary.appendChild(chevron()); 69 + details.appendChild(summary); 70 + 71 + var wrap = document.createElement('div'); 72 + wrap.className = 'alder-sec-body'; 73 + details.appendChild(wrap); 74 + 75 + // Keep the heading's id on the details element so existing anchors and 76 + // the table-of-contents macro still resolve to something. 77 + if (h2.id) { details.id = h2.id; h2.removeAttribute('id'); } 78 + 79 + content.insertBefore(details, h2); 80 + 81 + // Move the heading and everything up to the next h2 into the body. 82 + var node = h2; 83 + while (node && !(node !== h2 && node.tagName === 'H2')) { 84 + var next = node.nextSibling; 85 + wrap.appendChild(node); 86 + node = next; 87 + if (node && node.nodeType === 1 && node.tagName === 'H2') { break; } 88 + } 89 + made.push(details); 90 + }); 91 + 92 + if (!made.length) { return; } 93 + 94 + var tools = document.createElement('div'); 95 + tools.className = 'alder-tools'; 96 + tools.appendChild(button('Expand all', true, made)); 97 + tools.appendChild(button('Collapse all', false, made)); 98 + content.insertBefore(tools, made[0]); 99 + 100 + openFromHash(); 101 + window.addEventListener('hashchange', openFromHash); 102 + } 103 + 104 + function button(label, open, sections) { 105 + var b = document.createElement('button'); 106 + b.type = 'button'; 107 + b.textContent = label; 108 + b.addEventListener('click', function () { 109 + sections.forEach(function (d) { d.open = open; }); 110 + }); 111 + return b; 112 + } 113 + 114 + function openFromHash() { 115 + var hash = window.location.hash; 116 + if (!hash || hash.length < 2) { return; } 117 + var id = hash.slice(1); 118 + var target = null; 119 + try { 120 + target = document.getElementById(id); 121 + } catch (e) { 122 + return; 123 + } 124 + if (!target) { return; } 125 + // Open the target itself if it is a section, plus any collapsed ancestor. 126 + var node = target; 127 + while (node && node !== document.body) { 128 + if (node.tagName === 'DETAILS') { node.open = true; } 129 + node = node.parentNode; 130 + } 131 + if (target.scrollIntoView) { target.scrollIntoView(); } 132 + } 133 + 134 + ready(build); 135 +})(); - Name
-
... ... @@ -1,0 +1,1 @@ 1 +Article accordion - Parse content
-
... ... @@ -1,0 +1,1 @@ 1 +No - Use this extension
-
... ... @@ -1,0 +1,1 @@ 1 +always