User:Gary Queen/layout.js

/*	hook addOnloadHook(accessKeys); addOnloadHook(pagesLayout);

/*	useful functions function $(element) {	return document.getElementById(element); }

function addClass(element, newClass) {	if (!element instanceof Object) return false; if (element.className) {		var classes = element.className.split(' '); classes.push(newClass); return element.className = classes.join(' '); }	else return element.className = newClass; }

function hasClass(element, classToCheck) {	if (!element instanceof Object || !element.className) return false; var classes = element.className.split(' '); for (var i = 0; i < classes.length; i++) {		if (classes[i] == classToCheck) return true; }	return false; }

function removeClass(element, oldClass) {	if (!element instanceof Object || !element.className) return false; var classes = element.className.split(' '); var newClasses = []; for (var i = 0; i < classes.length; i++) {		if (classes[i] != oldClass) newClasses.push(classes[i]); }	return element.className = newClasses; }

String.prototype.trim = function {	return this.replace(/^[\s|\n]+|[\s|\n]+$/g, ''); }

String.prototype.ltrim = function {	return this.replace(/^[\s|\n]+/, ''); }

String.prototype.rtrim = function {	return this.replace(/[\s|\n]+$/, ''); }

/*	do access keys function accessKeys {	var caEdit = $('ca-edit'); var tPrint = $('t-print'); var content = $('content'); /*		DISABLE ACCESS KEYS */	// Disable logo $('p-logo').childNodes[1].accessKey = null; // disable access keys, so quickedit can use them if (wgAction == 'view' || wgAction == 'purge') {		if (caEdit) caEdit.firstChild.accessKey = null; // edit this page if (tPrint) tPrint.firstChild.accessKey = null; // printable version }	/*		ENABLE ACCESS KEYS */	// viewing a non-existent page if (caEdit && caEdit.firstChild && !caEdit.firstChild.accessKey && caEdit.firstChild.firstChild.nodeValue == 'Create this page') caEdit.firstChild.accessKey = 'e'; // Diff navigation links // check if we're viewing an oldid page var revisionNav = $('mw-revision-nav'); var mwPrevlink = document.getElementsByClassName('mw-prevlink'); var mwNextlink = document.getElementsByClassName('mw-nextlink'); var prevlink, nextlink; if (revisionNav) {		if (revisionNav.childNodes[1].firstChild.nodeValue == 'diff') {			// have both prev and next prevlink = revisionNav.childNodes[1]; nextlink = revisionNav.childNodes[11]; }		else // only have next nextlink = revisionNav.childNodes[7]; }	else if (mwPrevlink.length > 0 || mwNextlink.length > 0) {		prevlink = mwNextlink[0]; nextlink = mwPrevlink[0]; }	else {			prevlink = $('differences-prevlink'); nextlink = $('differences-nextlink'); }	// assign previous link if (prevlink && !$('wpPreview')) {		if (tPrint) tPrint.firstChild.accessKey = null; prevlink.accessKey = 'p'; }	// assign next link if (nextlink) {		$('pt-mytalk').firstChild.accessKey = null; nextlink.accessKey = 'n'; }	// Content accesskey var book = $('ca-nstab-book'); var portal = $('ca-nstab-portal'); var special = $('ca-nstab-special'); var contentTab; if (book) contentTab = book; else if (portal) contentTab = portal; else if (special) contentTab = special; else contentTab = ''; if (contentTab) contentTab.firstChild.accessKey = 'c';

// QuickEdit link var contentSub = $('contentSub'); if (contentSub.innerHTML != '' && !special) {		var qeAccessKey = 'b'; var qeLeadLink = $('sectionlink-0'); if (qeLeadLink) qeLeadLink.accessKey = qeAccessKey; console.log('1: ' + qeLeadLink); }	else if ($('t-find-edit')) {		$('t-find-edit').firstChild.setAttribute('accesskey', 'b'); console.log('2'); }	// creating new page, from search results page var newLinks = content.getElementsByClassName('new'); if (wgPageName == 'Special:Search' && newLinks[0]) newLinks[0].accessKey = 'e'; // Sidebar links var drafts = $('t-drafts'); var goals = $('t-goals'); var pageSize = $('t-page-size');

