Pull to refresh

Пишем сами расширение для Chrome: смена цвета социальной сети

Добрый день, дорогие посетители хабра. Однажды мне приелся стандартный цвет Вконтакте и я решил изменить эту ситуацию. Начал двигаться в сторону написания расширения. Почему именно Вконтакте? А потому что весь сайт выдержан в одном цвете.
А началось все примерно год назад, когда я начал экспериментировать с расширениями для Chrome. Сперва я просто хотел сделать несколько предустановленных цветов — красный, серый и т.п. Идей реализаций было много.

Сперва хотел получать все css файлы и менять коды HEX-коды цветов в них и подключать 1 css файл с полностью измененными цветами, но столкнулся с проблемами. Во-первых, надо было каждый раз мониторить новые css, т.к. все завязано на них, исключить определенные цвета, которые перекрывались другими стилями, что очень затратно по времени, учитывая размеры их CSS. Во-вторых, покраска изображений, если предустановленные стили, то можно и заранее перекрасить все иконки, но опять же нужно мониторить сайт на наличие новых. В итоге я забросил эту идею на некоторое время.

Через пол года я опять вернулся к этому расширению, но уже с другой позиции. Мне захотелось не только несколько цветов. Мне захотелось сделать выбор любого цвета. И я начал искать пути решения. Через несколько дней поиска решения я наткнулся на статью про фильтры изображений. И решил попробовать использовать их.
Сразу же заметил фильтр
-webkit-filter: hue-rotate(Xdeg);

Применил на тег и получил хорошую картину :)
image
Вроде бы все круто, здорово, но вот только фильтр накладывается на всю страницу и красит даже изображения. А что будет, если я добавлю тот же фильтр на тег , но только со знаком минус? Получилось как раз то, что нужно.
image

Осталось дело за малым — написать само расширение. Тут мне помогла документация гугла.
Сперва я создал popup окно расширения, в котором можно было бы выбирать нужный цвет и сохранять его.

popup.js:
document.addEventListener('DOMContentLoaded', function () {
    document.querySelector('#grey').addEventListener('click', save_options);
    document.querySelector('#invert').addEventListener('click', save_options);
});

chrome.storage.local.get('vkColorChanger', function(result){
    var values = result['vkColorChanger'];
    values = JSON.parse(values);

    if(values.grey =='on'){
        document.getElementById('grey').click();
    }
    if(values.invert =='on'){
        document.getElementById('invert').click();
        invert(1);
    }
            
    document.querySelector('#hue-deg').value =  values['hue-deg'];
});

function invert(val) {
    data = "#block_picker,canvas{-webkit-filter: invert("+val+");}";
    var css = document.getElementById("VKcolorChanger");
    if(css){
        css.innerHTML = data;    
    }else{ 
        var css = document.createElement("style");
        css.setAttribute("type", "text/css");
        css.setAttribute("rel", "stylesheet");
        css.setAttribute("id", "VKcolorChanger");
        css.innerHTML = data;
        document.getElementsByTagName("head")[0].appendChild(css);
    }      
}

function save_options(e) {
    var deg = e;
    var values = new Object();
        
    values['hue-deg'] = document.querySelector('#hue-deg').value;
    
    if(document.querySelector('#grey').checked){
        values['grey'] = document.querySelector('#grey').value;
    }else{
        values['grey'] = "";    
    }
    if(document.querySelector('#invert').checked){
        values['invert'] = document.querySelector('#invert').value;
        invert(1);
    }else{
         values['invert'] = "";
         invert(0);
    }  
        
    values = JSON.stringify(values);
    chrome.storage.local.set({'vkColorChanger': values});
    
    /**Изменение всех открытых вкладок */
    chrome.tabs.query({'url': 'http://vk.com/*'}, function(tabs) {
        for(var i = 0;i<tabs.length;i++){
            chrome.tabs.executeScript(tabs[i].id, {file : "bg.js"});
        }
    });
}

