Готовим расширение под Chrome, украшаем Хабр

    Чтобы сделать расширение достаточно минимальных знаний Javasctipt, HTML и CSS. Давайте добавим на хабр догрузку следующей страницы, а также систематическую проверку новых постов на текущей. Примерно как на twitter.

    Полностью готовый экстеншн можно установить и проверить в работе через Chrome Web Store, а здесь разберемся как написать основной код с нуля (полный занимает всего 6 KB).




    Для начала необходимо создать отдельную папку нашего экстеншна и положить в нее файл manifest.json с таким содержанием:

    {
        "name":"Habrahabr Demo",
        "version":"0.1",
        "description":"Demo plugin",
        "content_scripts":[
            {
                "matches":["http://habrahabr.ru/*"],
                "css":["style.css"],
                "js":["jquery.js", "script.js"]
            }
        ]
    }
    

    Экстеншн будет активирован только на habrahabr.ru. Подгрузит из своей папки пока еще отсутствующие style.css, script.js и библиотеку jQuery. Chrome будет ругаться на отсутствие этих файлов, поэтому положим рядом пустые style.css и script.js, а также скачаем самый свежий jquery (который всегда находится по адресу http://code.jquery.com/jquery.js) и тоже положим в папку.

    Теперь подключим наш экстеншн. Идем в настройки расширений хрома (chrome://settings/extensions), ставим там галочку «Developer mode» и нажам «Load unpacked extension...» указываем местоположение папки с нашими файлами. Модуль добавлен:

    image

    Перезагружаем хабр, убеждаемся что всё действительно работает. Точнее ничего, конечно, не изменится. Для проверки же добавим в style.css что-то вроде:

    #layout {
         max-width: none !important;
    }
    

    А в script.js, скажем:

    $(function(){
    	var username = $("#header .username").text();
    	$("#header .bottom").append(
    		'<a href="/users/' + username + '/topics/">топики</a>'+
    		'<a href="/users/' + username + '/qa/questions/">вопросы</a>'+
    		'<a href="/users/' + username + '/comments/">комментарии</a>'
    	);
    });
    

    Перезагрузите расширение кликнув на ссылку Reload (ее открывает треугольничек слева от иконки расширения). Затем перезагрузим хабр и убедимся что верстка стала резиновой, а под никнеймом добавились новые ссылки (если вы зарегистрированы).

    Приступим к AJAX загрузке. Для начала навесим обработчик клика на ссылку «Туда»:

    $(document).on("click", "#next_page", function () {
    	var nextPrevBlock = $(".next-prev"); // блок с кнопками Сюда/Туда
    	var href = $(this).attr("href"); // ссылка кнопки Туда
    	$.ajax({
    		url:href,
    		success:function (response) {
    			$(".posts").append($(response).find(".posts").html()); // добавляем посты в конец списка
    			$(".page-nav").html($(".page-nav", response).html()); // и заменяем ссылки туда/сюда/страницы на новые
    			stopTrackingScrollToBottom = false; // описание флага будет ниже
    		}
    	});
    	return false; // отменяем переход по ссылке
    });
    

    Теперь при клике по ссылке посты с новой страницы будут добавляться к постам на текущей (cнова не забываем перезагрузить экстеншн и хабр). Хорошим тоном считается показывать индикатор загрузки, здесь же опустим, простоты ради.

    Далее делаем так чтобы ссылка нажимала сама себя когда мы доскроллим до конца страницы

    var stopTrackingScrollToBottom = false;
    $(window).scroll(function () {
    	if ($(window).scrollTop() + 10 >= ($(document).height() - ($(window).height()))) { // за 10 пикселов до конца страницы
    		if (stopTrackingScrollToBottom == false) { // проверяем не инициирован ли уже процесс дозагрузки
    			stopTrackingScrollToBottom = true; // отключаем этот уловитель скролла на время дозагрузки
    			$("#next_page").click(); // загибаем пальцы за пользователя :)
    		}
    	}
    	if ($(window).scrollTop() == 0) { // юзер доскроллил до верха
    		checkForNewPosts();
    	}
    });
    


    И заодно заложили начало второй части скрипта — вызов checkForNewPosts() при скролле до начала страницы. Функция должна проверять наличие новых постов на текущей странице и сообщать бэйджиком:

    function checkForNewPosts(andLoadThem) {
    	if ($(".posts").length == 0) {
    		// это вообще не страница с постами, уходим
    		return;
    	}
    	$(".posts").prepend('<div class="new-posts-ajax"><img src="http://isbeauty.ru/images/icon_ajax_loader.gif"/></div>');
    	$.ajax({
    		url:window.location.href,
    		success:function (response) {
    			$(".new-posts-ajax").remove();
    			// Находим все айдишники постов на текущей странице и сравниваем с айишниками в ответе
    			var newPosts = getPostIds(response).diff(getPostIds());
    			Tinycon.setBubble(newPosts.length);
    		}
    	});
    }
    
    Array.prototype.diff = function (a) {
    	return this.filter(function (i) {
    		return !(a.indexOf(i) > -1);
    	});
    };
    
    function getPostIds(where) {
    	var postIds = [];
    	$(".post", where).each(function () {
    		var postId = $(this).attr("id");
    		postIds.push(postId);
    	});
    	return postIds;
    }
    
    


    Пока еще нет результата, потому что Tinycon.setBubble() не существует. Она должна выставлять бэйджик на фавиконке и реализована в библиотеке Tinycon. Чтобы ее подключить скачайте tinycon.js из github, положите в папку расширения и не забудьте подключить tinycon.js в manifest.json.

    Чтобы проверить что бэйджик работает — зайдем на http://habrahabr.ru/posts/top/daily/ (вообще лучше тренироваться на страницах топа, они по всей видимости кэшируются и не создают большой нагрузки). Откроем инспектр кода (F12), удалим пару дивов внутри <div class="posts">...</div> и проскроллим на начало страницы. Бэйджик должен показать количество отсутствующих топиков.

    Сделаем еще так, чтобы эта проверка происходила регулярно, раз в минуту:

    var MAX_CHECKS_FOR_NEW_POSTS = 60; // введем ограничение на количество запросов, на случай если надо выйти за пельменями
    var CHECK_FOR_NEW_POSTS_EACH = 60; // через сколько секунд проверять наличие новых
    
    $(function () {
    
    	window.checkNewPostsTimer = setInterval(function () {
    		MAX_CHECKS_FOR_NEW_POSTS--;
    		if (MAX_CHECKS_FOR_NEW_POSTS <= 0) {
    			// self-destroy timer
    			clearInterval(window.checkNewPostsTimer);
    		} else {
    			checkForNewPosts();
    		}
    	}, CHECK_FOR_NEW_POSTS_EACH * 1000);
    
    });
    


    Не так уж много кода осталось, но на этом закончу. Не охвачена эстетическая сторона вопроса, а также возможность дозагрузить найденные новые посты, отменить автоматическую дозагрузку следующей страницы (по кнопке и по <Esc>). Всё это реализовано в готовом экстеншне, а исходный код доступен после установки где-то в папке:
    C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data\Default\Extensions\glaccbllkhielccdhfbbpilnlbemgaji
    (если там нет, ищите папку glaccbllkhielccdhfbbpilnlbemgaji где-то еще).

    Осталось выложить расширение для публичного доступа. Для этого нужно получить приватный файл ключа, он требуется чтобы заливать эту и новые версии вашего экстеншна в дальнейшем. В настройках расширений кликаем кнопку «Pack extension», указываем путь к папке и оставляем путь к ключу пустым:

    image

    После упаковки хром создаст файл DemoExtension.crx и DemoExtension.pem, последний вам нужно переименовать в key.pem и кинуть в папку экстеншна (не теряйте его, а то не сможете обновлять это расширение). После чего всю папку расширения нужно заархивировать в DemoExtension.zip и залить в вашу панель управления. CRX файл при этом вообще не участвует.

    После заливки архива нужно будет заполнить анкетные данные расширения и можно публиковать. Публичным расширение в Chrome Web Store можно сделать после единоразового пожертвования корпорации $5, врочем это необязательно, полученный ранее DemoExtension.crx (не zip) можно выложить хоть на Dropbox, Chrome даст установить его после подтверждения безопасности.

    Вот как выглядит залитый в Web Store модуль:

    image

    Данное расширение не добавляет кнопок на панель, ни диалоговых окон, ни пунктов в контекстное меню, не имеет настроек, но вы сами разберетесь как это всё делать.

    Теперь же вперед, делать сайты лучше, удобнее, красивее! :)

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 10

      +3
      Спасибо! Приступаю к созданию расширения для своего проекта, очень полезно для меня.
        0
        Классно! Спасибо! Не думал, что всё так просто ;)
        После этой статьи расширений для хрома станет на порядок больше!
          0
          Я тоже на это расчитываю :)
          0
          Круто! Даеш неделю расширений Хрома для Хабра :)
            0
            И Хабра для Хрома :)
            0
            Буквально два дня назад сделал расширение для Chrome, связанное с одним из моих сайтов, но опубликовать не смог, т.к. требуется оплата. Проблема, впрочем, не в деньгах, а в том, что Google Wallet упорно не хочет принимать мою карту. В связи с этим хотелось бы задать вопрос: быть может есть способ оплаты этих 5$ через PayPal или каким-либо другим образом? Если Вы знаете какие-либо варианты, был бы очень признателен за информацию.
              0
              Главное потом избавиться от jquery.
                0


                КАК вы сделали это?!
                  0
                  Если кликнуть по этому месту там будет возможность создать/переключаться между профилями (аккаунтами), к ним на выбор аватарка.
                    0
                    Ааа, понял. Просто мультипрофилем Хрома не пользовался.

                Only users with full accounts can post comments. Log in, please.