Статьи

Создайте виджет Amazon Books с помощью jQuery и XML

Имеет смысл отказаться от таблиц базы данных и серверного кода, когда вам нужно хранить ограниченное количество нечувствительных данных. Доступ к этим данным может быть простым с jQuery, потому что библиотека была построена для легкого прохождения XML-документов. С помощью некоторых пользовательских JavaScript и магии jQuery вы можете создавать интересные виджеты. Хороший способ продемонстрировать эту функциональность — создать виджет книг Amazon.com с возможностью просмотра.




Одна вещь, которую нужно помнить, когда вы пытаетесь попробовать это самостоятельно, это то, что настройки безопасности Internet Explorer не позволяют вам выполнять вызовы XmlHttpRequest из локальной файловой системы. Даже если вы не используете серверный язык, вам все равно нужно запустить исходный код с веб-сервера, такого как HTTP-сервер Apache. Загрузка файлов в учетную запись веб-хостинга также будет работать.

В этом руководстве используется уменьшенный основной файл JavaScript jQuery 1.2.6, который можно загрузить здесь из Google Code. Никаких других плагинов не требуется. Вот скриншот виджета в окончательном виде:

Я создал следующий рисунок с помощью Illustrator, и это является основой для виджета книг. Окончательно нарезанные изображения можно легко заменить, чтобы создать элементы дизайна, которые соответствуют вашим потребностям. Иллюстрация включает кнопки «Следующая» и «Предыдущая», а также контейнер с изображениями книги. Исходный ZIP-файл содержит многослойный EPS, если вы хотите вносить изменения без необходимости начинать с нуля.

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

Светло-розовые сплошные блоки предназначены для демонстрации сетки срезов изображения. Есть две кнопки, а также четыре угла, верхний и нижний фон, а затем левый и правый фон. Темно-розовые сплошные линии должны демонстрировать блоки сдерживания, которые в конечном итоге окажутся в виде нескольких элементов div и неупорядоченного списка. Чтобы обеспечить плавную компоновку, внутренний div будет содержать фон левой стороны, а неупорядоченный список будет вложен в этот родительский div, который будет содержать фон правой стороны.

Прежде чем перейти к HTML, стоит отметить, что я не использую файлы PNG. Вы можете очень хорошо заменить PNG для GIF, и это не повлияет на функциональность. Однако это будет означать, что вам нужно будет исправить проблему отсутствия поддержки прозрачности PNG в Internet Explorer. Есть несколько плагинов jQuery, которые доступны.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml» dir=»ltr» lang=»en-US»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=UTF-8″ />
<title>Amazon.com Books Widget</title>
<link rel=»stylesheet» href=»css/books.css» type=»text/css» media=»screen» />
</head>
<body>
 
 
    <div id=»books»>
        <div class=»overclear buttons»>
            <a href=»#» class=»prev»><img src=»images/books_prev.gif» width=»40″ height=»30″ alt=»Previous» /></a>
            <div class=»showing»><!— showing —></div>
            <a href=»#» class=»next»><img src=»images/books_next.gif» width=»40″ height=»30″ alt=»Next» /></a>
        </div>
        <div class=»overclear top»>
            <img src=»images/books_left_top.gif» width=»20″ height=»20″ alt=»» class=»float_left» />
            <img src=»images/books_right_top.gif» width=»20″ height=»20″ alt=»» class=»float_right» />
        </div>
        <div class=»inner»>
            <ul class=»overclear»>
                <li class=»loader»><!— loader —></li>
            </ul>
        </div>
        <div class=»overclear btm»>
            <img src=»images/books_left_btm.gif» width=»20″ height=»20″ alt=»» class=»float_left» />
            <img src=»images/books_right_btm.gif» width=»20″ height=»20″ alt=»» class=»float_right» />
        </div>
    </div>
 
</body>
</html>

В HTML нет ничего революционного, но я бы хотел отметить несколько вещей. Первый касается «непрозрачного» класса, который появляется на нескольких элементах. Это отличный метод для очистки поплавков без дополнительной разметки. Я обсуждаю эту технику в блоге под названием «Шесть необходимых советов и приемов CSS», которые я использую в каждом проекте. Объявляя ширину и устанавливая свойство overflow скрытым в родительском div, дочерним элементам, которые перемещаются, больше не потребуется конечный элемент со свойством clear.

