Почему не понравились? Заменили адресную строку, стало неудобно просматривать почту, заменили закладки и убрали корректор адресной строки (под предлогом установки Punto Switcher, который может и хорош для обычного работника, но никак не для программиста. Поэтому и был удален почти сразу же, как установлен. Да и если можно было бы настроить, то всё равно желание пропало).
Немного погодя было решено создать свой подобный плагин, который будет включать в себя такие плюшки, как просмотр почты и корректор адресной строки. Чтож, раз не ты, так кто другой?
Первым делом решено было не создавать свой велосипед и воскресить Яндекс.Бар, который не хотел работать в 19 версии браузера. В интернете подсказали, что плагин — это обычный zip архив. Открыли, посмотрели, ужаснулись и закрыли. Воскресить не удалось, даже при всем желании.
Тогда заходим в центр разработчика: builder.addons.mozilla.org/. Я предпочел орудовать в веб-редакторе, хоть местами он иногда и не очень гладко работал. Посмотрев на другие плагины, позаимствовав код и немного поняв весь смысл сея устройства, началось сначала всё со стенобитной машины и закончилось надфилем.
Билдер включает в себя 3 раздела: это раздел со скриптами (Lib), раздел с загружаемым контентом (картинки, стили и скрипты) и раздел с готовыми библиотеками (Libraries)
Кстати, вот документация: addons.mozilla.org/en-US/developers/docs/sdk/latest/, добротно написанная.
Старт плагина начинается с загрузки файла main.js.
Вызывается функция: exports.main.
Пример файла main.js:
const tabs = require("tabs"); exports.main = function (options) { tabs.on("ready", function(tab){ tab.attach({ contentScript: "document.addEventListener('click', function(e) { \ var target = e.target; \ if(target.tagName == 'A') { \ var mail_to = target.href.match(/^mailto:(.*)/i); \ if(mail_to != null) { \ e.preventDefault(); \ var form = document.createElement('form'); \ form.setAttribute('action','http://mail.yandex.ru/neo2/#compose/mailto=' + mail_to[1]); \ form.setAttribute('target','_blank'); \ document.getElementsByTagName('body')[0].appendChild(form); \ form.submit(); \ form.parentNode.removeChild(form); \ } \ } \ }, false);" }); }); }
Что же за магия происходит в этом коде?
Первым делом подключается модуль tabs.
В данном случае он служит для того, чтобы можно было добавлять свой JavaScript код в страницу браузера.
Т.е. что у нас: при событии документа onready происходит добавление любого JavaScript кода в тело документа. В данном примере добавляется обработчик ссылок, у которых адрес начинается с mailto.
Ладно, давайте что-нибудь посложнее сделаем. Добавим-ка свою кнопку в верхний бар!
Опять же, не будем строить велосипеды, а с чистой совестью возьмем уже готовую библиотеку Toolbar Button Complete.
В ней же есть пример добавления кнопки в бар браузера. Я думаю, не стоит его сюда вываливать, т.к. там многоватенько кода.
Итак, кнопка есть, иконку поставили, всё вроде хорошо, но не очень. Как же у нас в Яндекс.Баре было? Ах да, напротив иконки еще и счетчик непрочитанных сообщений был.
Тут я разузнал несколько путей добавления счетчика:
- универсальный, но более легкий (с помощью стилей)
- не слишком универсальный, но не такой простой, как первый (с помощью canvas)
Второй способ, правда, нашелся методом тыка в интернет. Но я взял первый.
Нам известно, что верхний бар — это такой же набор элементов со своими классами, идентификаторами, свойствами и способами работы с ними.
Методом тыка типа:
for(var val in document.getElementById('yandex-menu')) { console.log(val); }
было обнаружено, что методы в точности совпадают с теми, что мы обычно используем при работе с элементами сайта. Но замечу, что по стандарту браузер не знает, что такое ни document, ни window в расширениях (да и еще есть отличия).
Пример решения:
var wuntils = require('sdk/window/utils'); var window = wuntils.getMostRecentBrowserWindow(); var document = window.document;
Замечу, что разработка билдера не стоит на месте и если раньше способ получения активного окна был таким:
var winUtils = require("window-utils"); for (window in winUtils.windowIterator()) { if ("chrome://browser/content/browser.xul" != window.location) return; console.log("An open window! " + window.location); }
то сейчас всё намного легче (пример я выше привел).
Чтож, немного рассказав о особенностях, вернусь к добавлению счетчика для кнопки.
Умные люди подсказали, что по стандарту стиль поля labelу кнопки равен display: none;, поэтому как-то нужно было внедрить свой css код в бар. Решение, как оказалось, не сложное (советую завернуть в файл, который будет инклюдится по мере надобности):
const { Cc, Ci } = require('chrome'); const { when: unload } = require('sdk/system/unload'); var ios = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService); /* Helper that registers style sheets and remembers to unregister on unload */ exports.addXULStylesheet = function addXULStylesheet(url) { var uri = newURI(url); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(uri, sss.USER_SHEET); unload(function () { if (sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.unregisterSheet(uri, sss.USER_SHEET); } }); return sss; }; function newURI(uriStr, base) { try { var baseURI = base ? ios.newURI(base, null, null) : null; return ios.newURI(uriStr, null, baseURI); } catch (e) { if (e.result === chrome.Cr.NS_ERROR_MALFORMED_URI) { throw new Error("malformed URI: " + uriStr); } else if (e.result === chrome.Cr.NS_ERROR_FAILURE || e.result === chrome.Cr.NS_ERROR_ILLEGAL_VALUE) { throw new Error("invalid URI: " + uriStr); } } return null; }
И в функцию exprorts.main добавляем что-то вроде (хотя добавлять можете куда угодно):
stylesheet.addXULStylesheet(data.url("stylesheet.css"));
не забыв создать в контенте файл stylesheet.css.
У меня файл содержит примерно следующее:
#yandex-mail { min-width: 16px; } #yandex-mail .toolbarbutton-text { float: right !important; display: inline-block !important; font-size: 13px; padding-left:20px; background: url(data:image/png;base64,iVB.............OCYII=) no-repeat left center; } #yandex-mail .toolbarbutton-icon { display: none; }
Почему мы скрываем иконку и добавляем фон? Всё потому, что если этого не сделать, то блоки всегда отображаются как display: block, какие бы значения я не выставлял (кстати, может кто знает по этой теме?) Поэтому и приходится так хитрить.
Также столкнулся с вопросом загрузки контента с других сайтов и парсинг xml.
С первым быстро разобрался, далеко ходить не надо: Request
А вот со вторым пришлось повозиться.
Как мы знаем, получить dom xml документа можно с помощью нескольких функций:
- XMLHttpRequest — отпал, т.к. выдало ошибку кроссдоменного запроса (может я не так что-то делал?)
- DOMParser — но тут тоже пришлось повозиться
В чем собственно возня: как и с получением window, так и тут:
var {Cc, Ci} = require("chrome"); var parser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser); var dom = parser.parseFromString(xmlPrepare (text), "application/xml");
Вот так создание плагинов для Firefox ничем не отличается от создания плагинов для jQuery 🙂
Кстати, конечное творение на сей день: CustomYandexBar, пока находится на проверке. Исходники, в них много чего полезного.
Если кому-нибудь не понравится, что использую «их» картинки, бренд или т.п. — пишите.
ссылка на оригинал статьи http://habrahabr.ru/post/171517/
Добавить комментарий