Инструментарий Dojo — сокровищница JavaScript классов. В ней вы можете найти основные JavaScript классы для AJAX: манипуляции с нодами, анимация и все то что есть в Dojo. Также вы можете найти элегантные и функциональные UI виджеты, например: выпадающее меню, интерфейсы со вкладками и элементы форм. В DojoX вы можете найти библиотеки графиков, специальные хранилища данных, векторную графику и много другое.
В этой статье мы создадим динамический поиск изображений из Flickr с помощью Dojo, а будем при этом использовать три коллекции скриптов.
Для начала построим интерфейс со вкладками для захвата изображений с Flickr, используя Dijit's TabContainer, далее возьмемся за хранилища данных на DojoX's Flickr, и в конце поработаем с кодом Dojo для обработки событий и манипуляций с нодами.
Выбираем тему
Есть два основных шага добавления темы на страницу: импорт стиля темы и добавление темы, как имя класса в элемент BODY
.
1 2 3 4 5 6 7 8 9 |
<style type="text/css"> /* bring in the claro theme */ @import "http://ajax.googleapis.com/ajax/libs/dojo/ 1.5/dijit/themes/claro/claro.css"; /* define styles per the images */ a.thumb { display:inline-block; margin:0 20px 20px 0; } </style> |
Тема «claro» является новой в Dojo 1.5 и выглядит очень приятно.
Импорт Dojo из CDN, parseOnLoad:true
Используя ресурсы CDN Google, Dojo будет загружаться быстрее, чем если бы он располагался на вашем сервере. А добавление атрибута djConfig
parseOnLoad:true
поручает Dojo просматривать страницу в поисках виджетов.
1 2 |
<script src="http://ajax.googleapis.com/ajax/libs/ dojo/1.5/dojo/dojo.xd.js" type="text/javascript" djConfig="parseOnLoad:true"></script> |
Как альтернатива, можно настроить Dojo, используя переменную djConfig
:
1 2 3 |
djConfig = { parseOnLoad: true }; |
В любом случае этого будет достаточно.
Создание HTML структуры: контейнер со вкладками и поисковая форма
Первыми идут настройки формы. Формы будут очень простыми. Они будут содержать окно поиска и кнопку «отправить». Каждый нод (форма, ввод и кнопка) преобразуется в эквивалентный Dijit виджет, что добавляет функциональности и более гибкого отображения.
1 2 3 4 5 |
<!-- search will be here --> <form dojoType="dijit.form.Form" id="searchForm"> <input dojoType="dijit.form.ValidationTextBox" id="searchBox" missingMessage="Please provide a term to search" placeholder="search term..." required="true" /> <button type="submit" dojoType="dijit.form.Button" id="searchButton">Submit Search</button> </form> |
Окно поиска становится dijit.form.ValidationTextBox
, которое позволяет нам запрашивать значение запроса и отображать сообщение об ошибке, если того требуют правила поиска.
Вторая часть — установка TabContainer и инициализация начального содержания в панели страницы. Начальный контент будет прост — это вкладка «welcome»:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!-- will set the eventual dimensions for the tab container --> <div style="width:675px;height:400px"> <!-- will host all tabs and their content panes --> <div dojoType="dijit.layout.TabContainer" id="tabContainer" style="width:100%;height:100%;"> <!-- welcome pane: title is tab name, make this tab selected --> <div dojoType="dijit.layout.ContentPane" title="Welcome Pane" selected="true"> <p> Welcome to the Flickr Search data store and Tab Container example. Submit your search and watch the tab load! </p> </div> </div> </div> |
Следующие вкладки можно будет закрывать.
Загрузка Dojo/Dijit/DojoX
Прежде, чем начать использовать классы и создавать наши виджеты, необходимо их загрузить:
1 2 3 4 5 6 7 8 |
/* require necessary classes */ dojo.require('dijit.layout.TabContainer'); dojo.require('dijit.layout.ContentPane'); dojo.require('dijit.form.Button'); dojo.require('dijit.form.Form'); dojo.require('dijit.form.ValidationTextBox'); dojo.require('dojox.data.FlickrStore'); dojo.require('dijit.Tooltip'); |
Dojo, Dijit, DojoX
И так, все практически готово для создания динамического поиска. Начнем с создания объекта, который будет содержаться во всех наших вкладках, и экземпляра dojox.data.FlickrStore
, который будет использоваться для запроса к Flickr:
1 2 3 |
/* settings */ var tabSubjects = {}; var flickrStore = new dojox.data.FlickrStore(); |
Затем собираются элементы формы и TabContainer:
1 2 3 4 5 |
/* collect proper elements */ var searchForm = dijit.byId('searchForm'); var searchBox = dijit.byId('searchBox'); var searchButton = dijit.byId('searchButton'); var tabContainer = dijit.byId('tabContainer'); |
Добавляем событие submit
в TabContainer
...
1 2 |
/* connect click event to search */ dojo.connect(searchForm,'onSubmit',function(e) { |
...которые остановят нормальное представление формы:
1 2 |
//stop! dojo.stopEvent(e); |
...забираем значение из поискового окна:
1 2 |
//store value - set to lower case to save to caching object var value = searchBox.get('value').toLowerCase(); |
Если значение актуально, проверяем, что нет открытой вкладки по этому запросу и фокусируемся на окне поиска. Если это новый поисковый запрос, обращаемся к dojox.data.FlickrStore
для поиска и возврата изображений для данного запроса. Во время поиска, создается новая вкладка для поискового запроса с заголовком и контентом по умолчанию, добавляется TabContainer, и выбирается новая вкладка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//if a value exists... if(value) { //if the tab isn't already there... if(!tabSubjects[value]) { //do the search... flickrStore.fetch({ query: { tags: value }, onBegin: function() { //create the tab tabSubjects[value] = new dijit.layout.ContentPane({ title:value, content:'Searching for ' + value + '...', closable:true, onClose: function() { //remove this from our saved tabs when closed tabSubjects[value] = null; return true; } }); //add to tabcontainer and select tabContainer.addChild(tabSubjects[value]); tabContainer.selectChild(tabSubjects[value]); }, |
Когда поиск будет завершен, мы очищаем контент на панели и обрабатываем каждое изображение, для добавления его на панель. В конце, мы создаем подсказку для каждого изображения, отображающую его название:
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 |
onComplete: function(items) { //if we got items... if(items.length) { //clear the tab's content' tabSubjects[value].set('content',''); //cycle through each image returned, inject into new tab, add tooltip dojo.forEach(items,function(item,i) { //create the link's ID for the tooltip var id = new Date().getTime() + '_' + i; var a = dojo.create('a',{ href: flickrStore.getValue(item,'link'), className: 'thumb', target: '_blank', id: id, innerHTML: '<img src="' + flickrStore.getValue(item,'imageUrlSmall') + '" alt="' + flickrStore.getValue(item,'title') +'" />' },tabSubjects[value].domNode); //tooltip! new dijit.Tooltip({ label: flickrStore.getValue(item,'title'), connectId: id }); }); } else { //provide "no images" content tabSubjects[value].set('content','There were no images available for this term.'); } //empty the search box searchBox.set('value',''); } }); |
Далее представлен весь JavaScript код для этого приложения:
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
/* require necessary classes */ dojo.require('dijit.layout.TabContainer'); dojo.require('dijit.layout.ContentPane'); dojo.require('dijit.form.Button'); dojo.require('dijit.form.Form'); dojo.require('dijit.form.ValidationTextBox'); dojo.require('dojox.data.FlickrStore'); dojo.require('dijit.Tooltip'); /* when all classes have loaded... */ dojo.ready(function() { /* settings */ var tabSubjects = {}; var flickrStore = new dojox.data.FlickrStore(); /* collect proper elements */ var searchForm = dijit.byId('searchForm'); var searchBox = dijit.byId('searchBox'); var searchButton = dijit.byId('searchButton'); var tabContainer = dijit.byId('tabContainer'); /* connect click event to search */ dojo.connect(searchForm,'onSubmit',function(e) { //stop! dojo.stopEvent(e); //store value var value = searchBox.get('value').toLowerCase(); //if a value exists... if(value) { //if the tab isn't already there... if(!tabSubjects[value]) { //do the search... flickrStore.fetch({ query: { tags: value }, onBegin: function() { //create the tab tabSubjects[value] = new dijit.layout.ContentPane({ title:value, content:'Searching for ' + value + '...', closable:true, onClose: function() { //remove this from our saved tabs when closed tabSubjects[value] = null; return true; } }); //add to tabcontainer and select tabContainer.addChild(tabSubjects[value]); tabContainer.selectChild(tabSubjects[value]); }, onComplete: function(items) { //if we got items... if(items.length) { //clear the tab's content' tabSubjects[value].set('content',''); //cycle through each image returned, inject into new tab, add tooltip dojo.forEach(items,function(item,i) { //create the link's ID for the tooltip var id = new Date().getTime() + '_' + i; var a = dojo.create('a',{ href: flickrStore.getValue(item,'link'), className: 'thumb', target: '_blank', id: id, innerHTML: '<img src="' + flickrStore.getValue(item,'imageUrlSmall') + '" alt="' + flickrStore.getValue(item,'title') +'" />' },tabSubjects[value].domNode); //tooltip! if(flickrStore.getValue(item,'title')) { new dijit.Tooltip({ label: flickrStore.getValue(item,'title'), connectId: id }); } }); } else { //provide "no images" content tabSubjects[value].set('content','There were no images available for this term.'); } //empty the search box searchBox.set('value',''); } }); } //if it does exist, focus on it else { tabContainer.selectChild(tabSubjects[value]); } } }); }); |
Вот и все.) Кстати, на DojoX можно написать такое же приложение для вытягивания картинок с Picasa.