Jump to content

User:Gary Queen/layout.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Gary Queen (talk | contribs) at 04:48, 14 August 2010 (t). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*
	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()
{
	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 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');
		
	// 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);
		}
	}
}