keydown 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,415 @@
1
+ (function() {
2
+ var doc = document;
3
+ var disableBuilds = true;
4
+
5
+ var ctr = 0;
6
+ var spaces = /\s+/, a1 = [''];
7
+
8
+ var toArray = function(list) {
9
+ return Array.prototype.slice.call(list || [], 0);
10
+ };
11
+
12
+ var byId = function(id) {
13
+ if (typeof id == 'string') {
14
+ return doc.getElementById(id);
15
+ }
16
+ return id;
17
+ };
18
+
19
+ var query = function(query, root) {
20
+ if (!query) {
21
+ return [];
22
+ }
23
+ if (typeof query != 'string') {
24
+ return toArray(query);
25
+ }
26
+ if (typeof root == 'string') {
27
+ root = byId(root);
28
+ if (!root) {
29
+ return [];
30
+ }
31
+ }
32
+
33
+ root = root || document;
34
+ var rootIsDoc = (root.nodeType == 9);
35
+ var doc = rootIsDoc ? root : (root.ownerDocument || document);
36
+
37
+ // rewrite the query to be ID rooted
38
+ if (!rootIsDoc || ('>~+'.indexOf(query.charAt(0)) >= 0)) {
39
+ root.id = root.id || ('qUnique' + (ctr++));
40
+ query = '#' + root.id + ' ' + query;
41
+ }
42
+ // don't choke on something like ".yada.yada >"
43
+ if ('>~+'.indexOf(query.slice(-1)) >= 0) {
44
+ query += ' *';
45
+ }
46
+
47
+ return toArray(doc.querySelectorAll(query));
48
+ };
49
+
50
+ var strToArray = function(s) {
51
+ if (typeof s == 'string' || s instanceof String) {
52
+ if (s.indexOf(' ') < 0) {
53
+ a1[0] = s;
54
+ return a1;
55
+ } else {
56
+ return s.split(spaces);
57
+ }
58
+ }
59
+ return s;
60
+ };
61
+
62
+ var addClass = function(node, classStr) {
63
+ classStr = strToArray(classStr);
64
+ var cls = ' ' + node.className + ' ';
65
+ for (var i = 0, len = classStr.length, c; i < len; ++i) {
66
+ c = classStr[i];
67
+ if (c && cls.indexOf(' ' + c + ' ') < 0) {
68
+ cls += c + ' ';
69
+ }
70
+ }
71
+ node.className = cls.trim();
72
+ };
73
+
74
+ var removeClass = function(node, classStr) {
75
+ var cls;
76
+ if (classStr !== undefined) {
77
+ classStr = strToArray(classStr);
78
+ cls = ' ' + node.className + ' ';
79
+ for (var i = 0, len = classStr.length; i < len; ++i) {
80
+ cls = cls.replace(' ' + classStr[i] + ' ', ' ');
81
+ }
82
+ cls = cls.trim();
83
+ } else {
84
+ cls = '';
85
+ }
86
+ if (node.className != cls) {
87
+ node.className = cls;
88
+ }
89
+ };
90
+
91
+ var toggleClass = function(node, classStr) {
92
+ var cls = ' ' + node.className + ' ';
93
+ if (cls.indexOf(' ' + classStr.trim() + ' ') >= 0) {
94
+ removeClass(node, classStr);
95
+ } else {
96
+ addClass(node, classStr);
97
+ }
98
+ };
99
+
100
+ var ua = navigator.userAgent;
101
+ var isFF = parseFloat(ua.split('Firefox/')[1]) || undefined;
102
+ var isWK = parseFloat(ua.split('WebKit/')[1]) || undefined;
103
+ var isOpera = parseFloat(ua.split('Opera/')[1]) || undefined;
104
+
105
+ var canTransition = (function() {
106
+ var ver = parseFloat(ua.split('Version/')[1]) || undefined;
107
+ // test to determine if this browser can handle CSS transitions.
108
+ var cachedCanTransition =
109
+ (isWK || (isFF && isFF > 3.6 ) || (isOpera && ver >= 10.5));
110
+ return function() {
111
+ return cachedCanTransition;
112
+ }
113
+ })();
114
+
115
+ //
116
+ // Slide class
117
+ //
118
+ var Slide = function(node, idx) {
119
+ this._node = node;
120
+ if (idx >= 0) {
121
+ this._count = idx + 1;
122
+ }
123
+ if (this._node) {
124
+ addClass(this._node, 'slide distant-slide');
125
+ }
126
+ this._makeCounter();
127
+ this._makeBuildList();
128
+ };
129
+
130
+ Slide.prototype = {
131
+ _node: null,
132
+ _count: 0,
133
+ _buildList: [],
134
+ _visited: false,
135
+ _currentState: '',
136
+ _states: [ 'distant-slide', 'far-past',
137
+ 'past', 'current', 'future',
138
+ 'far-future', 'distant-slide' ],
139
+ setState: function(state) {
140
+ if (typeof state != 'string') {
141
+ state = this._states[state];
142
+ }
143
+ if (state == 'current' && !this._visited) {
144
+ this._visited = true;
145
+ this._makeBuildList();
146
+ }
147
+ removeClass(this._node, this._states);
148
+ addClass(this._node, state);
149
+ this._currentState = state;
150
+
151
+ // delay first auto run. Really wish this were in CSS.
152
+ /*
153
+ this._runAutos();
154
+ */
155
+ var _t = this;
156
+ setTimeout(function() {
157
+ _t._runAutos();
158
+ }, 400);
159
+ },
160
+ _makeCounter: function() {
161
+ if (!this._count || !this._node) {
162
+ return;
163
+ }
164
+ var c = doc.createElement('span');
165
+ c.innerHTML = this._count;
166
+ c.className = 'counter';
167
+ this._node.appendChild(c);
168
+ },
169
+ _makeBuildList: function() {
170
+ this._buildList = [];
171
+ if (disableBuilds) {
172
+ return;
173
+ }
174
+ if (this._node) {
175
+ this._buildList = query('[data-build] > *', this._node);
176
+ }
177
+ this._buildList.forEach(function(el) {
178
+ addClass(el, 'to-build');
179
+ });
180
+ },
181
+ _runAutos: function() {
182
+ if (this._currentState != 'current') {
183
+ return;
184
+ }
185
+ // find the next auto, slice it out of the list, and run it
186
+ var idx = -1;
187
+ this._buildList.some(function(n, i) {
188
+ if (n.hasAttribute('data-auto')) {
189
+ idx = i;
190
+ return true;
191
+ }
192
+ return false;
193
+ });
194
+ if (idx >= 0) {
195
+ var elem = this._buildList.splice(idx, 1)[0];
196
+ var transitionEnd = isWK ? 'webkitTransitionEnd' : (isFF ? 'mozTransitionEnd' : 'oTransitionEnd');
197
+ var _t = this;
198
+ if (canTransition()) {
199
+ var l = function(evt) {
200
+ elem.parentNode.removeEventListener(transitionEnd, l, false);
201
+ _t._runAutos();
202
+ };
203
+ elem.parentNode.addEventListener(transitionEnd, l, false);
204
+ removeClass(elem, 'to-build');
205
+ } else {
206
+ setTimeout(function() {
207
+ removeClass(elem, 'to-build');
208
+ _t._runAutos();
209
+ }, 400);
210
+ }
211
+ }
212
+ },
213
+ buildNext: function() {
214
+ if (!this._buildList.length) {
215
+ return false;
216
+ }
217
+ removeClass(this._buildList.shift(), 'to-build');
218
+ return true;
219
+ }
220
+ };
221
+
222
+ //
223
+ // SlideShow class
224
+ //
225
+ var SlideShow = function(slides) {
226
+ this._slides = (slides || []).map(function(el, idx) {
227
+ return new Slide(el, idx);
228
+ });
229
+
230
+ this.init();
231
+ var _t = this;
232
+ doc.addEventListener('keydown',
233
+ function(e) {
234
+ _t.handleKeys(e);
235
+ }, false);
236
+ doc.addEventListener('mousewheel',
237
+ function(e) {
238
+ _t.handleWheel(e);
239
+ }, false);
240
+ doc.addEventListener('DOMMouseScroll',
241
+ function(e) {
242
+ _t.handleWheel(e);
243
+ }, false);
244
+ doc.addEventListener('touchstart',
245
+ function(e) {
246
+ _t.handleTouchStart(e);
247
+ }, false);
248
+ doc.addEventListener('touchend',
249
+ function(e) {
250
+ _t.handleTouchEnd(e);
251
+ }, false);
252
+ window.addEventListener('popstate',
253
+ function(e) {
254
+ if (e.state === null) {
255
+ _t.init();
256
+ } else {
257
+ _t.current = e.state;
258
+ }
259
+ _t.go();
260
+ }, false);
261
+ this._update();
262
+ };
263
+
264
+ SlideShow.prototype = {
265
+ _slides: [],
266
+ _update: function(dontPush) {
267
+ document.querySelector('#presentation-counter').innerText = this.current;
268
+ if (history.pushState) {
269
+ if (!dontPush) {
270
+ history.pushState(this.current, 'Slide ' + this.current, '#slide' + this.current);
271
+ }
272
+ } else {
273
+ window.location.hash = 'slide' + this.current;
274
+ }
275
+ for (var x = this.current - 1; x < this.current + 7; x++) {
276
+ if (this._slides[x - 4]) {
277
+ this._slides[x - 4].setState(Math.max(0, x - this.current));
278
+ }
279
+ }
280
+ },
281
+
282
+ current: 0,
283
+ init: function() {
284
+ var h = window.location.hash;
285
+ try {
286
+ this.current = parseInt(h.split('#slide')[1], 10);
287
+ } catch (e) { /* squeltch */
288
+ }
289
+ this.current = current = isNaN(this.current) ? 1 : this.current;
290
+ },
291
+ next: function() {
292
+ if (!this._slides[this.current - 1].buildNext()) {
293
+ this.current = Math.min(this.current + 1, this._slides.length);
294
+ this._update();
295
+ }
296
+ },
297
+ prev: function() {
298
+ this.current = Math.max(this.current - 1, 1);
299
+ this._update();
300
+ },
301
+ go: function() {
302
+ this._update(true);
303
+ },
304
+
305
+ _notesOn: false,
306
+ showNotes: function() {
307
+ var isOn = this._notesOn = !this._notesOn;
308
+ query('.notes').forEach(function(el) {
309
+ el.style.display = (notesOn) ? 'block' : 'none';
310
+ });
311
+ },
312
+ switch3D: function() {
313
+ toggleClass(document.body, 'three-d');
314
+ },
315
+ handleWheel: function(e) {
316
+ var delta = 0;
317
+ if (e.wheelDelta) {
318
+ delta = e.wheelDelta / 120;
319
+ if (isOpera) {
320
+ delta = -delta;
321
+ }
322
+ } else if (e.detail) {
323
+ delta = -e.detail / 3;
324
+ }
325
+
326
+ if (delta > 0) {
327
+ this.prev();
328
+ return;
329
+ }
330
+ if (delta < 0) {
331
+ this.next();
332
+ return;
333
+ }
334
+ },
335
+ handleKeys: function(e) {
336
+
337
+ if (/^(input|textarea)$/i.test(e.target.nodeName)) return;
338
+
339
+ switch (e.keyCode) {
340
+ case 37: // left arrow
341
+ this.prev(); break;
342
+ case 39: // right arrow
343
+ case 32: // space
344
+ this.next(); break;
345
+ case 50: // 2
346
+ this.showNotes(); break;
347
+ case 51: // 3
348
+ this.switch3D(); break;
349
+ }
350
+ },
351
+ _touchStartX: 0,
352
+ handleTouchStart: function(e) {
353
+ this._touchStartX = e.touches[0].pageX;
354
+ },
355
+ handleTouchEnd: function(e) {
356
+ var delta = this._touchStartX - e.changedTouches[0].pageX;
357
+ var SWIPE_SIZE = 150;
358
+ if (delta > SWIPE_SIZE) {
359
+ this.next();
360
+ } else if (delta < -SWIPE_SIZE) {
361
+ this.prev();
362
+ }
363
+ }
364
+ };
365
+
366
+ // Initialize
367
+ var slideshow = new SlideShow(query('.slide'));
368
+
369
+ document.querySelector('#toggle-counter').addEventListener('click', toggleCounter, false);
370
+ document.querySelector('#toggle-size').addEventListener('click', toggleSize, false);
371
+ document.querySelector('#toggle-transitions').addEventListener('click', toggleTransitions, false);
372
+ document.querySelector('#toggle-gradients').addEventListener('click', toggleGradients, false);
373
+
374
+ var counters = document.querySelectorAll('.counter');
375
+ var slides = document.querySelectorAll('.slide');
376
+
377
+ function toggleCounter() {
378
+ toArray(counters).forEach(function(el) {
379
+ el.style.display = (el.offsetHeight) ? 'none' : 'block';
380
+ });
381
+ }
382
+
383
+ function toggleSize() {
384
+ toArray(slides).forEach(function(el) {
385
+ if (!/reduced/.test(el.className)) {
386
+ addClass(el, 'reduced');
387
+ }
388
+ else {
389
+ removeClass(el, 'reduced');
390
+ }
391
+ });
392
+ }
393
+
394
+ function toggleTransitions() {
395
+ toArray(slides).forEach(function(el) {
396
+ if (!/no-transitions/.test(el.className)) {
397
+ addClass(el, 'no-transitions');
398
+ }
399
+ else {
400
+ removeClass(el, 'no-transitions');
401
+ }
402
+ });
403
+ }
404
+
405
+ function toggleGradients() {
406
+ toArray(slides).forEach(function(el) {
407
+ if (!/no-gradients/.test(el.className)) {
408
+ addClass(el, 'no-gradients');
409
+ }
410
+ else {
411
+ removeClass(el, 'no-gradients');
412
+ }
413
+ });
414
+ }
415
+ })();
@@ -0,0 +1,104 @@
1
+ /* To show bullests in unordered lists */
2
+ section.bulleted ul {
3
+ padding-left: 30px;
4
+ }
5
+
6
+ /* Full slide backgrounds */
7
+ .slide.full-background {
8
+ -webkit-background-size: cover;
9
+ -moz-background-size: cover;
10
+ background-size: cover;
11
+ background-position: center;
12
+ }
13
+ <% backgrounds.each do |background| %>
14
+ .<%= background[:classname] %> {
15
+ background-image: url(../<%= background[:path] %>);
16
+ }
17
+ <% end %>
18
+
19
+ .attribution {
20
+ font-size: 24px;
21
+ position: fixed;
22
+ bottom: 8px;
23
+ left: 40px;
24
+ -webkit-background-size: contain;
25
+ -moz-background-size: contain;
26
+ background-size: contain;
27
+ }
28
+
29
+ .attribution.flickr {
30
+ background: url(../images/flickr.png) left top no-repeat;
31
+ padding-left: 60px;
32
+ }
33
+
34
+ .attribution.cc {
35
+ background: url(../images/cc.large.png) left top no-repeat;
36
+ padding-left: 36px;
37
+ }
38
+
39
+ /* Happy generic hiding class */
40
+ .hidden {
41
+ display: none;
42
+ }
43
+
44
+ /* - Pygments sytles for code fragments - */
45
+ pre { background: none; }
46
+ pre .c { color: #999988; font-style: italic } /* Comment */
47
+ pre .err { color: #a61717; background-color: #e3d2d2 } /* Error */
48
+ pre .k { font-weight: bold } /* Keyword */
49
+ pre .o { font-weight: bold } /* Operator */
50
+ pre .cm { color: #999988; font-style: italic } /* Comment.Multiline */
51
+ pre .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
52
+ pre .c1 { color: #999988; font-style: italic } /* Comment.Single */
53
+ pre .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
54
+ pre .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
55
+ pre .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
56
+ pre .ge { font-style: italic } /* Generic.Emph */
57
+ pre .gr { color: #aa0000 } /* Generic.Error */
58
+ pre .gh { color: #999999 } /* Generic.Heading */
59
+ pre .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
60
+ pre .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
61
+ pre .go { color: #888888 } /* Generic.Output */
62
+ pre .gp { color: #555555 } /* Generic.Prompt */
63
+ pre .gs { font-weight: bold } /* Generic.Strong */
64
+ pre .gu { color: #aaaaaa } /* Generic.Subheading */
65
+ pre .gt { color: #aa0000 } /* Generic.Traceback */
66
+ pre .kc { font-weight: bold } /* Keyword.Constant */
67
+ pre .kd { font-weight: bold } /* Keyword.Declaration */
68
+ pre .kp { font-weight: bold } /* Keyword.Pseudo */
69
+ pre .kr { font-weight: bold } /* Keyword.Reserved */
70
+ pre .kt { color: #445588; font-weight: bold } /* Keyword.Type */
71
+ pre .m { color: #009999 } /* Literal.Number */
72
+ pre .s { color: #d14 } /* Literal.String */
73
+ pre .na { color: #008080 } /* Name.Attribute */
74
+ pre .nb { color: #0086B3 } /* Name.Builtin */
75
+ pre .nc { color: #445588; font-weight: bold } /* Name.Class */
76
+ pre .no { color: #008080 } /* Name.Constant */
77
+ pre .ni { color: #800080 } /* Name.Entity */
78
+ pre .ne { color: #990000; font-weight: bold } /* Name.Exception */
79
+ pre .nf { color: #990000; font-weight: bold } /* Name.Function */
80
+ pre .nn { color: #555555 } /* Name.Namespace */
81
+ pre .nt { color: #000080 } /* Name.Tag */
82
+ pre .nv { color: #008080 } /* Name.Variable */
83
+ pre .ow { font-weight: bold } /* Operator.Word */
84
+ pre .w { color: #bbbbbb } /* Text.Whitespace */
85
+ pre .mf { color: #009999 } /* Literal.Number.Float */
86
+ pre .mh { color: #009999 } /* Literal.Number.Hex */
87
+ pre .mi { color: #009999 } /* Literal.Number.Integer */
88
+ pre .mo { color: #009999 } /* Literal.Number.Oct */
89
+ pre .sb { color: #d14 } /* Literal.String.Backtick */
90
+ pre .sc { color: #d14 } /* Literal.String.Char */
91
+ pre .sd { color: #d14 } /* Literal.String.Doc */
92
+ pre .s2 { color: #d14 } /* Literal.String.Double */
93
+ pre .se { color: #d14 } /* Literal.String.Escape */
94
+ pre .sh { color: #d14 } /* Literal.String.Heredoc */
95
+ pre .si { color: #d14 } /* Literal.String.Interpol */
96
+ pre .sx { color: #d14 } /* Literal.String.Other */
97
+ pre .sr { color: #009926 } /* Literal.String.Regex */
98
+ pre .s1 { color: #d14 } /* Literal.String.Single */
99
+ pre .ss { color: #990073 } /* Literal.String.Symbol */
100
+ pre .bp { color: #999999 } /* Name.Builtin.Pseudo */
101
+ pre .vc { color: #008080 } /* Name.Variable.Class */
102
+ pre .vg { color: #008080 } /* Name.Variable.Global */
103
+ pre .vi { color: #008080 } /* Name.Variable.Instance */
104
+ pre .il { color: #009999 } /* Literal.Number.Integer.Long */
@@ -0,0 +1,125 @@
1
+ <!DOCTYPE html>
2
+ <!--
3
+ Original Project, HTML5 Rocks 'Slides Template' Copyright 2010 Google Inc.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ Original slides: Marcin Wichary (mwichary@google.com)
18
+ Modifications: Ernest Delgado (ernestd@google.com)
19
+ Alex Russell (slightlyoff@chromium.org)
20
+ Brad Neuberg
21
+
22
+ Keydown generates an HTML5 Rocks-style presentation from a Markdown file, adding
23
+ the ability to full screen backgrounds, CSS overrides, and additional JavaScript.
24
+
25
+ Keydown (http://infews.github.com/keydown), Copyright 2010 Infews LLC
26
+ -->
27
+ <html manifest="cache.manifest">
28
+ <head>
29
+ <!--[if gte IE 9]>
30
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
31
+ <![endif]-->
32
+
33
+ <!--[if lt IE 9]>
34
+ <meta http-equiv="X-UA-Compatible" content="IE=edge;chrome=1"/>
35
+ <![endif]-->
36
+
37
+ <meta charset="utf-8"/>
38
+ <title><%= title %></title>
39
+ <link href="http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans+Mono" rel="stylesheet" type="text/css"/>
40
+
41
+ <!--
42
+ Original HTML5 Rocks CSS extracted for readability
43
+ -->
44
+ <link href="css/rocks.css" rel="stylesheet" type="text/css"/>
45
+
46
+ <!--
47
+ Keydown provided CSS & your custom CSS
48
+ -->
49
+ <% css_files.each do |css_file| %>
50
+ <link href="<%= css_file %>" rel="stylesheet" type="text/css"/>
51
+ <% end %>
52
+
53
+ </head>
54
+ <body>
55
+ <div class="presentation">
56
+ <div id="presentation-counter"></div>
57
+ <div class="slides">
58
+ <!--
59
+ First slide has Title, Instructions & options. Remove (or display:none) this slide if you like
60
+ -->
61
+ <div class="slide">
62
+ <section class="middle">
63
+ <h1><%= title %></h1>
64
+ <p>
65
+ Press <span class="key"><b>&rarr;</b></span>, scroll, or swipe to advance
66
+ </p>
67
+ <h3>
68
+ Options
69
+ </h3>
70
+ <ul>
71
+ <li>
72
+ <input type="checkbox" id="toggle-size" />
73
+ <label for="toggle-size">
74
+ <span>Grow</span>
75
+ </label>
76
+ </li>
77
+ <li>
78
+ <input type="checkbox" id="toggle-transitions" checked/>
79
+ <label for="toggle-transitions">
80
+ <span>Transitions</span>
81
+ </label>
82
+ </li>
83
+ <li>
84
+ <input type="checkbox" id="toggle-gradients" checked/>
85
+ <label for="toggle-gradients">
86
+ <span>Gradients</span>
87
+ </label>
88
+ </li>
89
+ <li>
90
+ <input type="checkbox" id="toggle-counter" checked/>
91
+ <label for="toggle-counter">
92
+ <span>Slide numbers</span>
93
+ </label>
94
+ </li>
95
+ </ul>
96
+ <p>
97
+ Made with <a href="http://infews.github.com/keydown"><b>Keydown</b></a>
98
+ </p>
99
+ </section>
100
+ </div>
101
+ <% slides.each do |slide| %>
102
+ <%= slide.to_html %>
103
+ <% end %>
104
+ </div>
105
+ </div>
106
+
107
+ <!--
108
+ Original HTML5 Rocks JavaScript extracted for readability
109
+ -->
110
+ <script src="js/rocks.js" type="text/javascript"></script>
111
+
112
+ <!--[if lt IE 9]>
113
+ <script src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
114
+ <script>CFInstall.check({ mode: "overlay" });</script>
115
+ <![endif]-->
116
+
117
+ <!--
118
+ Keydown puts your custom JS here
119
+ -->
120
+ <% js_files.each do |js_file| %>
121
+ <script src="<%= js_file %>" type="text/javascript"></script>
122
+ <% end %>
123
+
124
+ </body>
125
+ </html>
@@ -0,0 +1,10 @@
1
+ <div class="<%= container_classnames %>">
2
+ <section<%= " class=\"#{classnames}\"" unless classnames.empty? %>>
3
+ <%= html_content %>
4
+ </section>
5
+ <div class="<%= background_attribution_classnames %>">
6
+ <a href="<%= background_image[:attribution_link] %>">
7
+ <%= background_image[:attribution_text] %>
8
+ </a>
9
+ </div>
10
+ </div>