Pull to refresh

Visual Search provider для IE 8 — задача на два помидора

Reading time8 min
Views534
Visual Search provider — это один из трех новых типов расширений в IE 8.0 Он позволит пользователям искать что-нибудь на вашем сайте, не переходя на его страницы. А если вы добавите к провайдеру favicon, ваш бренд (вернее 16-и пиксельный брендик) всегда будет вместе с пользователем. И главное, он позволит разбавить сухой текст результатов поиска симпатичными картинками, вот например так:

Мини игры на Play2Game.ru

А еще, вы можете рассказать о своем провайдере, выложив его в галерею расширений IE 8.0. Или выиграть плазменный телевизор, поучаствовав в конкурсе дополнений к IE 8.0, который проводится в рамках конференции ReMIX09.

Главный приз конкурса дополнений к IE 8.0
Между прочим, сейчас там зарегистрировано всего 3 визуальных провайдера. Так что если у вас есть что искать, а еще лучше — сайт с верной аудиторией, готовой поддержать его в конкурсе — давайте попробуем?

Все что от вас действительно потребуется — это метод, который будет возвращать найденные по запросу данные. Как он будет выглядеть, зависит от ваших любимых технологий и размера сайта. В моем случае (сайт с мини играми, который я написал на .NET) это было простое строковое сравнение в LINQ запросе. Кто-то посерьезнее настроит full text search в MS SQL Server, ну а приверженцы PHP и MySQL наверняка тоже подберут что-нибудь эффективное в своем арсенале.

Если у нас будет такой метод, все остальное — это задача на два помидора1, которую мы сделаем на раз-два-три. Причем, в отличие от web slices, простой вариант решения будет одновременно и хорошим, без всяких оговорок и нюансов.

Итак, в лучших традициях кулинарных программ, для успешного приготовления провайдера нам понадобится:
  • Сайт с картинками и текстом, которые мы сможем искать — 1 шт
  • Метод, который примет на вход строку, введенную пользователем в строке поиска, и вернет нам немножко текста и картинок — 1 шт
  • Модуль, к которому будет обращаться браузер, чтобы получить найденные результаты в xml формате — 1 шт
  • Еще немножко xml, чтобы описать наш провайдер
  • И для завершения — щепотка html, чтобы рассказать браузерам, какой чудесный провайдер мы приготовили
Ну что, продукты готовы, вода кипит — приступаем ...

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

Поиск на Play2Game.ru
  1. Принимал на вход текст, который пользователь набрал в строке поиска:
    Причем учтите, браузер будет обращаться к вашему сайту после каждой введенной буквы, так что искать лучше побыстрее.
  2. Для каждого найденного элемента возвращал:
    • Заголовок
    • Краткое описание
    • URL страницы, на которую мы попадем, выбрав этот элемент при поиске
    • URL картинки
    В принципе, достаточно возвращать только заголовок или url. Но, если мы хотим получить красивый результат, нам понадобятся все элементы.
Переходим ко второй части: модулю вашего сайта, который будет вызывать браузер, чтобы получить xml с вариантами поиска. Формат вызова вы сможете задать сами, браузер добавит к нему несколько параметров, описывающих запрос. Обязателен для нас только один, в котором будет передана строка поиска. Запрос может выглядеть примерно так:

http://{домен вашего сайта}/search.aspx?q={searchTerms}

Модуль может быть реализован по разному, например как IHttpModule или WebService. Я предпочел самый простой вариант — обычную .aspx страницу:
<%@ Page Language="C#" CodeBehind="visual.aspx.cs" Inherits="Play2game.VisualProvider" %><?xml version="1.0"?>
<SearchSuggestion xmlns="http://schemas.microsoft.com/Search/2008/suggestions">
 <Query><asp:Literal ID="ltKeyword" runat="server"/></Query>
 <Section title="Варианты Play2Game.ru">
  <asp:Literal ID="ltItems" runat="server"/>
 </Section>
