reveal-ck 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/files/reveal-ck/templates/index.html/body.html.erb +1 -1
  3. data/files/reveal-ck/templates/index.html/head.html.erb +1 -1
  4. data/files/reveal.js/CONTRIBUTING.md +20 -0
  5. data/files/reveal.js/Gruntfile.js +55 -19
  6. data/files/reveal.js/README.md +54 -39
  7. data/files/reveal.js/css/print/paper.css +193 -167
  8. data/files/reveal.js/css/print/pdf.css +18 -42
  9. data/files/reveal.js/css/reveal.css +937 -1636
  10. data/files/reveal.js/css/reveal.scss +1357 -0
  11. data/files/reveal.js/css/theme/beige.css +177 -55
  12. data/files/reveal.js/css/theme/black.css +258 -0
  13. data/files/reveal.js/css/theme/blood.css +190 -75
  14. data/files/reveal.js/css/theme/default.css +180 -58
  15. data/files/reveal.js/css/theme/moon.css +168 -46
  16. data/files/reveal.js/css/theme/night.css +164 -42
  17. data/files/reveal.js/css/theme/serif.css +180 -58
  18. data/files/reveal.js/css/theme/simple.css +172 -50
  19. data/files/reveal.js/css/theme/sky.css +169 -47
  20. data/files/reveal.js/css/theme/solarized.css +168 -46
  21. data/files/reveal.js/css/theme/source/black.scss +44 -0
  22. data/files/reveal.js/css/theme/source/blood.scss +4 -4
  23. data/files/reveal.js/css/theme/source/default.scss +1 -0
  24. data/files/reveal.js/css/theme/source/serif.scss +1 -1
  25. data/files/reveal.js/css/theme/source/sky.scss +1 -1
  26. data/files/reveal.js/css/theme/template/settings.scss +8 -3
  27. data/files/reveal.js/css/theme/template/theme.scss +181 -13
  28. data/files/reveal.js/index.html +70 -53
  29. data/files/reveal.js/js/reveal.js +1269 -371
  30. data/files/reveal.js/lib/css/zenburn.css +74 -71
  31. data/files/reveal.js/package.json +9 -7
  32. data/files/reveal.js/plugin/highlight/highlight.js +2 -4
  33. data/files/reveal.js/plugin/leap/leap.js +4 -2
  34. data/files/reveal.js/plugin/markdown/example.html +2 -2
  35. data/files/reveal.js/plugin/markdown/markdown.js +8 -7
  36. data/files/reveal.js/plugin/notes-server/client.js +49 -46
  37. data/files/reveal.js/plugin/notes-server/index.js +28 -21
  38. data/files/reveal.js/plugin/notes-server/notes.html +351 -97
  39. data/files/reveal.js/plugin/notes/notes.html +321 -182
  40. data/files/reveal.js/plugin/notes/notes.js +89 -45
  41. data/files/reveal.js/plugin/print-pdf/print-pdf.js +24 -20
  42. data/files/reveal.js/plugin/zoom-js/zoom.js +64 -56
  43. data/files/reveal.js/test/examples/barebones.html +2 -2
  44. data/files/reveal.js/test/examples/embedded-media.html +2 -2
  45. data/files/reveal.js/test/examples/math.html +2 -2
  46. data/files/reveal.js/test/examples/slide-backgrounds.html +29 -7
  47. data/files/reveal.js/test/test-markdown-element-attributes.html +6 -6
  48. data/files/reveal.js/test/test-markdown-slide-attributes.html +7 -7
  49. data/files/reveal.js/test/test-markdown.html +4 -4
  50. data/files/reveal.js/test/test-pdf.html +83 -0
  51. data/files/reveal.js/test/test-pdf.js +15 -0
  52. data/files/reveal.js/test/test.html +5 -4
  53. data/files/reveal.js/test/test.js +143 -9
  54. data/lib/reveal-ck/builders/reveal_js_files.rb +2 -2
  55. data/lib/reveal-ck/markdown.rb +12 -0
  56. data/lib/reveal-ck/markdown/post_processor.rb +110 -0
  57. data/lib/reveal-ck/markdown/pre_processor.rb +104 -0
  58. data/lib/reveal-ck/markdown/slide_markdown.rb +2 -20
  59. data/lib/reveal-ck/markdown/slide_markdown_template.rb +4 -1
  60. data/lib/reveal-ck/tilt/config.rb +3 -3
  61. data/lib/reveal-ck/version.rb +1 -1
  62. data/spec/lib/reveal-ck/builders/reveal_js_files_spec.rb +1 -1
  63. data/spec/lib/reveal-ck/builders/slides_builder_spec.rb +1 -1
  64. data/spec/lib/reveal-ck/builders/user_files_spec.rb +1 -1
  65. data/spec/lib/reveal-ck/markdown/post_processor_spec.rb +311 -0
  66. data/spec/lib/reveal-ck/markdown/pre_processor_spec.rb +301 -0
  67. data/spec/lib/reveal-ck/markdown/slide_markdown_spec.rb +1 -69
  68. metadata +15 -7
  69. data/files/reveal.js/css/reveal.min.css +0 -7
  70. data/files/reveal.js/js/reveal.min.js +0 -9
  71. data/files/reveal.js/plugin/postmessage/example.html +0 -39
  72. data/files/reveal.js/plugin/postmessage/postmessage.js +0 -42
