MediaWiki
MediaWiki:Group-Grouse.js
From Grouse House Wiki
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
$(function() { $('h2.c-header.active span.mw-headline').each(function () { var $header = $(this); var $headername = $header.html(); $headernameu = $headername.split(' ').join('_'); $headernameu = $headernameu.replace("'", "\\'").replace("?", "\\?").replace("!", "\\!"); var $secondheader = "#" + $headernameu + "_2"; var $editsection = $( $secondheader ).next().children('a').attr("href"); $header.after('[Edit]'); $header.next().css( 'font-size', '0.6em').css( 'margin-left', '1em'); $("a[href*='" + $secondheader + "']").hide(); }); }); $(function() { $('h2.c-header.hidden span.mw-headline').each(function () { var $header = $(this); var $headername = $header.html(); $headernameu = $headername.split(' ').join('_'); $headernameu = $headernameu.replace("'", "\\'").replace("?", "\\?").replace("!", "\\!"); var $secondheader = "#" + $headernameu + "_2"; var $editsection = $( $secondheader ).next().children('a').attr("href"); $header.after('[Edit]'); $header.next().css( 'font-size', '0.6em').css( 'margin-left', '1em'); $("a[href='" + $secondheader + "']").hide(); }); }); $(function() { $('h2.h-static span.mw-headline').each(function () { var $header = $(this); var $headername = $header.html(); $headernameu = $headername.split(' ').join('_'); $headernameu = $headernameu.replace("'", "\\'").replace("?", "\\?").replace("!", "\\!"); var $secondheader = "#" + $headernameu + "_2"; var $editsection = $( $secondheader ).next().children('a').attr("href"); $header.after('[Edit]'); $header.next().css( 'font-size', '0.6em').css( 'margin-left', '1em'); var $pagename = $('h1#firstHeading').html(); $pagenameu = $pagename.split(' ').join('_'); $toclink = "https://grousehouse.wiki/" + $pagenameu + $secondheader; $("a[href*='" + $secondheader + "']").hide(); }); }); $(function() { $('h3.c-header.active span.mw-headline').each(function () { var $header = $(this); var $headername = $header.html(); $headernameu = $headername.split(' ').join('_'); $headernameu = $headernameu.replace("'", "\\'").replace("?", "\\?").replace("!", "\\!"); var $secondheader = "#" + $headernameu + "_2"; var $editsection = $( $secondheader ).next().children('a').attr("href"); $header.after('[Edit]'); $header.next().css( 'font-size', '0.6em').css( 'margin-left', '1em'); $("a[href*='" + $secondheader + "']").hide(); }); }); $(function() { $('h3.c-header.hidden span.mw-headline').each(function () { var $header = $(this); var $headername = $header.html(); $headernameu = $headername.split(' ').join('_'); $headernameu = $headernameu.replace("'", "\\'").replace("?", "\\?").replace("!", "\\!"); var $secondheader = "#" + $headernameu + "_2"; var $editsection = $( $secondheader ).next().children('a').attr("href"); $header.after('[Edit]'); $header.next().css( 'font-size', '0.6em').css( 'margin-left', '1em'); var $pagename = $('h1#firstHeading').html(); $pagenameu = $pagename.split(' ').join('_'); $toclink = "https://grousehouse.wiki/" + $pagenameu + $secondheader; $("a[href*='" + $secondheader + "']").hide(); }); }); $(function() { $('h3.h-static span.mw-headline').each(function () { var $header = $(this); var $headername = $header.html(); $headernameu = $headername.split(' ').join('_'); $headernameu = $headernameu.replace("'", "\\'").replace("?", "\\?").replace("!", "\\!"); var $secondheader = "#" + $headernameu + "_2"; var $editsection = $( $secondheader ).next().children('a').attr("href"); $header.after('[Edit]'); $header.next().css( 'font-size', '0.6em').css( 'margin-left', '1em'); var $pagename = $('h1#firstHeading').html(); $pagenameu = $pagename.split(' ').join('_'); $toclink = "https://grousehouse.wiki/" + $pagenameu + $secondheader; $("a[href*='" + $secondheader + "']").hide(); }); }); /* Testing */ (function() { // Check for <template> support if ('content' in document.createElement('template')) { const tmpl = document.createElement('template') // Create the web component's template // featuring a <slot> for the Light DOM content tmpl.innerHTML = ` <h2> <button aria-expanded="false"> <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> </h2> <div class="content" hidden> <slot></slot> </div> <style> h2 { margin: 0; } h2 button { all: inherit; box-sizing: border-box; display: flex; justify-content: space-between; width: 100%; padding: 0.5em 0; } h2 button:focus svg { outline: 2px solid; } button svg { height: 1em; margin-left: 0.5em; } [aria-expanded="true"] .vert { display: none; } [aria-expanded] rect { fill: currentColor; } </style> ` // Check for latest Shadow DOM syntax support if (document.head.attachShadow) { class ToggleSection extends HTMLElement { constructor() { super() // Make the host element a region this.setAttribute('role', 'region') // Create a `shadowRoot` and populate from template this.attachShadow({ mode: 'open' }) this.shadowRoot.appendChild(tmpl.content.cloneNode(true)) // Assign the toggle button this.btn = this.shadowRoot.querySelector('h2 button') // Get the first element in Light DOM const oldHeading = this.querySelector(':first-child') // and cast its heading level (which should, but may not, exist) let level = parseInt(oldHeading.tagName.substr(1)) // Then take its `id` (may be null) let id = oldHeading.id // Get the Shadow DOM <h2> this.heading = this.shadowRoot.querySelector('h2') // If `id` exists, apply it if (id) { this.heading.id = id } // If there is no level, there is no heading. // Add a warning. if (!level) { console.warn('The first element inside each <toggle-section> should be a heading of an appropriate level.') } // If the level is a real integer but not 2 // set `aria-level` accordingly if (level && level !== 2) { this.heading.setAttribute('aria-level', level) } // Add the Light DOM heading label to the innerHTML of the toggle button // and remove the now unwanted Light DOM heading this.btn.innerHTML = oldHeading.textContent + this.btn.innerHTML oldHeading.parentNode.removeChild(oldHeading) // The main state switching function this.switchState = () => { let expanded = this.getAttribute('open') === 'true' || false // Toggle `aria-expanded` this.btn.setAttribute('aria-expanded', expanded) // Toggle the `.content` element's visibility this.shadowRoot.querySelector('.content').hidden = !expanded } this.btn.onclick = () => { // Change the component's `open` attribute value on click let open = this.getAttribute('open') === 'true' || false this.setAttribute('open', open ? 'false' : 'true') // Update the hash if the collapsible section's // heading has an `id` and we are opening, not closing if (this.heading.id && !open) { history.pushState(null, null, '#' + this.heading.id) } } } connectedCallback() { if (window.location.hash.substr(1) === this.heading.id) { this.setAttribute('open', 'true') this.btn.focus() } } // Identify just the `open` attribute as an observed attribute static get observedAttributes() { return ['open'] } // When `open` changes value, execute switchState() attributeChangedCallback(name) { if (name === 'open') { this.switchState() } } } // Add our new custom element to the window for use window.customElements.define('toggle-section', ToggleSection) // Define the expand/collapse all template const buttons = document.createElement('div') buttons.innerHTML = ` <ul class="controls" aria-label="section controls"> <li><button id="expand">expand all</button></li> <li><button id="collapse">collapse all</button></li> </ul> ` // Get the first `toggle-section` on the page // and all toggle sections as a node list const first = document.querySelector('toggle-section') const all = document.querySelectorAll('toggle-section') // Insert the button controls before the first <toggle-section> first.parentNode.insertBefore(buttons, first) // Place the click on the parent <ul>... buttons.addEventListener('click', (e) => { // ...then determine which button was the target let expand = e.target.id === 'expand' ? true : false // Iterate over the toggle sections to switch // each one's state uniformly Array.prototype.forEach.call(all, (t) => { t.setAttribute('open', expand) }) }) } } })()