Форум   Статьи   Новости   Файлы   Bugtraq   Сниффер   Друзья   О Клубе

Последнее на Форуме

Пожертвования

Liberty Reserve: U9999024
Кошельки WebMoney:
Z583322939655
E121331800314
R274644017049
U349709454906


YM: 410011220120073

Пожертвовать

Контакты

Связь с Администрацией

hpcteam1[@]gmail.com

Статьи rss

[ Добавить Статью на сайт ]

Статьи / Программирование / JavaScript

Создание расширения для Google Chrome (часть вторая)

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

После прочтения статьи вы сможете делать следующее:

1) Создавать расширения с полноценным popup-окном.
2) Работать с Cross-Origin XMLHttpRequest.
3) Работать с регулярными выражениями.
4) Работать с FileApi.
5) Работать Canvas.

Про работу нашего расширения


Наверное, каждый из нас искал изображения по ключевому слову при помощи Google. И сохранять приходилось не одну-две картинки рутинными действиями. Мы же предложим сохранять все изображения или по одному одним только кликом по изображения. Так же будем сохранять картинки похожие на выбранное изображение.

Теперь разберем технические моменты реализации сохранения картинок по ключевому слову:

1) Добавим в popup-страницу поле для ключевого слова. Google предлагает искать картинки по размеру и по цвету, так что это тоже надо добавить в popup.

2) Составляем URL-ссылку для поиска картинок, отправляем туда XMLHttpRequest и получаем ее response text.

3) Находим ссылки на картинки при помощи регулярных выражений.

4) Открываем новую страницу с этими картинками с кнопкой “Сохранить все” и onclick-функцией сохранения на каждом изображении.

Технические моменты реализации сохранения похожих картинок:

1) Добавим в контекстные меню изображений функцию “Сохранить похожие”.

2) При клике составляем ссылку для поиска по этой картинке, отправляем XMLHttpRequest и получаем response text. При помощи регулярных выражений находим ссылку на “Похожие изображения” и еще раз отправляем XMLHttpRequest по этой ссылке, затем находим ссылки на изображения. Дальше следует 4 пункт из текста выше.

Примечание: Во втором случае все длиннее из-за того что нельзя сразу получить похожие изображения и приходится находить ссылку в поиске по изображению.

manifest.json


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

Сама строка:

"permissions": [ "contextMenus", "tabs", "http://*/*", "https://*/*" ],

popup.html


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

http://www.google.com.ua/search?hl=uk&biw=1406&bih=735&gs_sm=&gs_upl=&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&q=ключевое слово


Если добавить цвет и размер необходимых изображений, то в конце ссылки добавится &tbs=isc:цвет изображения,ic:specific,isz: размер. Причем размер обозначается тремя буквами l-большие, m-Средние, isz-маленькие, а цвет простыми английскими словами: brown, grey, green и т.д.

На popup-странице будут располагаться 4 элемента: строка для ввода слова, квадраты разных цветов ,выпадающий список и кнопка “НАЙТИ”. Текстовое поле добавим в обрамляющий блок, для css-дизайна. Разноцветные квадраты будут radio-кнопками пробелами в лейблах. Стандартные ”кружки” мы уберем так:

input[type="radio"] {
   position: absolute;
   left: -9999px;
}

А цвет будем указывать для каждого отдельно, например:

.ch8+ label {
   background-color:white;
}

Осталось только добавить наши radio в таблицу 3*4 и не забыть про кнопку, т.к. много людей любят нажимать Enter, а не кликать по кнопке, то добавим в body при нажатии на кнопку проверку кода нажатой клавиши и если это Enter(ее код=13), то выполним функцию.

Вот то, что в конце получилось у меня:

<body onKeyDown="javascript:if(13==event.keyCode){google();}">
<div class="inp164"><input type="text" class="textq" id="text"></div>

<a href="#" class="myButton" onclick=google() style="width: 115px;">Найти</a>