Сохранение и получение происходит посредством chrome.storage.local.

popup.html
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <link rel="stylesheet" type="text/css" href="css/style.css">
        <script type="text/javascript" src="js/lib.js"></script>
        <script src="popup.js"></script>
    </head>
    <body>
        <div class="picker" id="primary_block" >
            <div id="line">
                <div id="arrows">
                    <div class="left_arrow"></div>
                    <div class="right_arrow"></div>
                </div>
            </div>
            <div id="block_picker"></div>
            <input type="hidden" id="hue-deg" />
        </div>
        <div class="options">
            <h4>Дополнительные настройки</h4>
           <label>Черно-белый <input type="checkbox" id="grey" name="grey" onclick="save_options()"/> </label><br>
           <label>Инвертирование <input type="checkbox" id="invert" name="invert" onclick="save_options()"/> </label>
        </div>
        <p id="message"></p>
        <script type="text/javascript" src="js/picker.js"></script>
    </body>
</html>

Результат:
image

Теперь надо было запустить расширение непосредственно на страницах ВК.
// Получаем цвета
chrome.storage.local.get('vkColorChanger', function(result){
    var values = result['vkColorChanger'];
    values = JSON.parse(values);
    var filter = "-webkit-filter:";
    var filterReverse = "-webkit-filter:";
    additionalParam = "";
    var deg = parseInt(values['hue-deg'])+145;
    if (values.grey == "on") {
        deg = 0;
        filter += " grayscale(100%) contrast(120%)";
        filterReverse += " grayscale(100%) contrast(120%)";
    }
    if(values.invert == "on"){
        filter += " invert(1)";
        additionalParam += "font-weight:bold !important";
        filterReverse += " invert(1)";    
    }

    filter += " hue-rotate("+deg+"deg)";
	filterReverse += " hue-rotate("+(-deg)+"deg)";
   
 // Формируем CSS
    data = "html{"+filter+";}"+
    "body{"+additionalParam+";}"+
    "img{"+filterReverse+";}"+
    ".video_image_div{"+filterReverse+";}"+
    ".video_external_inline{"+filterReverse+";}"+
    ".page_doc_photo{"+filterReverse+";}"+
    "#mv_content{"+filterReverse+";}"+
    ".page_video_inline_wrap{"+filterReverse+";}"+
    ".wall_module td.page_media_link_thumb{"+filterReverse+";}";
   
    //Вставляем в страницу или заменяем существующий 
    var css = document.getElementById("VKcolorChanger");
    if(css){
        css.innerHTML = data;    
    }else{ 
        var css = document.createElement("style");
        css.setAttribute("type", "text/css");
        css.setAttribute("rel", "stylesheet");
        css.setAttribute("id", "VKcolorChanger");
        css.innerHTML = data;
        document.getElementsByTagName("head")[0].appendChild(css);
    }
});


Для моментального изменения цвета без перезагрузки использовал chrome.tabs.query и chrome.tabs.executeScript
 /**Изменение всех открытых вкладок */
    chrome.tabs.query({'url': 'http://vk.com/*'}, function(tabs) {
        for(var i = 0;i<tabs.length;i++){
            chrome.tabs.executeScript(tabs[i].id, {file : "bg.js"});
        }
    });


Как можно было увидеть в коде выше, добавил черно-белое оформление(к сожалению, изображения так же стали ч/б) и контрастную, в ней пришлось правда сделать текст жирным, т.к. иначе было трудно читать.

Мой код очень далек от совершенства, т.к. мне многому еще надо научиться, а так же я очень торопился и делал исключительно для себя, но друзья попросили выложить в chrome.store.
Исходники расширения — http://joxi.ru/25-AUtg5CbD2GC7gFmU
Страница с расширением в chrome.store — https://chrome.google.com/webstore/detail/vk-color-changer....../jmdenoijfejikcljfggmiijccnmdifjj
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.