Статьи

Создайте собственное расширение для Chrome: инструмент для подсчета слов в Google Documents, часть 3

Здравствуйте, и добро пожаловать в третий и последний этап создания полного расширения Google Chrome с нуля. Напомним, что в первой части этой серии мы создали расширение Chrome, которое примерно посчитало слова в документе Google, который в данный момент находится в фокусе, и сделало это с помощью jQuery. Он добавил строку состояния в нижней части экрана и отобразил счетчик там.

Во второй части мы значительно обновили расширение — добавили точность счетчику слов, добавили счетчик страниц рядом со счетчиком слов, обновили манифест до последней версии, как того требует Chrome, и, самое главное, удалили jQuery в пользу ванильного JavaScript , чтобы получить прибыль с точки зрения производительности и потребления ресурсов.

В этой части мы доработаем наше расширение, добавив страницу параметров, доступ к которой можно получить через вкладку «Расширения», и которую можно использовать для настройки возможностей, которые мы хотим, чтобы наше расширение имело.

Добавление страницы параметров

Страница параметров расширения в основном представляет собой HTML-документ, который (обычно) содержит некоторые элементы формы. Теперь мы могли бы вручную построить страницу параметров и добавить некоторые элементы для хорошей меры, но я никогда не был фанатом переизобретения колеса, и уже есть удивительный пакет, который делает именно то, что мы хотим — он предлагает страницу настроек по умолчанию это выглядит и ощущается как родная страница настроек Chrome. Пожалуйста, скачайте Fancy Setting и разархивируйте его в папку вашего расширения, дав ему название «fancy-settings».

Чтобы наше расширение загружало страницу параметров, нам нужно добавить что угодно в наш файл манифеста:

"options_page": "fancy-settings/source/index.html" 

Это говорит расширению, что страница параметров должна быть загружена из fancy-settings/source/index.html , где мы распаковали скачанный код Fancy Settings. Пока мы редактируем файл manifest.json , давайте увеличим версию до 0.3.

Чтобы увидеть эту страницу параметров в действии (хотя она не будет сейчас полезна), перезагрузите расширение (согласно инструкциям в первой части ) и нажмите «Параметры» рядом с ним (оно должно быть рядом с «Разрешить в инкогнито» «). Это должно открыть новую вкладку, содержащую некоторые довольно красивые элементы формы для нас, чтобы редактировать и настраивать.

Редактирование страницы параметров

Мы добавим следующие простые опции: мы позволим пользователю выбрать одну из трех визуальных тем, мы позволим пользователю отключить счетчики слов и страниц, и мы позволим пользователю удалить ссылку GDWC из строки состояния. ,

Для первого нам нужна группа переключателей с тремя значениями. Для второго нам нужна группа флажков. Для третьего нам нужен одиночный флажок. Все они могут быть построены через fancy-settings, поэтому мы будем использовать их синтаксис. Чтобы узнать больше параметров, которые вы можете использовать с Fancy Settings, прочитайте их страницу документации .

Чтобы добавить нужные нам элементы, мы должны отредактировать манифест самой страницы параметров. Замените содержимое fancy-settings/source/manifest.js следующим текстом:

 window.manifest = { "name": "GDWC", "icon": "../../icon48.png", "settings": [ { "tab": "Main settings", "group": "Visual Settings", "name": "themepicker", "type": "radioGroup", "label": "Choose theme (default is light):", "options": [ ["light", "Light"], ["dark", "Dark"], ["terminal", "Terminal"], ], "default": "light" }, { "tab": "Main settings", "group": "Counter settings", "name": "pagecounter", "type": "checkbox", "label": "Enable Page Counter", "default": true }, { "tab": "Main settings", "group": "Counter settings", "name": "wordcounter", "type": "checkbox", "label": "Enable Word Counter", "default": true }, { "tab": "Main settings", "group": "Other options", "name": "gdwclink", "type": "checkbox", "label": "Show GDWC Sitepoint link?", "default": true } ] }; 

Это так просто. На странице настроек fancy-settings теперь автоматически будут собраны все необходимые элементы. Пожалуйста, перезагрузите расширение и нажмите на опции, чтобы увидеть его в действии.

Чтение настроек по умолчанию и сохраненных настроек

Fancy Settings поставляется с store.js , который помогает вам прочитать настройки расширения. Для этого нам нужно внести несколько изменений. Первое изменение — наш файл манифеста. + Изменить

 "background" : { "scripts": ["background.js"] } 

в

 "background" : { "page": "background.html" } 

Затем создайте страницу background.html в папке расширения и вставьте следующее содержимое:

 <script type="text/javascript" src="fancy-settings/source/lib/store.js"></script> <script type="text/javascript" src="background.js"></script> 

