Одной из наиболее востребованных тем является создание поиска по сайту. Первый способ – создать его самостоятельно “с нуля”. То есть использовать серверный язык программирования, например PHP, и составлять поисковые запросы к базе данных сайта, показывая результаты пользователю.
Второй способ – использовать сервисы, предоставляемые поисковыми системами, индекс которых уже всё обо всех знает. Да, вы угадали. В этом уроке мы будем использовать AJAX Search API от Google для создания пользовательского поиска, с помощью которого посетители смогут искать веб-страницы, изображения, видео и даже новости на вашем сайте.
Реклама: фильм Профессионалонлайн
HTML-код
Давайте начнём с HTML-разметки. После объявления нового HTML5 doctype мы устанавливаем заголовок страницы и подключаем CSS-стили внутри тега head
.
search.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Google Powered Site Search | Tutorialzine Demo</title> <link rel="stylesheet" type="text/css" href="styles.css" /> </head> <body> <div id="page"> <h1>Google Powered Site Search</h1> <form id="searchForm" method="post"> <fieldset> <input id="s" type="text" /> <input type="submit" value="Submit" id="submitButton" /> <div id="searchInContainer"> <input type="radio" name="check" value="site" id="searchSite" checked /> <label for="searchSite" id="siteNameLabel">Search</label> <input type="radio" name="check" value="web" id="searchWeb" /> <label for="searchWeb">Search The Web</label> </div> <ul class="icons"> <li class="web" title="Web Search" data-searchType="web">Web</li> <li class="images" title="Image Search" data-searchType="images">Images</li> <li class="news" title="News Search" data-searchType="news">News</li> <li class="videos" title="Video Search" data-searchType="video">Videos</li> </ul> </fieldset> </form> <div id="resultsDiv"></div> </div> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script src="script.js"></script> </body> </html> |
Внутри тега body
находится элемент, используемый в качестве контейнера – блок #page
. Форма внутри него работает не только, как форма поиска, но также и как контейнер. Она отлично выделяется на странице из-за закруглённых углов CSS3 и использованного для неё более тёмного цвета по сравнению с фоном.
Внутри формы находится текстовый input
, ниже которого расположена группа radio
-переключателей для поиска внутри сайта и по всему интернету. Для изменения типа поиска используются стильные иконки. В самом конце страницы мы подключаем библиотеку jQuery и скрипт script.js, о котором вы узнаете в заключительном шаге этого урока.
CSS-код
CSS-стили находятся в файле styles.css. В листингах ниже представлены только самые интересные фрагменты.
styles.css – Часть 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#searchForm{ /* Поисковая форма. */ background-color:#4C5A65; padding:50px 50px 30px; margin:80px 0; position:relative; -moz-border-radius:16px; -webkit-border-radius:16px; border-radius:16px; } fieldset{ border:none; } #s{ /* Поисковый input. */ border:none; color:#888888; background:url("img/searchBox.png") no-repeat; float:left; font-family:Arial,Helvetica,sans-serif; font-size:15px; height:36px; line-height:36px; margin-right:12px; outline:medium none; padding:0 0 0 35px; text-shadow:1px 1px 0 white; width:385px; } |
Как уже было сказано ранее, форма выполняет не только функцию отправки данных, но и служит в качестве контейнера. Благодаря этому количество кода разметки на странице сведено к минимуму, но, тем не менее, предоставляет богатый функционал.
Текстовый input
c id равным #s
стилизирован с помощью фонового изображения и отступов таким образом, чтобы вводимый текст не наплывал на увеличительное стекло.
styles.css – Часть 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
.icons{ list-style:none; margin:10px 0 0 335px; height:19px; position:relative; } .icons li{ background:url("img/icons.png") no-repeat; float:left; height:19px; text-indent:-999px; cursor:pointer; margin-right:5px; } /* Стилизация каждой иконки */ li.web{ width:15px;} li.web.active, li.web:hover{ background-position:left bottom;} li.images{ width:22px; background-position:-18px 0;} li.images.active, li.images:hover{ background-position:-18px bottom;} li.news{ width:14px; background-position:-44px 0;} li.news.active, li.news:hover{ background-position:-44px bottom;} li.videos{ width:17px; background-position:right 0;} li.videos.active, li.videos:hover{ background-position:right bottom;} span.arrow{ width:11px; height:6px; margin:21px 0 0 5px; position:absolute; background:url('img/arrow.png') no-repeat; left:0; } /* Кнопка submit */ #submitButton{ background:url('img/buttons.png') no-repeat; width:83px; height:36px; text-indent:-9999px; overflow:hidden; text-transform:uppercase; border:none; cursor:pointer; } #submitButton:hover{ background-position:left bottom; } |
Во фрагменте кода выше вы можете увидеть, что все иконки для переключения типа поиска используют одно общее фоновое изображение. Для каждой иконки задаётся правило background-position
так, чтобы соответствующая часть изображения показывалась для обычного состояния и при наведении курсора мыши.
Такая же техника используется для кнопки отправки формы.
styles.css – Часть 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/* Web & новые результаты */ .webResult{ text-shadow:1px 1px 0 #586a75;margin-bottom:50px;} .webResult h2{ background-color:#5D6F7B; font-size:18px; font-weight:normal; padding:8px 20px; /* Applying CSS3 rounded corners */ -moz-border-radius:18px; -webkit-border-radius:18px; border-radius:18px; } .webResult h2 b{ color:#fff; } .webResult h2 a{ color:#eee;border:none;} .webResult p{ line-height:1.5;padding:15px 20px;} .webResult p b{ color:white;} .webResult > a{ margin-left:20px;} /* Image & видео результаты */ .imageResult{ float:left; height:170px; margin:0 0 20px 40px; text-align:center; width:150px; } .imageResult img{ display:block;border:none;} .imageResult a.pic{ border:1px solid #fff; outline:1px solid #777; display:block; margin:0 auto 15px; } /* Показ кнопки more */ #more{ width:83px; height:24px; background:url('img/more.png') no-repeat; cursor:pointer; margin:40px auto; } #more:hover{ background-position:left bottom; } |
В последнем фрагменте CSS-кода мы стилизуем получаемые результаты. Несмотря на то, что у нас возможны четыре типа результатов – веб-страницы, новости, изображения и видео, нужный внешний вид достигается использованием всего двух классов — .webResult
и .imageResult
. В конце мы задаём стили для кнопки #more
, которая динамически добавляется на страницу в зависимости от результатов, возвращаемых Google.
jQuery-код
Как было сказано в начале урока, поиск который мы создаём, использует AJAX Search API от Google. Google предоставляет свою собственную JavaScript библиотеку, но если Вы решите её использовать, то будете ограничены стандартным графическим интерфейсом. Скорее всего, это не то, что бы вы хотели предоставить своим посетителям. Именно поэтому в этом уроке мы используем “голую версию” с прямыми JSONp-вызовами с помощью jQuery прямо к их API.
Перед тем как начать обзор jQuery-кода, давайте взглянем на данные, которые нам предоставляет Google посредством своего API.
Пример результирующих данных от API
1 2 3 4 5 6 7 8 9 10 |
{ "GsearchResultClass": "GwebSearch", "unescapedUrl": "http://tutorialzine.com/2010/02/html5-css3-website-template/", "url": "http://tutorialzine.com/2010/02/html5-css3-website-template/", "visibleUrl": "tutorialzine.com", "cacheUrl": "http://www.google.com/search?q=cache:_NSLxH-cQMAJ:tutorialzine.com", "title": "Coding a <b>CSS3</b> & <b>HTML5</b> One-Page Website Template | Tutorialzine", "titleNoFormatting": "Coding a CSS3 & HTML5 One-Page Website Template | Tutorialzine", "content": "Feb 16, 2010 <b>...</b> Here we are using the new version of HTML.." } |
Поиск, произведенный с помощью их API, возвратит идентичный результат тому, который бы вы получили прямо на сайте Google. Разница лишь в том, что здесь мы получаем JavaScript-массив, заполненный объектами, как показано выше. Каждый из этих объектов содержит данные о типе поиска, заголовок, URL-адрес, и текст со страницы, содержащий слова, которые мы ищем.
script.js – Часть 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
$(document).ready(function(){ var config = { siteURL : 'tutorialzine.com', // Введите адрес вашего сайта searchSite : true, type : 'web', append : false, perPage : 8, // Максимум 8, что позволяет Google page : 0 // Стартовая страница } var arrow = $('<span>',{className:'arrow'}).appendTo('ul.icons'); $('ul.icons li').click(function(){ var el = $(this); if(el.hasClass('active')){ // The icon is already active, exit return false; } el.siblings().removeClass('active'); el.addClass('active'); arrow.stop().animate({ left : el.position().left, marginLeft : (el.width()/2)-4 }); config.type = el.attr('data-searchType'); $('#more').fadeOut(); }); $('#siteNameLabel').append(' '+config.siteURL); $('#searchSite').click(); $('li.web').click(); $('#s').focus(); $('#searchForm').submit(function(){ googleSearch(); return false; }); $('#searchSite,#searchWeb').change(function(){ config.searchSite = this.id == 'searchSite'; }); |
Объект config
содержит основные настройки, такие как URL-адрес сайта, начальная страница (используется в постраничной навигации), тип поиска по умолчанию. Google позволяет выбрать до 8 результатов за один запрос. Этого вполне достаточно для пользователей ищущих веб-страницы, но мало для тех, кто ищет изображения. Будем надеяться, что Google увеличит это ограничение в будущем.
Когда форма отправлена, jQuery вызывает функцию googleSearch()
, код которой представлен ниже.
Для внедрения этого поиска в ваш сайт просто замените значение свойства siteURL в объекте config на URL-адрес вашего сайта.
script.js – Часть 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
function googleSearch(settings){ settings = $.extend({},config,settings); settings.term = settings.term || $('#s').val(); if(settings.searchSite){ settings.term = 'site:'+settings.siteURL+' '+settings.term; } // URL of Google's AJAX search API var apiURL = 'http://ajax.googleapis.com/ajax/services/search/'+settings.type+ '?v=1.0&callback=?'; var resultsDiv = $('#resultsDiv'); $.getJSON(apiURL,{ q : settings.term, rsz : settings.perPage, start : settings.page*settings.perPage },function(r){ var results = r.responseData.results; $('#more').remove(); if(results.length){ var pageContainer = $('<div>',{className:'pageContainer'}); for(var i=0;i<results.length;i++){ pageContainer.append(new result(results[i]) + ''); } if(!settings.append){ resultsDiv.empty(); } pageContainer.append('<div class="clear"></div>') .hide().appendTo(resultsDiv) .fadeIn('slow'); var cursor = r.responseData.cursor; if( +cursor.estimatedResultCount > (settings.page+1)*settings.perPage){ $('<div>',{id:'more'}).appendTo(resultsDiv).click(function(){ googleSearch({append:true,page:settings.page+1}); $(this).fadeOut(); }); } } else { // Не найдено. resultsDiv.empty(); $('<p>',{ className : 'notFound', html : 'No Results Were Found!' }).hide().appendTo(resultsDiv).fadeIn(); } }); } |
Функция googleSearch()
посылает JSONp-запрос к Google API, генерирует разметку для результатов и помещает её в блок #resultsDiv
. При нажатии кнопки “More” результаты дополняются новыми.
В обоих случаях создаётся блок .pageContainer
для каждой группы результатов (этот блок имеет нижнюю границу, чтобы каждая новая группа визуально была отделена от предыдущей).
script.js – Часть 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
function result(r){ var arr = []; // GsearchResultClass от google API switch(r.GsearchResultClass){ case 'GwebSearch': arr = [ '<div class="webResult">', '<h2><a href="',r.url,'">',r.title,'</a></h2>', '<p>',r.content,'</p>', '<a href="',r.url,'">',r.visibleUrl,'</a>', '</div>' ]; break; case 'GimageSearch': arr = [ '<div class="imageResult">', '<a href="',r.url,'" title="',r.titleNoFormatting, '" class="pic" style="width:',r.tbWidth,'px;height:',r.tbHeight,'px;">', '<img src="',r.tbUrl,'" width="',r.tbWidth,'" height="', r.tbHeight,'" /></a>','<div class="clear"></div>', '<a href="',r.originalContextUrl,'">',r.visibleUrl,'</a>', '</div>' ]; break; case 'GvideoSearch': arr = [ '<div class="imageResult">', '<a href="',r.url,'" title="',r.titleNoFormatting,' " class="pic" style="width:150px;height:auto;">', '<img src="',r.tbUrl,'" width="100%" /></a>', '<div class="clear"></div>','<a href="', r.originalContextUrl,'">',r.publisher,'</a>', '</div>' ]; break; case 'GnewsSearch': arr = [ '<div class="webResult">', '<h2><a href="',r.unescapedUrl,'">',r.title,'</a></h2>', '<p>',r.content,'</p>', '<a href="',r.unescapedUrl,'">',r.publisher,'</a>', '</div>' ]; break; } // Метод toString. this.toString = function(){ return arr.join(''); } } }); |
Эта функция работает конструктором класса result
. Она принимает объект, возвращенный Google API (его пример представлен в начале раздела с jQuery-кодом) и инициализирует переменную arr
в соответствии со значением свойства GsearchResultClass
. Обратите внимание, что переменная arr
– это массив. С массивом работать немного быстрее, чем делать конкатенации строк.
В конце функции находится метод toString()
, который в свою очередь использует внутренний метод join()
и конвертирует массив в строку.
Вот теперь наш собственный поиск от Google готов!
Выводы
Настроить это приложение для поиска по вашему собственному сайту очень просто. Просто измените значение свойства siteURL
в объекте config
в файле script.js. Существует много вариантов для улучшения этого примера. В данный момент используются не все данные, которые возвращаются от Google в качестве ответа. Также можно использовать модификатор filetype:
для поиска по конкретному типу файла.
Если у вас есть какие-то интересные идеи по улучшению поиска – добро пожаловать в комментарии!
Спасибо, прикольный поиск. Буду применять :)
Супер, благодарю, очень полезный и познавательный у вас ресурс
С осени гугл уже не поддерживает старый API, хотя еще выдает по таким запросам ответы, но уже не полные.
Пришлось доработать под новый API, с двумя ключами, но функциональная основа тут все равно отличная, взял из этой статьи, спасибо)