User:Gary Queen/layout.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | Documentation for this user script can be added at User:Gary Queen/layout. |
/*
GARY KING'S LAYOUT
FIXME When action=purge, icons are moved up higher.
TODO Change wikEd icon to text.
TODO Add a link to disable all (or also some) of the functions here.
TODO Separate page into functions.
TODO Consider templates (Template:) short pages? (In monobook.js)
TODO Automatically enlarge lead images to 300px when a size has not been set?
*/
/*
hook
*/
addOnloadHook(function()
{
accessKeys();
pagesLayout();
});
/*
useful functions
*/
function $(element)
{
return document.getElementById(element);
}
Object.prototype.addClass = function(newClass)
{
element = this;
if (element.className)
{
classes = element.className.split(' ');
classes.push(newClass);
return element.className = classes.join(' ');
}
else return element.className = newClass;
}
Object.prototype.hasClass = function(classToCheck)
{
element = this;
if (!element.className) return false;
classes = element.className.split(' ');
for (var i = 0; i < classes.length; i++)
{
if (classes[i] == classToCheck)
return true;
}
return false;
}
Object.prototype.removeClass = function(oldClass)
{
element = this;
if (!element.className) return false;
classes = element.className.split(' ');
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
book = $('ca-nstab-book');
portal = $('ca-nstab-portal');
special = $('ca-nstab-special');
if (book) contentTab = book;
else if (portal) contentTab = portal;
else if (special) contentTab = special;
else contentTab = '';
if (contentTab) contentTab.firstChild.accessKey = 'c';
// QuickEdit link
contentSub = $('contentSub');
if (contentSub.innerHTML != '' && !special)
{
var qeAccessKey = 'b';
qeLeadLink = $('sectionlink-0');
if (qeLeadLink) qeLeadLink.accessKey = qeAccessKey;
}
else if ($('t-find-edit'))
$('t-find-edit').firstChild.setAttribute('accesskey', 'b');
// creating new page, from search results page
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
// WikiBlame
sendToWikiBlame = function()
{
location.href = 'http://wikipedia.ramselehof.de/wikiblame.php?lang=en&article=' + escape(wgPageName.replace(/_/g, ' ')) + '&needle=' + window.getSelection() + '&limit=' + 1000;
}
// access key for edit box on uneditable page
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';
// 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
references = document.getElementsByClassName('references-small');
for (var i = 0; i < references.length; i++)
{
ref = references[i];
colCount = parseInt(ref.style.MozColumnCount || 1);
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)
{
ref.addClass('grey-border');
ref.style.clear = 'both';
}
}
// 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');
div.addClass('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
topIcons = document.getElementsByClassName('topicon');
numberOfTopIcons = topIcons.length;
function getRightDist(element)
{
return parseInt(element.style.right);
}
distanceRight = 0;
// ordered from left to right
firstIcon = $('protected-icon') || $('status-top');
secondIcon = $('spoken-icon');
thirdIcon = $('featured-star') || $('good-star') || $('rollback-icon') || $('script-icon');
if (firstIcon) distanceRight = getRightDist(firstIcon) + ($('status-top') ? 150 : 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';
link.addClass('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(wgPageName) + '&action=edit§ion=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 || !l.nextSibling.nextSibling.hasClass(className)) continue;
nextEl = l.nextSibling.nextSibling;
nextEl.addClass('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');
newPCDiv.addClass('contentSub');
newPCDiv.style.display = 'block';
newPCDiv.appendChild(pendingChanges);
contentSub.parentNode.insertBefore(newPCDiv, jumpToNav);
}
contentSub.addClass('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';
newDiv.addClass('contentSub');
contentSub.parentNode.insertBefore(newDiv, contentSub.nextSibling);
}
else contentSub.addClass('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 && !prev.previousSibling.previousSibling.hasClass('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) continue;
two = l.previousSibling.previousSibling;
three = two.previousSibling;
four = three.previousSibling;
if ((two && two.hasClass(leftAlignedThumb)) || (three && three.hasClass(leftAlignedThumb)) || (four && four.hasClass(leftAlignedThumb))) l.addClass('text-indent');
}
// proper padding for left- and right-aligned tables
function checkAndFixTableMargins(table, alignment)
{
if (alignment != 'left' && alignment != 'right') return false;
margin = (alignment == 'left' ? table.style.marginRight : table.style.marginLeft);
type = margin.substring(margin.length - 2, margin.length);
value = parseInt(margin);
if (type == 'em' && value < 1) result = '1em';
else if (type == 'px' && value < 13) result = '13px';
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], wikitables[i].align)
// 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');
number.addClass('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 (next.hasClass('dablink'))
{
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);
}
}
}