Расширение Google Chrome — корзина вкладок

    Пролог


    Доброго времени суток, уважаемый посетитель ХабраХабра!
    В этот очередной в нашей с Вами жизни день знаний (который я, однако, провел исключительно за работой, а не учебой), под влиянием данной статьи, пишу повествование о моем опыте создания расширения для Google Chrome – TabBasket (не знаю, как Вы, но я на названия неказист). Статья оформлена в смешанном стиле – перекликаются элементы урока, а так же пояснения по коду и описание ключевых моментов.
    Прежде чем перейти непосредственно к главному, замечу, что мои знания CSS немного сумбурны, опыта было совсем немного, поэтому какое-то мое решение может показаться слегка странным.

    Что мы имеем


    Для написания расширения нам практически не нужны никакие инструменты, всю работу можно провести хоть в блокноте или gedit. Выбираем редактор на свой вкус (лично я в таких случаях пользуюсь либо Notepad++, либо NetBeans; первое легче, второе функциональнее, выбор как всегда за Вами).

    Ближе к делу


    Перво-наперво исходники.

    Предполагается, что с основами создания расширений читатель уже знаком (опять же из упомянутой выше статьи), поэтому живенько начнем с манифеста:

    {
    "name" : "TabBasket ",
    "version" : "1.5",
    "permissions" : [
    "tabs", "http://*/*"
    ],
    "background_page" : "back.html",
    "browser_action" : {
       "default_title": "Closed tabs",
       "default_icon": "icon.png",
       "popup": "popup.html"
    }
    }


    * This source code was highlighted with Source Code Highlighter.

    Два элемента back.html и popup.html будут постепенно рассмотрены (созданы, написаны) далее. Никаких неожиданной в манифесте нет, все достаточно прозрачно. Для большего понимания процесса, кратенько изложу идею. Замечательная страничка back.html работает в тени, не имеет внешнего вида, её код стартует сразу после установки расширения или запуска браузера, если расширение уже было установлено. Ее роль – установить обработчики для событий создания, удаления или обновления вкладок. Popup.html непосредственно формирует список закрытых вкладок, позволяет восстановить какую – либо из них.

    Двигаемся дальше. Разбираем файл back.html:

    /* Tab constructor function. */
    function AnyTab()
    {
    this.id = 0
    this.url = ""
    this.name = ""
    this.favicon = ""
    }


    * This source code was highlighted with Source Code Highlighter.

    Функция-конструктор для объекта, хранящего информацию о вкладке. Язык позволяет создать инициализированный значениями по умолчанию объект разными методами, я выбрал именно этот. Хранится id вкладки (выдается самим браузером), url(что это о_О?), name (название сайта) и favicon (иконка сайта, с ней отдельная свистопляска). Далее по коду

    var active = []
    var closedTabs = []
    var maxTabCount = 15


    * This source code was highlighted with Source Code Highlighter.

    Нам понадобятся два массива – активных (открытых) вкладок и закрытых. Максимальное число вкладок я выбрал (по-моему мнению) оптимальное. Вешаем обработчики на события

    chrome.tabs.onUpdated.addListener(onTabUpdated)
    chrome.tabs.onRemoved.addListener(onTabRemoved)
    chrome.tabs.onCreated.addListener(onTabCreated)


    * This source code was highlighted with Source Code Highlighter.

    В таком случае onTabUpdated, onTabRemoved И onTabCreated – имена функций обработчиков. Теперь немного приоткроем завесу тайны – когда вкладка создается, необходимо запомнить необходимые нам характеристики (ссылку, название и др.). Делается это потому, что в функцию onTabRemoved приходит только id закрытой вкладки, а ее самой уже и в помине нет. Поэтому при закрытии вкладки она ищется по своему id в массиве active(кстати ее там может и не быть – если расширение было установлено в момент, когда в программе уже были открытие вкладки), данные копируются в массив closedTabs и, соответственно, удаляются из массива active. Теперь мы имеем полную информацию о закрытой вкладке и без труда можем ее восставить! Внимательный читатель, однако, обратит внимание на то, что я не упомянул про функцию onTabUpdated. У нее особенная роль, вызванная следующей особенностью (читай проблемой) – в функцию onTabCreated совсем не сразу приходит вся информация о вкладке. Невооруженным глазом видно, как у новоиспеченной вкладки меняется заголовок, прогружается иконка. Эти данные позднее дотекают в функцию onTabUpdated.

    Роль рабочей лошадки играет функция updateTab. Если первым параметром передать -1, то просто напросто создастся новая вкладка. В другом случае туда передается id вкладки, информацию о которой обновилась.

    function updateTab(index, tab) {
        /* Add new tab. index = -1 passed in onTabCreated */
        if (index === -1) {
          var newTab = new AnyTab()
          newTab.id = tab.id
          newTab.url = tab.url
          newTab.name = tab.title
          newTab.favicon = tab.favIconUrl
          active.push(newTab)
        }
        /* Or update tab. Find index first. */
        else {
          var j, tbCt = active.length

          for ( j = 0; j < tbCt; j++ ) {
            if ( index == active[j].id )
              break
          }
          
          if ( j == tbCt ) {
            console.log("updateTab not found ID "+index)
            return
          }
          
          active[j].id = tab.id
          active[j].url = tab.url
          active[j].name = tab.title
          active[j].favicon = tab.favIconUrl || "icon.png" 
        }
      }


    * This source code was highlighted with Source Code Highlighter.

    Самая сложная часть позади, теперь немного о внешнем виде и popup.html?
    Интерфейс данного расширения – всплывающее окошко со списком сайтов, слева иконка для более интуитивного использования. Так же сверху имеется div класса toolArea – это область инструментов, пока там почетно красуется одна единственная кнопочка – очистка списка.

    JavaScript’овая начинка данной странички достаточно типична и прозрачна, ключевой момент здесь – доступ к back.html, то бишь ко всем функциям и переменным, объявленным там, через вызов метода chrome.extension.getBackgroundPage().

    Скрипт объемный, но если разбить его на логические части, получается очень просто:
    • Создание списка
    • Задание обработчиков mouseover и mouseout
    • Реализация функций клика по элементу списка, а так же наведения курсора

    Это уже чистый, простой JavaScript, с небольшими примесями уже использованных нами приемов.
    Создание:

    var back = chrome.extension.getBackgroundPage()
      for ( var k = back.closedTabs.length - 1; k >= 0; k--) {  
        document.write ("<div id='" + back.closedTabs[k].id + "' onclick='divClick(this)' class='divClass'>")
        document.write ("<img src=" + back.closedTabs[k].favicon + " class='imgClass'>")
        var txtName = back.closedTabs[k].name
        if (txtName.length > 40)
            txtName = txtName.substr(0, 35) + "..."
        document.write ("<span class='labelClass'>" + txtName + "</span>")
        document.write ("</div>")
      }


    * This source code was highlighted with Source Code Highlighter.

    Обработчики:

    var divs = document.getElementsByTagName("div");
      for (var i = 0; i < divs.length; i++)
      {
        if (divs[i].id === "toolDiv") {
          divs[i].onclick = cleanToolClick
        } else {
          divs[i].onmouseover = mouseOverEvent
          divs[i].onmouseout = mouseOutEvent
        }
      }


    * This source code was highlighted with Source Code Highlighter.

    В определенный момент разработки подловил себя на мысли, что при создании новой вкладки в divClick с помощью функции chrome.tabs.create (которая, кстати, принимает объект аргументов, которые легче подсмотреть в документации, чем запоминать из статьи), вкладка автоматически попадает в onTabCreated, так что не нужно беспокоиться о добавлении в массив active вкладок, созданных программно!

    ToDo


    Пишите предложения по улучшению! Пока только очевидным кажется сделать страницу опций с выбором количества вкладок максимального, но из-за одного такого пунктика страницу не хочется (читай ленюсь) создавать!

    Эпилог


    В результате проделанной работы получаем достаточно полезное в хозяйстве и быту расширение, реализующее столь необходимую функциональность, как браузерная корзина. В статье рассмотрены основные приемы работы с вкладками, принципы тесного взаимодействия структурных элементов расширения Google Chrome. Создание расширений – очень интересное и увлекательное занятие! Желательным требованием является базовое знание html, css и JavaScript, однако не обязательным – перед живым интересом ничто не устоит!
    И принимаю замечания по коду, так как считаю себя новичком в JS!
    Удачи Вам в начинаниях, дерзайте, экспериментируйте, создавайте!

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 10

      +3
      А где ссылка на само расширение? Откуда устанавливать для пробы?
        +1
        Упс, об этом не подумал :)

        У меня небольшие проблемы со здоровьем, через часок добавлю, а пока можете в хроме в разделе «расширения» нажать «загрузиь распакованное расширение»!
          +2
            0
            Премного благодарен, что вы оперативно выложили вместо меня!
          0
          Установил, пробую…
            +1
            Оно поддерживает историю? Т.е. если я закрыл таб, потом открыл из корзины, кнопка «назад» будет работать или восстановится только последняя просмотренная в табе страница?
              +1
              Это в раздел ToDo, спасибо за совет!
              +1
              1. Восстановленная из корзины страница будет загружаться заново или, как в браузере Opera, мгновенно откроется из кэша?
              2. Восстановленная из корзины страница откроется в исходном состоянии (как вновь открытая) или, как в браузере Opera, сохранится состояние страницы на момент закрытия (например, сохранится перемотка в какую-то часть страницы)?
              3. Восстановленная из корзины страница откроется с нуля без истории или, как в браузере Opera, сохранится история переходов страницы?

              Иначе говоря, ваше расширение выполняет функцию «restore closed tab» или «reopen closed tab»?
                0
                И чем вас не устроили уже существующие расширения для Chrome с подобным функционалом:
                Trash Can
                Recently Closed Tabs
                TooManyTabs

                Или вашей основной целью было не получить данный функционал в браузере, а просто попробовать себя в создании расширения для Chrome?
                  0
                  Моё видение — в комментариях к статье, о которой упоминается в прологе!

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое