Wikipedia:WikiProject User scripts/Scripts/TwoColumns.js
Appearance
/* TwoColumns, version [0.0.5]
Documentation: Wikipedia:WikiProject User scripts/Scripts/TwoColumns
*/
if (mw.config.get('wgAction') == 'view' && mw.config.get('wgCanonicalNamespace')=='') addOnloadHook(fr_format)
var fr_columns;
var imgRegExp= /(thumb|frame)/i;
var trashNodes;
function fr_format() {
fr_addButton();
fr_columns=fr_getCookie ('fr_columns'); if (! (0<1*fr_columns)) fr_columns=1;
trashNodes=new Array;
if (fr_columns==1) return;
var bodyContent= document.getElementById('bodyContent');
if (! bodyContent || ! bodyContent.innerHTML || bodyContent.innerHTML=='') return;
var allNodes=bodyContent.childNodes;
var group=new Array, node, groupArea=0;
for (var i = allNodes.length-1; 0 <= i; i--) {
node=allNodes[i];
var pre= node.tagName=="PRE" || (node.tagName=="DIV" && node.childNodes[1] && node.childNodes[1].tagName=='PRE')
if (node.nodeValue && node.nodeValue.substr(0,1)=="\n") {
// } else if (node.tagName=="p" || node.tagName=="P" || node.tagName=="ul" || node.tagName=="UL" ) {
} else if (node.tagName && node.tagName.substr(0,1) !="H" && node.tagName.substr(0,5) !="TABLE" && node.tagName.substr(0,5) !="SCRIPT" && node.style.MozColumnCount<=0 && ! pre) { //everything but H
group.push(node);
groupArea += node.clientHeight * node.clientWidth;
} else {
if (node.tagName && node.tagName.substr(0,1) =="H") {
var prevNode=node;
var count=0;
do {
do {
prevNode=prevNode.previousSibling;count++;
} while (prevNode && (prevNode.clientHeight==0 || prevNode.clientHeight=== undefined));
if (prevNode && prevNode.className && imgRegExp.test(prevNode.className)) {
group.push(prevNode); i=i-count;count=0;
groupArea += prevNode.clientHeight * prevNode.clientWidth;
}
} while (prevNode && prevNode.className && imgRegExp.test(prevNode.className))
}
if (0<group.length) fr_layoutDiv (group, groupArea);
group=new Array; groupArea=0;
}
}
for (var i=trashNodes.length-1; 0<=i;i--) {
trashNodes[i].parentNode.removeChild(trashNodes[i]);
}
}
function fr_layoutDiv (aGroup, groupArea) {
var contentWidth=aGroup[0].parentNode.clientWidth;
if (groupArea < 100 * contentWidth) return;
var start=0, stop=aGroup.length-1;
var pieces=Math.round(groupArea / (window.innerHeight * contentWidth)+0.5);
var targetArea=groupArea/ pieces;
var targetHeight= (pieces==1) ? window.innerHeight : targetArea / contentWidth;
var divArea=0, first=true, imgHeight=0;
for (var i = stop; 0 <= i; i--) {
if (aGroup[i].className && imgRegExp.test(aGroup[i].className)) {
imgHeight +=aGroup[i].clientHeight;
}
divArea += aGroup[i].clientHeight * aGroup[i].clientWidth;
if (targetArea < divArea || targetHeight < imgHeight) {
fr_createDiv(aGroup, i+1,stop,fr_columns,first);
first=false;
stop=i;
if (aGroup[i].className && imgRegExp.test(aGroup[i].className)) {
imgHeight =aGroup[i].clientHeight;
} else {
imgHeight =0;
}
divArea = aGroup[i].clientHeight * aGroup[i].clientWidth;
}
}
if (0<=stop) {
divArea=0;
for (i=stop; 0<=i;i--) {
divArea += aGroup[i].clientHeight * aGroup[i].clientWidth;
}
if (100 * contentWidth < divArea) fr_createDiv(aGroup,0,stop,fr_columns,first);
}
}
function fr_createDiv(aGroup, start, stop, columns, noHR) { // start, stop: inclusive, (counting in the Group !), e.g. 0..3
if (stop<start) return;
var newDiv = document.createElement('div');
newDiv.style.MozColumnCount=columns;
newDiv.style.MozColumnGap='2em';
newDiv.style.textAlign='justify';
var tooBig=false;
for (var i = stop; start <= i; i--) { // first append the thumb
if (imgRegExp.test(aGroup[i].className)) {
newNode=aGroup[i].cloneNode(true);
newDiv.appendChild(newNode);
if (imgRegExp.test(aGroup[i].className) && aGroup[i].parentNode.clientWidth / columns < newNode.clientWidth) {
tooBig=true;
}
}
}
for (var i = stop; start <= i; i--) {
if (!imgRegExp.test(aGroup[i].className)) {
newNode=aGroup[i].cloneNode(true);
newDiv.appendChild(newNode)
}
}
if (window.innerHeight < newDiv.clientHeight || tooBig /* window.innerHeight-10 < imgHeight */) { // safety valve: too big
return;
}
aGroup[start].parentNode.insertBefore(newDiv,aGroup[start]);
if (!noHR) {
var HR=document.createElement('HR');
newDiv.parentNode.insertBefore(HR,newDiv);
}
for (var i = stop; start <= i; i--) {
trashNodes.push(aGroup[i]); //newDiv.parentNode.removeChild(aGroup[i])
}
}
// Button to increment the number of columns
function fr_addButton () {
var node = document.getElementById('p-personal');
if ( !node ) return null;
node = node.getElementsByTagName( "ul" )[0];
if ( !node ) return null;
var link = document.createElement( "img" );
link.src= 'http://up.wiki.x.io/wikipedia/commons/f/f5/FastReader_logo.PNG';
link.appendChild( document.createTextNode( "FastReader" ) );
link.onclick = function() {fr_next()};
var item = document.createElement( "li" );
item.appendChild( link );
link.setAttribute( "title", 'FastReader' );
node.appendChild( item ); // IE compatibility (?)
}
function fr_next() {
fr_columns= fr_columns % 2 +1;
fr_setCookie('fr_columns', fr_columns);
document.location.reload();
};
// Cookie routines to save the number of columns
function fr_getCookie (cookieName) {
var cookie = ' ' + document.cookie;
var search = ' ' + cookieName + '=';
var cookieValue = '';
var offset = 0;
var end = 0;
offset = cookie.indexOf(search);
if (offset != -1) {
offset += search.length;
end = cookie.indexOf(';', offset)
if (end == -1) {
end = cookie.length;
}
cookieValue = cookie.substring(offset, end);
cookieValue = cookieValue.replace(/\\+/g, ' ');
cookieValue = decodeURIComponent(cookieValue);
}
return(cookieValue);
}
function fr_setCookie (name, value) {
var cookie = name + '=' + encodeURIComponent(value);
var cookieExpire = new Date();
expires = cookieExpire.setTime(cookieExpire.getTime() + 30 * 24 * 60 * 60 * 1000);
expires = cookieExpire.toUTCString();
cookie += '; expires=' + expires;
document.cookie = cookie;
return;
}