if (drafts) drafts.firstChild.setAttribute('accesskey', 'd'); // Drafts if (goals) goals.firstChild.setAttribute('accesskey', 'g'); // Goals // if (pageSize) pageSize.firstChild.setAttribute('accesskey', 'a'); // Page Size // access key for edit box on uneditable page var permissionErrors = content.getElementsByClassName('permissions-errors'); if (permissionErrors.length > 0) $('wpTextbox1').accessKey = ','; }

/*	do page layout function pagesLayout {	/*		variables */	var content = $('content'); var jumpToNav = $('jump-to-nav'); var pPersonal = $('p-personal'); var afterJumpToNav = jumpToNav.nextSibling.nextSibling.nextSibling.nextSibling; var bodyContent = $('bodyContent'); var cactions = $('p-cactions'); var caEdit = $('ca-edit'); var caMain = $('ca-nstab-main'); var contentSub = $('contentSub'); var firstDiffElement = content.getElementsByClassName('diff')[0]; var globalWrapper = $('globalWrapper'); var h2 = content.getElementsByTagName('h2'); var paragraphs = content.getElementsByTagName('p'); var pBody = pPersonal.getElementsByClassName('pBody')[0]; var pendingChanges = $('mw-fr-revisiontag'); var relLinks = content.getElementsByClassName('rellink'); var section0 = $('section-0'); var siteSub = $('siteSub'); var toc = $('toc'); var tPrint = $('t-print'); var userMessages = content.getElementsByClassName('usermessage'); var wikiPreview = $('wikiPreview'); var wikitables = content.getElementsByClassName('wikitable'); /*		Layout */	// Fatter pages except when it would exceed page width if (window.innerWidth > 1425) globalWrapper.style.width = cactions.style.width = pBody.style.width = '1400px'; else globalWrapper.style.width = cactions.style.width = pBody.style.width = (window.innerWidth - 25) + 'px'; // Thinner page width for articles (1000 pixels wide) var thinnerPage = false; var fatterPage = false; // TODO fatterPages // fatterPageTerms if (typeof(fatterPageTerms) == 'object' && fatterPageTerms.length > 0) {		for (var i = 0; i < fatterPageTerms.length; i++) {			if (wgPageName.replace(/_/g, ' ').indexOf(fatterPageTerms[i]) != -1) {				fatterPage = true; break; }		}	}	// thinnerPages if (typeof(thinnerPages) == 'object' && thinnerPages.length > 0) {		for (var i = 0; i < thinnerPages.length; i++) {			if (wgPageName.indexOf(thinnerPages[i].replace(/ /g, '_')) == 0) {				thinnerPage = true; break; }		}	}	// TODO thinnerPageTerms // Thinner pages for articles if (window.innerWidth > 1025 && fatterPage == false && (wgCanonicalNamespace ==  || thinnerPage) && (wgAction == 'view' || wgAction == 'submit' || wgAction == 'edit' || wgAction == 'purge') && (location.href.indexOf('title=') && location.href.indexOf('diff=')) == -1 && !(wgCanonicalNamespace ==  && wgTitle == wgMainPageTitle)) globalWrapper.style.width = cactions.style.width = pBody.style.width = '1000px'; // Forced page to use article styles if ($('thinner-page')) {		globalWrapper.style.width = cactions.style.width = pBody.style.width = '1000px'; appendCSS('#bodyContent > p, #wikiPreview > p, .text-indent { text-indent: 2em !important; }'); }	// Shorter search text (searchGoButton, mw-searchButton) $('searchGoButton').value = 'G'; $('mw-searchButton').value = 'S'; // remove the extra space after editsections var editSections = document.getElementsByClassName('editsection'); var nextSibling; for (var i = 0; i < editSections.length; i++) {		nextSibling = editSections[i].nextSibling; if (nextSibling && nextSibling.nodeType == 3 && nextSibling.nodeValue == ' ') nextSibling.parentNode.removeChild(nextSibling); }	// adjust references var references = document.getElementsByClassName('references-small'); for (var i = 0; i < references.length; i++) {		var ref = references[i]; var colCount = parseInt(ref.style.MozColumnCount || 1); var colWidth = ref.style.MozColumnWidth || '30em'; if (colCount == 2 || (colWidth.substr(colWidth.length - 2, 2) == 'em' && parseInt(colWidth) >= 30)) ref.style.MozColumnCount = ref.style.MozColumnWidth = 'auto'; if (ref.scrollHeight > 250) {			addClass(ref, 'grey-border'); ref.style.clear = 'both'; }		// Indicate how many references there are in the box. var numberOfReferences = Math.floor(ref.childNodes[1].childNodes[1].childNodes.length / 2); var referencesHeading = ref.previousSibling.previousSibling; if (referencesHeading.nodeName == 'H2') {			var referencesHeadline = referencesHeading.getElementsByClassName('mw-headline')[0]; var newReferencesNode = document.createElement('span'); newReferencesNode.style.fontSize = '75%'; newReferencesNode.style.color = 'grey'; newReferencesNode.appendChild(document.createTextNode(' (' + numberOfReferences + ' total)')); referencesHeadline.appendChild(newReferencesNode); }	}	// changes for non-discussion and discussion pages; covers discussion pages not in a "talk:" namespace, such as many noticeboards isDiscussionPage = ($('ca-addsection')); // don't add fancy text changes on pages with short paragraphs (discussions), AND better separate discussions if (isDiscussionPage) {		importStylesheet('User:Gary King/short paragraphs.css'); importStylesheet('User:Gary King/discussions.css'); }	// insert clear: right; after h3, h4, h5	function addClears(elements) {		for (var i = 0; i < elements.length; i++) {			h = elements[i]; if (!h.nextSibling) continue; div = document.createElement('div'); addClass(div, 'clear-right'); h.parentNode.insertBefore(div, h.nextSibling); }	}	h3 = content.getElementsByTagName('h3'); h4 = content.getElementsByTagName('h4'); h5 = content.getElementsByTagName('h5'); /*addClears(h3); addClears(h4); addClears(h5);*/ // adjust top icons distance from right var topIcons = document.getElementsByClassName('topicon'); var numberOfTopIcons = topIcons.length; function getRightDist(element) {		return getLengthInPixels(element.style.right)[0]; }	// loop through top icons and get the one with the largest style.right value var leftMostTopIconRightValue = 0; for (var i = 0; i < numberOfTopIcons; i++) {		var rightDist = getRightDist(topIcons[i]) if (rightDist > leftMostTopIconRightValue) leftMostTopIconRightValue = rightDist; }	var trumpIconLength = getTrumpIconLength, distanceRight; if (trumpIconLength) distanceRight = trumpIconLength; else if (leftMostTopIconRightValue) distanceRight = leftMostTopIconRightValue + 25; else distanceRight = 0; function getTrumpIconLength {		var trumpIcons = { 'status-top': 175, 'TemplateUserinfo': 225 }; var trumpIconLength = 0;