Второе, на что я хотел бы обратить внимание — это элемент списка загрузчиков. Поскольку я собираюсь собрать все книги в файле XML одновременно, загрузчик должен появиться немедленно. Я сгенерировал загрузчик из Ajaxload, а затем центрировал его как фон. Когда загрузка XML завершена, я удаляю элемент списка из DOM, и загрузчик исчезает. Вот скриншот того, как это выглядит с применением только HTML и CSS.

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

CSS довольно прост и не требует пояснений, поэтому я не буду тратить много времени на объяснение всех аспектов каждого селектора. Почти все селекторы являются дочерними элементами родительского контейнера с идентификатором «books». Вы можете видеть, что применяемая ширина является необязательной. Удаление его позволит виджету свободно расширяться и сжиматься.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* foundation */
 
body {
    font: 100% normal «Arial», «Helvetica», sans-serif;
}
#books {
    width: 515px;
}
#books img {
    border: 0;
}
#books .clear_both {
    clear: both;
}
#books .float_left,
#books ul li {
    float: left;
    display: inline;
}
#books .float_right {
    float: right;
}
#books .overclear {
    width: 100%;
    overflow: hidden;
}
 
/* styles */
 
#books .buttons {
    position: relative;
    height: 30px;
    margin: 0 0 5px 0;
}
#books .prev {
    position: absolute;
    top: 0;
    left: 0;
    visibility: hidden;
}
#books .next {
    position: absolute;
    top: 0;
    right: 0;
}
#books .showing {
    margin: 5px 60px 0 60px;
    text-align: center;
    font-size: .8em;
}
#books .top {
    background: url(../images/books_top.gif) repeat-x;
}
#books .inner {
    padding: 0 0 0 20px;
    margin: 0 0 -20px 0;
    background: url(../images/books_left_mid.gif) repeat-y;
}
#books ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
    background: url(../images/books_right_mid.gif) repeat-y top right;
}
#books ul li {
    display: none;
    position: relative;
    margin: 0;
    padding: 0 20px 20px 0;
    font-size: .8em;
    z-index: 1;
}
#books ul li.loader {
    display: block;
    float: none;
    height: 115px;
    margin: 0 0 20px -20px;
    background: url(../images/books_loader.gif) no-repeat center center;
}
#books ul li a.info {
    position: absolute;
    bottom: 20px;
    right: 20px;
}
#books ul li a.thumb {
    display: block;
    border: 1px solid #ddd;
}
#books ul li a.thumb img {
    display: block;
    margin: 0;
    padding: 3px;
}
#books .btm {
    background: url(../images/books_btm.gif) repeat-x;
}
.books_tool_tip {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 350px;
    z-index: 9999;
}
.books_tool_tip .books_pointer_left {
    position: absolute;
    top: 0;
    left: 0;
    width: 10px;
    height: 10px;
    background: url(../images/books_pointer_left.gif);
}
.books_tool_tip .books_pointer_right {
    position: absolute;
    top: 0;
    right: 0;
    width: 10px;
    height: 10px;
    background: url(../images/books_pointer_right.gif);
}
.books_tool_tip .inner {
    border: 1px solid #ddd;
    padding: 15px 15px 3px 15px;
    margin: 0 0 0 9px;
    background: #fff;
}
.books_tool_tip .inner_right {
    margin: 0 9px 0 0;
}
.books_tool_tip .inner p {
    font-size: .8em;
    margin: 0;
    padding: 0 0 12px 0;
}

Есть одно исключение, и это информационная подсказка, применяемая к книге, когда вы наводите значок информации. Каждая подсказка содержит класс «books_tool_tip» и является дочерними элементами тела страницы. Они позиционируются с помощью JavaScript в соответствии с положением мыши в тот момент, когда пользователь перемещает курсор на значок.

Классы «books_pointer_left» и «books_pointer_right» управляют стрелками, которые связаны с подсказкой «Сведения о книге». Подсказка падает справа от курсора, но если она находится за пределами видимого окна браузера (называемого окном просмотра), то она сместится влево. Классы меняются местами, и стрелка также перемещается в противоположную сторону. Это позволяет разместить виджет в левом или правом столбце.

