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,480 @@
1
+ # Radialize the colors
2
+ Highcharts.setOptions
3
+ colors: [
4
+ '#96000F'
5
+ '#E10019'
6
+ '#AAA5A0'
7
+ '#46413C'
8
+ '#327D91'
9
+ '#4BBEE1'
10
+ '#560F32'
11
+ '#821350'
12
+ '#006450'
13
+ '#009682'
14
+ '#697D19'
15
+ '#9BC328'
16
+ '#AA5500'
17
+ '#FF8200'
18
+ ]
19
+ credits:
20
+ enabled: true
21
+ legend:
22
+ enabled: false
23
+ tooltip:
24
+ enabled: false
25
+ title:
26
+ text: ''
27
+ chart:
28
+ backgroundColor: 'rgba(0,0,0,0)'
29
+ plotBackgroundColor: null
30
+ plotBorderWidth: null
31
+ plotShadow: false
32
+ margin: [0, 0, 0, 0]
33
+ style:
34
+ fontFamily: 'Open Sans Light'
35
+ fontSize: '20px'
36
+ color: 'black'
37
+
38
+ Highcharts.getOptions().colors = Highcharts.map Highcharts.getOptions().colors, (color) ->
39
+ radialGradient:
40
+ cx: 0.5
41
+ cy: 0.3
42
+ r: 0.7
43
+ stops: [
44
+ [0, color]
45
+ [1, Highcharts.Color(color).brighten(-0.3).get('rgb')] # darken
46
+ ]
47
+
48
+ $.fn.extend
49
+ typewriter: ->
50
+ this.each ->
51
+ $el = $(this)
52
+ str = $el.text()
53
+ progress = 0
54
+ $el.text('')
55
+ timer = setInterval ->
56
+ $el.text(str.substring(0, progress) + '_')
57
+ if progress >= str.length
58
+ clearInterval(timer)
59
+ $el.text(str)
60
+ progress++
61
+ , 100
62
+ this
63
+
64
+ textfill: (maxFontSize, maxWords) ->
65
+ maxFontSize = parseInt(maxFontSize, 10) || 0
66
+ maxWords = parseInt(maxWords, 10) || 3
67
+ @each ->
68
+ calcSize = (text) ->
69
+ ourText = $("<span>" + text + "</span>").appendTo(self)
70
+ multiplier = maxWidth / ourText.width()
71
+ newSize = fontSize * (multiplier - 0.1)
72
+ ourText.css "fontSize", (if maxFontSize > 0 and newSize > maxFontSize then maxFontSize else newSize)
73
+ ourText.css "lineHeight", "1em"
74
+ #ourText.css "textTransform", "uppercase"
75
+ scrollHeight = self[0].scrollHeight
76
+ if scrollHeight > maxHeight
77
+ multiplier = maxHeight / scrollHeight
78
+ newSize = newSize * multiplier
79
+ ourText.css "fontSize", (if maxFontSize > 0 and newSize > maxFontSize then maxFontSize else newSize)
80
+ ourText.css "lineHeight", "1em"
81
+ #ourText.css "textTransform", "uppercase"
82
+ return
83
+
84
+ self = $(this)
85
+ orgText = self.text()
86
+ fontSize = parseInt(self.css("fontSize"), 10)
87
+ #lineHeight = parseInt(self.css("lineHeight"), "1em")
88
+ maxHeight = self.height()
89
+ maxWidth = self.width()
90
+
91
+ splittedText = self.html().split(/\s+|<.+?>/)
92
+ words = []
93
+ for word in splittedText
94
+ words.push(word) if word && !word.empty?
95
+ self.empty()
96
+ if words.length > maxWords
97
+ while words.length > 0
98
+ newText = words.splice(0, maxWords).join(" ")
99
+ console.log
100
+ calcSize newText
101
+ self.append "<br>"
102
+ else
103
+ calcSize orgText
104
+ return
105
+
106
+
107
+ class Transform
108
+ @body = document.body
109
+
110
+ @getScaleFactor: ->
111
+ denominator = Math.max(@body.clientWidth / window.innerWidth, @body.clientHeight / window.innerHeight)
112
+ 1 / denominator
113
+
114
+ @apply: (transform) ->
115
+ @body.style.WebkitTransform = transform
116
+ @body.style.MozTransform = transform
117
+ @body.style.msTransform = transform
118
+ @body.style.OTransform = transform
119
+ @body.style.transform = transform
120
+
121
+ @scale: ->
122
+ Transform.apply("scale(/#{@getScaleFactor()})")
123
+
124
+ @reset: ->
125
+ Transform.apply('none')
126
+
127
+ class Mode
128
+ @body = document.body
129
+
130
+ @dispatchSingleSlideMode: (e) ->
131
+ slideId = Mode.findSlideId(e.target)
132
+ presentSlideId = slideId?
133
+ if presentSlideId and Mode.isListMode()
134
+ Mode.enterSlideMode()
135
+ slide = Slide.fromSlideId(slideId)
136
+ slide.goto()
137
+ slide.replaceHistory()
138
+
139
+ @enterSlideMode: ->
140
+ @body.className = "full"
141
+ Transform.scale()
142
+
143
+ @enterListMode: ->
144
+ @body.className = "list"
145
+ Transform.reset()
146
+
147
+ @isListMode: ->
148
+ !@body.classList.contains("full")
149
+
150
+ @isSlideMode: ->
151
+ !Mode.isListMode()
152
+
153
+ @switchToListMode: ->
154
+ Mode.enterListMode()
155
+ slide = Slide.current()
156
+ slide.pushHistory()
157
+ slide.scrollTo()
158
+
159
+ @switchToSlideMode: ->
160
+ Mode.enterSlideMode()
161
+ slide = Slide.current()
162
+ slide.pushHistory()
163
+ slide.updateProgress()
164
+
165
+ @reload: ->
166
+ Slide.current() || Slide.first().goto()
167
+ if window.location.search.substr(1) is 'full'
168
+ Mode.enterSlideMode()
169
+ #Slide.current().updateProgress()
170
+ else
171
+ Mode.enterListMode()
172
+ Slide.current()?.scrollTo()
173
+
174
+ # private
175
+
176
+ # go up to element with class "slide" and return its id
177
+ @findSlideId: (node) ->
178
+ while "BODY" isnt node.nodeName and "HTML" isnt node.nodeName
179
+ return node.id if node.classList.contains("slide")
180
+ node = node.parentNode
181
+ null
182
+
183
+ class SlideInitializer
184
+ @init: ->
185
+ # SlideInitializer.initMouseClick()
186
+ $slides = $('.slide').not('.disabled')
187
+ totalSize = $slides.length
188
+ for slide in $slides
189
+ SlideInitializer.initSlideNumber(slide, totalSize)
190
+ SlideInitializer.initIncremental(slide)
191
+ SlideInitializer.initPause(slide)
192
+ SlideInitializer.initTypewriter(slide)
193
+
194
+ @initMouseClick: ->
195
+ # left click
196
+ $('body').click (e) ->
197
+ if e.which == 1
198
+ e.preventDefault()
199
+ UserInterface.nextStep()
200
+ # right click
201
+ $('body').on 'contextmenu', (e) ->
202
+ e.preventDefault()
203
+ UserInterface.prevStep()
204
+
205
+ @initSlideNumber: (slide, total) ->
206
+ slideNum = $(slide).index() - $(slide).prevAll('.slide.disabled').length
207
+ $(slide).attr('data-slide', slideNum).attr('data-slides', total)
208
+
209
+ @initIncremental: (slide) ->
210
+ $slide = $(slide)
211
+ if $slide.hasClass('incr-list')
212
+ $slide.find('> div > ul > li:first-child').addClass('current')
213
+ $slide.find('> div > ol > li:first-child').addClass('current')
214
+ $slide.find('> div > ul > li:not(:first-child)').addClass('inactive')
215
+ $slide.find('> div > ol > li:not(:first-child)').addClass('inactive')
216
+ if $slide.hasClass('incr-code')
217
+ $slide.find('pre > code:first-child').addClass('current')
218
+ $slide.find('pre > code:not(:first-child)').addClass('inactive')
219
+ if $slide.hasClass('incr-table')
220
+ $slide.find('table > tbody > tr:first-child').addClass('current')
221
+ $slide.find('table > tbody > tr:not(:first-child)').addClass('inactive')
222
+
223
+ @initPause: (slide) ->
224
+ pauses = $(slide).find(".pause")
225
+ for pause, i in pauses
226
+ last = i == pauses.length - 1
227
+ if last
228
+ wrappable = $(pause).nextAll()
229
+ else
230
+ wrappable = $(pause).nextUntil(".pause")
231
+ wrappable?.wrapAll('<div class="inactive"></div>')
232
+
233
+ @initTypewriter: (slide) ->
234
+ if $(slide).hasClass('typewriter')
235
+ $(slide).find('pre[data-lang=sh] code').addClass('inactive')
236
+
237
+ #TODO: Remove useless code
238
+ @initBodyClasses: ->
239
+ $.each @bodyClasses, (klass) ->
240
+ $('body').addClass(klass.split('=')[0])
241
+
242
+ #TODO: Remove useless code
243
+ @bodyClasses: ->
244
+ window.location.search.replace(/^\?/, '').split('&')
245
+
246
+ class Slide
247
+ constructor: (slideNumber) ->
248
+ @$element = $(@slideList()[@slideNumber])
249
+ @slideNumber = @normalizeSlideNumber(slideNumber)
250
+ @id = @slideList()[@slideNumber].id
251
+ @progress = $(".progress div").first()
252
+
253
+ @slideList: ->
254
+ slides = $("div.slide").not('.disabled')
255
+ slideList = []
256
+ slideList.push id: slide.id for slide in slides
257
+ slideList
258
+
259
+ @current: ->
260
+ id = window.location.hash.substr(1)
261
+ Slide.fromSlideId(id)
262
+
263
+ nextSection: ->
264
+ next = @nextSectionId()
265
+ Slide.fromSlideId("slide-#{next}-0")
266
+
267
+ prevSection: ->
268
+ prev = @prevSectionId()
269
+ Slide.fromSlideId("slide-#{prev}-0")
270
+
271
+ sectionId: ->
272
+ parseInt(@id.replace(/slide-/, '').split('-')[0], 10)
273
+
274
+ nextSectionId: ->
275
+ @normalizeSectionNumber(@sectionId() + 1)
276
+
277
+ prevSectionId: ->
278
+ @normalizeSectionNumber(@sectionId() - 1)
279
+
280
+ @currentSectionId: ->
281
+ Slide.current().sectionId()
282
+
283
+ @fromSlideId: (slideId) ->
284
+ for slide, index in Slide.slideList()
285
+ return new Slide(index) if slideId is slide.id
286
+ null
287
+
288
+ @first: -> new Slide(0)
289
+
290
+ @last: -> new Slide(@slideList().length - 1)
291
+
292
+ getHash: -> "#" + @id
293
+
294
+ html: -> $(@getHash())
295
+
296
+ goto: ->
297
+ hash = @getHash()
298
+ window.location.hash = hash
299
+ $('body').trigger('goto.slideoff', {target: hash})
300
+ $('body').trigger(hash+'.goto.slideoff', {target: hash})
301
+ @updateProgress() if Mode.isSlideMode()
302
+
303
+ scrollTo: -> window.scrollTo 0, @offsetTop()
304
+
305
+ offsetTop: -> @html()?.offset().top
306
+
307
+ next: -> new Slide(@slideNumber + 1)
308
+
309
+ prev: -> new Slide(@slideNumber - 1)
310
+
311
+ pushHistory: -> history.pushState null, null, @historyPath()
312
+
313
+ replaceHistory: -> history.replaceState null, null, @historyPath()
314
+
315
+ containsInactive: -> @firstInactiveElement().length > 0
316
+
317
+ firstInactiveElement: -> @html().find('.inactive').first()
318
+
319
+ removePresentElement: -> @html().find('.current').first().removeClass('current')
320
+
321
+ nextInactive: ->
322
+ @html().removeClass('incr') unless @containsInactive()
323
+ element = @firstInactiveElement()
324
+ @html().find('.current').first().addClass('visited')
325
+ @removePresentElement()
326
+ element.removeClass('inactive')
327
+ if element.is("pre[data-lang=sh] code")
328
+ element.typewriter()
329
+ else
330
+ element.addClass('current')
331
+
332
+ # private
333
+
334
+ slideList: -> Slide.slideList()
335
+
336
+ normalizeSlideNumber: (slideNumber) ->
337
+ lastIndex = @slideList().length - 1
338
+ @range(0, slideNumber, lastIndex)
339
+
340
+ normalizeSectionNumber: (sectionNumber) ->
341
+ lastIndex = @html().data('sections') - 1
342
+ @range(0, sectionNumber, lastIndex)
343
+
344
+ updateProgress: ->
345
+ return unless @progress?
346
+ width = (100 / (@slideList().length - 1) * @slideNumber).toFixed(2)
347
+ @progress.width("#{width}%")
348
+
349
+ historyPath: ->
350
+ path = window.location.pathname
351
+ path += "?full" if Mode.isSlideMode()
352
+ path += @getHash()
353
+ path
354
+
355
+ range: (min, i, max) ->
356
+ Math.min(Math.max(min, i), max)
357
+
358
+
359
+ class UserInterface
360
+ @gotoFirstSlide: ->
361
+ Slide.first().goto()
362
+
363
+ @gotoLastSlide: ->
364
+ Slide.last().goto()
365
+
366
+ @nextStep: ->
367
+ slide = Slide.current()
368
+ if Mode.isSlideMode() and slide.containsInactive()
369
+ slide.nextInactive()
370
+ else
371
+ slide.html().removeClass('incr')
372
+ slide.removePresentElement()
373
+ slide.next().goto()
374
+
375
+ @prevStep: ->
376
+ Slide.current().prev().goto()
377
+
378
+ @nextBigStep: ->
379
+ Slide.current().nextSection().goto()
380
+
381
+ @prevBigStep: ->
382
+ Slide.current().prevSection().goto()
383
+
384
+ @conditionalStep: (prev) ->
385
+ method = if prev then 'prev' else 'next'
386
+ UserInterface[method+'Step']()
387
+
388
+ @resize: ->
389
+ Transform.scale() if Mode.isSlideMode()
390
+
391
+ @init: ->
392
+ if Mode.isSlideMode()
393
+ Mode.enterSlideMode()
394
+ slide = Slide.current() || Slide.first()
395
+ slide.replaceHistory()
396
+ slide.updateProgress()
397
+
398
+ @switchToListMode: (e) ->
399
+ if Mode.isSlideMode()
400
+ e.preventDefault()
401
+ Mode.switchToListMode()
402
+
403
+ @switchToSlideMode: (e) ->
404
+ if Mode.isListMode()
405
+ e.preventDefault()
406
+ Mode.switchToSlideMode()
407
+
408
+ startEventSourceHandler = (uri) ->
409
+ return unless window["EventSource"]?
410
+ source = new EventSource(uri)
411
+ source.onmessage = (e) ->
412
+ switch e.data
413
+ when "next" then UserInterface.nextStep()
414
+ when "prev" then UserInterface.prevStep()
415
+ when "up" then UserInterface.switchToListMode(e)
416
+ when "down" then UserInterface.switchToSlideMode(e)
417
+ else console.log e
418
+
419
+ $ ->
420
+ SlideInitializer.init()
421
+
422
+ # Event handlers
423
+ window.addEventListener "DOMContentLoaded", ->
424
+ UserInterface.init()
425
+ , false
426
+
427
+ window.addEventListener "popstate", (e) ->
428
+ Mode.reload()
429
+ , false
430
+
431
+ window.addEventListener "resize", (e) ->
432
+ UserInterface.resize()
433
+ , false
434
+
435
+ document.addEventListener "keyup", (e) ->
436
+ # Shortcut for alt, ctrl and meta keys
437
+ return if e.altKey or e.ctrlKey or e.metaKey
438
+ switch e.which
439
+ when 116, 13 # F5, Enter
440
+ UserInterface.switchToSlideMode(e) if Slide.current()?
441
+ when 27 # Esc
442
+ UserInterface.switchToListMode(e)
443
+ when 33, 38, 37, 72, 75 # PgUp, Up, Left, h, k
444
+ e.preventDefault()
445
+ if e.shiftKey
446
+ UserInterface.prevBigStep()
447
+ else
448
+ UserInterface.prevStep()
449
+ when 34, 40, 39, 76, 74 # PgDown, Down, Right, l, j
450
+ e.preventDefault()
451
+ if e.shiftKey
452
+ UserInterface.nextBigStep()
453
+ else
454
+ UserInterface.nextStep()
455
+ when 36 # Home
456
+ e.preventDefault()
457
+ UserInterface.gotoFirstSlide()
458
+ when 35 # End
459
+ e.preventDefault()
460
+ UserInterface.gotoLastSlide()
461
+ when 9, 32 # Tab/Space = +1; &+Shift = -1
462
+ e.preventDefault()
463
+ UserInterface.conditionalStep(e.shiftKey)
464
+ , false
465
+
466
+ document.addEventListener "click", Mode.dispatchSingleSlideMode, false
467
+ document.addEventListener "touchend", Mode.dispatchSingleSlideMode, false
468
+ document.addEventListener "touchstart", (e) ->
469
+ if Mode.isSlideMode()
470
+ x = e.touches[0].pageX
471
+ UserInterface.conditionalStep(x <= window.innerWidth / 2)
472
+ , false
473
+
474
+ document.addEventListener "touchmove", (e) ->
475
+ e.preventDefault() if Mode.isSlideMode()
476
+ , false
477
+
478
+ window.setTimeout ->
479
+ startEventSourceHandler "/remote/sub/events"
480
+ , 100