slidemgr 1.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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +13 -0
- data/LICENCE +674 -0
- data/README.md +153 -0
- data/Rakefile +3 -0
- data/bin/setup +7 -0
- data/bin/slidemgr +10 -0
- data/config.yml +0 -0
- data/lib/command_router.rb +27 -0
- data/lib/commands/create.rb +61 -0
- data/lib/commands/init.rb +78 -0
- data/lib/commands/list.rb +12 -0
- data/lib/commands/refresh.rb +49 -0
- data/lib/commands/remove.rb +32 -0
- data/lib/commands/rename.rb +31 -0
- data/lib/commands/start.rb +36 -0
- data/lib/commands/sync.rb +31 -0
- data/lib/template/config.yml.erb +4 -0
- data/lib/template/content.md.erb +2 -0
- data/lib/template/index.erb +103 -0
- data/lib/template/overview_index.erb +9 -0
- data/lib/template/reveal.js-3.0.0/.DS_Store +0 -0
- data/lib/template/reveal.js-3.0.0/Gruntfile.js +174 -0
- data/lib/template/reveal.js-3.0.0/LICENSE +19 -0
- data/lib/template/reveal.js-3.0.0/css/print/paper.css +202 -0
- data/lib/template/reveal.js-3.0.0/css/print/pdf.css +157 -0
- data/lib/template/reveal.js-3.0.0/css/reveal.css +1141 -0
- data/lib/template/reveal.js-3.0.0/css/reveal.scss +1316 -0
- data/lib/template/reveal.js-3.0.0/css/theme/README.md +25 -0
- data/lib/template/reveal.js-3.0.0/css/theme/beige.css +265 -0
- data/lib/template/reveal.js-3.0.0/css/theme/black.css +261 -0
- data/lib/template/reveal.js-3.0.0/css/theme/blood.css +291 -0
- data/lib/template/reveal.js-3.0.0/css/theme/league.css +267 -0
- data/lib/template/reveal.js-3.0.0/css/theme/moon.css +265 -0
- data/lib/template/reveal.js-3.0.0/css/theme/night.css +259 -0
- data/lib/template/reveal.js-3.0.0/css/theme/serif.css +261 -0
- data/lib/template/reveal.js-3.0.0/css/theme/simple.css +261 -0
- data/lib/template/reveal.js-3.0.0/css/theme/sky.css +268 -0
- data/lib/template/reveal.js-3.0.0/css/theme/solarized.css +265 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/beige.scss +39 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/black.scss +49 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/blood.scss +91 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/league.scss +34 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/moon.scss +57 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/night.scss +35 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/serif.scss +35 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/simple.scss +38 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/sky.scss +46 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/solarized.scss +63 -0
- data/lib/template/reveal.js-3.0.0/css/theme/source/white.scss +49 -0
- data/lib/template/reveal.js-3.0.0/css/theme/template/mixins.scss +29 -0
- data/lib/template/reveal.js-3.0.0/css/theme/template/settings.scss +43 -0
- data/lib/template/reveal.js-3.0.0/css/theme/template/theme.scss +339 -0
- data/lib/template/reveal.js-3.0.0/css/theme/white.css +261 -0
- data/lib/template/reveal.js-3.0.0/js/reveal.js +4276 -0
- data/lib/template/reveal.js-3.0.0/lib/css/zenburn.css +117 -0
- data/lib/template/reveal.js-3.0.0/lib/font/league-gothic/LICENSE +2 -0
- data/lib/template/reveal.js-3.0.0/lib/font/league-gothic/league-gothic.css +10 -0
- data/lib/template/reveal.js-3.0.0/lib/font/league-gothic/league-gothic.eot +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/league-gothic/league-gothic.ttf +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/league-gothic/league-gothic.woff +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/LICENSE +45 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-italic.eot +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-italic.ttf +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-italic.woff +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-regular.eot +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-regular.ttf +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-regular.woff +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-semibold.eot +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-semibold.ttf +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-semibold.woff +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-semibolditalic.eot +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-semibolditalic.ttf +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro-semibolditalic.woff +0 -0
- data/lib/template/reveal.js-3.0.0/lib/font/source-sans-pro/source-sans-pro.css +39 -0
- data/lib/template/reveal.js-3.0.0/lib/js/classList.js +2 -0
- data/lib/template/reveal.js-3.0.0/lib/js/head.min.js +8 -0
- data/lib/template/reveal.js-3.0.0/lib/js/html5shiv.js +7 -0
- data/lib/template/reveal.js-3.0.0/plugin/highlight/highlight.js +30 -0
- data/lib/template/reveal.js-3.0.0/plugin/leap/leap.js +159 -0
- data/lib/template/reveal.js-3.0.0/plugin/markdown/example.html +129 -0
- data/lib/template/reveal.js-3.0.0/plugin/markdown/example.md +31 -0
- data/lib/template/reveal.js-3.0.0/plugin/markdown/markdown.js +393 -0
- data/lib/template/reveal.js-3.0.0/plugin/markdown/marked.js +37 -0
- data/lib/template/reveal.js-3.0.0/plugin/math/math.js +64 -0
- data/lib/template/reveal.js-3.0.0/plugin/multiplex/client.js +13 -0
- data/lib/template/reveal.js-3.0.0/plugin/multiplex/index.js +56 -0
- data/lib/template/reveal.js-3.0.0/plugin/multiplex/master.js +51 -0
- data/lib/template/reveal.js-3.0.0/plugin/notes/notes.html +406 -0
- data/lib/template/reveal.js-3.0.0/plugin/notes/notes.js +122 -0
- data/lib/template/reveal.js-3.0.0/plugin/notes-server/client.js +60 -0
- data/lib/template/reveal.js-3.0.0/plugin/notes-server/index.js +66 -0
- data/lib/template/reveal.js-3.0.0/plugin/notes-server/notes.html +396 -0
- data/lib/template/reveal.js-3.0.0/plugin/print-pdf/print-pdf.js +48 -0
- data/lib/template/reveal.js-3.0.0/plugin/remotes/remotes.js +39 -0
- data/lib/template/reveal.js-3.0.0/plugin/search/search.js +196 -0
- data/lib/template/reveal.js-3.0.0/plugin/zoom-js/zoom.js +278 -0
- data/lib/template/reveal.js-3.0.0/test/examples/assets/image1.png +0 -0
- data/lib/template/reveal.js-3.0.0/test/examples/assets/image2.png +0 -0
- data/lib/template/reveal.js-3.0.0/test/examples/barebones.html +41 -0
- data/lib/template/reveal.js-3.0.0/test/examples/embedded-media.html +49 -0
- data/lib/template/reveal.js-3.0.0/test/examples/math.html +185 -0
- data/lib/template/reveal.js-3.0.0/test/examples/slide-backgrounds.html +144 -0
- data/lib/template/reveal.js-3.0.0/test/qunit-1.12.0.css +244 -0
- data/lib/template/reveal.js-3.0.0/test/qunit-1.12.0.js +2212 -0
- data/lib/template/reveal.js-3.0.0/test/test-markdown-element-attributes.html +134 -0
- data/lib/template/reveal.js-3.0.0/test/test-markdown-element-attributes.js +46 -0
- data/lib/template/reveal.js-3.0.0/test/test-markdown-slide-attributes.html +128 -0
- data/lib/template/reveal.js-3.0.0/test/test-markdown-slide-attributes.js +47 -0
- data/lib/template/reveal.js-3.0.0/test/test-markdown.html +52 -0
- data/lib/template/reveal.js-3.0.0/test/test-markdown.js +15 -0
- data/lib/template/reveal.js-3.0.0/test/test-pdf.html +83 -0
- data/lib/template/reveal.js-3.0.0/test/test-pdf.js +15 -0
- data/lib/template/reveal.js-3.0.0/test/test.html +82 -0
- data/lib/template/reveal.js-3.0.0/test/test.js +572 -0
- data/lib/util.rb +99 -0
- data/lib/version.rb +3 -0
- data/slidemgr.gemspec +24 -0
- metadata +193 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
|
|
6
|
+
<title>reveal.js - Slide Notes</title>
|
|
7
|
+
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
font-family: Helvetica;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#current-slide,
|
|
14
|
+
#upcoming-slide,
|
|
15
|
+
#speaker-controls {
|
|
16
|
+
padding: 6px;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
-moz-box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#current-slide iframe,
|
|
22
|
+
#upcoming-slide iframe {
|
|
23
|
+
width: 100%;
|
|
24
|
+
height: 100%;
|
|
25
|
+
border: 1px solid #ddd;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#current-slide .label,
|
|
29
|
+
#upcoming-slide .label {
|
|
30
|
+
position: absolute;
|
|
31
|
+
top: 10px;
|
|
32
|
+
left: 10px;
|
|
33
|
+
font-weight: bold;
|
|
34
|
+
font-size: 14px;
|
|
35
|
+
z-index: 2;
|
|
36
|
+
color: rgba( 255, 255, 255, 0.9 );
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#current-slide {
|
|
40
|
+
position: absolute;
|
|
41
|
+
width: 65%;
|
|
42
|
+
height: 100%;
|
|
43
|
+
top: 0;
|
|
44
|
+
left: 0;
|
|
45
|
+
padding-right: 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#upcoming-slide {
|
|
49
|
+
position: absolute;
|
|
50
|
+
width: 35%;
|
|
51
|
+
height: 40%;
|
|
52
|
+
right: 0;
|
|
53
|
+
top: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#speaker-controls {
|
|
57
|
+
position: absolute;
|
|
58
|
+
top: 40%;
|
|
59
|
+
right: 0;
|
|
60
|
+
width: 35%;
|
|
61
|
+
height: 60%;
|
|
62
|
+
|
|
63
|
+
font-size: 18px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.speaker-controls-time.hidden,
|
|
67
|
+
.speaker-controls-notes.hidden {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.speaker-controls-time .label,
|
|
72
|
+
.speaker-controls-notes .label {
|
|
73
|
+
text-transform: uppercase;
|
|
74
|
+
font-weight: normal;
|
|
75
|
+
font-size: 0.66em;
|
|
76
|
+
color: #666;
|
|
77
|
+
margin: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.speaker-controls-time {
|
|
81
|
+
border-bottom: 1px solid rgba( 200, 200, 200, 0.5 );
|
|
82
|
+
margin-bottom: 10px;
|
|
83
|
+
padding: 10px 16px;
|
|
84
|
+
padding-bottom: 20px;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.speaker-controls-time .reset-button {
|
|
89
|
+
opacity: 0;
|
|
90
|
+
float: right;
|
|
91
|
+
color: #666;
|
|
92
|
+
text-decoration: none;
|
|
93
|
+
}
|
|
94
|
+
.speaker-controls-time:hover .reset-button {
|
|
95
|
+
opacity: 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.speaker-controls-time .timer,
|
|
99
|
+
.speaker-controls-time .clock {
|
|
100
|
+
width: 50%;
|
|
101
|
+
font-size: 1.9em;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.speaker-controls-time .timer {
|
|
105
|
+
float: left;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.speaker-controls-time .clock {
|
|
109
|
+
float: right;
|
|
110
|
+
text-align: right;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.speaker-controls-time span.mute {
|
|
114
|
+
color: #bbb;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.speaker-controls-notes {
|
|
118
|
+
padding: 10px 16px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.speaker-controls-notes .value {
|
|
122
|
+
margin-top: 5px;
|
|
123
|
+
line-height: 1.4;
|
|
124
|
+
font-size: 1.2em;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.clear {
|
|
128
|
+
clear: both;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@media screen and (max-width: 1080px) {
|
|
132
|
+
#speaker-controls {
|
|
133
|
+
font-size: 16px;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@media screen and (max-width: 900px) {
|
|
138
|
+
#speaker-controls {
|
|
139
|
+
font-size: 14px;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@media screen and (max-width: 800px) {
|
|
144
|
+
#speaker-controls {
|
|
145
|
+
font-size: 12px;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
</style>
|
|
150
|
+
</head>
|
|
151
|
+
|
|
152
|
+
<body>
|
|
153
|
+
|
|
154
|
+
<div id="current-slide"></div>
|
|
155
|
+
<div id="upcoming-slide"><span class="label">UPCOMING:</span></div>
|
|
156
|
+
<div id="speaker-controls">
|
|
157
|
+
<div class="speaker-controls-time">
|
|
158
|
+
<h4 class="label">Time <span class="reset-button">Click to Reset</span></h4>
|
|
159
|
+
<div class="clock">
|
|
160
|
+
<span class="clock-value">0:00 AM</span>
|
|
161
|
+
</div>
|
|
162
|
+
<div class="timer">
|
|
163
|
+
<span class="hours-value">00</span><span class="minutes-value">:00</span><span class="seconds-value">:00</span>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="clear"></div>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<div class="speaker-controls-notes hidden">
|
|
169
|
+
<h4 class="label">Notes</h4>
|
|
170
|
+
<div class="value"></div>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<script src="/socket.io/socket.io.js"></script>
|
|
175
|
+
<script src="/plugin/markdown/marked.js"></script>
|
|
176
|
+
|
|
177
|
+
<script>
|
|
178
|
+
(function() {
|
|
179
|
+
|
|
180
|
+
var notes,
|
|
181
|
+
notesValue,
|
|
182
|
+
currentState,
|
|
183
|
+
currentSlide,
|
|
184
|
+
upcomingSlide,
|
|
185
|
+
connected = false;
|
|
186
|
+
|
|
187
|
+
var socket = io.connect( window.location.origin ),
|
|
188
|
+
socketId = '{{socketId}}';
|
|
189
|
+
|
|
190
|
+
socket.on( 'statechanged', function( data ) {
|
|
191
|
+
|
|
192
|
+
// ignore data from sockets that aren't ours
|
|
193
|
+
if( data.socketId !== socketId ) { return; }
|
|
194
|
+
|
|
195
|
+
if( connected === false ) {
|
|
196
|
+
connected = true;
|
|
197
|
+
|
|
198
|
+
setupIframes( data );
|
|
199
|
+
setupKeyboard();
|
|
200
|
+
setupNotes();
|
|
201
|
+
setupTimer();
|
|
202
|
+
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
handleStateMessage( data );
|
|
206
|
+
|
|
207
|
+
} );
|
|
208
|
+
|
|
209
|
+
window.addEventListener( 'message', function( event ) {
|
|
210
|
+
|
|
211
|
+
var data = JSON.parse( event.data );
|
|
212
|
+
|
|
213
|
+
if( data && data.namespace === 'reveal' ) {
|
|
214
|
+
if( /ready/.test( data.eventName ) ) {
|
|
215
|
+
socket.emit( 'connect', { socketId: socketId } );
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
} );
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Called when the main window sends an updated state.
|
|
223
|
+
*/
|
|
224
|
+
function handleStateMessage( data ) {
|
|
225
|
+
|
|
226
|
+
// Store the most recently set state to avoid circular loops
|
|
227
|
+
// applying the same state
|
|
228
|
+
currentState = JSON.stringify( data.state );
|
|
229
|
+
|
|
230
|
+
// No need for updating the notes in case of fragment changes
|
|
231
|
+
if ( data.notes ) {
|
|
232
|
+
notes.classList.remove( 'hidden' );
|
|
233
|
+
if( data.markdown ) {
|
|
234
|
+
notesValue.innerHTML = marked( data.notes );
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
notesValue.innerHTML = data.notes;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
notes.classList.add( 'hidden' );
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Update the note slides
|
|
245
|
+
currentSlide.contentWindow.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ] }), '*' );
|
|
246
|
+
upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ] }), '*' );
|
|
247
|
+
upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: 'next' }), '*' );
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Limit to max one state update per X ms
|
|
252
|
+
handleStateMessage = debounce( handleStateMessage, 200 );
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Forward keyboard events to the current slide window.
|
|
256
|
+
* This enables keyboard events to work even if focus
|
|
257
|
+
* isn't set on the current slide iframe.
|
|
258
|
+
*/
|
|
259
|
+
function setupKeyboard() {
|
|
260
|
+
|
|
261
|
+
document.addEventListener( 'keydown', function( event ) {
|
|
262
|
+
currentSlide.contentWindow.postMessage( JSON.stringify({ method: 'triggerKey', args: [ event.keyCode ] }), '*' );
|
|
263
|
+
} );
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Creates the preview iframes.
|
|
269
|
+
*/
|
|
270
|
+
function setupIframes( data ) {
|
|
271
|
+
|
|
272
|
+
var params = [
|
|
273
|
+
'receiver',
|
|
274
|
+
'progress=false',
|
|
275
|
+
'history=false',
|
|
276
|
+
'transition=none',
|
|
277
|
+
'backgroundTransition=none'
|
|
278
|
+
].join( '&' );
|
|
279
|
+
|
|
280
|
+
var hash = '#/' + data.state.indexh + '/' + data.state.indexv;
|
|
281
|
+
var currentURL = '/?' + params + '&postMessageEvents=true' + hash;
|
|
282
|
+
var upcomingURL = '/?' + params + '&controls=false' + hash;
|
|
283
|
+
|
|
284
|
+
currentSlide = document.createElement( 'iframe' );
|
|
285
|
+
currentSlide.setAttribute( 'width', 1280 );
|
|
286
|
+
currentSlide.setAttribute( 'height', 1024 );
|
|
287
|
+
currentSlide.setAttribute( 'src', currentURL );
|
|
288
|
+
document.querySelector( '#current-slide' ).appendChild( currentSlide );
|
|
289
|
+
|
|
290
|
+
upcomingSlide = document.createElement( 'iframe' );
|
|
291
|
+
upcomingSlide.setAttribute( 'width', 640 );
|
|
292
|
+
upcomingSlide.setAttribute( 'height', 512 );
|
|
293
|
+
upcomingSlide.setAttribute( 'src', upcomingURL );
|
|
294
|
+
document.querySelector( '#upcoming-slide' ).appendChild( upcomingSlide );
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Setup the notes UI.
|
|
300
|
+
*/
|
|
301
|
+
function setupNotes() {
|
|
302
|
+
|
|
303
|
+
notes = document.querySelector( '.speaker-controls-notes' );
|
|
304
|
+
notesValue = document.querySelector( '.speaker-controls-notes .value' );
|
|
305
|
+
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Create the timer and clock and start updating them
|
|
310
|
+
* at an interval.
|
|
311
|
+
*/
|
|
312
|
+
function setupTimer() {
|
|
313
|
+
|
|
314
|
+
var start = new Date(),
|
|
315
|
+
timeEl = document.querySelector( '.speaker-controls-time' ),
|
|
316
|
+
clockEl = timeEl.querySelector( '.clock-value' ),
|
|
317
|
+
hoursEl = timeEl.querySelector( '.hours-value' ),
|
|
318
|
+
minutesEl = timeEl.querySelector( '.minutes-value' ),
|
|
319
|
+
secondsEl = timeEl.querySelector( '.seconds-value' );
|
|
320
|
+
|
|
321
|
+
function _updateTimer() {
|
|
322
|
+
|
|
323
|
+
var diff, hours, minutes, seconds,
|
|
324
|
+
now = new Date();
|
|
325
|
+
|
|
326
|
+
diff = now.getTime() - start.getTime();
|
|
327
|
+
hours = Math.floor( diff / ( 1000 * 60 * 60 ) );
|
|
328
|
+
minutes = Math.floor( ( diff / ( 1000 * 60 ) ) % 60 );
|
|
329
|
+
seconds = Math.floor( ( diff / 1000 ) % 60 );
|
|
330
|
+
|
|
331
|
+
clockEl.innerHTML = now.toLocaleTimeString( 'en-US', { hour12: true, hour: '2-digit', minute:'2-digit' } );
|
|
332
|
+
hoursEl.innerHTML = zeroPadInteger( hours );
|
|
333
|
+
hoursEl.className = hours > 0 ? '' : 'mute';
|
|
334
|
+
minutesEl.innerHTML = ':' + zeroPadInteger( minutes );
|
|
335
|
+
minutesEl.className = minutes > 0 ? '' : 'mute';
|
|
336
|
+
secondsEl.innerHTML = ':' + zeroPadInteger( seconds );
|
|
337
|
+
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Update once directly
|
|
341
|
+
_updateTimer();
|
|
342
|
+
|
|
343
|
+
// Then update every second
|
|
344
|
+
setInterval( _updateTimer, 1000 );
|
|
345
|
+
|
|
346
|
+
timeEl.addEventListener( 'click', function() {
|
|
347
|
+
start = new Date();
|
|
348
|
+
_updateTimer();
|
|
349
|
+
return false;
|
|
350
|
+
} );
|
|
351
|
+
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function zeroPadInteger( num ) {
|
|
355
|
+
|
|
356
|
+
var str = '00' + parseInt( num );
|
|
357
|
+
return str.substring( str.length - 2 );
|
|
358
|
+
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Limits the frequency at which a function can be called.
|
|
363
|
+
*/
|
|
364
|
+
function debounce( fn, ms ) {
|
|
365
|
+
|
|
366
|
+
var lastTime = 0,
|
|
367
|
+
timeout;
|
|
368
|
+
|
|
369
|
+
return function() {
|
|
370
|
+
|
|
371
|
+
var args = arguments;
|
|
372
|
+
var context = this;
|
|
373
|
+
|
|
374
|
+
clearTimeout( timeout );
|
|
375
|
+
|
|
376
|
+
var timeSinceLastCall = Date.now() - lastTime;
|
|
377
|
+
if( timeSinceLastCall > ms ) {
|
|
378
|
+
fn.apply( context, args );
|
|
379
|
+
lastTime = Date.now();
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
timeout = setTimeout( function() {
|
|
383
|
+
fn.apply( context, args );
|
|
384
|
+
lastTime = Date.now();
|
|
385
|
+
}, ms - timeSinceLastCall );
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
})();
|
|
393
|
+
</script>
|
|
394
|
+
|
|
395
|
+
</body>
|
|
396
|
+
</html>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* phantomjs script for printing presentations to PDF.
|
|
3
|
+
*
|
|
4
|
+
* Example:
|
|
5
|
+
* phantomjs print-pdf.js "http://lab.hakim.se/reveal-js?print-pdf" reveal-demo.pdf
|
|
6
|
+
*
|
|
7
|
+
* By Manuel Bieh (https://github.com/manuelbieh)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// html2pdf.js
|
|
11
|
+
var page = new WebPage();
|
|
12
|
+
var system = require( 'system' );
|
|
13
|
+
|
|
14
|
+
var slideWidth = system.args[3] ? system.args[3].split( 'x' )[0] : 960;
|
|
15
|
+
var slideHeight = system.args[3] ? system.args[3].split( 'x' )[1] : 700;
|
|
16
|
+
|
|
17
|
+
page.viewportSize = {
|
|
18
|
+
width: slideWidth,
|
|
19
|
+
height: slideHeight
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// TODO
|
|
23
|
+
// Something is wrong with these config values. An input
|
|
24
|
+
// paper width of 1920px actually results in a 756px wide
|
|
25
|
+
// PDF.
|
|
26
|
+
page.paperSize = {
|
|
27
|
+
width: Math.round( slideWidth * 2 ),
|
|
28
|
+
height: Math.round( slideHeight * 2 ),
|
|
29
|
+
border: 0
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
var inputFile = system.args[1] || 'index.html?print-pdf';
|
|
33
|
+
var outputFile = system.args[2] || 'slides.pdf';
|
|
34
|
+
|
|
35
|
+
if( outputFile.match( /\.pdf$/gi ) === null ) {
|
|
36
|
+
outputFile += '.pdf';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log( 'Printing PDF (Paper size: '+ page.paperSize.width + 'x' + page.paperSize.height +')' );
|
|
40
|
+
|
|
41
|
+
page.open( inputFile, function( status ) {
|
|
42
|
+
window.setTimeout( function() {
|
|
43
|
+
console.log( 'Printed succesfully' );
|
|
44
|
+
page.render( outputFile );
|
|
45
|
+
phantom.exit();
|
|
46
|
+
}, 1000 );
|
|
47
|
+
} );
|
|
48
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Touch-based remote controller for your presentation courtesy
|
|
3
|
+
* of the folks at http://remotes.io
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
(function(window){
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Detects if we are dealing with a touch enabled device (with some false positives)
|
|
10
|
+
* Borrowed from modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touch.js
|
|
11
|
+
*/
|
|
12
|
+
var hasTouch = (function(){
|
|
13
|
+
return ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
|
|
14
|
+
})();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Detects if notes are enable and the current page is opened inside an /iframe
|
|
18
|
+
* this prevents loading Remotes.io several times
|
|
19
|
+
*/
|
|
20
|
+
var isNotesAndIframe = (function(){
|
|
21
|
+
return window.RevealNotes && !(self == top);
|
|
22
|
+
})();
|
|
23
|
+
|
|
24
|
+
if(!hasTouch && !isNotesAndIframe){
|
|
25
|
+
head.ready( 'remotes.ne.min.js', function() {
|
|
26
|
+
new Remotes("preview")
|
|
27
|
+
.on("swipe-left", function(e){ Reveal.right(); })
|
|
28
|
+
.on("swipe-right", function(e){ Reveal.left(); })
|
|
29
|
+
.on("swipe-up", function(e){ Reveal.down(); })
|
|
30
|
+
.on("swipe-down", function(e){ Reveal.up(); })
|
|
31
|
+
.on("tap", function(e){ Reveal.next(); })
|
|
32
|
+
.on("zoom-out", function(e){ Reveal.toggleOverview(true); })
|
|
33
|
+
.on("zoom-in", function(e){ Reveal.toggleOverview(false); })
|
|
34
|
+
;
|
|
35
|
+
} );
|
|
36
|
+
|
|
37
|
+
head.js('https://hakim-static.s3.amazonaws.com/reveal-js/remotes.ne.min.js');
|
|
38
|
+
}
|
|
39
|
+
})(window);
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Handles finding a text string anywhere in the slides and showing the next occurrence to the user
|
|
3
|
+
* by navigatating to that slide and highlighting it.
|
|
4
|
+
*
|
|
5
|
+
* By Jon Snyder <snyder.jon@gmail.com>, February 2013
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
var RevealSearch = (function() {
|
|
9
|
+
|
|
10
|
+
var matchedSlides;
|
|
11
|
+
var currentMatchedIndex;
|
|
12
|
+
var searchboxDirty;
|
|
13
|
+
var myHilitor;
|
|
14
|
+
|
|
15
|
+
// Original JavaScript code by Chirp Internet: www.chirp.com.au
|
|
16
|
+
// Please acknowledge use of this code by including this header.
|
|
17
|
+
// 2/2013 jon: modified regex to display any match, not restricted to word boundaries.
|
|
18
|
+
|
|
19
|
+
function Hilitor(id, tag)
|
|
20
|
+
{
|
|
21
|
+
|
|
22
|
+
var targetNode = document.getElementById(id) || document.body;
|
|
23
|
+
var hiliteTag = tag || "EM";
|
|
24
|
+
var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM|SPAN)$");
|
|
25
|
+
var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"];
|
|
26
|
+
var wordColor = [];
|
|
27
|
+
var colorIdx = 0;
|
|
28
|
+
var matchRegex = "";
|
|
29
|
+
var matchingSlides = [];
|
|
30
|
+
|
|
31
|
+
this.setRegex = function(input)
|
|
32
|
+
{
|
|
33
|
+
input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|");
|
|
34
|
+
matchRegex = new RegExp("(" + input + ")","i");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.getRegex = function()
|
|
38
|
+
{
|
|
39
|
+
return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " ");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// recursively apply word highlighting
|
|
43
|
+
this.hiliteWords = function(node)
|
|
44
|
+
{
|
|
45
|
+
if(node == undefined || !node) return;
|
|
46
|
+
if(!matchRegex) return;
|
|
47
|
+
if(skipTags.test(node.nodeName)) return;
|
|
48
|
+
|
|
49
|
+
if(node.hasChildNodes()) {
|
|
50
|
+
for(var i=0; i < node.childNodes.length; i++)
|
|
51
|
+
this.hiliteWords(node.childNodes[i]);
|
|
52
|
+
}
|
|
53
|
+
if(node.nodeType == 3) { // NODE_TEXT
|
|
54
|
+
if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) {
|
|
55
|
+
//find the slide's section element and save it in our list of matching slides
|
|
56
|
+
var secnode = node.parentNode;
|
|
57
|
+
while (secnode.nodeName != 'SECTION') {
|
|
58
|
+
secnode = secnode.parentNode;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var slideIndex = Reveal.getIndices(secnode);
|
|
62
|
+
var slidelen = matchingSlides.length;
|
|
63
|
+
var alreadyAdded = false;
|
|
64
|
+
for (var i=0; i < slidelen; i++) {
|
|
65
|
+
if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) {
|
|
66
|
+
alreadyAdded = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (! alreadyAdded) {
|
|
70
|
+
matchingSlides.push(slideIndex);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if(!wordColor[regs[0].toLowerCase()]) {
|
|
74
|
+
wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
var match = document.createElement(hiliteTag);
|
|
78
|
+
match.appendChild(document.createTextNode(regs[0]));
|
|
79
|
+
match.style.backgroundColor = wordColor[regs[0].toLowerCase()];
|
|
80
|
+
match.style.fontStyle = "inherit";
|
|
81
|
+
match.style.color = "#000";
|
|
82
|
+
|
|
83
|
+
var after = node.splitText(regs.index);
|
|
84
|
+
after.nodeValue = after.nodeValue.substring(regs[0].length);
|
|
85
|
+
node.parentNode.insertBefore(match, after);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// remove highlighting
|
|
91
|
+
this.remove = function()
|
|
92
|
+
{
|
|
93
|
+
var arr = document.getElementsByTagName(hiliteTag);
|
|
94
|
+
while(arr.length && (el = arr[0])) {
|
|
95
|
+
el.parentNode.replaceChild(el.firstChild, el);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// start highlighting at target node
|
|
100
|
+
this.apply = function(input)
|
|
101
|
+
{
|
|
102
|
+
if(input == undefined || !input) return;
|
|
103
|
+
this.remove();
|
|
104
|
+
this.setRegex(input);
|
|
105
|
+
this.hiliteWords(targetNode);
|
|
106
|
+
return matchingSlides;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function openSearch() {
|
|
112
|
+
//ensure the search term input dialog is visible and has focus:
|
|
113
|
+
var inputbox = document.getElementById("searchinput");
|
|
114
|
+
inputbox.style.display = "inline";
|
|
115
|
+
inputbox.focus();
|
|
116
|
+
inputbox.select();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function toggleSearch() {
|
|
120
|
+
var inputbox = document.getElementById("searchinput");
|
|
121
|
+
if (inputbox.style.display !== "inline") {
|
|
122
|
+
openSearch();
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
inputbox.style.display = "none";
|
|
126
|
+
myHilitor.remove();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function doSearch() {
|
|
131
|
+
//if there's been a change in the search term, perform a new search:
|
|
132
|
+
if (searchboxDirty) {
|
|
133
|
+
var searchstring = document.getElementById("searchinput").value;
|
|
134
|
+
|
|
135
|
+
//find the keyword amongst the slides
|
|
136
|
+
myHilitor = new Hilitor("slidecontent");
|
|
137
|
+
matchedSlides = myHilitor.apply(searchstring);
|
|
138
|
+
currentMatchedIndex = 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//navigate to the next slide that has the keyword, wrapping to the first if necessary
|
|
142
|
+
if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) {
|
|
143
|
+
currentMatchedIndex = 0;
|
|
144
|
+
}
|
|
145
|
+
if (matchedSlides.length > currentMatchedIndex) {
|
|
146
|
+
Reveal.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v);
|
|
147
|
+
currentMatchedIndex++;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
var dom = {};
|
|
152
|
+
dom.wrapper = document.querySelector( '.reveal' );
|
|
153
|
+
|
|
154
|
+
if( !dom.wrapper.querySelector( '.searchbox' ) ) {
|
|
155
|
+
var searchElement = document.createElement( 'div' );
|
|
156
|
+
searchElement.id = "searchinputdiv";
|
|
157
|
+
searchElement.classList.add( 'searchdiv' );
|
|
158
|
+
searchElement.style.position = 'absolute';
|
|
159
|
+
searchElement.style.top = '10px';
|
|
160
|
+
searchElement.style.left = '10px';
|
|
161
|
+
//embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/:
|
|
162
|
+
searchElement.innerHTML = '<span><input type="search" id="searchinput" class="searchinput" style="vertical-align: top;"/><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJiSURBVHjatFZNaxNBGH5md+Mmu92NVdKDRipSAyqCghgQD4L4cRe86UUtAQ+eFCxoa4/25EXBFi8eBE+eRPoDhB6KgiiixdAPCEkx2pjvTXadd9yNsflwuyUDD/O+u8PzzDPvzOwyx3EwyCZhwG3gAkp7MnpjgbopjsltcD4gjuXZZKeAR348MYLYTm3LzOs/y3j3JTfZxgXWXmTuwPHIc4VmoOmv5IrI53+AO2DdHLjkDWQ3GoEEVFXtXQOvkSnPWcyUceviLhwbDYv8/XIVj97kse7TodLvZXxYxrPUHkQ1ufXs3FEdybEIxucySOesoNvUgWU1cP3MkCBfTFdw9fGaAMVmRELq7LBw2Q3/FaAxxWIRpw+ZIr/7IouPqzUBiqmdHAv7EuhRAwf1er2Vy4x1jW3b2d5Jfvu5IPp7l2LYbcgCFFNb+FoJ7oBqEAqFMPNqFcmEgVMJDfMT+1tvN0pNjERlMS6QA5pFOKxiKVPFhakPeL3It+WGJUDxt2wFR+JhzI7v5ctkd8DXOZAkCYYxhO+lKm4+Xfqz/rIixBuNBl7eOYzkQQNzqX249mRl6zUgEcYkaJrGhUwBinVdh6IouPzwE6/DL5w4oLkH8y981aDf+uq6hlKpJESiUdNfDZi7/ehG9K6KfiA3pml0PLcsq+cSMTj2NL9ukc4UOmz7AZ3+crkC4mHujFvXNaMFB3bEr8xPS6p5O+jXxq4VZtaen7/PwzrntjcLUE0iHPS1Ud1cdiEJl/8WivZk0wXd7zWOMkeF8s0CcAmkNrC2nvXZDbbbN73ccYnZoH9bfgswAFzAe9/h3dbKAAAAAElFTkSuQmCC" id="searchbutton" class="searchicon" style="vertical-align: top; margin-top: -1px;"/></span>';
|
|
163
|
+
dom.wrapper.appendChild( searchElement );
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
document.getElementById("searchbutton").addEventListener( 'click', function(event) {
|
|
167
|
+
doSearch();
|
|
168
|
+
}, false );
|
|
169
|
+
|
|
170
|
+
document.getElementById("searchinput").addEventListener( 'keyup', function( event ) {
|
|
171
|
+
switch (event.keyCode) {
|
|
172
|
+
case 13:
|
|
173
|
+
event.preventDefault();
|
|
174
|
+
doSearch();
|
|
175
|
+
searchboxDirty = false;
|
|
176
|
+
break;
|
|
177
|
+
default:
|
|
178
|
+
searchboxDirty = true;
|
|
179
|
+
}
|
|
180
|
+
}, false );
|
|
181
|
+
|
|
182
|
+
// Open the search when the 's' key is hit (yes, this conflicts with the notes plugin, disabling for now)
|
|
183
|
+
/*
|
|
184
|
+
document.addEventListener( 'keydown', function( event ) {
|
|
185
|
+
// Disregard the event if the target is editable or a
|
|
186
|
+
// modifier is present
|
|
187
|
+
if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
|
|
188
|
+
|
|
189
|
+
if( event.keyCode === 83 ) {
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
openSearch();
|
|
192
|
+
}
|
|
193
|
+
}, false );
|
|
194
|
+
*/
|
|
195
|
+
return { open: openSearch };
|
|
196
|
+
})();
|