Статьи

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

Здравствуйте и добро пожаловать во вторую часть нашего учебника по созданию собственного расширения Chrome!

В предыдущей части этой серии мы создали простое расширение Google Chrome, которое добавляет постоянный счетчик слов в ваши открытые Документы Google. Наше расширение определяет, когда оно находится в контексте, в котором оно должно активироваться, и периодически запускает ту часть себя, которая помогает ему подсчитать количество слов в документе. Хотя и не очень точная, это была достойная и полезная первая версия, которая хорошо служила своей первоначальной цели.

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

Давайте начнем!

Обновление файла манифеста

Как указали Майкл в разделе комментариев предыдущей установки и Мохамед Мансур в моем посте в Google+ , Google постепенно прекращает поддержку манифестных файлов v1 .

Файлы манифеста, как упоминалось ранее, представляют собой файлы, которые описывают в Chrome, что делает расширение, как оно работает, и следует ли ему разрешать что-либо делать. Директивы в этих файлах часто меняются с новыми версиями по мере развития Интернета, и Google Chrome добавляет новые функции для разработчиков, поэтому для того, чтобы наше расширение «продавалось» в Интернет-магазине Chrome, нам нужно добавить следующую строку в любом месте нашего файла манифеста :

"manifest_version" : 2, 

Я добавил это сразу под «версией». Пока мы на этом, давайте увеличим значение версии до 0,2.

Новая версия манифеста, однако, имеет некоторые дополнительные требования. Теперь нам нужно перечислить все ресурсы, которые мы будем загружать «на стороне», в ключе web_accessible_resources . Без этого наш statusbar.html не загрузится и выдаст ошибку «Отказ в загрузке chrome-extension: //…/statusbar.html. Ресурсы должны быть перечислены в web_accessible_resources манифеста web_accessible_resources для загрузки веб-страницами ». Чтобы избежать этого, мы просто добавляем следующее содержимое в наш файл манифеста:

  "web_accessible_resources" : ["statusbar.html"] 

Это оно! Если вы попытаетесь перезагрузить расширение сейчас (согласно части первой ), все должно идти так, как ожидалось, и никаких предупреждений не должно отображаться.

Добавление счетчика страниц

В прошлый раз мы узнали, что элемент «row» в документе Google — это span с классом «kix-lineview-text-block». При дальнейшей проверке мы узнаем, что элемент, который содержит реальную страницу, является, как и ожидалось, элементом div с классом «kix-page». Таким образом, не должно быть никаких проблем с добавлением счетчика страниц к нашему счетчику слов.

Измените содержимое метода countWords () в main.js следующим образом:

 var pageCount = $('div.kix-page').length; var wordCount = 0; $('span.kix-lineview-text-block').each(function(i, obj){ wordCount += $(obj).text().split(/s+/).length; }); $('span#GDWC_wordsTotal').text(pageCount + ' pages, ' + wordCount + ' total words'); timeout = setTimeout('countWords()', 5000); 

Как видите, мы добавили новую переменную pageCount . Поскольку разбивать на части нечего и элементы уже определены как страницы, все, что нам нужно сделать, это подсчитать их, используя свойство length. Затем мы просто добавляем сообщение «номер страницы» к нашему сообщению «общее количество слов», и все готово. Не стесняйтесь, чтобы перезагрузить расширение и попробовать.

Добавление точности в счетчик слов

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

 wordCount += $(obj).text().split(/s+/).length; 

в

 words = $(obj).text().match(/S+/g); wordCount += words && words.length || 0; 

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

Важно отметить, что Google Docs загружает контент динамически, то есть только по запросу. Таким образом, когда вы впервые запускаете документ, в котором уже есть какой-то контент, сначала прокрутите все это и вернитесь наверх, чтобы браузер получил данные всего документа.

Но что, если бы мы хотели исключить пунктуацию и другие символы из запускающего приращение числа слов? Все эти «…», запятые, точки и убегающие апострофы могут сместить правильный счет, и без них нам было бы лучше. Давайте заменим линию

 words = $(obj).text().match(/S+/g); 

с

 var words = $(obj).text().replace(/W+/g, ' ').match(/S+/g); 

Здесь мы заменили каждый набор из одного или нескольких не алфавитно-цифровых символов одним пробелом. Это означает, что «…» и «###» становятся единым пробелом, подобно запятым, точкам и другим символам, поэтому они не считаются словами. Хотя это добавляет точность при удалении мусорных символов, оно уменьшает точность при подсчете строк, таких как даты. Например, 1998.03.05 станет 1998 03 05, что означает три слова. Это вводит некоторые новые трудности, которые мы могли бы решить в следующей части. А пока давайте оставим это на этом.

Удаление jQuery