@@ -3,8 +3,6 @@
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
 
6
- <meta name="viewport" content="width=1150">
7
-
8
6
  <title>reveal.js - Slide Notes</title>
9
7
 
10
8
  <style>
@@ -12,130 +10,386 @@
12
10
  font-family: Helvetica;
13
11
  }
14
12
 
15
- #notes {
16
- font-size: 24px;
17
- width: 640px;
18
- margin-top: 5px;
19
- clear: left;
13
+ #current-slide,
14
+ #upcoming-slide,
15
+ #speaker-controls {
16
+ padding: 6px;
17
+ box-sizing: border-box;
18
+ -moz-box-sizing: border-box;
20
19
  }
21
20
 
22
- #wrap-current-slide {
23
- width: 640px;
24
- height: 512px;
25
- float: left;
26
- overflow: hidden;
21
+ #current-slide iframe,
22
+ #upcoming-slide iframe {
23
+ width: 100%;
24
+ height: 100%;
25
+ border: 1px solid #ddd;
27
26
  }
28
27
 
29
- #current-slide {
30
- width: 1280px;
31
- height: 1024px;
32
- border: none;
33
-
34
- -webkit-transform-origin: 0 0;
35
- -moz-transform-origin: 0 0;
36
- -ms-transform-origin: 0 0;
37
- -o-transform-origin: 0 0;
38
- transform-origin: 0 0;
39
-
40
- -webkit-transform: scale(0.5);
41
- -moz-transform: scale(0.5);
42
- -ms-transform: scale(0.5);
43
- -o-transform: scale(0.5);
44
- transform: scale(0.5);
45
- }
46
-
47
- #wrap-next-slide {
48
- width: 448px;
49
- height: 358px;
50
- float: left;
51
- margin: 0 0 0 10px;
52
- overflow: hidden;
53
- }
54
-
55
- #next-slide {
56
- width: 1280px;
57
- height: 1024px;
58
- border: none;
59
-
60
- -webkit-transform-origin: 0 0;
61
- -moz-transform-origin: 0 0;
62
- -ms-transform-origin: 0 0;
63
- -o-transform-origin: 0 0;
64
- transform-origin: 0 0;
65
-
66
- -webkit-transform: scale(0.35);
67
- -moz-transform: scale(0.35);
68
- -ms-transform: scale(0.35);
69
- -o-transform: scale(0.35);
70
- transform: scale(0.35);
71
- }
72
-
73
- .slides {
74
- position: relative;
75
- margin-bottom: 10px;
76
- border: 1px solid black;
77
- border-radius: 2px;
78
- background: rgb(28, 30, 32);
79
- }
80
-
81
- .slides span {
28
+ #current-slide .label,
29
+ #upcoming-slide .label {
82
30
  position: absolute;
83
- top: 3px;
84
- left: 3px;
31
+ top: 10px;
32
+ left: 10px;
85
33
  font-weight: bold;
86
34
  font-size: 14px;
35
+ z-index: 2;
87
36
  color: rgba( 255, 255, 255, 0.9 );
88
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
+
89
149
  </style>
90
150
  </head>
91
151
 
92
152
  <body>
93
153
 
94
- <div id="wrap-current-slide" class="slides">
95
- <iframe src="/?receiver" width="1280" height="1024" id="current-slide"></iframe>
96
- </div>
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>
97
167
 
98
- <div id="wrap-next-slide" class="slides">
99
- <iframe src="/?receiver" width="640" height="512" id="next-slide"></iframe>
100
- <span>UPCOMING:</span>
168
+ <div class="speaker-controls-notes hidden">
169
+ <h4 class="label">Notes</h4>
170
+ <div class="value"></div>
171
+ </div>
101
172
  </div>
102
- <div id="notes"></div>
103
173
 
104
174
  <script src="/socket.io/socket.io.js"></script>
105
175
  <script src="/plugin/markdown/marked.js"></script>
106
176
 
107
177
  <script>
108
- var socketId = '{{socketId}}';
109
- var socket = io.connect(window.location.origin);
110
- var notes = document.getElementById('notes');
111
- var currentSlide = document.getElementById('current-slide');
112
- var nextSlide = document.getElementById('next-slide');
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 ) {
113
210
 
114
- socket.on('slidedata', function(data) {
115
- // ignore data from sockets that aren't ours
116
- if (data.socketId !== socketId) { return; }
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' }), '*' );
117
248
 
118
- if (data.markdown) {
119
- notes.innerHTML = marked(data.notes);
120
249
  }
121
- else {
122
- notes.innerHTML = data.notes;
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
+
123
265
  }
124
266
 
125
- currentSlide.contentWindow.Reveal.slide(data.indexh, data.indexv);
126
- nextSlide.contentWindow.Reveal.slide(data.nextindexh, data.nextindexv);
127
- });
128
- socket.on('fragmentdata', function(data) {
129
- // ignore data from sockets that aren't ours
130
- if (data.socketId !== socketId) { return; }
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 );
131
295
 
132
- if (data.fragment === 'next') {
133
- currentSlide.contentWindow.Reveal.nextFragment();
134
296
  }
135
- else if (data.fragment === 'previous') {
136
- currentSlide.contentWindow.Reveal.prevFragment();
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
+
137
306
  }
138
- });
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
+ })();
139
393
  </script>
140
394
 
141
395
  </body>