User:Surjection/streamline.js

/** * make various non-definition headers collapsible boxes * *	mw.loader.load('//en.wiktionary.org/w/index.php?title=User:Surjection/streamline.js&action=raw&ctype=text/javascript'); * */

makeNavFrame = function(heading, editLinks, toggleCat, contents) { // now make a collapsible box var navHead = document.createElement("div"); navHead.className = "NavHead"; navHead.style.cursor = "pointer"; var navContent = document.createElement("div"); navContent.className = "NavContent"; navContent.style.textAlign = "left"; var navFrame = document.createElement("div"); navFrame.className = "NavFrame NavFrame-streamline"; if (toggleCat) navFrame.setAttribute("data-toggle-category", toggleCat); navFrame.appendChild(navHead); navFrame.appendChild(navContent); navHead.appendChild(document.createTextNode(heading)); createNavToggle(navFrame); if (editLinks) { navContent.appendChild(editLinks); editLinks.style.float = "right"; }	contents.forEach(function(ex) {		navContent.appendChild(ex);	}); return navFrame; };

isNavFrameOpen = function(frame) { var content = frame.querySelector(".NavContent"); return content ? window.getComputedStyle(content).style.display != "none" : false; }

openNavFrame = function(frame) { if (!isNavFrameOpen(frame)) { frame.querySelector(".NavHead").click; } }

anchorInUrl = function(anchor) { if (window.location.hash) { return window.location.hash == anchor; }	return false; }

hasElementClass = function(element, className) { if (element.classList) return element.classList.contains(className); return (" " + element.className + " ").indexOf(" " + className + " ") >= 0; }

shouldEndCollapsible = function(element) { return element.tagName.match(/^h[\dr]$/i)							// end on heading or horizontal line || hasElementClass(element, "NavFrame-streamline")	 			// no nested streamline navboxes || hasElementClass(element, "mw-heading")		 				// Parsoid }

shouldExcludeFromCollapsible = function(element) { return hasElementClass(element, "thumb")					 		// images || hasElementClass(element, "sister-project")					// sister project box || hasElementClass(element, "kanji-table")				 		// ja-kanjitab || hasElementClass(element, "floatright")				 		// various tables || hasElementClass(element, "etymid")					 		// etymid || hasElementClass(element, "template-anchor")					// anchor || hasElementClass(element, "t-thumbs-outer")					// thumbs || element.getAttribute("typeof") == "mw:File/Thumb"			// new floating image boxes || hasElementClass(element, "mw-halign-right")					// mw-halign-right, by new floating image boxes || element.getAttribute("align") == "right"						// anything that (explicitly) aligns || element.style.float == "right"								// anything that (explicitly) floats }

shouldCollapseForTheSakeOf = function(element) { if (element.nodeType == 1) { if (element.tagName == "P" || element.tagName == "DIV" || element.tagName == "SPAN") return Array.prototype.some.call(element.childNodes, shouldCollapseForTheSakeOf); return element.tagName != "BR"; } else if (element.nodeType == 3) { return !!element.textContent.trim; // only if not entirely whitespace } else { return false; } }

getHeadingQuery = function(onlyL3) { var head = ".ns-0 #mw-content-text "; if (onlyL3) { return head + "h2, " + head + "h3"; } else { return head + "h2, " + head + "h3, " + head + "h4"; } }

makeSingleCollapsible = function(heading, toggleCat, onlyL3) { document.querySelectorAll(getHeadingQuery(onlyL3)).forEach(function(e) {		var headingId;

var hl = e.querySelector(".mw-headline"); if (hl && hl.textContent == heading) headingId = hl.id;

// Parsoid if (hasElementClass(e.parentElement, "mw-heading") && e.textContent == heading) { headingId = e.id; e = e.parentElement; }

if (!headingId) return;

// pick all elements until next heading var contents = []; var nx = e.nextElementSibling; var collapse = false; while (nx) { if (shouldEndCollapsible(nx)) break; if (!shouldExcludeFromCollapsible(nx)) { contents.push(nx); collapse = collapse || shouldCollapseForTheSakeOf(nx); }			nx = nx.nextElementSibling; }		if (!collapse) return; navFrame = makeNavFrame(heading, e.querySelector(".mw-editsection"), toggleCat, contents); navFrame.id = headingId; e.parentNode.replaceChild(navFrame, e); if (anchorInUrl(navFrame.id)) openNavFrame(navFrame); }); };

makeNumberedCollapsible = function(heading, toggleCat) { var re = new RegExp("^" + heading + " \\d+$"); document.querySelectorAll(getHeadingQuery(false)).forEach(function(e) {		var headingId;

var hl = e.querySelector(".mw-headline"); if (hl && hl.textContent.match(re)) headingId = hl.id;

// Parsoid if (hasElementClass(e.parentElement, "mw-heading") && e.textContent.match(re)) { headingId = e.id; e = e.parentElement; }

if (!headingId) return;

// pick all elements until next heading var contents = []; var nx = e.nextElementSibling; var collapse = false; while (nx) { if (shouldEndCollapsible(nx)) break; if (!shouldExcludeFromCollapsible(nx)) { contents.push(nx); collapse = collapse || shouldCollapseForTheSakeOf(nx); }			nx = nx.nextElementSibling; }		if (!collapse)return; navFrame = makeNavFrame(heading, null, toggleCat, contents); navFrame.id = headingId; e.parentNode.insertBefore(navFrame, e.nextElementSibling); if (anchorInUrl(navFrame.id)) openNavFrame(navFrame); }); };

function moveAnagrams { // move the Anagrams box above Further reading and References document.querySelectorAll(".NavFrame[data-toggle-category=\"anagrams\"]").forEach(function(e) {		var p = e.previousElementSibling;		while (p) {			if (p.tagName.toUpperCase == "H2") {				break;			}			if (p.tagName.toUpperCase == "H3") {				var hl = p.querySelector(".mw-headline");				if (hl && (hl.textContent == "Further reading" || hl.textContent == "References")) {					e.parentElement.insertBefore(e, p);				}			}			p = p.previousElementSibling;		}	}); }

function addGaps { // add gaps before streamline navboxes if preceded by certain elements document.querySelectorAll(".NavFrame-streamline").forEach(function(sl) {		var prev = sl.previousElementSibling;		var next = sl.nextElementSibling;		if (prev) {			var tn = prev.tagName.toUpperCase;			if (tn == "OL" || tn == "UL") {				sl.style.marginTop = "1em";			}		}		if (next) {			var tn = next.tagName.toUpperCase;			if (tn == "HR") {				sl.style.marginBottom = "1em";			}		}	}); }

function defaultStreamline { makeSingleCollapsible("Alternative forms", "alternative forms", true); makeSingleCollapsible("Etymology", "etymology"); makeSingleCollapsible("Glyph origin", "etymology"); makeSingleCollapsible("Description", "description"); makeSingleCollapsible("Pronunciation", "pronunciations"); makeNumberedCollapsible("Etymology", "etymology"); makeNumberedCollapsible("Pronunciation", "pronunciations"); addGaps; }

function superStreamline { makeSingleCollapsible("Alternative forms", "alternative forms", false); makeSingleCollapsible("Inflection", "inflection"); makeSingleCollapsible("Declension", "inflection"); makeSingleCollapsible("Conjugation", "inflection"); makeSingleCollapsible("Mutation", "mutation"); makeSingleCollapsible("Synonyms", "synonyms"); makeSingleCollapsible("Antonyms", "antonyms"); makeSingleCollapsible("Hypernyms", "hypernyms"); makeSingleCollapsible("Hyponyms", "hyponyms"); makeSingleCollapsible("Meronyms", "meronyms"); makeSingleCollapsible("Holonyms", "holonyms"); makeSingleCollapsible("Troponyms", "troponyms"); makeSingleCollapsible("Coordinate terms", "coordinate terms"); makeSingleCollapsible("Derived terms", "derived terms"); makeSingleCollapsible("Compounds", "derived terms"); makeSingleCollapsible("Related terms", "related terms"); makeSingleCollapsible("Descendants", "descendants"); makeSingleCollapsible("See also", "related terms"); makeSingleCollapsible("Anagrams", "anagrams"); moveAnagrams; addGaps; }

mw.hook("wikipage.content").add(function($) {	if (createNavToggle) {		try {			defaultStreamline;			if (window.doSuperStreamline)				superStreamline;		} catch (e) {			console.error(e);		}	} else		console.warn("no createNavToggle, cannot create navboxes. cannot streamline") });