slideoff 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +218 -0
  5. data/bin/slideoff +127 -0
  6. data/lib/slideoff/config_builder.rb +60 -0
  7. data/lib/slideoff/flickr_api.rb +50 -0
  8. data/lib/slideoff/flickr_image.rb +92 -0
  9. data/lib/slideoff/markdown.rb +145 -0
  10. data/lib/slideoff/presentation.rb +90 -0
  11. data/lib/slideoff/remote_api.rb +53 -0
  12. data/lib/slideoff/routes.rb +20 -0
  13. data/lib/slideoff/server.rb +50 -0
  14. data/lib/slideoff/slides_api.rb +59 -0
  15. data/lib/slideoff/utils.rb +453 -0
  16. data/lib/slideoff.rb +15 -0
  17. data/themes/3d_slideshow/README +2 -0
  18. data/themes/3d_slideshow/css/main.css +232 -0
  19. data/themes/3d_slideshow/css/reset.css +57 -0
  20. data/themes/3d_slideshow/index.erb +31 -0
  21. data/themes/3d_slideshow/js/slideshow.js +288 -0
  22. data/themes/CSSS/README +2 -0
  23. data/themes/CSSS/css/slideshow.css +304 -0
  24. data/themes/CSSS/css/theme.css +250 -0
  25. data/themes/CSSS/images/rainbow-wood.jpg +0 -0
  26. data/themes/CSSS/index.erb +36 -0
  27. data/themes/CSSS/js/classList.js +116 -0
  28. data/themes/CSSS/js/prefixfree.min.js +5 -0
  29. data/themes/CSSS/js/slideshow.js +621 -0
  30. data/themes/common/css/pygments/colorful.css +62 -0
  31. data/themes/common/css/pygments/manni.css +61 -0
  32. data/themes/common/css/pygments/native.css +70 -0
  33. data/themes/common/css/pygments/solarized.css +66 -0
  34. data/themes/common/fonts/DroidSansMono.svg +626 -0
  35. data/themes/common/fonts/DroidSansMono.ttf +0 -0
  36. data/themes/common/fonts/Lato-BoldItalic.woff +0 -0
  37. data/themes/common/fonts/Lato-Italic.woff +0 -0
  38. data/themes/common/fonts/Lato-bold.woff +0 -0
  39. data/themes/common/fonts/Lato.woff +0 -0
  40. data/themes/common/fonts/OpenSans-Bold.woff +0 -0
  41. data/themes/common/fonts/OpenSans-BoldItalic.woff +0 -0
  42. data/themes/common/fonts/OpenSans-Italic.woff +0 -0
  43. data/themes/common/fonts/OpenSans.woff +0 -0
  44. data/themes/common/fonts/PTMono.woff +0 -0
  45. data/themes/common/fonts/PTSans.Bold.Italic.woff +0 -0
  46. data/themes/common/fonts/PTSans.Bold.woff +0 -0
  47. data/themes/common/fonts/PTSans.Italic.woff +0 -0
  48. data/themes/common/fonts/PTSans.Narrow.Bold.woff +0 -0
  49. data/themes/common/fonts/PTSans.Narrow.woff +0 -0
  50. data/themes/common/fonts/PTSans.woff +0 -0
  51. data/themes/common/fonts/TargetBlank.otf +0 -0
  52. data/themes/common/fonts/TargetBlank.svg +14 -0
  53. data/themes/common/fonts/YanoneKaffeesatz-Bold.woff +0 -0
  54. data/themes/common/fonts/YanoneKaffeesatz-Regular.woff +0 -0
  55. data/themes/common/fonts/crimson_text.ttf +0 -0
  56. data/themes/common/fonts/crimson_text_bold.ttf +0 -0
  57. data/themes/common/fonts/crimson_text_semibold.ttf +0 -0
  58. data/themes/common/fonts/league_gothic-webfont.ttf +0 -0
  59. data/themes/html5rocks/README +2 -0
  60. data/themes/html5rocks/css/default.css +501 -0
  61. data/themes/html5rocks/css/moon.css +543 -0
  62. data/themes/html5rocks/css/sand.css +508 -0
  63. data/themes/html5rocks/css/sea_wave.css +492 -0
  64. data/themes/html5rocks/index.erb +64 -0
  65. data/themes/html5rocks/js/slides.js +464 -0
  66. data/themes/io2012/README +2 -0
  67. data/themes/io2012/css/default.css +1481 -0
  68. data/themes/io2012/css/fonts.css +24 -0
  69. data/themes/io2012/css/phone.css +27 -0
  70. data/themes/io2012/images/google_developers_icon_128.png +0 -0
  71. data/themes/io2012/images/io2012_logo.png +0 -0
  72. data/themes/io2012/index.erb +73 -0
  73. data/themes/io2012/js/hammer.js +586 -0
  74. data/themes/io2012/js/modernizr.custom.45394.js +4 -0
  75. data/themes/io2012/js/order.js +8 -0
  76. data/themes/io2012/js/polyfills/classList.min.js +2 -0
  77. data/themes/io2012/js/polyfills/dataset.min.js +2 -0
  78. data/themes/io2012/js/polyfills/history.min.js +1 -0
  79. data/themes/io2012/js/prettify/lang-apollo.js +2 -0
  80. data/themes/io2012/js/prettify/lang-clj.js +18 -0
  81. data/themes/io2012/js/prettify/lang-css.js +2 -0
  82. data/themes/io2012/js/prettify/lang-go.js +1 -0
  83. data/themes/io2012/js/prettify/lang-hs.js +2 -0
  84. data/themes/io2012/js/prettify/lang-lisp.js +3 -0
  85. data/themes/io2012/js/prettify/lang-lua.js +2 -0
  86. data/themes/io2012/js/prettify/lang-ml.js +2 -0
  87. data/themes/io2012/js/prettify/lang-n.js +4 -0
  88. data/themes/io2012/js/prettify/lang-proto.js +1 -0
  89. data/themes/io2012/js/prettify/lang-scala.js +2 -0
  90. data/themes/io2012/js/prettify/lang-sql.js +2 -0
  91. data/themes/io2012/js/prettify/lang-tex.js +1 -0
  92. data/themes/io2012/js/prettify/lang-vb.js +2 -0
  93. data/themes/io2012/js/prettify/lang-vhdl.js +3 -0
  94. data/themes/io2012/js/prettify/lang-wiki.js +2 -0
  95. data/themes/io2012/js/prettify/lang-xq.js +3 -0
  96. data/themes/io2012/js/prettify/lang-yaml.js +2 -0
  97. data/themes/io2012/js/prettify/prettify.css +1 -0
  98. data/themes/io2012/js/prettify/prettify.js +28 -0
  99. data/themes/io2012/js/require-1.0.8.min.js +33 -0
  100. data/themes/io2012/js/slide-controller.js +109 -0
  101. data/themes/io2012/js/slide-deck.js +768 -0
  102. data/themes/io2012/js/slides.js +5 -0
  103. data/themes/memories/README +5 -0
  104. data/themes/memories/css/fonts.css +25 -0
  105. data/themes/memories/css/slideshow.css +286 -0
  106. data/themes/memories/css/theme.css +183 -0
  107. data/themes/memories/index.erb +37 -0
  108. data/themes/memories/js/prefixfree.min.js +13 -0
  109. data/themes/memories/js/slideshow.js +577 -0
  110. data/themes/modern/LICENSE +20 -0
  111. data/themes/modern/README.md +52 -0
  112. data/themes/modern/css/GENERATED_CONTENT +0 -0
  113. data/themes/modern/css/defaults.css +0 -0
  114. data/themes/modern/css/fonts.css +166 -0
  115. data/themes/modern/css/pygments/colorful.css +215 -0
  116. data/themes/modern/css/pygments/github.css +208 -0
  117. data/themes/modern/css/pygments/solarized-dark.css +213 -0
  118. data/themes/modern/css/pygments/solarized-light.css +213 -0
  119. data/themes/modern/css/reset.css +41 -0
  120. data/themes/modern/css/screen.css +1183 -0
  121. data/themes/modern/fonts/Collegiate.woff +0 -0
  122. data/themes/modern/fonts/GoudyBookletter.1911.woff +0 -0
  123. data/themes/modern/fonts/Inconsolata.Bold.woff +0 -0
  124. data/themes/modern/fonts/Inconsolata.woff +0 -0
  125. data/themes/modern/fonts/Junction.woff +0 -0
  126. data/themes/modern/fonts/LiberationMono.Bold.woff +0 -0
  127. data/themes/modern/fonts/LiberationMono.BoldItalic.woff +0 -0
  128. data/themes/modern/fonts/LiberationMono.Italic.woff +0 -0
  129. data/themes/modern/fonts/LiberationMono.Regular.woff +0 -0
  130. data/themes/modern/fonts/OpenSans.Bold.woff +0 -0
  131. data/themes/modern/fonts/OpenSans.BoldItalic.woff +0 -0
  132. data/themes/modern/fonts/OpenSans.ExtraBold.woff +0 -0
  133. data/themes/modern/fonts/OpenSans.ExtraBoldItalic.woff +0 -0
  134. data/themes/modern/fonts/OpenSans.Italic.woff +0 -0
  135. data/themes/modern/fonts/OpenSans.Light.woff +0 -0
  136. data/themes/modern/fonts/OpenSans.LightItalic.woff +0 -0
  137. data/themes/modern/fonts/OpenSans.Regular.woff +0 -0
  138. data/themes/modern/fonts/OpenSans.Semibold.woff +0 -0
  139. data/themes/modern/fonts/OpenSans.SemiboldItalic.woff +0 -0
  140. data/themes/modern/fonts/PTMono.woff +0 -0
  141. data/themes/modern/fonts/PTSans.Bold.Italic.woff +0 -0
  142. data/themes/modern/fonts/PTSans.Bold.woff +0 -0
  143. data/themes/modern/fonts/PTSans.Italic.woff +0 -0
  144. data/themes/modern/fonts/PTSans.Narrow.Bold.woff +0 -0
  145. data/themes/modern/fonts/PTSans.woff +0 -0
  146. data/themes/modern/fonts/Raleway.Thin.woff +0 -0
  147. data/themes/modern/fonts/STIXGeneral.Bold.woff +0 -0
  148. data/themes/modern/fonts/STIXGeneral.BoldItalic.woff +0 -0
  149. data/themes/modern/fonts/STIXGeneral.Italic.woff +0 -0
  150. data/themes/modern/fonts/STIXGeneral.Regular.woff +0 -0
  151. data/themes/modern/fonts/YanoneKaffeesatz.Bold.woff +0 -0
  152. data/themes/modern/fonts/YanoneKaffeesatz.ExtraLight.woff +0 -0
  153. data/themes/modern/fonts/YanoneKaffeesatz.Light.woff +0 -0
  154. data/themes/modern/fonts/YanoneKaffeesatz.Regular.woff +0 -0
  155. data/themes/modern/images/cc/by.svg +29 -0
  156. data/themes/modern/images/cc/cc-white.svg +23 -0
  157. data/themes/modern/images/cc/cc.svg +23 -0
  158. data/themes/modern/images/cc/nc-eu.svg +21 -0
  159. data/themes/modern/images/cc/nc-jp.svg +18 -0
  160. data/themes/modern/images/cc/nc.svg +23 -0
  161. data/themes/modern/images/cc/nd.svg +20 -0
  162. data/themes/modern/images/cc/pd.svg +24 -0
  163. data/themes/modern/images/cc/remix.svg +20 -0
  164. data/themes/modern/images/cc/sa.svg +22 -0
  165. data/themes/modern/images/cc/sampling.plus.svg +33 -0
  166. data/themes/modern/images/cc/sampling.svg +36 -0
  167. data/themes/modern/images/cc/share.svg +22 -0
  168. data/themes/modern/images/cc/zero.svg +24 -0
  169. data/themes/modern/images/flickr.svg +65 -0
  170. data/themes/modern/images/mesh.png +0 -0
  171. data/themes/modern/images/mesh@2x.png +0 -0
  172. data/themes/modern/images/progress-grayDark.svg +55 -0
  173. data/themes/modern/images/progress.svg +3 -0
  174. data/themes/modern/index.erb +76 -0
  175. data/themes/modern/js/highcharts.js +294 -0
  176. data/themes/modern/js/jquery-2.1.0.min.js +4 -0
  177. data/themes/modern/js/script.coffee +480 -0
  178. data/themes/modern/js/script.js +678 -0
  179. data/themes/modern/styles/_box.scss +89 -0
  180. data/themes/modern/styles/_figure.scss +81 -0
  181. data/themes/modern/styles/_full.scss +74 -0
  182. data/themes/modern/styles/_increment.scss +38 -0
  183. data/themes/modern/styles/_list.scss +129 -0
  184. data/themes/modern/styles/_progress.scss +19 -0
  185. data/themes/modern/styles/defaults.scss +46 -0
  186. data/themes/modern/styles/fonts.scss +197 -0
  187. data/themes/modern/styles/pygments/_solarized.scss +82 -0
  188. data/themes/modern/styles/pygments/colorful.scss +67 -0
  189. data/themes/modern/styles/pygments/github.scss +67 -0
  190. data/themes/modern/styles/pygments/solarized-dark.scss +15 -0
  191. data/themes/modern/styles/pygments/solarized-light.scss +15 -0
  192. data/themes/modern/styles/reset.scss +46 -0
  193. data/themes/modern/styles/screen.scss +841 -0
  194. data/themes/reveal/README +2 -0
  195. data/themes/reveal/css/main.css +1029 -0
  196. data/themes/reveal/css/reset.css +57 -0
  197. data/themes/reveal/index.erb +102 -0
  198. data/themes/reveal/js/classList.js +2 -0
  199. data/themes/reveal/js/head.min.js +8 -0
  200. data/themes/reveal/js/reveal.js +951 -0
  201. data/themes/shower/README +2 -0
  202. data/themes/shower/css/fonts.css +50 -0
  203. data/themes/shower/css/reset.css +42 -0
  204. data/themes/shower/css/style.css +418 -0
  205. data/themes/shower/images/grid.png +0 -0
  206. data/themes/shower/images/linen.png +0 -0
  207. data/themes/shower/images/ribbon.svg +4 -0
  208. data/themes/shower/index.erb +35 -0
  209. data/themes/shower/js/script.js +325 -0
  210. data/themes/template/README +5 -0
  211. data/themes/template/css/reset.css +42 -0
  212. data/themes/template/index.erb +35 -0
  213. data/themes/template/js/prefixfree.min.js +13 -0
  214. metadata +343 -0