В этом XML нет ничего революционного. Как вы увидите, каждая книга содержит заголовок, автора (ов), изображение, URL-адрес Amazon, общее количество отзывов и среднее количество отзывов. XML можно нормализовать в одной области, и это узел «автора». Строго говоря, может быть несколько авторов, и автор может быть одного из двух типов: автор или редактор. Тем не менее, я оставил это простым, чтобы сосредоточиться на основной функциональности. Хорошей домашней работой было бы посмотреть, как можно лучше оптимизировать этот узел, а затем успешно проанализировать его с помощью jQuery.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
<?xml version=»1.0″ encoding=»UTF-8″?>
<books>
    <book>
        <title><![CDATA[Design Patterns: Elements of Reusable Object-Oriented Software]]></title>
        <author>Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0201633612.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/]]></href>
        <reviews>
            <total>250</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[The Pragmatic Programmer: From Journeyman to Master]]></title>
        <author>Andrew Hunt, David Thomas</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_020161622X.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X/]]></href>
        <reviews>
            <total>131</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Refactoring: Improving the Design of Existing Code]]></title>
        <author>Martin Fowler, Kent Beck, John Brant, William Opdyke</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0201485672.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Refactoring-Improving-Existing-Addison-Wesley-Technology/dp/0201485672/]]></href>
        <reviews>
            <total>139</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Patterns of Enterprise Application Architecture]]></title>
        <author>Martin Fowler</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0321127420.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420/]]></href>
        <reviews>
            <total>56</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Head First Design Patterns]]></title>
        <author>Elisabeth Freeman, Eric Freeman, Bert Bates, Kathy Sierra</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0596007124.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Head-First-Design-Patterns/dp/0596007124/]]></href>
        <reviews>
            <total>252</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Introduction to Algorithms]]></title>
        <author>Thomas Cormen, Charles Leiserson, Ronald Rivest, Clifford Stein</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0262032937.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Introduction-Algorithms-Thomas-Cormen/dp/0072970545/]]></href>
        <reviews>
            <total>167</total>
            <average_rating>4.0</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition (2nd Edition)]]></title>
        <author>Frederick P. Brooks</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0201835959.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/]]></href>
        <reviews>
            <total>128</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Effective Java (2nd Edition)]]></title>
        <author>Joshua Bloch</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0321356683.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683/]]></href>
        <reviews>
            <total>120</total>
            <average_rating>5.0</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Mastering Regular Expressions]]></title>
        <author>Jeffrey Friedl</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0596528124.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Mastering-Regular-Expressions-Jeffrey-Friedl/dp/0596528124/]]></href>
        <reviews>
            <total>125</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Introduction to the Theory of Computation, Second Edition]]></title>
        <author>Michael Sipser</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0534950973.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Introduction-Theory-Computation-Second-Michael/dp/0534950973/]]></href>
        <reviews>
            <total>52</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Don’t Make Me Think: A Common Sense Approach to Web Usability (2nd Edition)]]></title>
        <author>Steve Krug</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0321344758.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Dont-Make-Me-Think-Usability/dp/0321344758/]]></href>
        <reviews>
            <total>453</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[The Visual Display of Quantitative Information, 2nd edition]]></title>
        <author>Edward R. Tufte</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0961392142.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Visual-Display-Quantitative-Information-2nd/dp/0961392142/]]></href>
        <reviews>
            <total>96</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[JavaScript: The Definitive Guide]]></title>
        <author>David Flanagan</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0596101996.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/JavaScript-Definitive-Guide-David-Flanagan/dp/0596101996/]]></href>
        <reviews>
            <total>278</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Designing Interfaces: Patterns for Effective Interaction Design]]></title>
        <author>Jenifer Tidwell</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0596008031.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Designing-Interfaces-Patterns-Effective-Interaction/dp/0596008031/]]></href>
        <reviews>
            <total>47</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Universal Principles of Design]]></title>
        <author>William Lidwell, Kritina Holden, Jill Butler</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_1592530079.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Universal-Principles-Design-William-Lidwell/dp/1592530079/]]></href>
        <reviews>
            <total>54</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Ambient Findability: What We Find Changes Who We Become]]></title>
        <author>Peter Morville</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_0596007655.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Ambient-Findability-What-Changes-Become/dp/0596007655/]]></href>
        <reviews>
            <total>46</total>
            <average_rating>4.0</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[The Search: How Google and Its Rivals Rewrote the Rules of Business and Transformed Our Culture]]></title>
        <author>John Battelle</author>
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_1591841410.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Search-Rewrote-Business-Transformed-Culture/dp/B000QRIHXE/]]></href>
        <reviews>
            <total>99</total>
            <average_rating>4.5</average_rating>
        </reviews>
    </book>
    <book>
        <title><![CDATA[Beginning PHP and MySQL 5 (2nd Edition)]]></title>
        <author>W.
        <image width=»95″ height=»115″>
            <src><![CDATA[images/books/isbn_1590595521.jpg]]></src>
        </image>
        <href><![CDATA[http://www.amazon.com/Beginning-PHP-MySQL-Novice-Professional/dp/1590595521/]]></href>
        <reviews>
            <total>100</total>
            <average_rating>4.0</average_rating>
        </reviews>
    </book>
</books>

JavaScript, безусловно, самая сложная часть учебника. Насколько я могу, я обычно начинаю такие сценарии с того, что заглушаю состояние и поведение объекта, чтобы почувствовать функциональность. Этот конкретный объект просто называется «КНИГИ». Я также использую так называемый шаблон модуля, который подробно описан Эриком Мираглией на Yahoo! Пользовательский интерфейс Блог. Этот шаблон проектирования дает вам возможность создавать частные методы и свойства. Всякий раз, когда вы выпускаете скрипт в дикую природу (как сейчас), этот шаблон помогает исключить возможность конфликтов с другими функциями и объектами, которые уже могут использовать другие разработчики.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var BOOKS = function(){
    var _P = {
        init : function( params ) {},
        params : null,
        data : null,
        loadXml : function() {},
        first : 0,
        max : 0,
        count : 0,
        preloadBooks : function() {},
        browseBooks : function( browse ) {},
        tooltip : {
            show : function( e, $o ) {},
            hide : function( e, $o ) {},
            getMouseCoord : function( v, e ) {},
            getViewport : function() {}
        }
    };
    return {
        init : function( params ) {
            _P.init( params );
        }
    };
}();

Все мои личные члены я поместил внутри объекта с именем «_P». Это больше связано с организационными усилиями, чем с чем-либо. Пока элемент не находится в операторе возврата BOOKS, я вполне мог бы создать его как отдельную переменную или функцию. Поскольку мне нужен способ связать общедоступные параметры (настройки) с закрытыми членами, у меня есть один публичный метод. Этот общедоступный метод инициализации передает настройки частному методу инициализации, выступая в качестве посредника. Я вернусь к этим настройкам на последнем этапе.

Вот посмотрите теперь на окончательный JavaScript:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
var BOOKS = function(){
    var _P = {
        init : function( params ) {
            _P.params = params;
            _P.loadXml();
        },
        params : null,
        data : null,
        loadXml : function() {
            $.ajax({
                type : «GET»,
                url : _P.params.xmlPath,
                dataType : «xml»,
                success : function( data ) {
                    _P.data = data;
                    _P.max = _P.params.perView;
                    _P.count = $( «book», data ).length;
                    _P.preloadBooks();
                    _P.browseBooks();
                }
            });
        },
        first : 0,
        max : 0,
        count : 0,
        preloadBooks : function() {
            $( «ul», «#books» ).empty();
            $( «book», _P.data ).each(function( i ) {
                var title = $.trim( $( «title», this ).text() );
                var href = $.trim( $( «href», this ).text() );
                $( «ul», «#books» ).append([
                    «<li><a href='»,
                    href,
                    «‘ class=’info’><img src='»,
                    _P.params.imgPath,
                    «/books_info.gif’ width=’15’ height=’16’ alt=’More Info’ /></a><a href='»,
                    href,
                    «‘ class=’thumb’><img src='»,
                    $.trim( $( «image > src», this ).text() ),
                    «‘ width='»,
                    $( «image», this ).attr( «width» ),
                    «‘ height='»,
                    $( «image», this ).attr( «height» ),
                    «‘ alt='»,
                    title,
                    «‘ /></a></li>» ].join( «» ));
                $( «body» ).append([
                    «<div class=’books_tool_tip’ id=’books_tool_tip_»,
                    i,
                    «‘><div class=’books_pointer_left’><!— books pointer —></div><div class=’inner’><p>»,
                    title,
                    » (by <em>»,
                    $.trim( $( «author», this ).text() ),
                    «</em>)»,
                    «</p><p><img src='»,
                    _P.params.imgPath,
                    «/stars_»,
                    $.trim( $( «reviews > average_rating», this ).text() ),
                    ,».gif’ width=’55’ height=’12’ /> («,
                    $.trim( $( «reviews > total», this ).text() ),
                    «)»,
                    «</p></div></div>» ].join( «» ));
            });
            $( «.info», «#books» ).hover(function( e ) {
                _P.tooltip.show( e, $( «#books_tool_tip_» + $( «a.info», «#books» ).index( this ) ) );
            }, function( e ) {
                _P.tooltip.hide( e, $( «#books_tool_tip_» + $( «a.info», «#books» ).index( this ) ) );
            });
            $( «#books .prev» ).click(function() {
                _P.browseBooks( «prev» );
                return false;
            });
            $( «#books .next» ).click(function() {
                _P.browseBooks( «next» );
                return false;
            });
        },
        browseBooks : function( browse ) {
            if ( browse == «prev» ) {
                if ( _P.first == _P.count && ( _P.count % _P.max > 0 ) ) {
                    _P.first = _P.first — ( ( _P.count % _P.max ) + _P.max );
                } else {
                    _P.first = _P.first — ( _P.max * 2 );
                }
            }
            var range = _P.first + _P.max;
            var start = 1;
            if ( range > _P.max ) {
                start = ( ( range — _P.max ) + 1 );
            }
            if ( _P.first == 0 ) {
                $( «#books .prev» ).css( «visibility», «hidden» );
            } else {
                $( «#books .prev» ).css( «visibility», «visible» );
            }
            if ( range < _P.count ) {
                $( «#books .next» ).css( «visibility», «visible» );
            } else if ( range >= _P.count ) {
                range = _P.count;
                $( «#books .next» ).css( «visibility», «hidden» );
            }
            $( «book», _P.data ).each(function( i ) {
                if ( i >= _P.first && i < range ) {
                    $( «#books li:eq(» + i + «)» ).fadeIn( «slow» );
                } else {
                    $( «#books li:eq(» + i + «)» ).css( «display», «none» );
                }
            });
            _P.first = range;
            $( «#books .showing» ).html([
                «Viewing <strong>»,
                start,
                » — «,
                range,
                «</strong> of <strong>»,
                _P.count,
                «</strong>» ].join( «» ));
        },
        tooltip : {
            show : function( e, $o ) {
                var v = _P.tooltip.getViewport();
                var pageX = _P.tooltip.getMouseCoord( v, e )[0] + 15;
                var pageY = _P.tooltip.getMouseCoord( v, e )[1];
                $o.find( «.books_pointer_right» ).addClass( «books_pointer_left» ).removeClass( «books_pointer_right» );
                if ( pageX + $o.width() > v.innerWidth + v.pageXOffset ) {
                    pageX = pageX — $o.width() — 30;
                    $o.find( «.inner» ).addClass( «inner_right» );
                    $o.find( «.books_pointer_left» ).addClass( «books_pointer_right» ).removeClass( «books_pointer_left» );
                }
                $o.css( «left», pageX ).css( «top», pageY ).css( «display», «block» );
            },
            hide : function( e, $o ) {
                $o.css( «display», «none» );
            },
            getMouseCoord : function( v, e ) {
                ( !e ) ?
                ( e.pageX ) ?
                ( e.pageY ) ?
                return [ e.pageX, e.pageY ];
            },
            getViewport : function() {
                var viewport = {}
                if ( self.innerHeight ) {
                    viewport.pageYOffset = self.pageYOffset;
                    viewport.pageXOffset = self.pageXOffset;
                    viewport.innerHeight = self.innerHeight;
                    viewport.innerWidth = self.innerWidth;
                } else if ( document.documentElement && document.documentElement.clientHeight ) {
                    viewport.pageYOffset = document.documentElement.scrollTop;
                    viewport.pageXOffset = document.documentElement.scrollLeft;
                    viewport.innerHeight = document.documentElement.clientHeight;
                    viewport.innerWidth = document.documentElement.clientWidth;
                }
                return viewport;
            }
        }
    };
    return {
        init : function( params ) {
            _P.init( params );
        }
    };
}();

Я не буду описывать все функциональные возможности, но я хотел бы выделить несколько очень важных аспектов сценария — первым является метод loadXml. Это одна из утилит jQuery AJAX и одна из самых простых реализаций AJAX. Подробнее об этом вы можете прочитать в официальной документации. После извлечения файла XML многие разработчики будут выполнять действия с данными в рамках успешной части вызова. Это трудно устранить, и я предпочитаю передавать эти данные извне другим методам, чтобы воздействовать на них. Это мышление в объектно-ориентированных терминах, и это может быть хорошей привычкой.

Метод preloadBooks — это то, что анализирует данные XML и превращает каждый узел в соответствующий XHTML, включая как книгу, так и подсказку книги. Самое замечательное в jQuery — то, что узлы XML можно обрабатывать так же, как узлы HTML. Вам не нужно изучать два стиля синтаксиса, единственное предостережение в том, что вы должны использовать метод text () jQuery для захвата содержимого между начальным и конечным тегом. С HTML вы бы использовали метод html ().

Существует большая часть HTML, которая должна быть построена с помощью JavaScript. Это часто связано с конкатенацией строк. Традиционный подход заключается в использовании арифметического оператора сложения, но более быстрый подход заключается в размещении частей строки внутри массива и последующем их объединении. Я делаю это в нескольких местах, особенно когда это происходит непрерывно на протяжении всего цикла, тогда это предпочтительный стиль.

Теперь, когда HTML-код книги был вставлен в DOM, пришло время прикрепить соответствующие события для просмотра. Действие просмотра происходит в методе «browseBooks». Этот метод принимает параметр «browse», который принимает один из двух аргументов: «prev» или «next». Это не прокручиваемое действие, а переход с постепенным исчезновением. Метод установит первую (текущую) позицию, максимальное количество книг для просмотра, количество книг, оставшихся для просмотра, а затем выполнит переход. Это также помогает определить, когда следует отображать предыдущую или следующую кнопку, чтобы пользователи не могли просматривать больше книг, перечисленных в списке.

Подсказка включает небольшое количество пользовательских JavaScript, и я хотел описать две функции — методы «getMouseCoord» и «getViewport». Это кросс-браузерные реализации для определения положения мыши в соответствии с тем, как далеко страница прокручивалась вверх / вниз или влево / вправо. Вам никогда не придется редактировать их, и я успешно использовал их в нескольких проектах без каких-либо проблем. Метод «show» также обрабатывает сценарий, который я описал ранее, когда всплывающая подсказка выходит за пределы вычисленного окна просмотра.

Конечный продукт

Последнее, что нужно сделать, это передать настройки методу инициализации JavaScript из HTML. Есть три аргумента: путь к файлу XML, путь к изображениям, используемым в JavaScript, и количество книг, которые вы хотели бы отобразить для каждого просмотра. Для этого урока предполагается, что на странице есть только один виджет книг (так называемые «книги»), поэтому для идентификатора или имени класса нет параметра. Вот XHTML в окончательной форме:

01
02
03
04
05
06
07
08
09
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
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml» dir=»ltr» lang=»en-US»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=UTF-8″ />
<title>Amazon.com Books Widget</title>
<link rel=»stylesheet» href=»css/books.css» type=»text/css» media=»screen» />
<script language=»javascript» type=»text/javascript» src=»js/jquery-1.2.6.min.js»></script>
<script language=»javascript» type=»text/javascript» src=»js/books.js»></script>
<script language=»javascript» type=»text/javascript»>
 
    $(function(){
        BOOKS.init({
            xmlPath : «data/books.xml»,
            imgPath : «images»,
            perView : 4
        });
    });
 
</script>
</head>
<body>
 
    <div id=»books»>
        <div class=»overclear buttons»>
            <a href=»#» class=»prev»><img src=»images/books_prev.gif» width=»40″ height=»30″ alt=»Previous» /></a>
            <div class=»showing»><!— showing —></div>
            <a href=»#» class=»next»><img src=»images/books_next.gif» width=»40″ height=»30″ alt=»Next» /></a>
        </div>
        <div class=»overclear top»>
            <img src=»images/books_left_top.gif» width=»20″ height=»20″ alt=»» class=»float_left» />
            <img src=»images/books_right_top.gif» width=»20″ height=»20″ alt=»» class=»float_right» />
        </div>
        <div class=»inner»>
            <ul class=»overclear»>
                <li class=»loader»><!— loader —></li>
            </ul>
        </div>
        <div class=»overclear btm»>
            <img src=»images/books_left_btm.gif» width=»20″ height=»20″ alt=»» class=»float_left» />
            <img src=»images/books_right_btm.gif» width=»20″ height=»20″ alt=»» class=»float_right» />
        </div>
    </div>
 
</body>
</html>
JQuery Amazon Book List

Наслаждайтесь своим виджетом книг Amazon.com!