<p>Цвет

<table><tr>
<td><input type="radio"  class="ch4" id="ch3" value="red" name="color"/> <label for="ch3">     </label><br /></td>
<td><input type="radio"  class="ch1" id="ch0" value="orange" name="color"/> <label for="ch0">     </label><br /></td>
<td><input type="radio"  class="ch2" id="ch1" value="yellow" name="color"/> <label for="ch1">     </label><br /></td>
<td><input type="radio"  class="ch3" id="ch2" value="green" name="color"/> <label for="ch2">     </label><br /></td>
</tr>
<tr>
<td><input type="radio"  class="ch5" id="ch4" value="teal" name="color"/> <label for="ch4">     </label><br /></td>
<td><input type="radio"  class="ch9" id="ch8" value="blue" name="color"/> <label for="ch8">     </label><br /></td>
<td><input type="radio"  class="ch12" id="ch11" value="purple" name="color"/> <label for="ch11">     </label><br /></td>
<td><input type="radio"  class="ch11" id="ch10" value="pink" name="color"/> <label for="ch10">     </label><br /></td>
</tr>
<tr>
<td><input type="radio"  class="ch8" id="ch7" value="white" name="color"/> <label for="ch7">     </label><br /></td>
<td><input type="radio"  class="ch10" id="ch9" value="grey" name="color"/> <label for="ch9">     </label><br /></td>
<td><input type="radio"  class="ch7" id="ch6" value="balck" name="color"/> <label for="ch6">     </label><br /></td>
<td><input type="radio"  class="ch6" id="ch5" value="brown" name="color"/> <label for="ch5">     </label><br /></td>
</tr>
</table>
</p>
<p>Размер
<select id="more2">
<option value="">Любые</option>
<option value="isz:l">Большие</option>
<option value="isz:m">Средние</option>
<option value="isz:i">Маленькие</option>
</select>
</div>
</body>

Примечание: css-код приводить не буду, его вы найдете в исходниках.

Вот какой вид будет иметь наш popup:


Напишем javascript-функцию google() для составления URL и сохранения его в локальное хранилище. Первым мы получим текстовое поле по id, чтобы узнать введенное в него слово. Затем объявим tcolor=-1 ,получим все radio, напишем цикл и узнаем, какой цвет выбран, прочитав значение. Если он не выбран, то переменная tcolor останется -1. Дальше получим выбранное поле в теге select и если оно не равно -1, то прочитаем и его значение. Если tcolor=-1 и индекс выбранного поля равен тоже -1, то пользователь ничего не выбирал и к http://www.google.com.ua/search?hl=uk&biw=1406&bih=735&gs_sm=&gs_upl=&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&q=
надо прибавить text.value.

Если хоть одно условие ложно, то к ссылке надо прибавить

text.value&tbs=isc:"+tcolor+",ic:specific,"+morec[more2].value

где morec= document.getElementById("more2"), а more2 выбранный индекс.

Сохраняем составленный URL в локальное хранилище и открываем новую вкладку newtab.html.

Код функции:

function google() {
var tcolor=-1;
var text = document.getElementById("text");

var more1=document.getElementsByName("color");
    for (var g=0; g < more1.length; g++) {
       if (more1[g].checked) {
          tcolor= more1[g].value;
       }											
}

var more2 = document.getElementById("more2").selectedIndex;

morec = document.getElementById("more2");
if(tcolor==-1 && more2==-1)
{
var url = "http://www.google.com.ua/search?hl=uk&biw=1406&bih=735&gs_sm=&gs_upl=&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&q=" + text.value;
}
else
{
var url = "http://www.google.com.ua/search?hl=uk&biw=1406&bih=735&gs_sm=&gs_upl=&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&q=" + text.value+"&tbs=isc:"+tcolor+",ic:specific,"+morec[more2].value;
}

localStorage["img"] = url;
chrome.tabs.create({url:"newtab.html"});

}