for (var icon in trumpIcons) {			if ($(icon)) {				var trumpIconLength = trumpIcons[icon]; break; }		}		return trumpIconLength; }	/*var distanceRight = 0; // ordered from left to right var firstIcon = $('protected-icon') || $('status-top'); var secondIcon = $('spoken-icon'); var thirdIcon = $('commons-icon') || $('featured-star') || $('good-star') || $('rollback-icon') || $('script-icon'); var trumpIcons = { 'status-top': 150, 'TemplateUserinfo': 225 }; var trumpIconLength = getTrumpIconLength; if (trumpIconLength) distanceRight = trumpIconLength; else if (firstIcon) distanceRight = getRightDist(firstIcon) + 25; else if (secondIcon) distanceRight = getRightDist(secondIcon) + 25; else if (thirdIcon) distanceRight = getRightDist(thirdIcon) + 30;*/ // move QuickEdit section-0 link to top-right corner of page sectionLink0 = $('sectionlink-0'); // QE is adding an edit link to the lead section, so move it to the corner if (sectionLink0) {		link = sectionLink0.parentNode; link.id = 'editsection-0'; addClass(link, 'lead-qe-link'); link.style.marginRight = distanceRight + 'px'; // add new edit link into QE edit link newLink = document.createElement('a'); newLink.href = wgScript + '?title=' + encodeURIComponent(mw.config.get('wgPageName')) + '&action=edit&section=0'; newLink.title = 'Edit section'; newLink.appendChild(document.createTextNode('edit')); link.insertBefore(newLink, sectionLink0); link.insertBefore(document.createTextNode('/'), sectionLink0); // move it		content.insertBefore(link, section0); }	// better padding for boxes aligned to the left and right toccolours = content.getElementsByClassName('toccolours'); for (var i = 0; i < toccolours.length; i++) {		tocColour = toccolours[i]; textSideMargin = '1.5em'; if (tocColour.style.cssFloat == 'right') {			tocColour.style.marginRight = 0; tocColour.style.marginLeft = textSideMargin; }		else if (tocColour.style.cssFloat == 'left') {			tocColour.style.marginLeft = 0; tocColour.style.marginRight = textSideMargin; }	}	// don't indent lines in certain cases // italicized lines that are not indented and therefore look like hatnotes for (var i = 0; i < paragraphs.length; i++) {		p = paragraphs[i]; if (p.parentNode != bodyContent && p.parentNode != wikiPreview) continue; if (p.childNodes.length == 1 && p.firstChild.nodeName == 'I' && p.previousSibling.previousSibling.previousSibling.previousSibling != jumpToNav) p.style.textIndent = 0; }		// merge multiple hatnotes together // TODO Make these work together? i.e. if a dablink is followed by a reflink, merge them anyway. function mergeLinks(className) {		links = content.getElementsByClassName(className); for (var i = links.length - 1; i >= 0; i--) {			l = links[i]; // give "title" attribute to node l.title = className; if (!l.nextSibling || !l.nextSibling.nextSibling || !hasClass(l.nextSibling.nextSibling, className)) continue;