</SearchSuggestion>


* This source code was highlighted with Source Code Highlighter.
Это xml, который нужно будет вернуть браузеру. Он содержит два placeholders (в виде простейших элементов управления Literal из ASP.NET). Вместо первого нам нужно будет вставить строку, которую искал пользователь. Браузер проверит ее и выведет результаты, только если эта строка совпадет со строкой, которую он передал вам в запросе.

Вместо второго placeholder мы подставим xml с описаниями найденных элементов. Перед тем как разбираться с ним, обратите внимание еще на две вещи:
  1. Строка <?xml version=«1.0»?> находится в одной строке с декларацией страницы не случайно. Если вы напишите ее с новой строки (как это сделал я, так как ненавижу криво отформатированный текст), результирующий xml будет начинатся с символа перевода каретки и он не будет распознан браузером (а вы увидите сообщение «ошибка», которое значит «у вас какие-то проблемы, попробуйте что-то поменять в вашем коде и попробовать снова»).
  2. В теге Section мы передали название заголовка, которое будет выведено в самом верху, вместе с серой линией — разделителем. Если бы мы этого не сделали, IE сформировал его сам как "{Название вашего провайдера} вариантов", что может выглядеть достаточно криво.
Теперь переходим к формату xml с самими результатами (который вставится на место второго placeholder). Он довольно простой:
<Item>
 <!-- Заголовок элемента -->
 <Text>То, не знаю что</Text>
 <!-- Описание элемента -->
 <Description>Это именно то, что ты искал.</Description>
 <!-- Url, на который мы перейдем, выбрав этот элемент -->
 <Url>/something.html</Url>
 <!-- Url картинки -->
 <Image source="/something.gif" alt="то, что ты искал" width="45" height="45" />
</Item>
...
<Separator title="Еще один список не знаю чего"/>
<Item>
 ...
</Item>


* This source code was highlighted with Source Code Highlighter.
Тут тоже стоит обратить внимание на два момента. Первый — это размеры картинки. Если их указать — все будет работать отлично. Но если ваши изображения немного отличаются по размеру — это может быть проблемой. Если в обычном html у тега img указать только одну размерность из двух — ваше изображение будет пропорционально смасштабировано. Тут такой фокус не пройдет — картинки просто перестают выводиться (когда я попробовал вообще не указывать размер, изображения нормально выводились при первом запросе после подключения провайдера, а потом все таки исчезли). Так что вам придется придумать, как правильно вычислять размеры.

В этом случае мне повезло — все иконки были одинакового размера 44 на 44. В другой раз было хуже, картинки попались разные и если указать что-то типа 45x45 — все масштабировалось в этот квадрат и безжалостно искажалось. В конце концов, я добавил метод, который находил физический файл, определял его размеры и корректно проставлял аттрибуты width и height. Вопреки опасениям, работало это достаточно шустро — благодаря второму моменту, о котором мы сейчас поговорим.

Поиск игр на Play2Game.ru

Дело в том, что размер списка ограничен — в нем будет выведено не более 10 элементов (поэтому проверить размеры максимум 10 файлов было достаточно легко). Эти элементы можно разделять «сепараторами» — тег <Separator title=«Еще один список не знаю чего»/> в нашем xml. Однако сепараторы тоже занимают одно из 10 мест. Так что вам нужно будет решать, выводить ли разделители, чтобы красиво сгруппировать найденные элементы или отобразить побольше результатов поиска.

Xml с результатами я создавал при помощи простого ASP.NET StringBuilder и вставлял на место placeholder. Если же вы сторонник сложных, но правильных решений, обязательно прочтите пост "Building an IE8 Visual Search Provider for my Twitter Friends" в котором Guy Burstein рассказывает, как правильно создавать такие модуль при помощи WCF REST service и XML serialization.