newtab.html


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

Для начала разберемся с HTML-кодом. Я уже говорил про возможность сохранения в один клик при помощи FileApi, но для этого нам нужно знать data картинки. При клике мы будем прорисовывать выбранное изображение в canvas. К счастью, я нашел скрипт на Github, который существенно облегчит нам задание, после прорисовки можно сохранить изображение в 2 строки, вместо того чтобы получать data’у в base64 из canvas при помощи toDataUrl, затем расшифровывать ее и писать еще 10 строк для сохранения.

Первым делом добавим таблицу стилей css и javascript-библиотеки (Первая для того, чтобы получить данные картинки, вторая для сохранения в 1 строку). Дальше добавим canvas и установим display:none для того чтобы пользователь не видел прорисовку в canvas. Для всего содержимого страницы воспользуемся таблицей для правильного расположения элементов. В div-контейнере для кнопки установим position:fixed чтобы при прокрутке кнопка всегда оставалась. При клике на кнопку функция SaveAll будет сохранять все изображения на странице. Т.к. подгруздка изображений займет некоторое время, то будем показывать прелоадер (loading.gif), пока все не загрузится, а потом поставим display:none. И наконец, в div-контейнере с id content будем добавлять найденные изображения.

<link href=style.css rel="stylesheet" type="text/css" />
<script type="text/javascript" src="https://raw.github.com/eligrey/canvas-toBlob.js/master/canvas-toBlob.min.js"></script>
<script type="text/javascript" src="https://raw.github.com/eligrey/BlobBuilder.js/master/BlobBuilder.min.js"></script>
<script type="text/javascript" src="https://raw.github.com/eligrey/FileSaver.js/master/FileSaver.min.js"></script>
<canvas id="can1" style="display:none"></canvas>
<table border="0">
 
<tr>
<td width="200px" height="100%" align="center" valign="top">
<div class="unscroll">
<p id="svall"  onclick="SaveAll()" class="myButton" style="display:none">Save All</p>
</div>
</td>
<td>
<img src = loading.gif id="resp2"/>

<div id="content">
 </td>
</tr>
</table>
</div>

Теперь рассмотрим, как мы будем получать изображения. Для получения кода страницы с результатами мы будем использовать XMLHttpRequest, который не ограничен same origin policy. XMLHttpRequest позволяет посылать HTTP-запросы без перезагрузки страницы. Работать с XMLHttpRequest можно объявив переменную как новый XMLHttpRequest. Сам запрос выглядит так:

Переменная. Open(“метод”,” адрес запроса”, флаг использования асинхронного запроса)

Подробнее тут.

Для наглядности работы регулярных выражений я рекомендую сайты:

http://regexpres.narod.ru/calculator.html
http://gskinner.com/RegExr/

На них можно посмотреть на работу регулярного выражения “в живую”. Также там есть все основные конструкции. Тем, кто ничего не знает про регулярные выражения, советую прочитать эту статью.

Первым делом читаем из локального хранилища ячейку img, посылаем по ней XMLHttpRequest и получаем исходный код страницы в переменную cptext. Затем в массив записываем те типы картинок, ссылки на которые мы будем искать в исходном коде. Быстрее будет отдельно находить изображения и подгружать их в цикле по очереди, чем грузить все вместе. При поиске ссылок на изображения нам нужно получить массив из ссылок, поэтому мы используем метод match с флагом для глобального поиска (это означает, что регулярное выражение ищет совпадения во всем исходном коде страницы).

Структура нашего регулярного выражения:

1) http:\/\/ - тоже, что и http:// но после каждого символа слеша должен идти обратный слеш.

2) [^:;=\s]{1,} – любые символов кроме “:”,”;”,”=” (минимум 1 символ).

3) jpg – тип изображения.

4) g – флаг глобального поиска.

Если нашлось хоть одно изображение, то продолжаем и вызываем функцию imagessite(). Эта функция подгружает изображения на страницу. И в конце кода напишем xhr.send(), что означает что мы ничего не посылаем.

