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 themif (wgAction == 'view' || wgAction == 'purge'){if (caEdit) caEdit.firstChild.accessKey = null; // edit this pageif (tPrint) tPrint.firstChild.accessKey = null; // printable version}/*ENABLE ACCESS KEYS*/// viewing a non-existent pageif (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 pagevar 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 nextprevlink = revisionNav.childNodes[1];nextlink = revisionNav.childNodes[11];}else // only have nextnextlink = 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 linkif (prevlink && !$('wpPreview')){if (tPrint) tPrint.firstChild.accessKey = null;prevlink.accessKey = 'p';}// assign next linkif (nextlink){$('pt-mytalk').firstChild.accessKey = null;nextlink.accessKey = 'n';}// Content accesskeyvar 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 linkvar 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 pagevar newLinks = content.getElementsByClassName('new');if (wgPageName == 'Special:Search' && newLinks[0])newLinks[0].accessKey = 'e';// Sidebar linksvar drafts = $('t-drafts');var goals = $('t-goals');var pageSize = $('t-page-size');if (drafts) drafts.firstChild.setAttribute('accesskey', 'd'); // Draftsif (goals) goals.firstChild.setAttribute('accesskey', 'g'); // Goals// if (pageSize) pageSize.firstChild.setAttribute('accesskey', 'a'); // Page Size// access key for edit box on uneditable pagevar 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 widthif (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// fatterPageTermsif (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;}}}// thinnerPagesif (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 articlesif (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 stylesif ($('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 editsectionsvar 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 referencesvar 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 noticeboardsisDiscussionPage = ($('ca-addsection'));// don't add fancy text changes on pages with short paragraphs (discussions), AND better separate discussionsif (isDiscussionPage){importStylesheet('User:Gary King/short paragraphs.css');importStylesheet('User:Gary King/discussions.css');}// insert clear: right; after h3, h4, h5function 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 rightvar 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 valuevar 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 rightvar 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 pagesectionLink0 = $('sectionlink-0');// QE is adding an edit link to the lead section, so move it to the cornerif (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 linknewLink = 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 itcontent.insertBefore(link, section0);}// better padding for boxes aligned to the left and righttoccolours = 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 hatnotesfor (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 nodel.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 itleftAlignedThumb = '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 itif (!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 itif (!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 itfor (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 pixelsfunction getLengthInPixels(length, emInPixels){// 1em ~ 13pxif (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 tablesfunction 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"sif (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 Pageif (wgCanonicalNamespace == '' && wgTitle == wgMainPageTitle && userMessages.length > 0)userMessages[0].style.margin = '2em 0 0 0';// have no max width for non-standard TOCstoctitle = $('toctitle');if (!toctitle) appendCSS('.toc { max-width: none; }');// add accesskeys for QE section linksfor (var i = 1; i <= 9; i++){link = $('sectionlink-' + i);if (!link) break;link.accessKey = i;}// number h2 headersif (!(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-addedlinedeletedLines = 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 leastif (wgCanonicalNamespace == ''){// at the beginning of the pagenext = 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 TOCif (toc && toc.previousSibling.previousSibling){beforeTOC = toc.previousSibling.previousSibling;if (beforeTOC.nodeName == 'P' && beforeTOC.childNodes.length == 1 && beforeTOC.firstChild.nodeName == 'BR')beforeTOC.parentNode.removeChild(beforeTOC);}}}