Пишем расширение для google chrome (часть 2)

22-01-2011

Продолжим написание нашего расширения для google chrome, которое начали писать на прошлом "уроке".

В прошлый раз мы сделали "каркас" для нашего расширения и страницу настроек. Подключили JQuery для удобства и научились эти самые настройки со страницы сохранять в локальное хранилище.

В это уроке мы научим наше расширение получать необходимые данные с главной страницы фриланса.

Создадим файл popup.html в корневой папке нашего расширения, который мы ранее указали в файле manifest.json:

Copy Source | Copy HTML
  1. DOCTYPE html>
  2. <html>
  3. <head>
  4.     <link rel="stylesheet" href="img/popup.css" />
  5.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  6. head>
  7. <body>
  8. <div id="main">
  9.     <div id="jobs" class="jobs">
  10.     div>
  11.     <div id="help" class="jobs">
  12.         <a href="#" name="job001" class="new">Новые проектыa><a href="" class="delete" onclick="return false">a>
  13.         <div class="hr">div>
  14.         <a href="#" name="job001" class="">Не просмотренные проектыa><a href="" class="delete" onclick="return false">a>
  15.         <div class="hr">div>
  16.         <a href="#" name="job001" class="clicked">Просмотренные проектыa><a href="" class="delete" onclick="return false">a>
  17.         <div class="hr">div>
  18.         <a href="#" name="job001" class="deleted">Удаленные проектыa>
  19.         <div class="hr">div>
  20.     div>
  21.     Разработка дополнения: <a href="http://cramen.ru">Cramen.rua>
  22. div>
  23. body>
  24. html>
  25.  

Это и есть та страница, которая отображается при клике на иконку нашего расширения. Добавим так же в папку img файл стилей popup.css для нашей новой страницы:

