Tuesday, May 21, 2019

Eye-friendly dark styling for the browser

It is easier on the eyes to have a darker color than white as the background of the websites we browse.

I can think of 2 possible approaches to achieve this :

  1. Setting a web-proxy in the browser settings, and manipulating HTML thru the proxy. The problem is with https traffic which is encrypted and cannot be read/changed in between. There are proxy servers like https://www.charlesproxy.com/ which get around this by generating their own certificates.
  2. Using a JS browser plugin/extension, which allows us to execute JS/inject CSS on the fly after the page loads. Stylish was one such user extension, which allowed custom styles. However, it had issues with snoooping on your data, so i decided not to go with it. Stylus seems to be another alternative. But doing it via javascript is more powerful. I had written one such extension for chrome : https://chrome.google.com/webstore/detail/onload-scripts/gddicpebdonjdnkhonkkfkibnjpaclok
So i started off with injecting css using javascript to change the background color to gray. However, there are sites like Facebook, which seem to check that their divs are not being changed. I found that this is usually true for divs containing images. So i thought, maybe i can exclude such divs from the styling, and it seems to be working. Below is the javascript used. Disclaimer : I have copied some of it from a  stackoverflow answer.

UPDATE : The mutationsObserver seems to take too much time on FB.
The evenlistener seems to work well.

    document.addEventListener("DOMNodeInserted", function(e) {
        //console.log( "DNI" + e);
        anode = e.target;
        if( anode.tagName && (anode.tagName.toLowerCase() == 'div' || anode.tagName.toLowerCase()  == 'span'  || anode.tagName.toLowerCase()  == 'td')){
            setbgcolor(anode);
        }
    },
    false);

-----------

function addCss(rule) {
  let css = document.createElement('style');
  css.type = 'text/css';
  if (css.styleSheet) css.styleSheet.cssText = rule; // Support for IE
  else css.appendChild(document.createTextNode(rule)); // Support for the rest
  document.getElementsByTagName("head")[0].appendChild(css);
}
var bgcolor = 'lightgray';

function setbgcolor( elem){
    // Don't change if first child elem is image. For sites like FB
    if(  ! elem.firstElementChild || (elem.firstElementChild && elem.firstElementChild.tagName.toLowerCase() != 'img') ){
        elem.style.backgroundColor = bgcolor;
        //console.log( "ONLS:" + elem.outerHTML);
    }

}

// divs with images
var allDivs = document.getElementsByTagName("div");
for( var i=0; i< allDivs.length; i++){
    var currDiv = allDivs[i];
    setbgcolor(currDiv);
}
// CSS rules
let rule  = 'body {background-color: ' + bgcolor + '} ';
    //rule += 'div {background-color: ' + bgcolor + '} ';
    rule += 'pre {background-color:' + bgcolor + '} ';
    rule += 'td {background-color:' + bgcolor + '} ';

addCss(rule);


// Select the node that will be observed for mutations
var targetNode = document.getElementsByTagName('body')[0];

// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true, subtree: true };

// Callback function to execute when mutations are observed
var callback = function(mutationsList, observer) {
    for(var mutation of mutationsList) {
        if (mutation.type == 'childList') {
            for (var i = 0; i < mutation.addedNodes.length; i++) {
                var anode = mutation.addedNodes[i];
                //console.log( "ONLSMO" +  anode.tagName + anode.id );
                if( anode.tagName && anode.tagName.toLowerCase() == 'div' || anode.tagName.toLowerCase()  == 'span'  || anode.tagName.toLowerCase()  == 'td'){
                    setbgcolor(anode);
                }
            }
        }
    }
};

// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

// Later, you can stop observing
//observer.disconnect();

No comments:

Post a Comment