var b;
var forsite;
var truesearch = new Array();
var url=readProperty("img");
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
var cptext = xhr.responseText;
truesearch[0]="jpg";
truesearch[1]="png";
truesearch[2]="gif";
var cptext = xhr.responseText;

console.log(cptext);

for (var r=0;r< truesearch.length ;r++ )
{
if(poisk=="jpg")
{
resalt = cptext.match(/http:\/\/[^:;=\s]{1,}.jpg/g);
}
 
if (poisk=="png")
{
resalt = cptext.match(/http:\/\/[^:;=\s]{1,}.png/g);
}
if (poisk=="gif")
{
resalt = cptext.match(/http:\/\/[^:;=\s]{1,}.gif/g);
}
if (resalt!=null)

{

forsite= resalt;

imagessite();

}
}

}
}
xhr.send();

Функция imagessite должна, имея адреса изображений в массиве, вставить их в div контейнер. Так же поверх каждого изображения будет полупрозрачная иконка загрузки, чтобы пользователь понял, что сохранять можно и кликом по изображению. Еще надо присваивать каждому изображению id, а при клике на полупрозрачную иконку загрузки передавать id картинки под иконкой в функцию сохранения.

Из-за того что адреса некоторых картинок не всегда такие “красивые” как хотелось бы, то наше регулярное выражение могло выдать “кривые” адреса. Первым делом мы проверяем, есть тип у нашего адреса. Это можно сделать проверив “.” в последних четырех символах адреса.

Если ссылка прошла, то функция savecanvas будет сохранять изображение, id которого ей передадут при клике. Под изображением также будет текстовое поле, с адресом изображения выше. Если ссылка не подошла под условие, то мы уменьшаем b, так как в противном случае id у изображений будут не строго увеличивающимися на 1 и функция SaveAll не сработает.

После подгрузки изображений появится кнопка “Сохранить все” и пропадет прелоадер.

function imagessite(){
for(var i =0;i<forsite.length;i++)
{
var testsite=forsite[i].substr(forsite[i].length-4,forsite[i].length);
if(testsite.replace(/[^.]/g,"").length==1&&forsite[i].replace(/[^%]/g,"").length==0 )
//проверка на корректность
{
 document.getElementById("content").innerHTML += '<div class="content"><img src="' +forsite[i] + '" id="chh'+b+'" onclick="savecanvas('+b+')" width="200" height="200"><img class="dnld" src="dnld.png" onclick="savecanvas('+b+')" /><input type="text" id="ctt'+b+'" value="' +forsite[i] + '" style="position:relative; top: -200px; width: 180px"></div>';
//добавляем миниатюры изображений
}
else
{
b=b-1;
}

b++;
}
var hhh1 = document.getElementById("svall");
hhh1.style.display = 'block';
var hhh1 = document.getElementById("resp2");
hhh1.style.display = 'none';
//убираем прелоадер
}

Реализацию сохранения изображений будет разбита на 2 функции: прорисовка и сохранение. Сохранение всех изображений будет представлять собой вызов функции прорисовки столько раз, сколько изображений на странице. Для наглядности работы функций можно заменить none на block в стиле canvas’а.

Сначала приравниваем высоту canvas’а к настоящей высоте изображения и рисуем переданное изображение в canvas’е.
Чтобы сохранить изображение с оригинальным названием надо найти его в адресе изображения при помощи регулярных выражений.

Структура нашего регулярного выражения:

1) [^/]{1,} - любое количество (только не ноль) любых символов кроме слеша.

2) (?:jpg|png|gif|JPG|PNG|GIF) – конструкция, означающая или jpg или png или GIF и т.д. "?:" говорит, что
запоминать надо найденное не по этой конструкции, а по всему регулярному выражению.

В конце вызываем функцию scanvas() для сохранения.

