//Original copyright Nicholas Lum 2010
//Modified as compromise between several color schemes
//For reference: Dark = (151,0,0)/(0,5,127), Blues = (132,13,210)/(0,0,255), Grays = (102,102,102)/(102,102,102)
function beelineReaderColoring( ) {
var htmlEl = document.documentElement;
var headEl = htmlEl.getElementsByTagName("head")[0];
if (headEl != null) {
var bodyEl = headEl.nextSibling;
while (bodyEl.nodeName.toLowerCase() != "body") {
bodyEl = bodyEl.nextSibling;
}
//was readInner, but we're not using readability.js here
var parseNode = document.getElementById("wikiPreview");
//fall back to body content if not an edit page
if ( !parseNode ) parseNode = document.getElementById("bodyContent");
if ( !parseNode ) parseNode = bodyEl;
if (parseNode.hasChildNodes()) {
// 0 = anchor to color1; 1 = color1 to anchor; 2 = anchor to color2; 3 = color2 to anchor
var thisColor = 0;
var xmin=0; var xmax=0; var xcoord=0; var xlast=0;
// white space regex
var whtSpc = new RegExp(/^\s+$/);
var whtSpcFlag = 0;
// NOTE: this call doesn't work in IE8
var rect = parseNode.getBoundingClientRect();
xmin = rect.left;
xmax = rect.right;
// wrap all characters in span elements - each of these span elements has a class Z0
makeChildrenSpan(parseNode);
// mark each of these span elements with an x coordinate
markSpansXcoords(parseNode);
// to prevent division by zero:
if (xmin == xmax) xmax++;
var r=0; var g=0; var b=0;
xlast = null;
var spanEls = parseNode.getElementsByTagName("span");
for (i=0; i<spanEls.length; i++) {
var spanEl = spanEls.item(i);
if(spanEl.className == "Z0") {
if (xlast == null) {
// starting a new walk - we set the last coord to the start of the span
xlast = xmin;
} else {
// in midst of a walk, we track where the xcoord was on the last iteration
xlast = xcoord;
}
// set xcoord to current position
xcoord = spanEl.id;
var testLine = xcoord-xlast;
if (testLine<0 || whtSpcFlag) {
//looks like a new line - don't count this unless we have a visible character
if (whtSpc.test(spanEl.firstChild.nodeValue) || spanEl.firstChild.nodeValue==null) {
whtSpcFlag = 1;
} else {
whtSpcFlag = 0;
thisColor = getNextColor(thisColor);
}
}
var colors = null;
switch(thisColor) {
case 0:
maxr = 129;
minr = 0;
maxg = 32;
ming = 0;
maxb = 104;
minb = 0;
colors = getColor(thisColor, xcoord, xmin, xmax, maxr, minr, maxg, ming, maxb, minb);
break;
case 1:
maxr = 129;
minr = 0;
maxg = 32;
ming = 0;
maxb = 104;
minb = 0;
colors = getColor(thisColor, xcoord, xmin, xmax, maxr, minr, maxg, ming, maxb, minb);
break;
case 2:
maxr = 26;
minr = 0;
maxg = 28;
ming = 0;
maxb = 153;
minb = 0;
colors = getColor(thisColor, xcoord, xmin, xmax, maxr, minr, maxg, ming, maxb, minb);
break;
case 3:
maxr = 26;
minr = 0;
maxg = 28;
ming = 0;
maxb = 153;
minb = 0;
colors = getColor(thisColor, xcoord, xmin, xmax, maxr, minr, maxg, ming, maxb, minb);
break;
default:
maxr = 127;
minr = 127;
maxg = 127;
ming = 127;
maxb = 127;
minb = 127;
colors = getColor(thisColor, xcoord, xmin, xmax, maxr, minr, maxg, ming, maxb, minb);
break;
}
var red = colors.red; var green = colors.green; var blue = colors.blue;
// give this character its color
spanEl.style.color = "rgb(" + red + ", " + green + ", " + blue + ")";
}
}
}
}
function makeChildrenSpan(node) {
var next;
if (node.nodeType === 1) {
// element node
if (node = node.firstChild) {
do {
next = node.nextSibling;
makeChildrenSpan(node);
} while(node = next);
}
} else if (node.nodeType === 3) {
// text node
var numchars = node.length;
var readNode = node.cloneNode(0);
var copyNode = node.cloneNode(0); // don't include its children - a text node has no children anyways
var copySpan = document.createElement("span"); // new span that will replace this text node
copySpan.appendChild(copyNode);
var thisParent = node.parentNode;
thisParent.replaceChild(copySpan, node); // now we will read the readNode - inserting span elements of each char after this node
//build new paragraph, create a new text node containing spans around each char
for (j=0; j<numchars; j++) {
var newSpan = document.createElement("span");
var thisChar = readNode.nodeValue.charAt(j);
var newText = document.createTextNode(thisChar);
newSpan.className = "Z0";
newSpan.appendChild(newText);
thisParent.insertBefore(newSpan,copySpan); // instead of: node.parentNode.appendChild(newSpan);
}
thisParent.removeChild(copySpan); // get rid of the original text, which is now the span node
}
}
function markSpansXcoords(node) {
var next;
if (node.nodeType === 1 && node.className !== "Z0") {
if (node = node.firstChild) {
do {
next = node.nextSibling;
markSpansXcoords(node);
} while(node = next);
}
} else if (node.nodeType === 1 && node.className === "Z0") {
var x = findPosition(node);
node.id = x;
}
}
function findPosition(obj) {
var cleft = ctop = 0;
if (obj.offsetParent) {
do {
cleft += obj.offsetLeft;
ctop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return cleft;
}
function getColor(thisColor, xcoord, xmin, xmax, maxr, minr, maxg, ming, maxb, minb) {
var _r = 0;
var _g = 0;
var _b = 0;
var xhere = 0;
var y=0;var yup=0;var ydown=0;
// slope for Y val
var m0 = Math.PI/(xmax - xmin);
var mr = maxr - minr; var mg = maxg - ming; var mb = maxb - minb;
var yup = 0;
var ydown = 0;
var yr = 0; var yg = 0; var yb = 0;
var ycosup = 0; var ycosdown = 0;
// y = m(x - x1) + y1;
switch (thisColor) {
case 0:
// increase color
xhere = xcoord-xmin;
y = m0*xhere;
yup = y-Math.PI;
ycosup = Math.cos(yup);
ycosup++;
ycosup = ycosup/2;
yr = mr*ycosup;
yr = yr + minr;
yg = mg*ycosup;
yg = yg + ming;
yb = mb*ycosup;
yb = yb + minb;
_r = Math.round(yr);
_g = Math.round(yg);
_b = Math.round(yb);
break;
case 1:
// decrease color
xhere = xcoord-xmin;
y = m0*xhere;
ydown = y;
ycosdown = Math.cos(ydown);
ycosdown++;
ycosdown = ycosdown/2;
yr = mr*ycosdown;
yr = yr + minr;
yg = mg*ycosdown;
yg = yg + ming;
yb = mb*ycosdown;
yb = yb + minb;
_r = Math.round(yr);
_g = Math.round(yg);
_b = Math.round(yb);
break;
case 2:
// increase color
xhere = xcoord-xmin;
y = m0*xhere;
yup = y-Math.PI;
ycosup = Math.cos(yup);
ycosup++;
ycosup = ycosup/2;
yr = mr*ycosup;
yr = yr + minr;
yg = mg*ycosup;
yg = yg + ming;
yb = mb*ycosup;
yb = yb + minb;
_r = Math.round(yr);
_g = Math.round(yg);
_b = Math.round(yb);
break;
case 3:
// decrease color
xhere = xcoord-xmin;
y = m0*xhere;
ydown = y;
ycosdown = Math.cos(ydown);
ycosdown++;
ycosdown = ycosdown/2;
yr = mr*ycosdown;
yr = yr + minr;
yg = mg*ycosdown;
yg = yg + ming;
yb = mb*ycosdown;
yb = yb + minb;
_r = Math.round(yr);
_g = Math.round(yg);
_b = Math.round(yb);
break;
default:
_r = 127;
_g = 127;
_b = 127;
break;
}
return { red: _r, green: _g, blue: _b };
}
function getNextColor( thisColor ) {
var numColors = 4;
var nextColor;
thisColor++;
if (thisColor>=numColors) {
nextColor = 0;
} else {
nextColor = thisColor;
}
return nextColor;
}
var myPortletLink = $( '#ca-beelinereader' );
if ( myPortletLink ) myPortletLink.remove( );
}
function toggleSpoilerBoxes( ) {
//XXX: Is there an official function to expand all tables at once?
for ( var i = 0; i <= 9; i++ ) {
if ( document.getElementById( 'collapsibleTable' + i ) ) {
collapseTable( i );
}
else { break; }
}
}
function beelineReaderColoringWrapper( ) {
toggleSpoilerBoxes( );
beelineReaderColoring( );
}
if ( window.beelineReaderAutoColor ) {
$( beelineReaderColoring );
}
else {
var plnk = mw.util.addPortletLink(
'p-tb',
'#br-' + Math.random( ),
'BeeLine Reader',
'ca-beelinereader'
);
$( plnk ).click( function ( e ) {
e.preventDefault( );
beelineReaderColoringWrapper( );
});
}