|
|
// Quick-and-dirty code for making a web page grayscale. Doesn't transform
// images, flash movies, or inline styles. Requires Prototype >= 1.5.0.
// Tested in Firefox and nowhere else. (I was bored one Sunday afternoon.)
var Desaturator = {
on: function() {
$A(document.styleSheets).each(Desaturator.swapStyleSheet);
},
off: function() {
Desaturator.styleNodes.each(Element.remove);
Desaturator.styleNodes = [];
},
toggle: function() {
if (Desaturator.styleNodes.length > 0) Desaturator.off();
else Desaturator.on();
},
styleNodes: [],
swapStyleSheet: function(sheet) {
var media = sheet.ownerNode.getAttribute('media');
if (media && media.indexOf('screen') == -1) return;
var bwStyle = $A(sheet.cssRules).pluck('cssText').map(Desaturator.transform).join('\n');
var style = document.createElement('style');
style.appendChild(document.createTextNode(bwStyle));
Desaturator.styleNodes.push(style);
document.getElementsByTagName('head')[0].appendChild(style);
},
transform: function(cssText) {
return cssText.gsub(/rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)(\b|\s|$|;)/, function(m) {
return Desaturator.desaturate(m[0]);
});
},
desaturate: function(str) {
var m;
if (m = str.match(/rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)(\b|\s|$|;)/)) {
var values = m.slice(1, 4).map(function(val) { return parseInt(val, 10); });
// take the average value of the R, G, and B channels and set each
// channel to that value (quick but reliable way of desaturating)
var v = Math.floor((values[0] + values[1] + values[2]) / 3);
return new Template("rgb(#{v}, #{v}, #{v})").evaluate({ v: v }) + m[4];
}
}
};
Event.observe(window, 'load', function() {
$('toggleDesaturation').observe('click', Desaturator.toggle);
});
|