var canvas ;
var imagename;
var savecanvas = function savecan(number) {
var imgforcanvas = document.getElementById('chh'+number+'');
canvas = document.getElementById("can1");
canvas.width = imgforcanvas.naturalWidth;

canvas.height = imgforcanvas.naturalHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(imgforcanvas, 0, 0);
//отрисовываем изображение
var VRegExp = new RegExp(/[^/]{1,}.(?:jpg|png|gif|JPG|PNG|GIF)/);
var AInputText=document.getElementById('ctt'+number+'').value;
imagename= AInputText.match(VRegExp); 
scanvas();

}
	
function scanvas(){
canvas = document.getElementById("can1");
canvas.toBlob(function(blob) {
saveAs(blob, imagename);
//сохраняем изображение
}, "image/png");
 
}

function SaveAll(){
for(var s=0;s<b;s++)
{
savecanvas(s);
}

 }

Конечный вид страницы:



background.html


Если воспользоваться поиском по изображению от Google, написав адрес изображение, получим такую ссылку:

http://www.google.com/searchbyimage?image_url=ссылка на изображение.

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

Вот код функции:

function saveSimilar(info,tab) {
   localStorage["chsurl"] = "http://www.google.com/searchbyimage?image_url=" + info.srcUrl;
   chrome.tabs.create({url:"similar.html"});
}

Добавим в контекстные меню изображений надпись "Сохранить похожие". При клике на нее будет выполняться saveSimilar.
chrome.contextMenus.create({"title": "Сохранить похожие", 
                                             "contexts": ["image"],
                                             "onclick": saveSimilar});

similar.html


Код этой вкладки будет точно таким же, как и в newtab.html, кроме поиска адресов изображений.
Первый запрос чтобы найти ссылку на страницу похожих изображений. Из-за того что у авторизированных и не авторизированных пользователей ссылка на страницу похожих изображений будет разная, приходится выкручиваться универсальным вариантом, который находит часть ссылки, обрезает ненужные символы и заменяет неопределенные параметры. Из-за того что ссылка не содержит весь путь и стандартных параметров их нужно добавить (я взял свои).

var findurl=readProperty("chsurl");
var xhr = new XMLHttpRequest();

xhr.open("GET", findurl, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
var cptext = xhr.responseText;
resalt = cptext.match(/hl=[\w]{2}&amp;tbs=simg:[\S]{1,}/);
resalt2 = resalt[0].substr(0,resalt[0].length-16);
//обрезаем найденное, для получение части ссылки
resalt2="https://www.google.com/search?"+resalt2;
resalt2=resalt2.replace(/&amp/g,"");
resalt2=resalt2.replace(/;/g,"&");
//убираем ненужные символы
url=resalt2+"&ei=4CPyTq3aLc-ZOtX-oK8B&ved=0CD4Qsw4&biw=756&bih=738";
//конечная ссылка


Заключение


Теперь у нас есть полноценное расширение для браузера Google Chrome. Как видите, писать расширение не так уж и сложно, достаточно знать основные моменты javascript и узнать в документации, какие возможности предоставляет браузер для расширений.

P.S.Для корректной работы расширения у пользователя в настройках должно стоять автоматическое сохранение в указанную папку.
P.P.S.Исходники можно скачать тут.
P.P.P.S.Обсуждаем в этой теме.

Автор: thref2

Материал добавил thref2


Комментарии(0)

Дата: 2012-03-17 14:38:36

Добавить Комментарий к Материалу

Вы должны быть авторизованы на форуме чтобы добавлять комментарии. Регистрация Уже авторизованы?

Комментариев к материалу пока нет.

Последнее на Сайте

Новости

Статьи

Bugtraq

Файлы

Copyright © 2008 - 2017 «HPC». При копировании материалов ставьте ссылку на источник.
Все материалы представлены только в ознакомительных целях, администрация за их использование ответственности не несет.
Пользовательское соглашение Реклама на сайте