Здесь мы изменили фоновую страницу с JS на HTML, чтобы мы также могли загружать содержимое HTML и другие сценарии в фоновом режиме. На этой HTML-странице мы просто включаем все JS-скрипты, которые хотим загрузить при запуске расширения (в нашем случае, store.js из fancy-settings и наш собственный background.js из ранее). Теперь, когда store.js активен и загружен, мы можем использовать его на самой фоновой странице.

Откройте background.js и в самом верху файла вставьте следующее:

 var settings = new Store("settings", { "themepicker": 'light', "pagecounter": true, "wordcounter": true, "gdwclink": true }); 

Это выбирает параметры из localStorage клиентского компьютера, и, если они еще не установлены, устанавливает значения по умолчанию. Однако нам нужно иметь доступ к этим настройкам через наш контент-скрипт main.js Помните, что вызов фонового скрипта из первой части, где мы сделали это:

 chrome.extension.sendRequest({}, function(response) {}); 

только для отображения значка расширения? Давайте использовать это для лучшего использования.

В background.js измените:

 sendResponse({}); 

в

 sendResponse(settings.toObject()); 

Это отправит восстановленные настройки обратно в скрипт main.js Откройте main.js сейчас и измените:

 chrome.extension.sendRequest({}, function(response) {}); 

в

 var options; chrome.extension.sendRequest({}, function(response) {options = response;}); 

Это означает, что вызов sendRequest не только показывает значок, но теперь также извлекает настройки и заполняет вновь добавленную переменную параметров полученным ответом. Теперь у нас есть опции, доступные в нашем main.js Однако, если мы попытаемся выполнить наш основной сценарий за пределами обратного вызова sendRequest и по-прежнему установить в обратном вызове options = response , внешний код будет выполняться немного быстрее, чем код обратного вызова, поэтому жалоба на то, что переменная «параметры» еще не установлена. Асинхронная природа JavaScript — это то, что нужно тщательно рассмотреть здесь, поэтому, чтобы избежать этих проблем, мы перемещаем этот существующий код:

 var readyStateCheckInterval = setInterval(function() { if (document.readyState === "complete") { countWords(); clearInterval(readyStateCheckInterval); } }, 10); 

после

 options = response; 

но все еще внутри обратного вызова, так что весь обратный вызов sendRequest выглядит следующим образом:

 var options; chrome.extension.sendRequest({}, function(response) { options = response; var readyStateCheckInterval = setInterval(function() { if (document.readyState === "complete") { countWords(); clearInterval(readyStateCheckInterval); } }, 10); }); 

Это изменение гарантирует, что наше расширение вызывает фоновые сценарии и извлекает параметры, прежде чем что-либо еще, таким образом, обеспечивая доступность параметров для всех последующих частей расширения. В положительном повороте событий все это также обрабатывало сохранение наших опций автоматически через библиотеку Store.js .

Использование настроек для управления строкой состояния

Теперь, когда наши настройки можно сохранить и загрузить, и у нас есть все необходимые элементы, давайте добавим некоторые из этих функций. В конце нашего обратного вызова main.js в main.js добавьте следующий код:

 var gdwclink = document.getElementById('gdwclink'); if (options.gdwclink) { gdwclink.style.display = 'inline-block'; } else { gdwclink.style.display = 'none'; } 

Этот код захватывает ссылку GDWC SitePoint, проверяет, должна ли она быть видимой, и действует соответствующим образом. У нас на самом деле нет идентификатора gdwclink в строке состояния, поэтому давайте обернем ссылку и разделитель после нее в промежуток с таким идентификатором. Откройте statusbar.html и измените его:

 <div id='GDWC_statusBar'> <span class='GDWC_statusBarCounter'><a href='http://www.sitepoint.com'>GDWC</a></span> <span class='GDWC_statusBarSeparator'></span> <span class='GDWC_statusBarCounter' id='GDWC_wordsTotal'>Warming up...</span> </div> 

к этому:

 <div id='GDWC_statusBar'> <span id="gdwclink" style='inline-block'> <span class='GDWC_statusBarCounter'><a href='http://www.sitepoint.com'>GDWC</a></span> <span class='GDWC_statusBarSeparator'></span> </span> <span class='GDWC_statusBarCounter' id='GDWC_wordsTotal'>Warming up...</span> </div> 