Почти все готово, осталось две мелочи. Первая — создать xml файл с описанием нашего провайдера:
<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:ie="http://schemas.microsoft.com/Search/2008/">
 <ShortName>{Название вашего провайдера}</ShortName>
 <Image height="16" width="16" type="image/icon">http://{доменное имя сайта}/favicon.ico</Image>
 <Url type="text/html" template="http://{доменное имя сайта}/search-page.aspx?q={searchTerms}"/>
 <Url type="application/x-suggestions+xml" template="http://{доменное имя сайта}/search.aspx?q={searchTerms}"/>
</OpenSearchDescription>


* This source code was highlighted with Source Code Highlighter.
На что стоит обратить внимание здесь:
  1. Тег <Url type=«text/html» определяет url, который будет вызван, если пользователь просто нажмет ввод в строке поиска, так и не выбрав ни одного из вариантов в предложенном списке. Url вы можете указать произвольный, главное, чтобы он включал placeholder {searchTerms}, место которого браузер подставит введенную пользователем строку.
    Если на вашем сайте уже реализован поиск — направьте этот url туда. Если нет — доверьте это вашему любимому поисковому серверу, например вот так:

    <Url type="text/html" template="http://www.google.com/search?q={searchTerms}"/>

  2. Тег <Url type=«application/x-suggestions+xml» определяет url нашего модуля, который должен вернуть xml с результатами. Условия те же: произвольный url с обязательным placeholder {searchTerms}, вместо которого браузер подставит строку для поиска. Кроме этого, вы можете использовать еще несколько placeholders и тогда браузер передаст вам чуть больше полезной информации. Так, например, запрос вида:

    <Url type="text/html" template="http://www.google.com/search?q={searchTerms}&language={Language}"/>

    позволит вам узнать язык, установленный у пользователя (user's system's locale). Подробнее о дополнительных параметрах вы сможете узнать из документации, ссылка на которую приведена в конце статьи. Там нет ничего особо полезного, практически все сводится к определению размеров выпадающего списка с результатами, чтобы лучше рассчитать размеры картинок и текста.
Последний штрих художника — добавим html тег с описанием провайдера в head нашего сайта. Выглядит он вот так:

<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Наш новый провайдер" />

Добавление поисквого провайдера

Найдя его на нашем сайте IE станет оранжевым от нетерпения и предложит поскорее добавить его к уже зарегистрированным в нем расширениям.

Обратите внимание, значение аттрибута «Title» должно точно совпадать с аналогичным названием в теге «ShortName» описания провайдера. Если эти строки будут различаться, браузер не поверит, что уже добавил этот провайдер и будет предлагать добавить его снова.

Ну что, прошу к столу, вскипело!

Еще один совет, который сможет упростить вам жизнь. Браузер кеширует полученный xml, так что постоянно меняйте вводимые во время тестирования слова. Какое-то время я сидел под отладчиком и безуспешно пытался понять, почему не вызывается мой модуль, когда я набирал классическое «sdfsdf» (еще варианты «йцукен» или «qwerty»).

А если вам захочется разобраться во всех деталях — загляните в главную поваренную книгу Microsoft: Search Provider Extensibility in Internet Explorer и XML Search Suggestions Format Specification, а так же прочтите статью Себастьяна Циммермана (основного разработчика функции Visual Search) Hello, World или начинаем работать с IE8 Visual Search и чуть более подробную редакцию статьи о создании Visual Search провайдера для IE 8.0 в моем блоге ".NET: Записки программиста".

Приятной вам готовки и победы в конкурсе!

1 В XP время может измеряться в произвольных единицах, например баллах или Мишках Гамми. Мартин Фаулер как-то рассказывал о Франческо Чирилло, который купил и принес на работу тридцатиминутный кухонный таймер в форме помидора. С тех пор в команде появилось выражение «задачка на шесть помидоров».
Tags:
Hubs:
Total votes 14: ↑11 and ↓3+8
Comments1

Articles