Changes for page Alder Support Center scripts
Last modified by wiki admin on 2026/08/26 01:04
From version 7.1
edited by wiki admin
on 2026/08/24 22:31
on 2026/08/24 22:31
Change comment:
There is no comment for this version
To 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
Summary
-
Page properties (1 modified, 0 added, 0 removed)
-
Objects (0 modified, 0 added, 1 removed)
Details
- Page properties
-
- Content
-
... ... @@ -1,1 +1,1 @@ 1 -Article accordion. Edit the object, not this text. 1 +Article accordion for the customer-facing design. Edit the object, not this text.
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,166 +1,0 @@ 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 isWikiHome() { 42 - // The employees home page has several H2s (departments, article status, 43 - // publishing workflow). Collapsing a landing page into rows hides the 44 - // thing people came for, so skip it. Matches both URL schemes this 45 - // deployment serves: /bin/view/Main/ and /wiki/<name>/view/Main/. 46 - var path = (window.location.pathname || '').replace(/\/+$/, ''); 47 - return /\/view\/Main(\/WebHome)?$/.test(path); 48 - } 49 - 50 - function build() { 51 - var body = document.body; 52 - if (!body || body.className.indexOf('viewbody') === -1) { 53 - return; // edit, preview, or anything that is not a rendered page 54 - } 55 - if (isWikiHome()) { return; } 56 - var content = document.getElementById('xwikicontent'); 57 - if (!content) { return; } 58 - 59 - // Find the element the section headings actually live in. XWiki wraps 60 - // rendered content in its own container (.f-accordion-panel on this 61 - // instance), so the headings are NOT direct children of #xwikicontent -- 62 - // an earlier version of this script looked only at content.children, found 63 - // nothing on every real article, and silently did nothing. The Preview 64 - // page hid that, because hand-written wiki markup does put headings at the 65 - // top level. 66 - var found = content.querySelectorAll('h2'); 67 - if (found.length < MIN_SECTIONS) { return; } 68 - 69 - // Group headings that share a parent, using the parent holding the most of 70 - // them. Taking every h2 regardless of depth would tear headings out of 71 - // tables and macro boxes they belong to. 72 - var byParent = []; 73 - for (var f = 0; f < found.length; f++) { 74 - var parent = found[f].parentNode; 75 - var slot = null; 76 - for (var b = 0; b < byParent.length; b++) { 77 - if (byParent[b].parent === parent) { slot = byParent[b]; break; } 78 - } 79 - if (!slot) { slot = { parent: parent, items: [] }; byParent.push(slot); } 80 - slot.items.push(found[f]); 81 - } 82 - byParent.sort(function (a, b) { return b.items.length - a.items.length; }); 83 - 84 - var container = byParent[0].parent; 85 - var headings = byParent[0].items; 86 - if (headings.length < MIN_SECTIONS) { return; } 87 - 88 - var made = []; 89 - headings.forEach(function (h2, index) { 90 - var details = document.createElement('details'); 91 - details.className = 'alder-sec'; 92 - if (index === 0) { details.open = true; } 93 - 94 - var summary = document.createElement('summary'); 95 - var title = document.createElement('span'); 96 - title.className = 'alder-sec-title'; 97 - title.textContent = (h2.textContent || '').trim(); 98 - summary.appendChild(title); 99 - summary.appendChild(chevron()); 100 - details.appendChild(summary); 101 - 102 - var wrap = document.createElement('div'); 103 - wrap.className = 'alder-sec-body'; 104 - details.appendChild(wrap); 105 - 106 - // Keep the heading's id on the details element so existing anchors and 107 - // the table-of-contents macro still resolve to something. 108 - if (h2.id) { details.id = h2.id; h2.removeAttribute('id'); } 109 - 110 - container.insertBefore(details, h2); 111 - 112 - // Move the heading and everything up to the next h2 into the body. 113 - var node = h2; 114 - while (node && !(node !== h2 && node.tagName === 'H2')) { 115 - var next = node.nextSibling; 116 - wrap.appendChild(node); 117 - node = next; 118 - if (node && node.nodeType === 1 && node.tagName === 'H2') { break; } 119 - } 120 - made.push(details); 121 - }); 122 - 123 - if (!made.length) { return; } 124 - 125 - var tools = document.createElement('div'); 126 - tools.className = 'alder-tools'; 127 - tools.appendChild(button('Expand all', true, made)); 128 - tools.appendChild(button('Collapse all', false, made)); 129 - container.insertBefore(tools, made[0]); 130 - 131 - openFromHash(); 132 - window.addEventListener('hashchange', openFromHash); 133 - } 134 - 135 - function button(label, open, sections) { 136 - var b = document.createElement('button'); 137 - b.type = 'button'; 138 - b.textContent = label; 139 - b.addEventListener('click', function () { 140 - sections.forEach(function (d) { d.open = open; }); 141 - }); 142 - return b; 143 - } 144 - 145 - function openFromHash() { 146 - var hash = window.location.hash; 147 - if (!hash || hash.length < 2) { return; } 148 - var id = hash.slice(1); 149 - var target = null; 150 - try { 151 - target = document.getElementById(id); 152 - } catch (e) { 153 - return; 154 - } 155 - if (!target) { return; } 156 - // Open the target itself if it is a section, plus any collapsed ancestor. 157 - var node = target; 158 - while (node && node !== document.body) { 159 - if (node.tagName === 'DETAILS') { node.open = true; } 160 - node = node.parentNode; 161 - } 162 - if (target.scrollIntoView) { target.scrollIntoView(); } 163 - } 164 - 165 - ready(build); 166 -})(); - Name
-
... ... @@ -1,1 +1,0 @@ 1 -Article accordion - Parse content
-
... ... @@ -1,1 +1,0 @@ 1 -No - Use this extension
-
... ... @@ -1,1 +1,0 @@ 1 -always