@@ -0,0 +1,768 @@
1
+ /**
2
+ * @authors Luke Mahe
3
+ * @authors Eric Bidelman
4
+ * @fileoverview TODO
5
+ */
6
+ document.cancelFullScreen = document.webkitCancelFullScreen ||
7
+ document.mozCancelFullScreen;
8
+
9
+ /**
10
+ * @constructor
11
+ */
12
+ function SlideDeck(el) {
13
+ this.curSlide_ = 0;
14
+ this.prevSlide_ = 0;
15
+ this.config_ = null;
16
+ this.container = el || document.querySelector('slides');
17
+ this.slides = [];
18
+ this.controller = null;
19
+
20
+ this.getCurrentSlideFromHash_();
21
+
22
+ // Call this explicitly. Modernizr.load won't be done until after DOM load.
23
+ this.onDomLoaded_.bind(this)();
24
+ }
25
+
26
+ /**
27
+ * @const
28
+ * @private
29
+ */
30
+ SlideDeck.prototype.SLIDE_CLASSES_ = [
31
+ 'far-past', 'past', 'current', 'next', 'far-next'];
32
+
33
+ /**
34
+ * @const
35
+ * @private
36
+ */
37
+ SlideDeck.prototype.CSS_DIR_ = 'theme/css/';
38
+
39
+ /**
40
+ * @private
41
+ */
42
+ SlideDeck.prototype.getCurrentSlideFromHash_ = function() {
43
+ var slideNo = parseInt(document.location.hash.substr(1));
44
+
45
+ if (slideNo) {
46
+ this.curSlide_ = slideNo - 1;
47
+ } else {
48
+ this.curSlide_ = 0;
49
+ }
50
+ };
51
+
52
+ /**
53
+ * @param {number} slideNo
54
+ */
55
+ SlideDeck.prototype.loadSlide = function(slideNo) {
56
+ if (slideNo) {
57
+ this.curSlide_ = slideNo - 1;
58
+ this.updateSlides_();
59
+ }
60
+ };
61
+
62
+ /**
63
+ * @private
64
+ */
65
+ SlideDeck.prototype.onDomLoaded_ = function(e) {
66
+ document.body.classList.add('loaded'); // Add loaded class for templates to use.
67
+
68
+ this.slides = this.container.querySelectorAll('slide:not([hidden]):not(.backdrop)');
69
+
70
+ // If we're on a smartphone, apply special sauce.
71
+ if (Modernizr.mq('only screen and (max-device-width: 480px)')) {
72
+ // var style = document.createElement('link');
73
+ // style.rel = 'stylesheet';
74
+ // style.type = 'text/css';
75
+ // style.href = this.CSS_DIR_ + 'phone.css';
76
+ // document.querySelector('head').appendChild(style);
77
+
78
+ // No need for widescreen layout on a phone.
79
+ this.container.classList.remove('layout-widescreen');
80
+ }
81
+
82
+ // this.loadConfig_(SLIDE_CONFIG);
83
+ this.addEventListeners_();
84
+ this.updateSlides_();
85
+
86
+ // Add slide numbers and total slide count metadata to each slide.
87
+ var that = this;
88
+ for (var i = 0, slide; slide = this.slides[i]; ++i) {
89
+ slide.dataset.slideNum = i + 1;
90
+ slide.dataset.totalSlides = this.slides.length;
91
+
92
+ slide.addEventListener('click', function(e) {
93
+ if (document.body.classList.contains('overview')) {
94
+ that.loadSlide(this.dataset.slideNum);
95
+ e.preventDefault();
96
+ window.setTimeout(function() {
97
+ that.toggleOverview();
98
+ }, 500);
99
+ }
100
+ }, false);
101
+ }
102
+
103
+ // Note: this needs to come after addEventListeners_(), which adds a
104
+ // 'keydown' listener that this controller relies on.
105
+ // Also, no need to set this up if we're on mobile.
106
+ if (!Modernizr.touch) {
107
+ this.controller = new SlideController(this);
108
+ if (this.controller.isPopup) {
109
+ document.body.classList.add('popup');
110
+ }
111
+ }
112
+ };
113
+
114
+ /**
115
+ * @private
116
+ */
117
+ SlideDeck.prototype.addEventListeners_ = function() {
118
+ document.addEventListener('keydown', this.onBodyKeyDown_.bind(this), false);
119
+ window.addEventListener('popstate', this.onPopState_.bind(this), false);
120
+
121
+ // var transEndEventNames = {
122
+ // 'WebkitTransition': 'webkitTransitionEnd',
123
+ // 'MozTransition': 'transitionend',
124
+ // 'OTransition': 'oTransitionEnd',
125
+ // 'msTransition': 'MSTransitionEnd',
126
+ // 'transition': 'transitionend'
127
+ // };
128
+ //
129
+ // // Find the correct transitionEnd vendor prefix.
130
+ // window.transEndEventName = transEndEventNames[
131
+ // Modernizr.prefixed('transition')];
132
+ //
133
+ // // When slides are done transitioning, kickoff loading iframes.
134
+ // // Note: we're only looking at a single transition (on the slide). This
135
+ // // doesn't include autobuilds the slides may have. Also, if the slide
136
+ // // transitions on multiple properties (e.g. not just 'all'), this doesn't
137
+ // // handle that case.
138
+ // this.container.addEventListener(transEndEventName, function(e) {
139
+ // this.enableSlideFrames_(this.curSlide_);
140
+ // }.bind(this), false);
141
+
142
+ // document.addEventListener('slideenter', function(e) {
143
+ // var slide = e.target;
144
+ // window.setTimeout(function() {
145
+ // this.enableSlideFrames_(e.slideNumber);
146
+ // this.enableSlideFrames_(e.slideNumber + 1);
147
+ // }.bind(this), 300);
148
+ // }.bind(this), false);
149
+ };
150
+
151
+ /**
152
+ * @private
153
+ * @param {Event} e The pop event.
154
+ */
155
+ SlideDeck.prototype.onPopState_ = function(e) {
156
+ if (e.state != null) {
157
+ this.curSlide_ = e.state;
158
+ this.updateSlides_(true);
159
+ }
160
+ };
161
+
162
+ /**
163
+ * @param {Event} e
164
+ */
165
+ SlideDeck.prototype.onBodyKeyDown_ = function(e) {
166
+ if (/^(input|textarea)$/i.test(e.target.nodeName) ||
167
+ e.target.isContentEditable) {
168
+ return;
169
+ }
170
+
171
+ // Forward keydowns to the main slides if we're the popup.
172
+ if (this.controller && this.controller.isPopup) {
173
+ this.controller.sendMsg({keyCode: e.keyCode});
174
+ }
175
+
176
+ switch (e.keyCode) {
177
+ case 13: // Enter
178
+ if (document.body.classList.contains('overview')) {
179
+ this.toggleOverview();
180
+ }
181
+ break;
182
+
183
+ case 39: // right arrow
184
+ case 32: // space
185
+ case 34: // PgDn
186
+ this.nextSlide();
187
+ e.preventDefault();
188
+ break;
189
+
190
+ case 37: // left arrow
191
+ case 8: // Backspace
192
+ case 33: // PgUp
193
+ this.prevSlide();
194
+ e.preventDefault();
195
+ break;
196
+
197
+ case 40: // down arrow
198
+ this.nextSlide();
199
+ e.preventDefault();
200
+ break;
201
+
202
+ case 38: // up arrow
203
+ this.prevSlide();
204
+ e.preventDefault();
205
+ break;
206
+
207
+ case 72: // H: Toggle code highlighting
208
+ document.body.classList.toggle('highlight-code');
209
+ break;
210
+
211
+ case 79: // O: Toggle overview
212
+ this.toggleOverview();
213
+ break;
214
+
215
+ case 80: // P
216
+ if (this.controller && this.controller.isPopup) {
217
+ document.body.classList.toggle('with-notes');
218
+ } else if (this.controller && !this.controller.popup) {
219
+ document.body.classList.toggle('with-notes');
220
+ }
221
+ break;
222
+
223
+ case 82: // R
224
+ // TODO: implement refresh on main slides when popup is refreshed.
225
+ break;
226
+
227
+ case 27: // ESC: Hide notes and highlighting
228
+ document.body.classList.remove('with-notes');
229
+ document.body.classList.remove('highlight-code');
230
+
231
+ if (document.body.classList.contains('overview')) {
232
+ this.toggleOverview();
233
+ }
234
+ break;
235
+
236
+ case 70: // F: Toggle fullscreen
237
+ // Only respect 'f' on body. Don't want to capture keys from an <input>.
238
+ // Also, ignore browser's fullscreen shortcut (cmd+shift+f) so we don't
239
+ // get trapped in fullscreen!
240
+ if (e.target == document.body && !(e.shiftKey && e.metaKey)) {
241
+ if (document.mozFullScreen !== undefined && !document.mozFullScreen) {
242
+ document.body.mozRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
243
+ } else if (document.webkitIsFullScreen !== undefined && !document.webkitIsFullScreen) {
244
+ document.body.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
245
+ } else {
246
+ document.cancelFullScreen();
247
+ }
248
+ }
249
+ break;
250
+
251
+ case 87: // W: Toggle widescreen
252
+ // Only respect 'w' on body. Don't want to capture keys from an <input>.
253
+ if (e.target == document.body && !(e.shiftKey && e.metaKey)) {
254
+ this.container.classList.toggle('layout-widescreen');
255
+ }
256
+ break;
257
+ }
258
+ };
259
+
260
+ /**
261
+ *
262
+ */
263
+ SlideDeck.prototype.focusOverview_ = function() {
264
+ var overview = document.body.classList.contains('overview');
265
+
266
+ for (var i = 0, slide; slide = this.slides[i]; i++) {
267
+ slide.style[Modernizr.prefixed('transform')] = overview ?
268
+ 'translateZ(-2500px) translate(' + (( i - this.curSlide_ ) * 105) +
269
+ '%, 0%)' : '';
270
+ }
271
+ };
272
+
273
+ /**
274
+ */
275
+ SlideDeck.prototype.toggleOverview = function() {
276
+ document.body.classList.toggle('overview');
277
+
278
+ this.focusOverview_();
279
+ };
280
+
281
+ /**
282
+ * @private
283
+ */
284
+ SlideDeck.prototype.loadConfig_ = function(config) {
285
+ if (!config) {
286
+ return;
287
+ }
288
+
289
+ this.config_ = config;
290
+
291
+ var settings = this.config_.settings;
292
+
293
+ this.loadTheme_(settings.theme || []);
294
+
295
+ if (settings.favIcon) {
296
+ this.addFavIcon_(settings.favIcon);
297
+ }
298
+
299
+ // Prettyprint. Default to on.
300
+ if (!!!('usePrettify' in settings) || settings.usePrettify) {
301
+ prettyPrint();
302
+ }
303
+
304
+ if (settings.analytics) {
305
+ this.loadAnalytics_();
306
+ }
307
+
308
+ if (settings.fonts) {
309
+ this.addFonts_(settings.fonts);
310
+ }
311
+
312
+ // Builds. Default to on.
313
+ if (!!!('useBuilds' in settings) || settings.useBuilds) {
314
+ this.makeBuildLists_();
315
+ }
316
+
317
+ if (settings.title) {
318
+ document.title = settings.title.replace(/<br\/?>/, ' ') + ' - Google IO 2012';
319
+ document.querySelector('[data-config-title]').innerHTML = settings.title;
320
+ }
321
+
322
+ if (settings.subtitle) {
323
+ document.querySelector('[data-config-subtitle]').innerHTML = settings.subtitle;
324
+ }
325
+
326
+ if (this.config_.presenters) {
327
+ var presenters = this.config_.presenters;
328
+ var dataConfigContact = document.querySelector('[data-config-contact]');
329
+
330
+ var html = [];
331
+ if (presenters.length == 1) {
332
+ var p = presenters[0];
333
+
334
+ html = [p.name, p.company].join('<br>');
335
+
336
+ var gplus = p.gplus ? '<span>g+</span><a href="' + p.gplus +
337
+ '">' + p.gplus.replace(/https?:\/\//, '') + '</a>' : '';
338
+
339
+ var twitter = p.twitter ? '<span>twitter</span>' +
340
+ '<a href="http://twitter.com/' + p.twitter + '">' +
341
+ p.twitter + '</a>' : '';
342
+
343
+ var www = p.www ? '<span>www</span><a href="' + p.www +
344
+ '">' + p.www.replace(/https?:\/\//, '') + '</a>' : '';
345
+
346
+ var github = p.github ? '<span>github</span><a href="' + p.github +
347
+ '">' + p.github.replace(/https?:\/\//, '') + '</a>' : '';
348
+
349
+ var html2 = [gplus, twitter, www, github].join('<br>');
350
+
351
+ if (dataConfigContact) {
352
+ dataConfigContact.innerHTML = html2;
353
+ }
354
+ } else {
355
+ for (var i = 0, p; p = presenters[i]; ++i) {
356
+ html.push(p.name + ' - ' + p.company);
357
+ }
358
+ html = html.join('<br>');
359
+ if (dataConfigContact) {
360
+ dataConfigContact.innerHTML = html;
361
+ }
362
+ }
363
+
364
+ var dataConfigPresenter = document.querySelector('[data-config-presenter]');
365
+ if (dataConfigPresenter) {
366
+ document.querySelector('[data-config-presenter]').innerHTML = html;
367
+ }
368
+ }
369
+
370
+ /* Left/Right tap areas. Default to including. */
371
+ if (!!!('enableSlideAreas' in settings) || settings.enableSlideAreas) {
372
+ var el = document.createElement('div');
373
+ el.classList.add('slide-area');
374
+ el.id = 'prev-slide-area';
375
+ el.addEventListener('click', this.prevSlide.bind(this), false);
376
+ this.container.appendChild(el);
377
+
378
+ var el = document.createElement('div');
379
+ el.classList.add('slide-area');
380
+ el.id = 'next-slide-area';
381
+ el.addEventListener('click', this.nextSlide.bind(this), false);
382
+ this.container.appendChild(el);
383
+ }
384
+
385
+ if (Modernizr.touch && (!!!('enableTouch' in settings) ||
386
+ settings.enableTouch)) {
387
+ var self = this;
388
+
389
+ // Note: this prevents mobile zoom in/out but prevents iOS from doing
390
+ // it's crazy scroll over effect and disaligning the slides.
391
+ window.addEventListener('touchstart', function(e) {
392
+ e.preventDefault();
393
+ }, false);
394
+
395
+ var hammer = new Hammer(this.container);
396
+ hammer.ondragend = function(e) {
397
+ if (e.direction == 'right' || e.direction == 'down') {
398
+ self.prevSlide();
399
+ } else if (e.direction == 'left' || e.direction == 'up') {
400
+ self.nextSlide();
401
+ }
402
+ };
403
+ }
404
+ };
405
+
406
+ /**
407
+ * @private
408
+ * @param {Array.<string>} fonts
409
+ */
410
+ SlideDeck.prototype.addFonts_ = function(fonts) {
411
+ var el = document.createElement('link');
412
+ el.rel = 'stylesheet';
413
+ el.href = ('https:' == document.location.protocol ? 'https' : 'http') +
414
+ '://fonts.googleapis.com/css?family=' + fonts.join('|') + '&v2';
415
+ document.querySelector('head').appendChild(el);
416
+ };
417
+
418
+ /**
419
+ * @private
420
+ */
421
+ SlideDeck.prototype.buildNextItem_ = function() {
422
+ var slide = this.slides[this.curSlide_];
423
+ var toBuild = slide.querySelector('.to-build');
424
+ var built = slide.querySelector('.build-current');
425
+
426
+ if (built) {
427
+ built.classList.remove('build-current');
428
+ if (built.classList.contains('fade')) {
429
+ built.classList.add('build-fade');
430
+ }
431
+ }
432
+
433
+ if (!toBuild) {
434
+ var items = slide.querySelectorAll('.build-fade');
435
+ for (var j = 0, item; item = items[j]; j++) {
436
+ item.classList.remove('build-fade');
437
+ }
438
+ return false;
439
+ }
440
+
441
+ toBuild.classList.remove('to-build');
442
+ toBuild.classList.add('build-current');
443
+
444
+ return true;
445
+ };
446
+
447
+ /**
448
+ * @param {boolean=} opt_dontPush
449
+ */
450
+ SlideDeck.prototype.prevSlide = function(opt_dontPush) {
451
+ if (this.curSlide_ > 0) {
452
+ var bodyClassList = document.body.classList;
453
+ bodyClassList.remove('highlight-code');
454
+
455
+ // Toggle off speaker notes if they're showing when we move backwards on the
456
+ // main slides. If we're the speaker notes popup, leave them up.
457
+ if (this.controller && !this.controller.isPopup) {
458
+ bodyClassList.remove('with-notes');
459
+ } else if (!this.controller) {
460
+ bodyClassList.remove('with-notes');
461
+ }
462
+
463
+ this.prevSlide_ = this.curSlide_--;
464
+
465
+ this.updateSlides_(opt_dontPush);
466
+ }
467
+ };
468
+
469
+ /**
470
+ * @param {boolean=} opt_dontPush
471
+ */
472
+ SlideDeck.prototype.nextSlide = function(opt_dontPush) {
473
+ if (!document.body.classList.contains('overview') && this.buildNextItem_()) {
474
+ return;
475
+ }
476
+
477
+ if (this.curSlide_ < this.slides.length - 1) {
478
+ var bodyClassList = document.body.classList;
479
+ bodyClassList.remove('highlight-code');
480
+
481
+ // Toggle off speaker notes if they're showing when we advanced on the main
482
+ // slides. If we're the speaker notes popup, leave them up.
483
+ if (this.controller && !this.controller.isPopup) {
484
+ bodyClassList.remove('with-notes');
485
+ } else if (!this.controller) {
486
+ bodyClassList.remove('with-notes');
487
+ }
488
+
489
+ this.prevSlide_ = this.curSlide_++;
490
+
491
+ this.updateSlides_(opt_dontPush);
492
+ }
493
+ };
494
+
495
+ /* Slide events */
496
+
497
+ /**
498
+ * Triggered when a slide enter/leave event should be dispatched.
499
+ *
500
+ * @param {string} type The type of event to trigger
501
+ * (e.g. 'slideenter', 'slideleave').
502
+ * @param {number} slideNo The index of the slide that is being left.
503
+ */
504
+ SlideDeck.prototype.triggerSlideEvent = function(type, slideNo) {
505
+ var el = this.getSlideEl_(slideNo);
506
+ if (!el) {
507
+ return;
508
+ }
509
+
510
+ // Call onslideenter/onslideleave if the attribute is defined on this slide.
511
+ var func = el.getAttribute(type);
512
+ if (func) {
513
+ new Function(func).call(el); // TODO: Don't use new Function() :(
514
+ }
515
+
516
+ // Dispatch event to listeners setup using addEventListener.
517
+ var evt = document.createEvent('Event');
518
+ evt.initEvent(type, true, true);
519
+ evt.slideNumber = slideNo + 1; // Make it readable
520
+ evt.slide = el;
521
+
522
+ el.dispatchEvent(evt);
523
+ };
524
+
525
+ /**
526
+ * @private
527
+ */
528
+ SlideDeck.prototype.updateSlides_ = function(opt_dontPush) {
529
+ var dontPush = opt_dontPush || false;
530
+
531
+ var curSlide = this.curSlide_;
532
+ for (var i = 0; i < this.slides.length; ++i) {
533
+ switch (i) {
534
+ case curSlide - 2:
535
+ this.updateSlideClass_(i, 'far-past');
536
+ break;
537
+ case curSlide - 1:
538
+ this.updateSlideClass_(i, 'past');
539
+ break;
540
+ case curSlide:
541
+ this.updateSlideClass_(i, 'current');
542
+ break;
543
+ case curSlide + 1:
544
+ this.updateSlideClass_(i, 'next');
545
+ break;
546
+ case curSlide + 2:
547
+ this.updateSlideClass_(i, 'far-next');
548
+ break;
549
+ default:
550
+ this.updateSlideClass_(i);
551
+ break;
552
+ }
553
+ };
554
+
555
+ this.triggerSlideEvent('slideleave', this.prevSlide_);
556
+ this.triggerSlideEvent('slideenter', curSlide);
557
+
558
+ // window.setTimeout(this.disableSlideFrames_.bind(this, curSlide - 2), 301);
559
+ //
560
+ // this.enableSlideFrames_(curSlide - 1); // Previous slide.
561
+ // this.enableSlideFrames_(curSlide + 1); // Current slide.
562
+ // this.enableSlideFrames_(curSlide + 2); // Next slide.
563
+
564
+ // Enable current slide's iframes (needed for page loat at current slide).
565
+ this.enableSlideFrames_(curSlide + 1);
566
+
567
+ // No way to tell when all slide transitions + auto builds are done.
568
+ // Give ourselves a good buffer to preload the next slide's iframes.
569
+ window.setTimeout(this.enableSlideFrames_.bind(this, curSlide + 2), 1000);
570
+
571
+ this.updateHash_(dontPush);
572
+
573
+ if (document.body.classList.contains('overview')) {
574
+ this.focusOverview_();
575
+ return;
576
+ }
577
+
578
+ };
579
+
580
+ /**
581
+ * @private
582
+ * @param {number} slideNo
583
+ */
584
+ SlideDeck.prototype.enableSlideFrames_ = function(slideNo) {
585
+ var el = this.slides[slideNo - 1];
586
+ if (!el) {
587
+ return;
588
+ }
589
+
590
+ var frames = el.querySelectorAll('iframe');
591
+ for (var i = 0, frame; frame = frames[i]; i++) {
592
+ this.enableFrame_(frame);
593
+ }
594
+ };
595
+
596
+ /**
597
+ * @private
598
+ * @param {number} slideNo
599
+ */
600
+ SlideDeck.prototype.enableFrame_ = function(frame) {
601
+ var src = frame.dataset.src;
602
+ if (src && frame.src != src) {
603
+ frame.src = src;
604
+ }
605
+ };
606
+
607
+ /**
608
+ * @private
609
+ * @param {number} slideNo
610
+ */
611
+ SlideDeck.prototype.disableSlideFrames_ = function(slideNo) {
612
+ var el = this.slides[slideNo - 1];
613
+ if (!el) {
614
+ return;
615
+ }
616
+
617
+ var frames = el.querySelectorAll('iframe');
618
+ for (var i = 0, frame; frame = frames[i]; i++) {
619
+ this.disableFrame_(frame);
620
+ }
621
+ };
622
+
623
+ /**
624
+ * @private
625
+ * @param {Node} frame
626
+ */
627
+ SlideDeck.prototype.disableFrame_ = function(frame) {
628
+ frame.src = 'about:blank';
629
+ };
630
+
631
+ /**
632
+ * @private
633
+ * @param {number} slideNo
634
+ */
635
+ SlideDeck.prototype.getSlideEl_ = function(no) {
636
+ if ((no < 0) || (no >= this.slides.length)) {
637
+ return null;
638
+ } else {
639
+ return this.slides[no];
640
+ }
641
+ };
642
+
643
+ /**
644
+ * @private
645
+ * @param {number} slideNo
646
+ * @param {string} className
647
+ */
648
+ SlideDeck.prototype.updateSlideClass_ = function(slideNo, className) {
649
+ var el = this.getSlideEl_(slideNo);
650
+
651
+ if (!el) {
652
+ return;
653
+ }
654
+
655
+ if (className) {
656
+ el.classList.add(className);
657
+ }
658
+
659
+ for (var i = 0, slideClass; slideClass = this.SLIDE_CLASSES_[i]; ++i) {
660
+ if (className != slideClass) {
661
+ el.classList.remove(slideClass);
662
+ }
663
+ }
664
+ };
665
+
666
+ /**
667
+ * @private
668
+ */
669
+ SlideDeck.prototype.makeBuildLists_ = function () {
670
+ for (var i = this.curSlide_, slide; slide = this.slides[i]; ++i) {
671
+ var items = slide.querySelectorAll('.build > *');
672
+ for (var j = 0, item; item = items[j]; ++j) {
673
+ if (item.classList) {
674
+ item.classList.add('to-build');
675
+ if (item.parentNode.classList.contains('fade')) {
676
+ item.classList.add('fade');
677
+ }
678
+ }
679
+ }
680
+ }
681
+ };
682
+
683
+ /**
684
+ * @private
685
+ * @param {boolean} dontPush
686
+ */
687
+ SlideDeck.prototype.updateHash_ = function(dontPush) {
688
+ if (!dontPush) {
689
+ var slideNo = this.curSlide_ + 1;
690
+ var hash = '#' + slideNo;
691
+ if (window.history.pushState) {
692
+ window.history.pushState(this.curSlide_, 'Slide ' + slideNo, hash);
693
+ } else {
694
+ window.location.replace(hash);
695
+ }
696
+
697
+ // Record GA hit on this slide.
698
+ window['_gaq'] && window['_gaq'].push(['_trackPageview',
699
+ document.location.href]);
700
+ }
701
+ };
702
+
703
+
704
+ /**
705
+ * @private
706
+ * @param {string} favIcon
707
+ */
708
+ SlideDeck.prototype.addFavIcon_ = function(favIcon) {
709
+ var el = document.createElement('link');
710
+ el.rel = 'icon';
711
+ el.type = 'image/png';
712
+ el.href = favIcon;
713
+ document.querySelector('head').appendChild(el);
714
+ };
715
+
716
+ /**
717
+ * @private
718
+ * @param {string} theme
719
+ */
720
+ SlideDeck.prototype.loadTheme_ = function(theme) {
721
+ var styles = [];
722
+ if (theme.constructor.name === 'String') {
723
+ styles.push(theme);
724
+ } else {
725
+ styles = theme;
726
+ }
727
+
728
+ for (var i = 0, style; themeUrl = styles[i]; i++) {
729
+ var style = document.createElement('link');
730
+ style.rel = 'stylesheet';
731
+ style.type = 'text/css';
732
+ if (themeUrl.indexOf('http') == -1) {
733
+ style.href = this.CSS_DIR_ + themeUrl + '.css';
734
+ } else {
735
+ style.href = themeUrl;
736
+ }
737
+ document.querySelector('head').appendChild(style);
738
+ }
739
+ };
740
+
741
+ /**
742
+ * @private
743
+ */
744
+ SlideDeck.prototype.loadAnalytics_ = function() {
745
+ var _gaq = window['_gaq'] || [];
746
+ _gaq.push(['_setAccount', this.config_.settings.analytics]);
747
+ _gaq.push(['_trackPageview']);
748
+
749
+ (function() {
750
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
751
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
752
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
753
+ })();
754
+ };
755
+
756
+
757
+ // Polyfill missing APIs (if we need to), then create the slide deck.
758
+ // iOS < 5 needs classList, dataset, and window.matchMedia. Modernizr contains
759
+ // the last one.
760
+ (function() {
761
+ Modernizr.load({
762
+ test: !!document.body.classList && !!document.body.dataset,
763
+ nope: ['js/polyfills/classList.min.js', 'js/polyfills/dataset.min.js'],
764
+ complete: function() {
765
+ window.slidedeck = new SlideDeck();
766
+ }
767
+ });
768
+ })();