slide-em-up 0.2.3 → 0.2.4
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.
- data/README.md +4 -3
- data/lib/slide-em-up/presentation.rb +5 -4
- data/lib/slide-em-up/version.rb +1 -1
- data/themes/CSSS/index.erb +1 -1
- data/themes/common/css/pygments/colorful.css +62 -324
- data/themes/common/css/pygments/native.css +70 -70
- data/themes/common/css/pygments/solarized.css +66 -0
- data/themes/common/fonts/YanoneKaffeesatz-Bold.woff +0 -0
- data/themes/common/fonts/YanoneKaffeesatz-Regular.woff +0 -0
- data/themes/memories/README +5 -0
- data/themes/memories/css/fonts.css +25 -0
- data/themes/memories/css/slideshow.css +145 -0
- data/themes/memories/css/theme.css +154 -0
- data/themes/memories/index.erb +35 -0
- data/themes/memories/js/slideshow.js +420 -0
- data/themes/shower/css/fonts.css +0 -0
- metadata +24 -15
@@ -0,0 +1,35 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
6
|
+
<title><%= meta.title %></title>
|
7
|
+
<% (theme.css + meta.css).each do |css| %>
|
8
|
+
<link rel="stylesheet" href="<%= css%>">
|
9
|
+
<% end %>
|
10
|
+
<link rel="stylesheet" href="css/pygments/solarized.css">
|
11
|
+
</head>
|
12
|
+
<body data-duration="<%= meta.duration %>">
|
13
|
+
<section>
|
14
|
+
<header class="slide">
|
15
|
+
<h1><%= meta.title %></h1>
|
16
|
+
</header>
|
17
|
+
</section>
|
18
|
+
<% sections.each do |section| %>
|
19
|
+
<section>
|
20
|
+
<header class="slide">
|
21
|
+
<h1><%= section.title %></h1>
|
22
|
+
</header>
|
23
|
+
<% section.slides.each do |slide| %>
|
24
|
+
<section class="slide <%= slide.classes %>">
|
25
|
+
<%= slide.html %>
|
26
|
+
</section>
|
27
|
+
<% end %>
|
28
|
+
</section>
|
29
|
+
<% end %>
|
30
|
+
<% (theme.js + meta.js).each do |js| %>
|
31
|
+
<script src="<%= js %>"></script>
|
32
|
+
<% end %>
|
33
|
+
<script>slideshow = new SlideShow();</script>
|
34
|
+
</body>
|
35
|
+
</html>
|
@@ -0,0 +1,420 @@
|
|
1
|
+
/**
|
2
|
+
* CSSS javascript code
|
3
|
+
* @author Lea Verou (http://leaverou.me)
|
4
|
+
* @version 2.0
|
5
|
+
*/
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Make the environment a bit friendlier
|
9
|
+
*/
|
10
|
+
function $(expr, con) {
|
11
|
+
return (con || document).querySelector(expr);
|
12
|
+
}
|
13
|
+
function $$(expr, con) {
|
14
|
+
return [].slice.call((con || document).querySelectorAll(expr));
|
15
|
+
}
|
16
|
+
|
17
|
+
(function(body){
|
18
|
+
|
19
|
+
// Cache <title> element, we may need it for slides that don't have titles
|
20
|
+
var documentTitle = document.title + '';
|
21
|
+
|
22
|
+
var self = window.SlideShow = function(container, slide) {
|
23
|
+
var me = this;
|
24
|
+
|
25
|
+
// Set instance
|
26
|
+
if(!window.slideshow) {
|
27
|
+
window.slideshow = this;
|
28
|
+
}
|
29
|
+
|
30
|
+
container = container || body;
|
31
|
+
|
32
|
+
// Current slide
|
33
|
+
this.slide = slide || 0;
|
34
|
+
|
35
|
+
// Current .delayed item in the slide
|
36
|
+
this.item = 0;
|
37
|
+
|
38
|
+
// Do we need to add a timer?
|
39
|
+
this.duration = container.getAttribute('data-duration');
|
40
|
+
|
41
|
+
if(this.duration > 0) {
|
42
|
+
var timer = document.createElement('div'),
|
43
|
+
declaration = 'transition: ' + this.duration * 60 + 's linear; ';
|
44
|
+
|
45
|
+
timer.id = 'timer';
|
46
|
+
timer.setAttribute('style', '-moz-' + declaration + '-webkit-' + declaration + '-o-' + declaration + '-ms-' + declaration + declaration);
|
47
|
+
container.appendChild(timer);
|
48
|
+
|
49
|
+
setTimeout(function() {
|
50
|
+
timer.className = 'end';
|
51
|
+
}, 1);
|
52
|
+
}
|
53
|
+
|
54
|
+
var delayed = $$('ol li', container);
|
55
|
+
for (var i=0; i<delayed.length; i++) {
|
56
|
+
delayed[i].className = "delayed";
|
57
|
+
}
|
58
|
+
|
59
|
+
// Get the slide elements into an array
|
60
|
+
this.slides = Array.prototype.slice.apply($$('.slide', container));
|
61
|
+
|
62
|
+
for(var i=0; i<this.slides.length; i++) {
|
63
|
+
var slide = this.slides[i]; // to speed up references
|
64
|
+
|
65
|
+
// Asign ids to slides that don't have one
|
66
|
+
if(!slide.id) {
|
67
|
+
slide.id = 'slide' + (i+1);
|
68
|
+
}
|
69
|
+
|
70
|
+
// Set data-title attribute to the title of the slide
|
71
|
+
if(!slide.title) {
|
72
|
+
// no title attribute, fetch title from heading(s)
|
73
|
+
var heading = $('hgroup', slide) || $('h1,h2,h3,h4,h5,h6', slide);
|
74
|
+
|
75
|
+
if(heading && heading.textContent.trim()) {
|
76
|
+
slide.setAttribute('data-title', heading.textContent);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
else {
|
80
|
+
// The title attribute is set, use that
|
81
|
+
slide.setAttribute('data-title', slide.title);
|
82
|
+
slide.removeAttribute('title');
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
// If there's already a hash, update current slide number...
|
87
|
+
this.goto(location.hash.substr(1) || 0);
|
88
|
+
|
89
|
+
// ...and keep doing so every time the hash changes
|
90
|
+
this.onhashchange = function() {
|
91
|
+
me.goto(location.hash.substr(1) || 0);
|
92
|
+
};
|
93
|
+
window.addEventListener('hashchange', this.onhashchange, false);
|
94
|
+
|
95
|
+
me.startEventSourceHandler('/remote/sub/events');
|
96
|
+
|
97
|
+
if(window.name === 'projector') {
|
98
|
+
document.body.classList.add('projector');
|
99
|
+
}
|
100
|
+
|
101
|
+
// Adjust the font-size when the window is resized
|
102
|
+
addEventListener('resize', function() {
|
103
|
+
me.adjustFontSize();
|
104
|
+
}, false);
|
105
|
+
|
106
|
+
// In some browsers DOMContentLoaded is too early, so try again onload
|
107
|
+
addEventListener('load', function() {
|
108
|
+
me.adjustFontSize();
|
109
|
+
}, false);
|
110
|
+
|
111
|
+
/**
|
112
|
+
Keyboard navigation
|
113
|
+
Home : First slide
|
114
|
+
End : Last slide
|
115
|
+
Space/Up/Right arrow : Next item/slide
|
116
|
+
Ctrl + Space/Up/Right arrow : Next slide
|
117
|
+
Down/Left arrow : Previous item/slide
|
118
|
+
Ctrl + Down/Left arrow : Previous slide
|
119
|
+
(Shift instead of Ctrl works too)
|
120
|
+
*/
|
121
|
+
document.addEventListener('keydown', function(evt) {
|
122
|
+
if(evt.target === body || evt.target === body.parentNode || evt.altKey) {
|
123
|
+
if(evt.keyCode >= 32 && evt.keyCode <= 40) {
|
124
|
+
evt.preventDefault();
|
125
|
+
}
|
126
|
+
|
127
|
+
switch(evt.keyCode) {
|
128
|
+
case 33: //page up
|
129
|
+
me.previous();
|
130
|
+
break;
|
131
|
+
case 34: //page down
|
132
|
+
me.next();
|
133
|
+
break;
|
134
|
+
case 35: // end
|
135
|
+
me.end();
|
136
|
+
break;
|
137
|
+
case 36: // home
|
138
|
+
me.start();
|
139
|
+
break;
|
140
|
+
case 37: // <-
|
141
|
+
case 38: // up arrow
|
142
|
+
me.previous(evt.ctrlKey || evt.shiftKey);
|
143
|
+
break;
|
144
|
+
case 32: // space
|
145
|
+
case 39: // ->
|
146
|
+
case 40: // down arrow
|
147
|
+
me.next(evt.ctrlKey || evt.shiftKey);
|
148
|
+
break;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}, false);
|
152
|
+
|
153
|
+
// Rudimentary style[scoped] polyfill
|
154
|
+
var scoped = $$('style[scoped]', container);
|
155
|
+
|
156
|
+
for(var i=scoped.length; i--;) {
|
157
|
+
var style = scoped[i],
|
158
|
+
rulez = style.sheet.cssRules,
|
159
|
+
parentid = style.parentNode.id || self.getSlide(style).id;
|
160
|
+
|
161
|
+
for(var j=rulez.length; j--;) {
|
162
|
+
var cssText = rulez[j].cssText.replace(/^|,/g, function($0) { return '#' + parentid + ' ' + $0 });
|
163
|
+
|
164
|
+
style.sheet.deleteRule(0);
|
165
|
+
style.sheet.insertRule(cssText, 0);
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
self.prototype = {
|
171
|
+
start: function() {
|
172
|
+
this.goto(0);
|
173
|
+
},
|
174
|
+
|
175
|
+
end: function() {
|
176
|
+
this.goto(this.slides.length - 1);
|
177
|
+
},
|
178
|
+
|
179
|
+
/**
|
180
|
+
@param hard {Boolean} Whether to advance to the next slide (true) or
|
181
|
+
just the next step (which could very well be showing a list item)
|
182
|
+
*/
|
183
|
+
next: function(hard) {
|
184
|
+
if(!hard && this.items.length) {
|
185
|
+
// If there's no current, then just mark the first one as such
|
186
|
+
if(!this.item) {
|
187
|
+
this.items[this.item++].classList.add('current');
|
188
|
+
}
|
189
|
+
// Add .current to current item if it exists, otherwise advance to next slide
|
190
|
+
else if(this.item < this.items.length) {
|
191
|
+
classes = this.items[this.item - 1].classList; // to speed up lookups
|
192
|
+
|
193
|
+
classes.remove('current');
|
194
|
+
classes.add('displayed');
|
195
|
+
|
196
|
+
this.items[this.item++].classList.add('current');
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
this.item = 0;
|
200
|
+
this.next(true);
|
201
|
+
}
|
202
|
+
}
|
203
|
+
else {
|
204
|
+
this.goto(this.slide + 1);
|
205
|
+
|
206
|
+
this.item = 0;
|
207
|
+
|
208
|
+
// Mark all items as not displayed, if there are any
|
209
|
+
if(this.items.length) {
|
210
|
+
for (var i=0; i<this.items.length; i++) {
|
211
|
+
if(this.items[i].classList) {
|
212
|
+
this.items[i].classList.remove('displayed');
|
213
|
+
this.items[i].classList.remove('current');
|
214
|
+
}
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
},
|
219
|
+
|
220
|
+
previous: function(hard) {
|
221
|
+
if(!hard && this.item > 0) {
|
222
|
+
var classes = this.items[this.item - 1].classList; // to speed up lookups
|
223
|
+
|
224
|
+
classes.remove('current');
|
225
|
+
|
226
|
+
if(this.item > 1) {
|
227
|
+
classes = this.items[--this.item - 1].classList;
|
228
|
+
|
229
|
+
classes.remove('displayed');
|
230
|
+
classes.add('current');
|
231
|
+
}
|
232
|
+
else {
|
233
|
+
this.item = 0;
|
234
|
+
}
|
235
|
+
}
|
236
|
+
else {
|
237
|
+
|
238
|
+
this.goto(this.slide - 1);
|
239
|
+
|
240
|
+
this.item = this.items.length;
|
241
|
+
|
242
|
+
// Mark all items as displayed, if there are any
|
243
|
+
if(this.items.length) {
|
244
|
+
for (var i=0; i<this.items.length; i++) {
|
245
|
+
if(this.items[i].classList) {
|
246
|
+
this.items[i].classList.add('displayed');
|
247
|
+
}
|
248
|
+
}
|
249
|
+
|
250
|
+
// Mark the last one as current
|
251
|
+
var lastItem = this.items[this.items.length - 1];
|
252
|
+
|
253
|
+
lastItem.classList.remove('displayed');
|
254
|
+
lastItem.classList.add('current');
|
255
|
+
}
|
256
|
+
}
|
257
|
+
},
|
258
|
+
|
259
|
+
/**
|
260
|
+
Go to an aribtary slide
|
261
|
+
@param which {String|Integer} Which slide (identifier or slide number)
|
262
|
+
*/
|
263
|
+
goto: function(which) {
|
264
|
+
var slide;
|
265
|
+
|
266
|
+
// We have to remove it to prevent multiple calls to goto messing up
|
267
|
+
// our current item (and there's no point either, so we save on performance)
|
268
|
+
window.removeEventListener('hashchange', this.onhashchange, false);
|
269
|
+
|
270
|
+
if(which + 0 === which && which in this.slides) { // Argument is a valid slide number
|
271
|
+
this.slide = which;
|
272
|
+
|
273
|
+
slide = this.slides[this.slide];
|
274
|
+
location.hash = '#' + slide.id;
|
275
|
+
}
|
276
|
+
else if(which + '' === which) { // Argument is a slide id
|
277
|
+
slide = document.getElementById(which);
|
278
|
+
|
279
|
+
if(slide) {
|
280
|
+
this.slide = this.slides.indexOf(slide);
|
281
|
+
location.hash = '#' + which;
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
if(slide) { // Slide actually changed, perform any other tasks needed
|
286
|
+
document.title = slide.getAttribute('data-title') || documentTitle;
|
287
|
+
|
288
|
+
this.adjustFontSize();
|
289
|
+
|
290
|
+
// Update items collection
|
291
|
+
this.items = $$('.delayed, .delayed-children > *', this.slides[this.slide]);
|
292
|
+
this.item = 0;
|
293
|
+
|
294
|
+
// Tell other windows
|
295
|
+
if(this.projector && this.projector.slideshow && this.projector.slideshow.slide != this.slide) {
|
296
|
+
this.projector.slideshow.goto(this.slide);
|
297
|
+
}
|
298
|
+
|
299
|
+
if(window.opener && opener.slideshow && opener.slideshow.slide != this.slide) {
|
300
|
+
opener.slideshow.goto(this.slide);
|
301
|
+
}
|
302
|
+
|
303
|
+
// Update next/previous
|
304
|
+
for (var i=this.slides.length; i--;) {
|
305
|
+
this.slides[i].classList.remove('previous');
|
306
|
+
this.slides[i].classList.remove('next');
|
307
|
+
}
|
308
|
+
|
309
|
+
this.slides.previous = this.slides[this.slide-1];
|
310
|
+
this.slides.next = this.slides[this.slide+1];
|
311
|
+
|
312
|
+
this.slides.previous && this.slides.previous.classList.add('previous');
|
313
|
+
this.slides.next && this.slides.next.classList.add('next');
|
314
|
+
}
|
315
|
+
|
316
|
+
// If you attach the listener immediately again then it will catch the event
|
317
|
+
// We have to do it asynchronously
|
318
|
+
var me = this;
|
319
|
+
setTimeout(function() {
|
320
|
+
window.addEventListener('hashchange', me.onhashchange, false);
|
321
|
+
}, 1000);
|
322
|
+
},
|
323
|
+
|
324
|
+
adjustFontSize: function() {
|
325
|
+
// Cache long lookup chains, for performance
|
326
|
+
var bodyStyle = body.style,
|
327
|
+
scrollRoot = document[document.documentElement.scrollHeight? 'documentElement' : 'body'],
|
328
|
+
innerHeight = window.innerHeight,
|
329
|
+
innerWidth = window.innerWidth,
|
330
|
+
slide = this.slides[this.slide];
|
331
|
+
|
332
|
+
// Clear previous styles
|
333
|
+
bodyStyle.fontSize = '';
|
334
|
+
|
335
|
+
if(body.classList.contains('show-thumbnails')
|
336
|
+
|| slide.classList.contains('dont-resize')) {
|
337
|
+
return;
|
338
|
+
}
|
339
|
+
|
340
|
+
for(
|
341
|
+
var percent = 100;
|
342
|
+
(scrollRoot.scrollHeight > innerHeight || scrollRoot.scrollWidth > innerWidth) && percent >= 35;
|
343
|
+
percent-=5
|
344
|
+
) {
|
345
|
+
bodyStyle.fontSize = percent + '%';
|
346
|
+
}
|
347
|
+
|
348
|
+
// Individual slide
|
349
|
+
|
350
|
+
if(slide.clientHeight && slide.clientWidth) {
|
351
|
+
// Strange FF bug: scrollHeight doesn't work properly with overflow:hidden
|
352
|
+
var previousStyle = slide.getAttribute('style');
|
353
|
+
slide.style.overflow = 'auto';
|
354
|
+
|
355
|
+
for(
|
356
|
+
;
|
357
|
+
(slide.scrollHeight > slide.clientHeight || slide.scrollWidth > slide.clientWidth) && percent >= 35;
|
358
|
+
percent--
|
359
|
+
) {
|
360
|
+
bodyStyle.fontSize = percent + '%';
|
361
|
+
}
|
362
|
+
|
363
|
+
slide.setAttribute('style', previousStyle);
|
364
|
+
}
|
365
|
+
},
|
366
|
+
|
367
|
+
// Is the element on the current slide?
|
368
|
+
onCurrent: function(element) {
|
369
|
+
var slide = self.getSlide(element);
|
370
|
+
|
371
|
+
if(slide) {
|
372
|
+
return '#' + slide.id === location.hash;
|
373
|
+
}
|
374
|
+
|
375
|
+
return false;
|
376
|
+
},
|
377
|
+
|
378
|
+
startEventSourceHandler: function(uri) {
|
379
|
+
if (window['EventSource'] == undefined) return ;
|
380
|
+
|
381
|
+
var source = new EventSource(uri);
|
382
|
+
var me = this;
|
383
|
+
|
384
|
+
source.onmessage = function(e) {
|
385
|
+
switch(e.data){
|
386
|
+
case 'next':
|
387
|
+
me.next();
|
388
|
+
break;
|
389
|
+
case 'prev':
|
390
|
+
me.previous();
|
391
|
+
break;
|
392
|
+
case 'up':
|
393
|
+
me.end();
|
394
|
+
break;
|
395
|
+
case 'down':
|
396
|
+
me.start();
|
397
|
+
break;
|
398
|
+
default:
|
399
|
+
console.log(e);
|
400
|
+
};
|
401
|
+
};
|
402
|
+
}
|
403
|
+
};
|
404
|
+
|
405
|
+
/**********************************************
|
406
|
+
* Static methods
|
407
|
+
**********************************************/
|
408
|
+
|
409
|
+
// Helper method for plugins
|
410
|
+
self.getSlide = function(element) {
|
411
|
+
var slide = element;
|
412
|
+
|
413
|
+
while (slide && slide.classList && !slide.classList.contains('slide')) {
|
414
|
+
slide = slide.parentNode;
|
415
|
+
}
|
416
|
+
|
417
|
+
return slide;
|
418
|
+
}
|
419
|
+
|
420
|
+
})(document.body);
|