nextEl = l.nextSibling.nextSibling; addClass(nextEl, 'merged-hatnote'); text = document.createTextNode(className == 'dablink' ? ' ' : '. '); l.appendChild(text); l.appendChild(nextEl); }	}	mergeLinks('dablink'); mergeLinks('rellink'); // contentSub (redirects, contribution page user info, etc.) /*if (contentSub.firstChild) {		if (pendingChanges) {			newPCDiv = document.createElement('div'); addClass(newPCDiv, 'contentSub'); newPCDiv.style.display = 'block'; newPCDiv.appendChild(pendingChanges); contentSub.parentNode.insertBefore(newPCDiv, jumpToNav); }		addClass(contentSub, 'merged-content-sub'); if (contentSub.firstChild.nodeType == 3) contentSub.firstChild.nodeValue = contentSub.firstChild.nodeValue.replace(/^\s+/g, ''); newDiv = document.createElement('div'); newDiv.style.display = 'block'; addClass(newDiv, 'contentSub'); contentSub.parentNode.insertBefore(newDiv, contentSub.nextSibling); }	else addClass(contentSub, 'contentSub');*/

// move a left-aligned thumb image to before any header that immediately precedes it	leftAlignedThumb = 'tleft'; thumbs = content.getElementsByClassName(leftAlignedThumb); for (var i = 0; i < thumbs.length; i++) {		t = thumbs[i]; movedText = 'This left-aligned image thumb was moved from the section below to the section above, in accordance with the Manual of Style (WP:MOS).'; // immediately precedes it		if (!t.previousSibling && !t.previousSibling.previousSibling) continue; prev = t.previousSibling.previousSibling; if (prev.nodeName == 'H3' || prev.nodeName == 'H4' || prev.nodeName == 'H5') {			t.parentNode.insertBefore(t, prev); t.title = movedText; }		// preceded by a rellink, then precedes it		if (!prev.previousSibling && !prev.previousSibling.previousSibling && !hasClass(prev.previousSibling.previousSibling, 'rellink')) continue; prev = prev.previousSibling.previousSibling; if (prev && (prev.nodeName == 'H3' || prev.nodeName == 'H4' || prev.nodeName == 'H5')) {			t.parentNode.insertBefore(t, prev); t.title = movedText; }	}	// indent rellinks if an image is to the left of it	for (var i = 0; i < relLinks.length; i++) {		l = relLinks[i]; if (!l.previousSibling || !l.previousSibling.previousSibling) continue; two = l.previousSibling.previousSibling; if (!two.previousSibling) continue; three = two.previousSibling; if (!three.previousSibling) continue; four = three.previousSibling; if ((two && hasClass(two, leftAlignedThumb)) || (three && hasClass(three, leftAlignedThumb)) || (four && hasClass(four, leftAlignedThumb))) addClass(l, 'text-indent'); }