Copy Source | Copy HTML
  1.  
  2. * {
  3.     margin:  0;
  4.     padding:  0;
  5.     color: inherit;
  6.     font-size: inherit;
  7. }
  8.  
  9. body {
  10.     background: #F3F3FF;
  11. }
  12.  
  13. #main {
  14.     font-size: 13px;
  15.     color: #456;
  16.     width:500px;
  17.     margin: 5px 20px 5px 5px;
  18. }
  19.  
  20. .clear {
  21.     clear:both;
  22. }
  23.  
  24. .hr {
  25.     clear:both;
  26.     width: 100%;
  27.     display: block;
  28.     background: #9AB;
  29.     height: 1px;
  30.     border-collapse:collapse;
  31. }
  32.  
  33. .jobs .hr:nth-last-child(1)
  34. {
  35.     background: none;
  36. }
  37.  
  38.  
  39. .jobs {
  40.     border: 2px solid #F3F3FF;
  41.     border-radius: 8px;
  42.     background: -webkit-gradient(linear, left top, left bottom, from(#D0D7E4), to(#B3BBD5));
  43.     -webkit-box-shadow: 0px 0px 5px #888F99;
  44.     margin: 0px 0px 10px 0px;
  45.     min-height: 20px;
  46.     padding: 4px 4px;
  47. }
  48.  
  49. .jobs a {
  50.     text-decoration: none;
  51.     display: block;
  52.     width: 482px;
  53.     height: 14px;
  54.     padding-top: 1px;
  55.     padding-bottom: 1px;
  56.     padding-left:5px;
  57.     margin-right: -16px;
  58.     float: left;
  59.     overflow: hidden;
  60. }
  61.  
  62. .jobs a.todelete {
  63.     background-color: #F7DDD9;
  64. }
  65.  
  66. .jobs a:hover {
  67.     background-color: #D9DDF7;
  68. }
  69.  
  70. .jobs a.new {
  71.     padding-left:16px;
  72.     width: 471px;
  73.     background-image: url("icon_new.png");
  74.     background-repeat: no-repeat;
  75. }
  76.  
  77. .jobs a.clicked {
  78.     color: #889;
  79. }
  80.  
  81. .jobs a.deleted {
  82.     color: #99A;
  83.     text-decoration:line-through;
  84. }
  85.  
  86. .jobs a.delete {
  87.     margin:  0;
  88.     padding:  0;
  89.     display: block;
  90.     width:16px;
  91.     height:14px;
  92.     border: none;
  93.     background: url("icon_delete.png") no-repeat;
  94.     padding:  0;
  95.     margin:  0;
  96. }

Не забываем перезагрузить наше расширение. Теперь мы сможем увидеть красивую, но пока не функциональную страницу, появляющуюся при клике на значок расширения.

Подключим в нашу созданную страницу три файла с яваскриптами. Уже скачанный нами JQuery и два новых для нас: sys.js и popup.js:

Copy Source | Copy HTML
  1. <script type="text/javascript" src="js/jquery.js">script>
  2. <script type="text/javascript" src="js/sys.js">script>
  3. <script type="text/javascript" src="js/popup.js">script>
  4.  

И создадим два новых файла. Пока пустыми. В файле sys.js мы определим пару функций для получения контента с главной страницы фриланса методами GET и POST а так же фунции логина, логаута и релогина на сайт:

Copy Source | Copy HTML
  1.  
  2. var doGet = function(param1,param2)
  3. {
  4.     $.get('http://www.free-lance.ru/',param1,param2);
  5. }
  6.  
  7. var doPost = function(param1,param2)
  8. {
  9.     $.post('http://www.free-lance.ru/',param1,param2);
  10. }
  11.  
  12. var doLogin = function(param1)
  13. {
  14.     doGet(function(data){
  15.         var logouOutForm = $(data).find("#___logout_frm___").length;
  16.         if (logouOutForm == 0)
  17.         {
  18.             doPost({
                    action:     'login',
                    login:      localStorage.login,
                    passwd:     localStorage.passwd,
                    autologin:  1
                });
  19.         }
  20.     },param1);
  21. }
  22.  
  23. var doLogout = function(param1)
  24. {
  25.     doPost({
            action: 'logout'
        },param1);
  26. }
  27.  
  28. var doRelogin = function()
  29. {
  30.     doLogout(doLogin);
  31. }

Подробно комментировать этот код не имеет смысла. Используются элементарные функции JQuery и уже знакомое нам локальное хранилище браузера google chrome.

И наконец, самая магия! Пишем наш файл popup.js, который и будет выводить нам новые проекты с сайта free-lance.ru:

Copy Source | Copy HTML
  1. $(function(){
  2.  
  3.  
  4.     //получаем данные с сайта
  5.     doGet(function(data){
  6.  
  7.         var current_count=1;
  8.  
  9.         //проходимся по всем дивам div.project-preview
  10.         $(data).find("div.project-preview").each(function(){
  11.  
  12.             //если мы перебрали больше проектов, чем надо (указывается в настройках страницы конфигурации), то возпращаемся из функции.
  13.             if (current_count>localStorage['proj_count']) return;
  14.             current_count++;
  15.  
  16.             var link = $(this).find("h3>a"); // сама ссылка на проект
  17.             var name = link.attr("name"); //атрибут name
  18.             var href = link.attr("href"); //атрибут href
  19.             var deleteLink = $("").addClass("delete").attr("href","#"); //создаем объект - ссылку для удаления проекта 
  20.             var clearDiv = $("
    ").addClass("hr"); //создаем объект - div для визуального разделения проектов.
  21.  
  22.             var priceTag = $(this).find(".project-budjet nobr"); //получаем цену проекта
  23.  
  24.             //если цена проекта указана, то добавляем ее к названию.
  25.             if (priceTag.length==1)
  26.             {
  27.                 link.html(link.html()+("+priceTag.html()+")");
  28.             }
  29.  
  30.             $("#jobs").append(link);//добавляем ссылку на всплывающую страницу
  31.             if (!localStorage["deleted_"+name])//если проект не удален, добавляем ссылку на удаление
  32.             {
  33.                 $("#jobs").append(deleteLink);
  34.             }
  35.             $("#jobs").append(clearDiv);//добавляем разделитель
  36.  
  37.             //обработчик ссылки удаления
  38.             deleteLink.click(function(){
  39.                 link.removeClass("new"); //убираем отметку новой
  40.                 link.addClass("deleted"); //метим ссылку, как удаленную
  41.                 localStorage["deleted_"+name] = "yes"; //отмечаем, что ссылка удалена
  42.                 $(this).remove();
  43.                 return false;
  44.             });
  45.  
  46.             //визуальное наведение красоты при наведении на ссылку удаления
  47.             deleteLink.hover(function(){
  48.                 link.addClass("todelete");
  49.             },function(){
  50.                 link.removeClass("todelete");
  51.             });
  52.  
  53.             //обработчик нажатия на ссылку
  54.             link.click(function(){
  55.                 $(this).addClass("clicked"); //метим ссылку, как кликнутую
  56.                 localStorage["clicked_"+name] = true; //отмечаем, что кликали уже на эту ссылку
  57.                 chrome.tabs.create({"url":"http://www.free-lance.ru"+$(this).attr('href'), "selected":false}); // открываем новый таб с нужной страницей
  58.                 return false;
  59.             });
  60.  
  61.             //добавляем класс улаленным ссылкам
  62.             if (localStorage["deleted_"+name])
  63.             {
  64.                 link.addClass("deleted");
  65.                 return;
  66.             }
  67.  
  68.             //если ссылка не просматривалась, метим ее, как новую
  69.             if (!localStorage["view_"+name])
  70.             {
  71.                 link.addClass("new");
  72.                 link.click(function(){
  73.                     $(this).removeClass("new");
  74.                 });
  75.                 localStorage["view_"+name] = true;
  76.             }
  77.  
  78.             //если ссылка кликалась, метим ее, как кликнутую
  79.             if (localStorage["clicked_"+name])
  80.             {
  81.                 link.addClass("clicked");
  82.             }
  83.  
  84.         });
  85.     });
  86.  
  87.  
  88. });

Тут я в коде текста прокомментировал некоторые моменты. Думаю, что этого будет достаточно для понимания сути происходящего.

Не забываем опять же перезагрузить расширение.

Итак! У нас все готово, кроме одного. Пока что не происходит логина на сайт с нашими учетными данным. Исправим это. Чуток поправим наш файл manifest.json:

Copy Source | Copy HTML
  1. {
  2.  "name": "Free-Lance checker by Cramen", // Название расширения
  3.  "version": "2.0", // Номер версии
  4.  "description": "Проверялка новых проектоф на free-lance.ru", // Описание расширения
  5.  
  6.  "permissions": [
  7.   "tabs", // Разрешить расширению работать с вкладками
  8.   "http://www.free-lance.ru/*" // Разрешить расширению обращаться к указанному адресу
  9.  ],
  10.  
  11.  "browser_action": { // Элементы браузера
  12.   "default_title": "Free-Lance checker", // Название кнопки
  13.   "default_icon": "img/icon.png", // Иконка для кнопки
  14.   "popup": "popup.html" // Всплывающее окно
  15.  },
  16.  
  17.  "options_page": "options.html", // Страница настроек
  18.  "background_page": "background.html" // Всплывающее окно
  19. }

Как видно, мы добавили всего одну строку:

"background_page": "background.html" // Всплывающее окно

Эта строка говорит браузеру о том, что следует использовать в качестве фоновой страницы файл background.html. Этот файл будет загружаться один раз при загрузке расширения. В нем то мы и будем логинится!

Создадим background.html со следующим содержимым:

Copy Source | Copy HTML
  1. DOCTYPE html>
  2. <html>
  3. <head>
  4.     <script type="text/javascript" src="js/jquery.js">script>
  5.     <script type="text/javascript" src="js/sys.js">script>
  6.     <script type="text/javascript" src="js/background.js">script>
  7.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  8. head>
  9. <body>
  10. body>
  11. html>

Тут ничего интересного. Самое интересное происходит в подключаемом background.js:

Copy Source | Copy HTML
  1. var onSettingsUpdate = function()
  2. {
  3.     doRelogin();
  4.     alert('Настройки успешно обновлены.');
  5. }
  6.  
  7. doLogin();
  8.  

И в нашем файле options.js мы заменим наш alert на следующую строчку:

Copy Source | Copy HTML
  1. chrome.extension.getBackgroundPage().onSettingsUpdate();

Теперь наше расширение вполне функционально и может информировать нас о новых проектах в удомном для восприятия виде:

внешний вид готового расширения

Пожалуй, на этом я остановлюсь. Конечно, еще много можно сделать в этом расширении. Например подсвечивать или мигать иконкой, когда появляются новые проекты. Опять же, мигать при появлении новых сообщений и т.д. Но это уже не станет проблемой. Все это делается по аналогии того, что уже сделано, так что оставлю это Вам в качестве домашнего задания ;)

Оставлю три подсказки:

  1. Для проверки по расписанию (интервал времени мы уже сохранили в настройках нашего расширения) используйте стандартный setTimeout.
  2. Для изменения иконки используйте chrome.browserAction.setIcon
  3. Не брезгуйте документацией

Надеюсь, написанное мной было Вам полезным.

Все исходники расширения вы можете скачать в этом архиве.

Приветствую критику и комментарии.

Вернуться в блог

Комментарии

Андрей
22-01-2011 08:01

Большое спасибо за такой подробный tutorial.

Андрей
22-01-2011 08:14

У меня вопрос. Скажите пожалуйста, какой средой разработки пользуетесь (для разработки Gooogle расширений) и какие требуются библиотеки для начала разработки?

Заранее, спасибо за ответ.

Антон Еськин
22-01-2011 08:18

Я пользуюсь Eclipse (просто он подсвечивает синтаксис html и javascript). По сути можно пользоваться любым текстовым редактором.

Никаких библиотек не надо. Все, что нужно иметь для разработки расширений google chrome - это сам браузер и любой текстовый редактор.

Андрей
22-01-2011 08:21

Антон, большое спасибо, ушёл качать Eclipce и пробовать.

Dima
23-01-2011 03:44

Антон, спасибо за статью!

p.s. У копи/пастящих код из статьи могут возникнуть трудности, в листингах *.html файлов "съедены" закрывающие теги.

Антон Еськин
23-01-2011 03:47

Да, есть проблема с тегами. Парсер tinyMCE съедает.

Позже исправлю, пока времени нету ))

Илья
09-09-2011 04:50

Добрый день.

Считаю ваше приложение очень полезным и попытался его установить. Но не получается через него подключиться. Скажите, исходники актуальны на данный момент?

Антон Еськин
09-09-2011 09:03

Нет, на данный момент исходники не актуальны. На сайте фриланса изменился исходный код страницы и нужно изменять функции логина/выхода

Оставить комментарий

 

Warning: count(): Parameter must be an array or an object that implements Countable in /var/www/cramen.ru/library/Zend/Db/Table/Abstract.php on line 1259