Хотя это не так важно для расширений Chrome, как для веб-сайтов, поскольку все файлы загружаются на клиент и хранятся там (удаленная загрузка jQuery не выполняется при каждом запуске расширения), удаление jQuery уменьшит размер нашего файла и занимает немного памяти и позволяет нам взглянуть на альтернативный синтаксис JavaScript. Кроме того, поскольку нам не нужна обратная совместимость и кросс-браузерная работоспособность jQuery из-за создания этого расширения только для Google Chrome, наличие всей его функциональности является своего рода излишним.

Поскольку main.js — наш единственный файл, содержащий jQuery, давайте сейчас откроем его и начнем с самой первой команды — вызова ajax нашего файла statusbar.html . + Изменить

  $.get(chrome.extension.getURL("statusbar.html"), {}, function(data) {$('body').append(data);}, 'html'); 

в

 var xhReq = new XMLHttpRequest(); xhReq.onreadystatechange = function onSumResponse() { if (xhReq.readyState == 4) { var serverResponse = xhReq.responseText; var body = document.getElementsByTagName("body")[0]; var div = document.createElement('div'); div.innerHTML = serverResponse; body.appendChild(div); } } xhReq.open("GET", chrome.extension.getURL("statusbar.html"), true); xhReq.send(null); 

Хм, мы превратили чрезвычайно простую строку кода в беспорядок. Или мы? Это в основном то, что делал наш предыдущий код — он просто служил оболочкой для вызова, идентичного этому. Таким образом, хотя этот код немного больше, в ретроспективе он фактически запускает меньше кода, потому что нет никаких накладных расходов на вызов jQuery, который, в свою очередь, должен решить, какую оболочку XHR вызывать следующим и т. Д. Так что же делает этот беспорядок? Во-первых, он создает экземпляр XMLHttpRequest, который представляет собой объект JS, «используемый для отправки запросов HTTP или HTTPS непосредственно на веб-сервер и загрузки данных ответа сервера непосредственно обратно в сценарий» . По сути, это то, что выполняет вызов Ajax. Затем мы гарантируем, что когда его свойство readyState изменится на 4 (готово), оно извлекает текст нашего ответа (нашу строку состояния), вставляет его в пустой div и добавляет этот div в конец «body». Наконец, мы начинаем запрос с open() и send() .

Давайте обратим наше внимание на проверку того, готов ли документ к использованию сейчас. замещать

 $(document).ready(function(){ countWords(); }); 

с

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

Этот фрагмент кода удаляет метод проверки jQuery, готов ли документ к манипулированию, и создает интервальную проверку, которая проверяет, готов ли документ каждые 10 мс. Как только он обнаруживает, что это так, он вызывает countWords() , очищает интервал и проверка останавливается.

Теперь давайте посмотрим, что мы можем сделать с переменной pageCount . замещать

 var pageCount = $('div.kix-page').length; 

с

 var pageCount = 0; var divs = document.getElementsByTagName('div'), i; for (i in divs) { if((" " + divs[i].className + " ").indexOf(" kix-page ") > -1) { pageCount++; } } 

Это извлекает все элементы div на веб-сайте и определяет, содержит ли их свойство class наше.

Теперь давайте заменим цикл jQuery, который подсчитывал количество строк, на самодельный. замещать

 $('span.kix-lineview-text-block').each(function(i, obj){ var words = $(obj).text().replace(/W+/g, ' ').match(/S+/g); wordCount += words && words.length || 0; }); 

с

 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; } } 

Наконец, мы можем заменить

 $('span#GDWC_wordsTotal').text(pageCount + ' pages, ' + wordCount + ' total words'); 

с

 document.getElementById('GDWC_wordsTotal').innerText = pageCount + ' pages, ' + wordCount + ' total words'; 

… Чтобы отобразить сообщение без jQuery. Конечно, нам также нужно удалить загрузку jQuery из манифеста расширения, поэтому измените

 "js": ["jq.js","main.js"], 

в

 "js": ["main.js"], 

и не стесняйтесь удалять файл jq.js

Вывод

Во второй части серии из трех частей о создании расширения Google Chrome мы рассмотрели, как немного изменить наше расширение, чтобы оно работало быстрее и соответствовало новейшим стандартам разработки Google. Мы добавили некоторую точность в наш счетчик слов, реализовали счетчик страниц рядом со счетчиком слов, обновили файл манифеста с некоторыми новыми обязательными директивами и объявлением версии, и мы взялись за гигантскую задачу преобразования нашего кода jQuery в ванильный JavaScript, тем самым выигрывая в скорости, использовании памяти и уменьшенном размере файла. В следующей и последней части этой серии мы еще больше повысим производительность нашего расширения и добавим некоторые полезные функции в саму строку состояния. Будьте на связи!