// get length in pixels function getLengthInPixels(length, emInPixels) {		// 1em ~ 13px if (typeof(emInPixels) == 'undefined') emInPixels = 13; var value = parseInt(length); var type = length.substring(length.length - 2, length.length);

if (type == 'em') {			value = value * emInPixels; type = 'px'; }		return [value, type]; }	// proper padding for left- and right-aligned tables function checkAndFixTableMargins(table) {		var alignment, result; // calculate "alignment" if (wikitables[i].align) alignment = wikitables[i].align; else if (wikitables[i].style.cssFloat) alignment = wikitables[i].style.cssFloat; if (alignment != 'left' && alignment != 'right') return false; var margin = alignment == 'left' ? table.style.marginRight : table.style.marginLeft; var pixelLengths = getLengthInPixels(margin) var value = pixelLengths[0]; var type = pixelLengths[1]; if (type == 'px' && value < 13) result = '13px'; else if ((type == 'em' && value < 1) || !type) result = '1em'; else result = '1em'; // may need to add checks for more "type"s if (alignment == 'left') table.style.marginRight = result; else table.style.marginLeft = result;

return result; }	for (var i = 0; i < wikitables.length; i++) checkAndFixTableMargins(wikitables[i]) // add more space above .usermessage on Main Page if (wgCanonicalNamespace == '' && wgTitle == wgMainPageTitle && userMessages.length > 0) userMessages[0].style.margin = '2em 0 0 0'; // have no max width for non-standard TOCs toctitle = $('toctitle'); if (!toctitle) appendCSS('.toc { max-width: none; }'); // add accesskeys for QE section links for (var i = 1; i <= 9; i++) {		link = $('sectionlink-' + i); if (!link) break; link.accessKey = i;	} // number h2 headers if (!(wgCanonicalNamespace == '' && wgTitle == wgMainPageTitle) && (wgAction == 'view' || wgAction == 'purge')) {		if (firstDiffElement) start = 2; else if (toc) start = 1; else start = 0; begin = 0; for (var i = start; i < h2.length; i++) {			number = document.createElement('span'); addClass(number, 'heading-number'); number.appendChild(document.createTextNode(begin + 1 + '. '));			h2[i].insertBefore(number, h2[i].firstChild); begin++; }	}	// remove diff whitespace, around .diff-deletedline and .diff-addedline deletedLines = content.getElementsByClassName('diff-deletedline'); addedLines = content.getElementsByClassName('diff-addedline'); function trimDiffs(elements) {		for (var i = 0; i < elements.length; i++) {			if (!elements[i].firstChild) continue; elements[i].firstChild.innerHTML = elements[i].firstChild.innerHTML.trim; }	}	// FIXME Removes * and perhaps other characters at beginning of the line. /*trimDiffs(deletedLines); trimDiffs(addedLines);*/ // TODO Use white-space: pre-wrap; on deletedLines[i].firstChild and strip whtiespace added // by the software so that added/removed whitespaces are more clear? // remove extra line breaks - only in articles, for now at least if (wgCanonicalNamespace == '') {		// at the beginning of the page next = afterJumpToNav; if (hasClass(next, 'dablink') || next.nodeName == 'DL') {			next2 = next.nextSibling.nextSibling; next3 = next2.nextSibling.nextSibling; if (next2.nodeName == 'P' && next2.firstChild.nodeName == 'BR') next2.removeChild(next2.firstChild); else if (next3.nodeName == 'P' && next3.firstChild.nodeName == 'BR') next3.removeChild(next3.firstChild); }		// before the TOC if (toc && toc.previousSibling.previousSibling) {			beforeTOC = toc.previousSibling.previousSibling; if (beforeTOC.nodeName == 'P' && beforeTOC.childNodes.length == 1 && beforeTOC.firstChild.nodeName == 'BR') beforeTOC.parentNode.removeChild(beforeTOC); }	} }