Это должно сделать. Давайте сделаем счетчик вариантов сейчас. Замените все тело функции countwords() в main.js следующим main.js :

 var wordCount = 0; var pageCount = 0; var message = ''; if (options.pagecounter) { var divs = document.getElementsByTagName('div'), i; for (i in divs) { if((" " + divs[i].className + " ").indexOf(" kix-page ") > -1) { pageCount++; } } message += pageCount + ' pages'; } if (options.wordcounter) { var spans = document.getElementsByTagName('span'), i; for (i in spans) { if((" " + spans[i].className + " ").indexOf(" kix-lineview-text-block ") > -1) { var words = spans[i].innerText.replace(/W+/g, ' ').match(/S+/g); wordCount += words && words.length || 0; } } if (message != '') {message += ', ';} message += wordCount + ' total words'; } document.getElementById('GDWC_wordsTotal').innerText = message; timeout = setTimeout('countWords()', 5000); 

Как видите, мы добавили несколько проверок if перед каждым счетчиком и создали переменную для хранения сообщения, отображаемого в строке состояния. Содержание этого сообщения зависит от выбранных нами опций, то есть от того, хотим ли мы видеть количество страниц, количество слов, ни одного, или оба.

Наконец, давайте сосредоточимся на темах. Мы выбрали «светлый», «темный» и «терминал» в качестве наших опций. Допустим, в CSS-форме они означают следующее:

 div#GDWC_statusBar.light { background-color: #ebebeb; border-top: 1px solid silver; color: black; } div#GDWC_statusBar.dark { background-color: darkgrey; border-top: 1px solid #2d2d2d; color: orange; } div#GDWC_statusBar.terminal { background-color: #000; border-top: 1px solid #2d2d2d; color: green; } 

Вы уже можете видеть, куда мы идем с этим — мы заставим выбранную опцию стать классом нашей строки состояния. Замените весь блок statusbar.html следующим кодом:

 <style type="text/css"> div#GDWC_statusBar.light { background-color: #ebebeb; border-top: 1px solid silver; color: black; } div#GDWC_statusBar.light span.GDWC_statusBarCounter a { color: black; } div#GDWC_statusBar.dark { background-color: #333; border-top: 1px solid #2d2d2d; color: orange; } div#GDWC_statusBar.dark span.GDWC_statusBarCounter a { color: orange; } div#GDWC_statusBar.terminal { background-color: #000; border-top: 1px solid #2d2d2d; color: green; } div#GDWC_statusBar.terminal span.GDWC_statusBarCounter a { color: green; } div#GDWC_statusBar { width: 100%; height: 18px; position: fixed; bottom: 0; z-index: 25000; text-align: right; } span.GDWC_statusBarCounter { padding: 0 10px 0 10px; line-height: 18px; font-family: verdana; font-size: 10pt; } span.GDWC_statusBarCounter a { text-decoration: none; } span.GDWC_statusBarSeparator { border-left: 1px solid silver; border-right: 1px solid silver; margin: 0 1px; display: inline-block; width: 1px; height: 10px; } </style> 

Если вы перезагрузите сейчас, строка состояния будет прозрачным и неуклюжим. Сначала нужно наложить тему по умолчанию. В конце обратного вызова sendRequest, сразу после логики gdwc show / hide, добавьте это:

 var statusbar = document.getElementById('GDWC_statusBar'); statusbar.className = options.themepicker; 

Вот и все. Теперь перезагрузите расширение и документ Google, на котором вы его тестировали. Без изменений, верно? Теперь перейдите к опциям нашего расширения и попробуйте выбрать опцию, а затем обновите документ, на котором вы его тестировали, чтобы увидеть изменения в действии. Поиграйте и добавьте еще несколько собственных опций, если хотите.

К сожалению, нам нужно перезагрузить расширение для параметров, которые мы выбрали для вступления в силу. Хотя расширение расширений в отношении новых настроек не слишком сложно, оно выходит за рамки данной статьи из-за его длины и уровня. В любом случае, позвольте мне указать вам правильное направление, если вы захотите сделать это самостоятельно — все элементы Fancy Settings могут иметь прослушиватели событий, поэтому для этого вы должны прослушать событие change для элементов, которые мы используем, и получить доступ ко всем экземпляры расширения для редактирования содержимого строки состояния. Дополнительную информацию можно найти на вики-странице «Необычные настройки», ссылки на которую приведены выше, и в Руководстве для разработчиков Google .

Вывод

В этой заключительной части серии мы дополнительно обновили наше расширение страницей параметров, напоминающей страницы собственных настроек Chrome, и добавили возможность выбирать темы, отключать определенные функции и скрывать некоторые элементы в строке состояния. Я надеюсь, что этого введения в страницы опций было достаточно, чтобы разжечь ваш аппетит, и что это побудит вас экспериментировать самостоятельно. Мир расширений Chrome — это большой мир, и есть ниша для высококачественных инновационных расширений, улучшающих рабочий процесс. Кто знает? Вы могли бы даже сделать коммерчески жизнеспособным с некоторой практикой.

Вы можете скачать исходный код этого руководства по расширению Chrome с github. Желаем удачи в ваших экспериментах с Chrome!