MediaWiki:Common.js: Difference between revisions
From WikiMSK
No edit summary |
No edit summary |
||
Line 13: | Line 13: | ||
$('document').ready(function() { | $('document').ready(function() { | ||
// Get all the <h2> headings | // Get all the <h2> headings | ||
const headings = document.querySelectorAll('.mw-parser-output h2') | const headings = document.querySelectorAll('.mw-parser-output h2') | ||
Array.prototype.forEach.call(headings, heading => { | Array.prototype.forEach.call(headings, heading => { | ||
Line 26: | Line 26: | ||
</svg> | </svg> | ||
</button> | </button> | ||
` | ` | ||
// Function to create a node list | // Function to create a node list | ||
// of the content between this <h2> and the next | // of the content between this <h2> and the next | ||
const getContent = (elem) => { | const getContent = (elem) => { | ||
let elems = [] | let elems = [] | ||
while (elem.nextElementSibling && elem.nextElementSibling.tagName !== 'H2') { | while (elem.nextElementSibling && elem.nextElementSibling.tagName !== 'H2') { | ||
elems.push(elem.nextElementSibling) | elems.push(elem.nextElementSibling) | ||
elem = elem.nextElementSibling | elem = elem.nextElementSibling | ||
} | } | ||
// Delete the old versions of the content nodes | // Delete the old versions of the content nodes | ||
elems.forEach((node) => { | elems.forEach((node) => { | ||
node.parentNode.removeChild(node) | node.parentNode.removeChild(node) | ||
}) | }) | ||
return elems | return elems | ||
} | } | ||
// Assign the contents to be expanded/collapsed (array) | // Assign the contents to be expanded/collapsed (array) | ||
let contents = getContent(heading) | let contents = getContent(heading) | ||
// Create a wrapper element for `contents` and hide it | // Create a wrapper element for `contents` and hide it | ||
let wrapper = document.createElement('div') | let wrapper = document.createElement('div') | ||
wrapper.hidden = true | wrapper.hidden = true | ||
// Add each element of `contents` to `wrapper` | // Add each element of `contents` to `wrapper` | ||
contents.forEach(node => { | contents.forEach(node => { | ||
wrapper.appendChild(node) | wrapper.appendChild(node) | ||
}) | }) | ||
// Add the wrapped content back into the DOM | // Add the wrapped content back into the DOM | ||
// after the heading | // after the heading | ||
heading.parentNode.insertBefore(wrapper, heading.nextElementSibling) | heading.parentNode.insertBefore(wrapper, heading.nextElementSibling) | ||
// Assign the button | // Assign the button | ||
let btn = heading.querySelector('button') | let btn = heading.querySelector('button') | ||
btn.onclick = () => { | btn.onclick = () => { | ||
// Cast the state as a boolean | // Cast the state as a boolean | ||
let expanded = btn.getAttribute('aria-expanded') === 'true' || false | let expanded = btn.getAttribute('aria-expanded') === 'true' || false | ||
// Switch the state | // Switch the state | ||
btn.setAttribute('aria-expanded', !expanded) | btn.setAttribute('aria-expanded', !expanded) | ||
// Switch the content's visibility | // Switch the content's visibility | ||
wrapper.hidden = expanded | wrapper.hidden = expanded | ||
} | } | ||
}) | }) | ||
})() | })() |
Revision as of 08:12, 22 August 2020
/* Any JavaScript here will be loaded for all users on every page load. */
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
$('document').ready(function() {
// Get all the <h2> headings
const headings = document.querySelectorAll('.mw-parser-output h2')
Array.prototype.forEach.call(headings, heading => {
// Give each <h2> a toggle button child
// with the SVG plus/minus icon
heading.innerHTML = `
<button aria-expanded="false">
${heading.textContent}
<svg aria-hidden="true" focusable="false" viewBox="0 0 10 10">
<rect class="vert" height="8" width="2" y="1" x="4"/>
<rect height="2" width="8" y="4" x="1"/>
</svg>
</button>
`
// Function to create a node list
// of the content between this <h2> and the next
const getContent = (elem) => {
let elems = []
while (elem.nextElementSibling && elem.nextElementSibling.tagName !== 'H2') {
elems.push(elem.nextElementSibling)
elem = elem.nextElementSibling
}
// Delete the old versions of the content nodes
elems.forEach((node) => {
node.parentNode.removeChild(node)
})
return elems
}
// Assign the contents to be expanded/collapsed (array)
let contents = getContent(heading)
// Create a wrapper element for `contents` and hide it
let wrapper = document.createElement('div')
wrapper.hidden = true
// Add each element of `contents` to `wrapper`
contents.forEach(node => {
wrapper.appendChild(node)
})
// Add the wrapped content back into the DOM
// after the heading
heading.parentNode.insertBefore(wrapper, heading.nextElementSibling)
// Assign the button
let btn = heading.querySelector('button')
btn.onclick = () => {
// Cast the state as a boolean
let expanded = btn.getAttribute('aria-expanded') === 'true' || false
// Switch the state
btn.setAttribute('aria-expanded', !expanded)
// Switch the content's visibility
wrapper.hidden = expanded
}
})
})()