Как стать автором
Обновить

Пишем сами расширение для 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
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.