reveal-ck 0.1.2 → 0.1.3
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 +8 -8
- data/README.md +13 -0
- data/bin/reveal-ck +23 -8
- data/lib/reveal-ck.rb +6 -0
- data/lib/reveal-ck/build_task.rb +14 -0
- data/lib/reveal-ck/builder.rb +21 -0
- data/lib/reveal-ck/config.rb +43 -0
- data/lib/reveal-ck/file_slicer.rb +19 -17
- data/lib/reveal-ck/file_splicer.rb +30 -28
- data/lib/reveal-ck/file_string_replacer.rb +17 -0
- data/lib/reveal-ck/haml_processor.rb +17 -15
- data/lib/reveal-ck/presentation_builder.rb +69 -0
- data/lib/reveal-ck/slide_builder.rb +66 -0
- data/lib/reveal-ck/version.rb +1 -1
- data/rakelib/cucumber.rake +14 -1
- data/reveal.js/Gruntfile.js +132 -0
- data/reveal.js/LICENSE +1 -1
- data/reveal.js/README.md +362 -50
- data/reveal.js/css/print/paper.css +14 -14
- data/reveal.js/css/print/pdf.css +60 -30
- data/reveal.js/css/reveal.css +444 -149
- data/reveal.js/css/reveal.min.css +2 -2
- data/reveal.js/css/theme/README.md +8 -10
- data/reveal.js/css/theme/beige.css +24 -45
- data/reveal.js/css/theme/default.css +24 -45
- data/reveal.js/css/theme/moon.css +142 -0
- data/reveal.js/css/theme/night.css +24 -44
- data/reveal.js/css/theme/serif.css +27 -45
- data/reveal.js/css/theme/simple.css +25 -45
- data/reveal.js/css/theme/sky.css +26 -43
- data/reveal.js/css/theme/solarized.css +142 -0
- data/reveal.js/css/theme/source/beige.scss +2 -2
- data/reveal.js/css/theme/source/default.scss +2 -2
- data/reveal.js/css/theme/source/moon.scss +68 -0
- data/reveal.js/css/theme/source/night.scss +4 -4
- data/reveal.js/css/theme/source/serif.scss +8 -6
- data/reveal.js/css/theme/source/simple.scss +5 -5
- data/reveal.js/css/theme/source/sky.scss +9 -4
- data/reveal.js/css/theme/source/solarized.scss +74 -0
- data/reveal.js/css/theme/template/settings.scss +2 -2
- data/reveal.js/examples/assets/image1.png +0 -0
- data/reveal.js/examples/assets/image2.png +0 -0
- data/reveal.js/examples/barebones.html +42 -0
- data/reveal.js/examples/embedded-media.html +49 -0
- data/reveal.js/examples/slide-backgrounds.html +101 -0
- data/reveal.js/index.html +63 -56
- data/reveal.js/js/reveal.js +997 -216
- data/reveal.js/js/reveal.min.js +3 -3
- data/reveal.js/package.json +43 -29
- data/reveal.js/plugin/highlight/highlight.js +28 -6
- data/reveal.js/plugin/markdown/example.html +97 -0
- data/reveal.js/plugin/markdown/example.md +29 -0
- data/reveal.js/plugin/markdown/markdown.js +164 -11
- data/reveal.js/plugin/markdown/marked.js +37 -0
- data/reveal.js/plugin/multiplex/client.js +13 -0
- data/reveal.js/plugin/multiplex/index.js +56 -0
- data/reveal.js/plugin/multiplex/master.js +50 -0
- data/reveal.js/plugin/notes-server/index.js +1 -0
- data/reveal.js/plugin/notes-server/notes.html +8 -5
- data/reveal.js/plugin/notes/notes.html +133 -44
- data/reveal.js/plugin/notes/notes.js +3 -1
- data/reveal.js/plugin/print-pdf/print-pdf.js +8 -3
- data/reveal.js/plugin/remotes/remotes.js +13 -4
- data/reveal.js/plugin/search/search.js +196 -0
- data/reveal.js/plugin/zoom-js/zoom.js +26 -21
- data/spec/data/config/config.toml +6 -0
- data/spec/data/string_replacer/after_replace +4 -0
- data/spec/data/string_replacer/before_replace +4 -0
- data/spec/lib/reveal-ck/config_spec.rb +50 -0
- data/spec/lib/reveal-ck/file_slicer_spec.rb +29 -27
- data/spec/lib/reveal-ck/file_splicer_spec.rb +28 -26
- data/spec/lib/reveal-ck/file_string_replacer_spec.rb +32 -0
- data/spec/lib/reveal-ck/haml_processor_spec.rb +28 -26
- metadata +82 -27
- data/rakelib/presentation.rake +0 -41
- data/rakelib/reveal.rake +0 -15
- data/reveal.js/css/shaders/tile-flip.fs +0 -64
- data/reveal.js/css/shaders/tile-flip.vs +0 -141
- data/reveal.js/grunt.js +0 -84
- data/reveal.js/plugin/markdown/showdown.js +0 -62
data/reveal.js/js/reveal.js
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
* http://lab.hakim.se/reveal-js
|
4
4
|
* MIT licensed
|
5
5
|
*
|
6
|
-
* Copyright (C)
|
6
|
+
* Copyright (C) 2013 Hakim El Hattab, http://hakim.se
|
7
7
|
*/
|
8
8
|
var Reveal = (function(){
|
9
9
|
|
@@ -16,6 +16,19 @@ var Reveal = (function(){
|
|
16
16
|
|
17
17
|
// Configurations defaults, can be overridden at initialization time
|
18
18
|
config = {
|
19
|
+
|
20
|
+
// The "normal" size of the presentation, aspect ratio will be preserved
|
21
|
+
// when the presentation is scaled to fit different resolutions
|
22
|
+
width: 960,
|
23
|
+
height: 700,
|
24
|
+
|
25
|
+
// Factor of the display size that should remain empty around the content
|
26
|
+
margin: 0.1,
|
27
|
+
|
28
|
+
// Bounds for smallest/largest possible scale to apply to content
|
29
|
+
minScale: 0.2,
|
30
|
+
maxScale: 1.0,
|
31
|
+
|
19
32
|
// Display controls in the bottom right corner
|
20
33
|
controls: true,
|
21
34
|
|
@@ -31,7 +44,7 @@ var Reveal = (function(){
|
|
31
44
|
// Enable the slide overview mode
|
32
45
|
overview: true,
|
33
46
|
|
34
|
-
// Vertical
|
47
|
+
// Vertical centring of slides
|
35
48
|
center: true,
|
36
49
|
|
37
50
|
// Enables touch navigation on devices with touch input
|
@@ -43,6 +56,9 @@ var Reveal = (function(){
|
|
43
56
|
// Change the presentation direction to be RTL
|
44
57
|
rtl: false,
|
45
58
|
|
59
|
+
// Turns fragments on and off globally
|
60
|
+
fragments: true,
|
61
|
+
|
46
62
|
// Number of milliseconds between automatically proceeding to the
|
47
63
|
// next slide, disabled when set to 0, this value can be overwritten
|
48
64
|
// by using a data-autoslide attribute on your slides
|
@@ -54,21 +70,29 @@ var Reveal = (function(){
|
|
54
70
|
// Apply a 3D roll to links on hover
|
55
71
|
rollingLinks: true,
|
56
72
|
|
73
|
+
// Opens links in an iframe preview overlay
|
74
|
+
previewLinks: false,
|
75
|
+
|
57
76
|
// Theme (see /css/theme)
|
58
77
|
theme: null,
|
59
78
|
|
60
79
|
// Transition style
|
61
80
|
transition: 'default', // default/cube/page/concave/zoom/linear/fade/none
|
62
81
|
|
82
|
+
// Transition speed
|
83
|
+
transitionSpeed: 'default', // default/fast/slow
|
84
|
+
|
85
|
+
// Transition style for full page slide backgrounds
|
86
|
+
backgroundTransition: 'default', // default/linear
|
87
|
+
|
63
88
|
// Script dependencies to load
|
64
89
|
dependencies: []
|
65
90
|
},
|
66
91
|
|
67
|
-
//
|
68
|
-
|
69
|
-
autoSlide = config.autoSlide,
|
92
|
+
// The current auto-slide duration
|
93
|
+
autoSlide = 0,
|
70
94
|
|
71
|
-
// The horizontal and
|
95
|
+
// The horizontal and vertical index of the currently active slide
|
72
96
|
indexh = 0,
|
73
97
|
indexv = 0,
|
74
98
|
|
@@ -81,6 +105,9 @@ var Reveal = (function(){
|
|
81
105
|
// all current slides.
|
82
106
|
state = [],
|
83
107
|
|
108
|
+
// The current scale of the presentation (see width/height config)
|
109
|
+
scale = 1,
|
110
|
+
|
84
111
|
// Cached references to DOM elements
|
85
112
|
dom = {},
|
86
113
|
|
@@ -99,7 +126,7 @@ var Reveal = (function(){
|
|
99
126
|
'transform' in document.body.style,
|
100
127
|
|
101
128
|
// Throttles mouse wheel navigation
|
102
|
-
|
129
|
+
lastMouseWheelStep = 0,
|
103
130
|
|
104
131
|
// An interval used to automatically move on to the next slide
|
105
132
|
autoSlideTimeout = 0,
|
@@ -113,6 +140,9 @@ var Reveal = (function(){
|
|
113
140
|
// A delay used to deactivate the overview mode
|
114
141
|
deactivateOverviewTimeout = 0,
|
115
142
|
|
143
|
+
// Flags if the interaction event listeners are bound
|
144
|
+
eventsAreBound = false,
|
145
|
+
|
116
146
|
// Holds information about the currently ongoing touch input
|
117
147
|
touch = {
|
118
148
|
startX: 0,
|
@@ -128,7 +158,7 @@ var Reveal = (function(){
|
|
128
158
|
*/
|
129
159
|
function initialize( options ) {
|
130
160
|
|
131
|
-
if(
|
161
|
+
if( !supports2DTransforms && !supports3DTransforms ) {
|
132
162
|
document.body.setAttribute( 'class', 'no-transforms' );
|
133
163
|
|
134
164
|
// If the browser doesn't support core features we won't be
|
@@ -162,8 +192,15 @@ var Reveal = (function(){
|
|
162
192
|
dom.wrapper = document.querySelector( '.reveal' );
|
163
193
|
dom.slides = document.querySelector( '.reveal .slides' );
|
164
194
|
|
195
|
+
// Background element
|
196
|
+
if( !document.querySelector( '.reveal .backgrounds' ) ) {
|
197
|
+
dom.background = document.createElement( 'div' );
|
198
|
+
dom.background.classList.add( 'backgrounds' );
|
199
|
+
dom.wrapper.appendChild( dom.background );
|
200
|
+
}
|
201
|
+
|
165
202
|
// Progress bar
|
166
|
-
if( !dom.wrapper.querySelector( '.progress' )
|
203
|
+
if( !dom.wrapper.querySelector( '.progress' ) ) {
|
167
204
|
var progressElement = document.createElement( 'div' );
|
168
205
|
progressElement.classList.add( 'progress' );
|
169
206
|
progressElement.innerHTML = '<span></span>';
|
@@ -171,7 +208,7 @@ var Reveal = (function(){
|
|
171
208
|
}
|
172
209
|
|
173
210
|
// Arrow controls
|
174
|
-
if( !dom.wrapper.querySelector( '.controls' )
|
211
|
+
if( !dom.wrapper.querySelector( '.controls' ) ) {
|
175
212
|
var controlsElement = document.createElement( 'aside' );
|
176
213
|
controlsElement.classList.add( 'controls' );
|
177
214
|
controlsElement.innerHTML = '<div class="navigate-left"></div>' +
|
@@ -181,11 +218,11 @@ var Reveal = (function(){
|
|
181
218
|
dom.wrapper.appendChild( controlsElement );
|
182
219
|
}
|
183
220
|
|
184
|
-
//
|
221
|
+
// State background element [DEPRECATED]
|
185
222
|
if( !dom.wrapper.querySelector( '.state-background' ) ) {
|
186
|
-
var
|
187
|
-
|
188
|
-
dom.wrapper.appendChild(
|
223
|
+
var stateBackgroundElement = document.createElement( 'div' );
|
224
|
+
stateBackgroundElement.classList.add( 'state-background' );
|
225
|
+
dom.wrapper.appendChild( stateBackgroundElement );
|
189
226
|
}
|
190
227
|
|
191
228
|
// Overlay graphic which is displayed during the paused mode
|
@@ -213,16 +250,96 @@ var Reveal = (function(){
|
|
213
250
|
|
214
251
|
}
|
215
252
|
|
253
|
+
/**
|
254
|
+
* Creates the slide background elements and appends them
|
255
|
+
* to the background container. One element is created per
|
256
|
+
* slide no matter if the given slide has visible background.
|
257
|
+
*/
|
258
|
+
function createBackgrounds() {
|
259
|
+
|
260
|
+
if( isPrintingPDF() ) {
|
261
|
+
document.body.classList.add( 'print-pdf' );
|
262
|
+
}
|
263
|
+
|
264
|
+
// Clear prior backgrounds
|
265
|
+
dom.background.innerHTML = '';
|
266
|
+
dom.background.classList.add( 'no-transition' );
|
267
|
+
|
268
|
+
// Helper method for creating a background element for the
|
269
|
+
// given slide
|
270
|
+
function _createBackground( slide, container ) {
|
271
|
+
|
272
|
+
var data = {
|
273
|
+
background: slide.getAttribute( 'data-background' ),
|
274
|
+
backgroundSize: slide.getAttribute( 'data-background-size' ),
|
275
|
+
backgroundImage: slide.getAttribute( 'data-background-image' ),
|
276
|
+
backgroundColor: slide.getAttribute( 'data-background-color' ),
|
277
|
+
backgroundRepeat: slide.getAttribute( 'data-background-repeat' ),
|
278
|
+
backgroundPosition: slide.getAttribute( 'data-background-position' ),
|
279
|
+
backgroundTransition: slide.getAttribute( 'data-background-transition' )
|
280
|
+
};
|
281
|
+
|
282
|
+
var element = document.createElement( 'div' );
|
283
|
+
element.className = 'slide-background';
|
284
|
+
|
285
|
+
if( data.background ) {
|
286
|
+
// Auto-wrap image urls in url(...)
|
287
|
+
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) {
|
288
|
+
element.style.backgroundImage = 'url('+ data.background +')';
|
289
|
+
}
|
290
|
+
else {
|
291
|
+
element.style.background = data.background;
|
292
|
+
}
|
293
|
+
}
|
294
|
+
|
295
|
+
// Additional and optional background properties
|
296
|
+
if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
|
297
|
+
if( data.backgroundImage ) element.style.backgroundImage = 'url("' + data.backgroundImage + '")';
|
298
|
+
if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
|
299
|
+
if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat;
|
300
|
+
if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition;
|
301
|
+
if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );
|
302
|
+
|
303
|
+
container.appendChild( element );
|
304
|
+
|
305
|
+
return element;
|
306
|
+
|
307
|
+
}
|
308
|
+
|
309
|
+
// Iterate over all horizontal slides
|
310
|
+
toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( slideh ) {
|
311
|
+
|
312
|
+
var backgroundStack;
|
313
|
+
|
314
|
+
if( isPrintingPDF() ) {
|
315
|
+
backgroundStack = _createBackground( slideh, slideh );
|
316
|
+
}
|
317
|
+
else {
|
318
|
+
backgroundStack = _createBackground( slideh, dom.background );
|
319
|
+
}
|
320
|
+
|
321
|
+
// Iterate over all vertical slides
|
322
|
+
toArray( slideh.querySelectorAll( 'section' ) ).forEach( function( slidev ) {
|
323
|
+
|
324
|
+
if( isPrintingPDF() ) {
|
325
|
+
_createBackground( slidev, slidev );
|
326
|
+
}
|
327
|
+
else {
|
328
|
+
_createBackground( slidev, backgroundStack );
|
329
|
+
}
|
330
|
+
|
331
|
+
} );
|
332
|
+
|
333
|
+
} );
|
334
|
+
|
335
|
+
}
|
336
|
+
|
216
337
|
/**
|
217
338
|
* Hides the address bar if we're on a mobile device.
|
218
339
|
*/
|
219
340
|
function hideAddressBar() {
|
220
341
|
|
221
|
-
if( navigator.userAgent
|
222
|
-
// Give the page some scrollable overflow
|
223
|
-
document.documentElement.style.overflow = 'scroll';
|
224
|
-
document.body.style.height = '120%';
|
225
|
-
|
342
|
+
if( /iphone|ipod|android/gi.test( navigator.userAgent ) && !/crios/gi.test( navigator.userAgent ) ) {
|
226
343
|
// Events that should trigger the address bar to hide
|
227
344
|
window.addEventListener( 'load', removeAddressBar, false );
|
228
345
|
window.addEventListener( 'orientationchange', removeAddressBar, false );
|
@@ -261,7 +378,7 @@ var Reveal = (function(){
|
|
261
378
|
}
|
262
379
|
}
|
263
380
|
|
264
|
-
// Called once synchronous
|
381
|
+
// Called once synchronous scripts finish loading
|
265
382
|
function proceed() {
|
266
383
|
if( scriptsAsync.length ) {
|
267
384
|
// Load asynchronous scripts
|
@@ -292,22 +409,12 @@ var Reveal = (function(){
|
|
292
409
|
// Make sure we've got all the DOM elements we need
|
293
410
|
setupDOM();
|
294
411
|
|
295
|
-
// Subscribe to input
|
296
|
-
addEventListeners();
|
297
|
-
|
298
412
|
// Updates the presentation to match the current configuration values
|
299
413
|
configure();
|
300
414
|
|
301
|
-
// Force an initial layout, will thereafter be invoked as the window
|
302
|
-
// is resized
|
303
|
-
layout();
|
304
|
-
|
305
415
|
// Read the initial hash
|
306
416
|
readURL();
|
307
417
|
|
308
|
-
// Start auto-sliding if it's enabled
|
309
|
-
cueAutoSlide();
|
310
|
-
|
311
418
|
// Notify listeners that the presentation is ready but use a 1ms
|
312
419
|
// timeout to ensure it's not fired synchronously after #initialize()
|
313
420
|
setTimeout( function() {
|
@@ -321,42 +428,71 @@ var Reveal = (function(){
|
|
321
428
|
}
|
322
429
|
|
323
430
|
/**
|
324
|
-
* Applies the configuration settings from the config
|
431
|
+
* Applies the configuration settings from the config
|
432
|
+
* object. May be called multiple times.
|
325
433
|
*/
|
326
|
-
function configure() {
|
434
|
+
function configure( options ) {
|
327
435
|
|
328
|
-
|
329
|
-
config.transition = 'linear';
|
330
|
-
}
|
436
|
+
dom.wrapper.classList.remove( config.transition );
|
331
437
|
|
332
|
-
|
333
|
-
|
334
|
-
|
438
|
+
// New config options may be passed when this method
|
439
|
+
// is invoked through the API after initialization
|
440
|
+
if( typeof options === 'object' ) extend( config, options );
|
335
441
|
|
336
|
-
|
337
|
-
|
442
|
+
// Force linear transition based on browser capabilities
|
443
|
+
if( supports3DTransforms === false ) config.transition = 'linear';
|
444
|
+
|
445
|
+
dom.wrapper.classList.add( config.transition );
|
446
|
+
|
447
|
+
dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
|
448
|
+
dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
|
449
|
+
|
450
|
+
if( dom.controls ) {
|
451
|
+
dom.controls.style.display = ( config.controls && dom.controls ) ? 'block' : 'none';
|
338
452
|
}
|
339
453
|
|
340
|
-
if(
|
341
|
-
dom.
|
454
|
+
if( dom.progress ) {
|
455
|
+
dom.progress.style.display = ( config.progress && dom.progress ) ? 'block' : 'none';
|
342
456
|
}
|
343
457
|
|
344
458
|
if( config.rtl ) {
|
345
459
|
dom.wrapper.classList.add( 'rtl' );
|
346
460
|
}
|
461
|
+
else {
|
462
|
+
dom.wrapper.classList.remove( 'rtl' );
|
463
|
+
}
|
347
464
|
|
348
465
|
if( config.center ) {
|
349
466
|
dom.wrapper.classList.add( 'center' );
|
350
467
|
}
|
468
|
+
else {
|
469
|
+
dom.wrapper.classList.remove( 'center' );
|
470
|
+
}
|
351
471
|
|
352
472
|
if( config.mouseWheel ) {
|
353
473
|
document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
|
354
474
|
document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
|
355
475
|
}
|
476
|
+
else {
|
477
|
+
document.removeEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
|
478
|
+
document.removeEventListener( 'mousewheel', onDocumentMouseScroll, false );
|
479
|
+
}
|
356
480
|
|
357
|
-
// 3D links
|
481
|
+
// Rolling 3D links
|
358
482
|
if( config.rollingLinks ) {
|
359
|
-
|
483
|
+
enableRollingLinks();
|
484
|
+
}
|
485
|
+
else {
|
486
|
+
disableRollingLinks();
|
487
|
+
}
|
488
|
+
|
489
|
+
// Iframe link previews
|
490
|
+
if( config.previewLinks ) {
|
491
|
+
enablePreviewLinks();
|
492
|
+
}
|
493
|
+
else {
|
494
|
+
disablePreviewLinks();
|
495
|
+
enablePreviewLinks( '[data-preview-link]' );
|
360
496
|
}
|
361
497
|
|
362
498
|
// Load the theme in the config, if it's not already loaded
|
@@ -371,6 +507,8 @@ var Reveal = (function(){
|
|
371
507
|
}
|
372
508
|
}
|
373
509
|
|
510
|
+
sync();
|
511
|
+
|
374
512
|
}
|
375
513
|
|
376
514
|
/**
|
@@ -378,13 +516,22 @@ var Reveal = (function(){
|
|
378
516
|
*/
|
379
517
|
function addEventListeners() {
|
380
518
|
|
519
|
+
eventsAreBound = true;
|
520
|
+
|
381
521
|
window.addEventListener( 'hashchange', onWindowHashChange, false );
|
382
522
|
window.addEventListener( 'resize', onWindowResize, false );
|
383
523
|
|
384
524
|
if( config.touch ) {
|
385
|
-
|
386
|
-
|
387
|
-
|
525
|
+
dom.wrapper.addEventListener( 'touchstart', onTouchStart, false );
|
526
|
+
dom.wrapper.addEventListener( 'touchmove', onTouchMove, false );
|
527
|
+
dom.wrapper.addEventListener( 'touchend', onTouchEnd, false );
|
528
|
+
|
529
|
+
// Support pointer-style touch interaction as well
|
530
|
+
if( window.navigator.msPointerEnabled ) {
|
531
|
+
dom.wrapper.addEventListener( 'MSPointerDown', onPointerDown, false );
|
532
|
+
dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false );
|
533
|
+
dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false );
|
534
|
+
}
|
388
535
|
}
|
389
536
|
|
390
537
|
if( config.keyboard ) {
|
@@ -392,17 +539,18 @@ var Reveal = (function(){
|
|
392
539
|
}
|
393
540
|
|
394
541
|
if ( config.progress && dom.progress ) {
|
395
|
-
dom.progress.addEventListener( 'click',
|
542
|
+
dom.progress.addEventListener( 'click', onProgressClicked, false );
|
396
543
|
}
|
397
544
|
|
398
545
|
if ( config.controls && dom.controls ) {
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
546
|
+
[ 'touchstart', 'click' ].forEach( function( eventName ) {
|
547
|
+
dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } );
|
548
|
+
dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } );
|
549
|
+
dom.controlsUp.forEach( function( el ) { el.addEventListener( eventName, onNavigateUpClicked, false ); } );
|
550
|
+
dom.controlsDown.forEach( function( el ) { el.addEventListener( eventName, onNavigateDownClicked, false ); } );
|
551
|
+
dom.controlsPrev.forEach( function( el ) { el.addEventListener( eventName, onNavigatePrevClicked, false ); } );
|
552
|
+
dom.controlsNext.forEach( function( el ) { el.addEventListener( eventName, onNavigateNextClicked, false ); } );
|
553
|
+
} );
|
406
554
|
}
|
407
555
|
|
408
556
|
}
|
@@ -412,28 +560,35 @@ var Reveal = (function(){
|
|
412
560
|
*/
|
413
561
|
function removeEventListeners() {
|
414
562
|
|
563
|
+
eventsAreBound = false;
|
564
|
+
|
415
565
|
document.removeEventListener( 'keydown', onDocumentKeyDown, false );
|
416
566
|
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
417
567
|
window.removeEventListener( 'resize', onWindowResize, false );
|
418
568
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
569
|
+
dom.wrapper.removeEventListener( 'touchstart', onTouchStart, false );
|
570
|
+
dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false );
|
571
|
+
dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false );
|
572
|
+
|
573
|
+
if( window.navigator.msPointerEnabled ) {
|
574
|
+
dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false );
|
575
|
+
dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false );
|
576
|
+
dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false );
|
423
577
|
}
|
424
578
|
|
425
579
|
if ( config.progress && dom.progress ) {
|
426
|
-
dom.progress.removeEventListener( 'click',
|
580
|
+
dom.progress.removeEventListener( 'click', onProgressClicked, false );
|
427
581
|
}
|
428
582
|
|
429
583
|
if ( config.controls && dom.controls ) {
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
584
|
+
[ 'touchstart', 'click' ].forEach( function( eventName ) {
|
585
|
+
dom.controlsLeft.forEach( function( el ) { el.removeEventListener( eventName, onNavigateLeftClicked, false ); } );
|
586
|
+
dom.controlsRight.forEach( function( el ) { el.removeEventListener( eventName, onNavigateRightClicked, false ); } );
|
587
|
+
dom.controlsUp.forEach( function( el ) { el.removeEventListener( eventName, onNavigateUpClicked, false ); } );
|
588
|
+
dom.controlsDown.forEach( function( el ) { el.removeEventListener( eventName, onNavigateDownClicked, false ); } );
|
589
|
+
dom.controlsPrev.forEach( function( el ) { el.removeEventListener( eventName, onNavigatePrevClicked, false ); } );
|
590
|
+
dom.controlsNext.forEach( function( el ) { el.removeEventListener( eventName, onNavigateNextClicked, false ); } );
|
591
|
+
} );
|
437
592
|
}
|
438
593
|
|
439
594
|
}
|
@@ -476,18 +631,46 @@ var Reveal = (function(){
|
|
476
631
|
}
|
477
632
|
|
478
633
|
/**
|
479
|
-
*
|
480
|
-
*
|
481
|
-
*
|
482
|
-
* @param {Function} delegate The method to call
|
483
|
-
* after the wrapper has been executed
|
634
|
+
* Retrieves the height of the given element by looking
|
635
|
+
* at the position and height of its immediate children.
|
484
636
|
*/
|
485
|
-
function
|
637
|
+
function getAbsoluteHeight( element ) {
|
486
638
|
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
639
|
+
var height = 0;
|
640
|
+
|
641
|
+
if( element ) {
|
642
|
+
var absoluteChildren = 0;
|
643
|
+
|
644
|
+
toArray( element.childNodes ).forEach( function( child ) {
|
645
|
+
|
646
|
+
if( typeof child.offsetTop === 'number' && child.style ) {
|
647
|
+
// Count # of abs children
|
648
|
+
if( child.style.position === 'absolute' ) {
|
649
|
+
absoluteChildren += 1;
|
650
|
+
}
|
651
|
+
|
652
|
+
height = Math.max( height, child.offsetTop + child.offsetHeight );
|
653
|
+
}
|
654
|
+
|
655
|
+
} );
|
656
|
+
|
657
|
+
// If there are no absolute children, use offsetHeight
|
658
|
+
if( absoluteChildren === 0 ) {
|
659
|
+
height = element.offsetHeight;
|
660
|
+
}
|
661
|
+
|
662
|
+
}
|
663
|
+
|
664
|
+
return height;
|
665
|
+
|
666
|
+
}
|
667
|
+
|
668
|
+
/**
|
669
|
+
* Checks if this instance is being used to print a PDF.
|
670
|
+
*/
|
671
|
+
function isPrintingPDF() {
|
672
|
+
|
673
|
+
return ( /print-pdf/gi ).test( window.location.search );
|
491
674
|
|
492
675
|
}
|
493
676
|
|
@@ -497,9 +680,18 @@ var Reveal = (function(){
|
|
497
680
|
*/
|
498
681
|
function removeAddressBar() {
|
499
682
|
|
683
|
+
if( window.orientation === 0 ) {
|
684
|
+
document.documentElement.style.overflow = 'scroll';
|
685
|
+
document.body.style.height = '120%';
|
686
|
+
}
|
687
|
+
else {
|
688
|
+
document.documentElement.style.overflow = '';
|
689
|
+
document.body.style.height = '100%';
|
690
|
+
}
|
691
|
+
|
500
692
|
setTimeout( function() {
|
501
693
|
window.scrollTo( 0, 1 );
|
502
|
-
},
|
694
|
+
}, 10 );
|
503
695
|
|
504
696
|
}
|
505
697
|
|
@@ -519,42 +711,222 @@ var Reveal = (function(){
|
|
519
711
|
/**
|
520
712
|
* Wrap all links in 3D goodness.
|
521
713
|
*/
|
522
|
-
function
|
714
|
+
function enableRollingLinks() {
|
523
715
|
|
524
716
|
if( supports3DTransforms && !( 'msPerspective' in document.body.style ) ) {
|
525
|
-
var
|
717
|
+
var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' );
|
526
718
|
|
527
|
-
for( var i = 0, len =
|
528
|
-
var
|
719
|
+
for( var i = 0, len = anchors.length; i < len; i++ ) {
|
720
|
+
var anchor = anchors[i];
|
529
721
|
|
530
|
-
if(
|
722
|
+
if( anchor.textContent && !anchor.querySelector( '*' ) && ( !anchor.className || !anchor.classList.contains( anchor, 'roll' ) ) ) {
|
531
723
|
var span = document.createElement('span');
|
532
|
-
span.setAttribute('data-title',
|
533
|
-
span.innerHTML =
|
724
|
+
span.setAttribute('data-title', anchor.text);
|
725
|
+
span.innerHTML = anchor.innerHTML;
|
534
726
|
|
535
|
-
|
536
|
-
|
537
|
-
|
727
|
+
anchor.classList.add( 'roll' );
|
728
|
+
anchor.innerHTML = '';
|
729
|
+
anchor.appendChild(span);
|
538
730
|
}
|
539
731
|
}
|
540
732
|
}
|
541
733
|
|
542
734
|
}
|
543
735
|
|
736
|
+
/**
|
737
|
+
* Unwrap all 3D links.
|
738
|
+
*/
|
739
|
+
function disableRollingLinks() {
|
740
|
+
|
741
|
+
var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a.roll' );
|
742
|
+
|
743
|
+
for( var i = 0, len = anchors.length; i < len; i++ ) {
|
744
|
+
var anchor = anchors[i];
|
745
|
+
var span = anchor.querySelector( 'span' );
|
746
|
+
|
747
|
+
if( span ) {
|
748
|
+
anchor.classList.remove( 'roll' );
|
749
|
+
anchor.innerHTML = span.innerHTML;
|
750
|
+
}
|
751
|
+
}
|
752
|
+
|
753
|
+
}
|
754
|
+
|
755
|
+
/**
|
756
|
+
* Bind preview frame links.
|
757
|
+
*/
|
758
|
+
function enablePreviewLinks( selector ) {
|
759
|
+
|
760
|
+
var anchors = toArray( document.querySelectorAll( selector ? selector : 'a' ) );
|
761
|
+
|
762
|
+
anchors.forEach( function( element ) {
|
763
|
+
if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {
|
764
|
+
element.addEventListener( 'click', onPreviewLinkClicked, false );
|
765
|
+
}
|
766
|
+
} );
|
767
|
+
|
768
|
+
}
|
769
|
+
|
770
|
+
/**
|
771
|
+
* Unbind preview frame links.
|
772
|
+
*/
|
773
|
+
function disablePreviewLinks() {
|
774
|
+
|
775
|
+
var anchors = toArray( document.querySelectorAll( 'a' ) );
|
776
|
+
|
777
|
+
anchors.forEach( function( element ) {
|
778
|
+
if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {
|
779
|
+
element.removeEventListener( 'click', onPreviewLinkClicked, false );
|
780
|
+
}
|
781
|
+
} );
|
782
|
+
|
783
|
+
}
|
784
|
+
|
785
|
+
/**
|
786
|
+
* Opens a preview window for the target URL.
|
787
|
+
*/
|
788
|
+
function openPreview( url ) {
|
789
|
+
|
790
|
+
closePreview();
|
791
|
+
|
792
|
+
dom.preview = document.createElement( 'div' );
|
793
|
+
dom.preview.classList.add( 'preview-link-overlay' );
|
794
|
+
dom.wrapper.appendChild( dom.preview );
|
795
|
+
|
796
|
+
dom.preview.innerHTML = [
|
797
|
+
'<header>',
|
798
|
+
'<a class="close" href="#"><span class="icon"></span></a>',
|
799
|
+
'<a class="external" href="'+ url +'" target="_blank"><span class="icon"></span></a>',
|
800
|
+
'</header>',
|
801
|
+
'<div class="spinner"></div>',
|
802
|
+
'<div class="viewport">',
|
803
|
+
'<iframe src="'+ url +'"></iframe>',
|
804
|
+
'</div>'
|
805
|
+
].join('');
|
806
|
+
|
807
|
+
dom.preview.querySelector( 'iframe' ).addEventListener( 'load', function( event ) {
|
808
|
+
dom.preview.classList.add( 'loaded' );
|
809
|
+
}, false );
|
810
|
+
|
811
|
+
dom.preview.querySelector( '.close' ).addEventListener( 'click', function( event ) {
|
812
|
+
closePreview();
|
813
|
+
event.preventDefault();
|
814
|
+
}, false );
|
815
|
+
|
816
|
+
dom.preview.querySelector( '.external' ).addEventListener( 'click', function( event ) {
|
817
|
+
closePreview();
|
818
|
+
}, false );
|
819
|
+
|
820
|
+
setTimeout( function() {
|
821
|
+
dom.preview.classList.add( 'visible' );
|
822
|
+
}, 1 );
|
823
|
+
|
824
|
+
}
|
825
|
+
|
826
|
+
/**
|
827
|
+
* Closes the iframe preview window.
|
828
|
+
*/
|
829
|
+
function closePreview() {
|
830
|
+
|
831
|
+
if( dom.preview ) {
|
832
|
+
dom.preview.setAttribute( 'src', '' );
|
833
|
+
dom.preview.parentNode.removeChild( dom.preview );
|
834
|
+
dom.preview = null;
|
835
|
+
}
|
836
|
+
|
837
|
+
}
|
838
|
+
|
839
|
+
/**
|
840
|
+
* Return a sorted fragments list, ordered by an increasing
|
841
|
+
* "data-fragment-index" attribute.
|
842
|
+
*
|
843
|
+
* Fragments will be revealed in the order that they are returned by
|
844
|
+
* this function, so you can use the index attributes to control the
|
845
|
+
* order of fragment appearance.
|
846
|
+
*
|
847
|
+
* To maintain a sensible default fragment order, fragments are presumed
|
848
|
+
* to be passed in document order. This function adds a "fragment-index"
|
849
|
+
* attribute to each node if such an attribute is not already present,
|
850
|
+
* and sets that attribute to an integer value which is the position of
|
851
|
+
* the fragment within the fragments list.
|
852
|
+
*/
|
853
|
+
function sortFragments( fragments ) {
|
854
|
+
|
855
|
+
var a = toArray( fragments );
|
856
|
+
|
857
|
+
a.forEach( function( el, idx ) {
|
858
|
+
if( !el.hasAttribute( 'data-fragment-index' ) ) {
|
859
|
+
el.setAttribute( 'data-fragment-index', idx );
|
860
|
+
}
|
861
|
+
} );
|
862
|
+
|
863
|
+
a.sort( function( l, r ) {
|
864
|
+
return l.getAttribute( 'data-fragment-index' ) - r.getAttribute( 'data-fragment-index');
|
865
|
+
} );
|
866
|
+
|
867
|
+
return a;
|
868
|
+
|
869
|
+
}
|
870
|
+
|
544
871
|
/**
|
545
872
|
* Applies JavaScript-controlled layout rules to the
|
546
873
|
* presentation.
|
547
874
|
*/
|
548
875
|
function layout() {
|
549
876
|
|
550
|
-
if(
|
877
|
+
if( dom.wrapper && !isPrintingPDF() ) {
|
878
|
+
|
879
|
+
// Available space to scale within
|
880
|
+
var availableWidth = dom.wrapper.offsetWidth,
|
881
|
+
availableHeight = dom.wrapper.offsetHeight;
|
882
|
+
|
883
|
+
// Reduce available space by margin
|
884
|
+
availableWidth -= ( availableHeight * config.margin );
|
885
|
+
availableHeight -= ( availableHeight * config.margin );
|
886
|
+
|
887
|
+
// Dimensions of the content
|
888
|
+
var slideWidth = config.width,
|
889
|
+
slideHeight = config.height;
|
890
|
+
|
891
|
+
// Slide width may be a percentage of available width
|
892
|
+
if( typeof slideWidth === 'string' && /%$/.test( slideWidth ) ) {
|
893
|
+
slideWidth = parseInt( slideWidth, 10 ) / 100 * availableWidth;
|
894
|
+
}
|
895
|
+
|
896
|
+
// Slide height may be a percentage of available height
|
897
|
+
if( typeof slideHeight === 'string' && /%$/.test( slideHeight ) ) {
|
898
|
+
slideHeight = parseInt( slideHeight, 10 ) / 100 * availableHeight;
|
899
|
+
}
|
900
|
+
|
901
|
+
dom.slides.style.width = slideWidth + 'px';
|
902
|
+
dom.slides.style.height = slideHeight + 'px';
|
903
|
+
|
904
|
+
// Determine scale of content to fit within available space
|
905
|
+
scale = Math.min( availableWidth / slideWidth, availableHeight / slideHeight );
|
906
|
+
|
907
|
+
// Respect max/min scale settings
|
908
|
+
scale = Math.max( scale, config.minScale );
|
909
|
+
scale = Math.min( scale, config.maxScale );
|
910
|
+
|
911
|
+
// Prefer applying scale via zoom since Chrome blurs scaled content
|
912
|
+
// with nested transforms
|
913
|
+
if( typeof dom.slides.style.zoom !== 'undefined' && !navigator.userAgent.match( /(iphone|ipod|ipad|android)/gi ) ) {
|
914
|
+
dom.slides.style.zoom = scale;
|
915
|
+
}
|
916
|
+
// Apply scale transform as a fallback
|
917
|
+
else {
|
918
|
+
var transform = 'translate(-50%, -50%) scale('+ scale +') translate(50%, 50%)';
|
919
|
+
|
920
|
+
dom.slides.style.WebkitTransform = transform;
|
921
|
+
dom.slides.style.MozTransform = transform;
|
922
|
+
dom.slides.style.msTransform = transform;
|
923
|
+
dom.slides.style.OTransform = transform;
|
924
|
+
dom.slides.style.transform = transform;
|
925
|
+
}
|
551
926
|
|
552
927
|
// Select all slides, vertical and horizontal
|
553
928
|
var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) );
|
554
929
|
|
555
|
-
// Determine the minimum top offset for slides
|
556
|
-
var minTop = -dom.wrapper.offsetHeight / 2;
|
557
|
-
|
558
930
|
for( var i = 0, len = slides.length; i < len; i++ ) {
|
559
931
|
var slide = slides[ i ];
|
560
932
|
|
@@ -563,16 +935,24 @@ var Reveal = (function(){
|
|
563
935
|
continue;
|
564
936
|
}
|
565
937
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
slide.
|
938
|
+
if( config.center ) {
|
939
|
+
// Vertical stacks are not centred since their section
|
940
|
+
// children will be
|
941
|
+
if( slide.classList.contains( 'stack' ) ) {
|
942
|
+
slide.style.top = 0;
|
943
|
+
}
|
944
|
+
else {
|
945
|
+
slide.style.top = Math.max( - ( getAbsoluteHeight( slide ) / 2 ) - 20, -slideHeight / 2 ) + 'px';
|
946
|
+
}
|
570
947
|
}
|
571
948
|
else {
|
572
|
-
slide.style.top =
|
949
|
+
slide.style.top = '';
|
573
950
|
}
|
951
|
+
|
574
952
|
}
|
575
953
|
|
954
|
+
updateProgress();
|
955
|
+
|
576
956
|
}
|
577
957
|
|
578
958
|
}
|
@@ -587,14 +967,14 @@ var Reveal = (function(){
|
|
587
967
|
*/
|
588
968
|
function setPreviousVerticalIndex( stack, v ) {
|
589
969
|
|
590
|
-
if( stack ) {
|
970
|
+
if( typeof stack === 'object' && typeof stack.setAttribute === 'function' ) {
|
591
971
|
stack.setAttribute( 'data-previous-indexv', v || 0 );
|
592
972
|
}
|
593
973
|
|
594
974
|
}
|
595
975
|
|
596
976
|
/**
|
597
|
-
* Retrieves the vertical index which was stored using
|
977
|
+
* Retrieves the vertical index which was stored using
|
598
978
|
* #setPreviousVerticalIndex() or 0 if no previous index
|
599
979
|
* exists.
|
600
980
|
*
|
@@ -602,8 +982,11 @@ var Reveal = (function(){
|
|
602
982
|
*/
|
603
983
|
function getPreviousVerticalIndex( stack ) {
|
604
984
|
|
605
|
-
if( stack && stack.classList.contains( 'stack' ) ) {
|
606
|
-
|
985
|
+
if( typeof stack === 'object' && typeof stack.setAttribute === 'function' && stack.classList.contains( 'stack' ) ) {
|
986
|
+
// Prefer manually defined start-indexv
|
987
|
+
var attributeName = stack.hasAttribute( 'data-start-indexv' ) ? 'data-start-indexv' : 'data-previous-indexv';
|
988
|
+
|
989
|
+
return parseInt( stack.getAttribute( attributeName ) || 0, 10 );
|
607
990
|
}
|
608
991
|
|
609
992
|
return 0;
|
@@ -622,6 +1005,9 @@ var Reveal = (function(){
|
|
622
1005
|
// Only proceed if enabled in config
|
623
1006
|
if( config.overview ) {
|
624
1007
|
|
1008
|
+
// Don't auto-slide while in overview mode
|
1009
|
+
cancelAutoSlide();
|
1010
|
+
|
625
1011
|
var wasActive = dom.wrapper.classList.contains( 'overview' );
|
626
1012
|
|
627
1013
|
dom.wrapper.classList.add( 'overview' );
|
@@ -639,7 +1025,8 @@ var Reveal = (function(){
|
|
639
1025
|
|
640
1026
|
for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) {
|
641
1027
|
var hslide = horizontalSlides[i],
|
642
|
-
|
1028
|
+
hoffset = config.rtl ? -105 : 105,
|
1029
|
+
htransform = 'translateZ(-2500px) translate(' + ( ( i - indexh ) * hoffset ) + '%, 0%)';
|
643
1030
|
|
644
1031
|
hslide.setAttribute( 'data-index-h', i );
|
645
1032
|
hslide.style.display = 'block';
|
@@ -741,6 +1128,8 @@ var Reveal = (function(){
|
|
741
1128
|
|
742
1129
|
slide( indexh, indexv );
|
743
1130
|
|
1131
|
+
cueAutoSlide();
|
1132
|
+
|
744
1133
|
// Notify observers of the overview hiding
|
745
1134
|
dispatchEvent( 'overviewhidden', {
|
746
1135
|
'indexh': indexh,
|
@@ -764,7 +1153,7 @@ var Reveal = (function(){
|
|
764
1153
|
override ? activateOverview() : deactivateOverview();
|
765
1154
|
}
|
766
1155
|
else {
|
767
|
-
|
1156
|
+
isOverview() ? deactivateOverview() : activateOverview();
|
768
1157
|
}
|
769
1158
|
|
770
1159
|
}
|
@@ -775,12 +1164,28 @@ var Reveal = (function(){
|
|
775
1164
|
* @return {Boolean} true if the overview is active,
|
776
1165
|
* false otherwise
|
777
1166
|
*/
|
778
|
-
function
|
1167
|
+
function isOverview() {
|
779
1168
|
|
780
1169
|
return dom.wrapper.classList.contains( 'overview' );
|
781
1170
|
|
782
1171
|
}
|
783
1172
|
|
1173
|
+
/**
|
1174
|
+
* Checks if the current or specified slide is vertical
|
1175
|
+
* (nested within another slide).
|
1176
|
+
*
|
1177
|
+
* @param {HTMLElement} slide [optional] The slide to check
|
1178
|
+
* orientation of
|
1179
|
+
*/
|
1180
|
+
function isVerticalSlide( slide ) {
|
1181
|
+
|
1182
|
+
// Prefer slide argument, otherwise use current slide
|
1183
|
+
slide = slide ? slide : currentSlide;
|
1184
|
+
|
1185
|
+
return slide && !!slide.parentNode.nodeName.match( /section/i );
|
1186
|
+
|
1187
|
+
}
|
1188
|
+
|
784
1189
|
/**
|
785
1190
|
* Handling the fullscreen functionality via the fullscreen API
|
786
1191
|
*
|
@@ -793,6 +1198,7 @@ var Reveal = (function(){
|
|
793
1198
|
|
794
1199
|
// Check which implementation is available
|
795
1200
|
var requestMethod = element.requestFullScreen ||
|
1201
|
+
element.webkitRequestFullscreen ||
|
796
1202
|
element.webkitRequestFullScreen ||
|
797
1203
|
element.mozRequestFullScreen ||
|
798
1204
|
element.msRequestFullScreen;
|
@@ -809,8 +1215,15 @@ var Reveal = (function(){
|
|
809
1215
|
*/
|
810
1216
|
function pause() {
|
811
1217
|
|
1218
|
+
var wasPaused = dom.wrapper.classList.contains( 'paused' );
|
1219
|
+
|
1220
|
+
cancelAutoSlide();
|
812
1221
|
dom.wrapper.classList.add( 'paused' );
|
813
1222
|
|
1223
|
+
if( wasPaused === false ) {
|
1224
|
+
dispatchEvent( 'paused' );
|
1225
|
+
}
|
1226
|
+
|
814
1227
|
}
|
815
1228
|
|
816
1229
|
/**
|
@@ -818,8 +1231,15 @@ var Reveal = (function(){
|
|
818
1231
|
*/
|
819
1232
|
function resume() {
|
820
1233
|
|
1234
|
+
var wasPaused = dom.wrapper.classList.contains( 'paused' );
|
821
1235
|
dom.wrapper.classList.remove( 'paused' );
|
822
1236
|
|
1237
|
+
cueAutoSlide();
|
1238
|
+
|
1239
|
+
if( wasPaused ) {
|
1240
|
+
dispatchEvent( 'resumed' );
|
1241
|
+
}
|
1242
|
+
|
823
1243
|
}
|
824
1244
|
|
825
1245
|
/**
|
@@ -854,8 +1274,9 @@ var Reveal = (function(){
|
|
854
1274
|
* @param {int} v Vertical index of the target slide
|
855
1275
|
* @param {int} f Optional index of a fragment within the
|
856
1276
|
* target slide to activate
|
1277
|
+
* @param {int} o Optional origin for use in multimaster environments
|
857
1278
|
*/
|
858
|
-
function slide( h, v, f ) {
|
1279
|
+
function slide( h, v, f, o ) {
|
859
1280
|
|
860
1281
|
// Remember where we were at before
|
861
1282
|
previousSlide = currentSlide;
|
@@ -913,7 +1334,7 @@ var Reveal = (function(){
|
|
913
1334
|
}
|
914
1335
|
|
915
1336
|
// If the overview is active, re-activate it to update positions
|
916
|
-
if(
|
1337
|
+
if( isOverview() ) {
|
917
1338
|
activateOverview();
|
918
1339
|
}
|
919
1340
|
|
@@ -932,7 +1353,7 @@ var Reveal = (function(){
|
|
932
1353
|
|
933
1354
|
// Show fragment, if specified
|
934
1355
|
if( typeof f !== 'undefined' ) {
|
935
|
-
var fragments = currentSlide.querySelectorAll( '.fragment' );
|
1356
|
+
var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
|
936
1357
|
|
937
1358
|
toArray( fragments ).forEach( function( fragment, indexf ) {
|
938
1359
|
if( indexf < f ) {
|
@@ -945,12 +1366,14 @@ var Reveal = (function(){
|
|
945
1366
|
}
|
946
1367
|
|
947
1368
|
// Dispatch an event if the slide changed
|
948
|
-
|
1369
|
+
var slideChanged = ( indexh !== indexhBefore || indexv !== indexvBefore );
|
1370
|
+
if( slideChanged ) {
|
949
1371
|
dispatchEvent( 'slidechanged', {
|
950
1372
|
'indexh': indexh,
|
951
1373
|
'indexv': indexv,
|
952
1374
|
'previousSlide': previousSlide,
|
953
|
-
'currentSlide': currentSlide
|
1375
|
+
'currentSlide': currentSlide,
|
1376
|
+
'origin': o
|
954
1377
|
} );
|
955
1378
|
}
|
956
1379
|
else {
|
@@ -980,8 +1403,44 @@ var Reveal = (function(){
|
|
980
1403
|
}
|
981
1404
|
}
|
982
1405
|
|
1406
|
+
// Handle embedded content
|
1407
|
+
if( slideChanged ) {
|
1408
|
+
stopEmbeddedContent( previousSlide );
|
1409
|
+
startEmbeddedContent( currentSlide );
|
1410
|
+
}
|
1411
|
+
|
1412
|
+
updateControls();
|
1413
|
+
updateProgress();
|
1414
|
+
updateBackground();
|
1415
|
+
|
1416
|
+
}
|
1417
|
+
|
1418
|
+
/**
|
1419
|
+
* Syncs the presentation with the current DOM. Useful
|
1420
|
+
* when new slides or control elements are added or when
|
1421
|
+
* the configuration has changed.
|
1422
|
+
*/
|
1423
|
+
function sync() {
|
1424
|
+
|
1425
|
+
// Subscribe to input
|
1426
|
+
removeEventListeners();
|
1427
|
+
addEventListeners();
|
1428
|
+
|
1429
|
+
// Force a layout to make sure the current config is accounted for
|
1430
|
+
layout();
|
1431
|
+
|
1432
|
+
// Reflect the current autoSlide value
|
1433
|
+
autoSlide = config.autoSlide;
|
1434
|
+
|
1435
|
+
// Start auto-sliding if it's enabled
|
1436
|
+
cueAutoSlide();
|
1437
|
+
|
1438
|
+
// Re-create the slide backgrounds
|
1439
|
+
createBackgrounds();
|
1440
|
+
|
983
1441
|
updateControls();
|
984
1442
|
updateProgress();
|
1443
|
+
updateBackground();
|
985
1444
|
|
986
1445
|
}
|
987
1446
|
|
@@ -1024,7 +1483,7 @@ var Reveal = (function(){
|
|
1024
1483
|
|
1025
1484
|
// Optimization; hide all slides that are three or more steps
|
1026
1485
|
// away from the present slide
|
1027
|
-
if(
|
1486
|
+
if( isOverview() === false ) {
|
1028
1487
|
// The distance loops so that it measures 1 between the first
|
1029
1488
|
// and last slides
|
1030
1489
|
var distance = Math.abs( ( index - i ) % ( slidesLength - 3 ) ) || 0;
|
@@ -1032,27 +1491,33 @@ var Reveal = (function(){
|
|
1032
1491
|
element.style.display = distance > 3 ? 'none' : 'block';
|
1033
1492
|
}
|
1034
1493
|
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1494
|
+
var reverse = config.rtl && !isVerticalSlide( element );
|
1495
|
+
|
1496
|
+
element.classList.remove( 'past' );
|
1497
|
+
element.classList.remove( 'present' );
|
1498
|
+
element.classList.remove( 'future' );
|
1499
|
+
|
1500
|
+
// http://www.w3.org/html/wg/drafts/html/master/editing.html#the-hidden-attribute
|
1501
|
+
element.setAttribute( 'hidden', '' );
|
1038
1502
|
|
1039
1503
|
if( i < index ) {
|
1040
1504
|
// Any element previous to index is given the 'past' class
|
1041
|
-
|
1505
|
+
element.classList.add( reverse ? 'future' : 'past' );
|
1042
1506
|
}
|
1043
1507
|
else if( i > index ) {
|
1044
1508
|
// Any element subsequent to index is given the 'future' class
|
1045
|
-
|
1509
|
+
element.classList.add( reverse ? 'past' : 'future' );
|
1046
1510
|
}
|
1047
1511
|
|
1048
1512
|
// If this element contains vertical slides
|
1049
1513
|
if( element.querySelector( 'section' ) ) {
|
1050
|
-
|
1514
|
+
element.classList.add( 'stack' );
|
1051
1515
|
}
|
1052
1516
|
}
|
1053
1517
|
|
1054
1518
|
// Mark the current slide as present
|
1055
1519
|
slides[index].classList.add( 'present' );
|
1520
|
+
slides[index].removeAttribute( 'hidden' );
|
1056
1521
|
|
1057
1522
|
// If this slide has a state associated with it, add it
|
1058
1523
|
// onto the current state of the deck
|
@@ -1066,7 +1531,7 @@ var Reveal = (function(){
|
|
1066
1531
|
var slideAutoSlide = slides[index].getAttribute( 'data-autoslide' );
|
1067
1532
|
if( slideAutoSlide ) {
|
1068
1533
|
autoSlide = parseInt( slideAutoSlide, 10 );
|
1069
|
-
}
|
1534
|
+
}
|
1070
1535
|
else {
|
1071
1536
|
autoSlide = config.autoSlide;
|
1072
1537
|
}
|
@@ -1139,6 +1604,7 @@ var Reveal = (function(){
|
|
1139
1604
|
if ( config.controls && dom.controls ) {
|
1140
1605
|
|
1141
1606
|
var routes = availableRoutes();
|
1607
|
+
var fragments = availableFragments();
|
1142
1608
|
|
1143
1609
|
// Remove the 'enabled' class from all directions
|
1144
1610
|
dom.controlsLeft.concat( dom.controlsRight )
|
@@ -1147,6 +1613,7 @@ var Reveal = (function(){
|
|
1147
1613
|
.concat( dom.controlsPrev )
|
1148
1614
|
.concat( dom.controlsNext ).forEach( function( node ) {
|
1149
1615
|
node.classList.remove( 'enabled' );
|
1616
|
+
node.classList.remove( 'fragmented' );
|
1150
1617
|
} );
|
1151
1618
|
|
1152
1619
|
// Add the 'enabled' class to the available routes
|
@@ -1159,10 +1626,60 @@ var Reveal = (function(){
|
|
1159
1626
|
if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); } );
|
1160
1627
|
if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); } );
|
1161
1628
|
|
1629
|
+
// Highlight fragment directions
|
1630
|
+
if( currentSlide ) {
|
1631
|
+
|
1632
|
+
// Always apply fragment decorator to prev/next buttons
|
1633
|
+
if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
|
1634
|
+
if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
|
1635
|
+
|
1636
|
+
// Apply fragment decorators to directional buttons based on
|
1637
|
+
// what slide axis they are in
|
1638
|
+
if( isVerticalSlide( currentSlide ) ) {
|
1639
|
+
if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
|
1640
|
+
if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
|
1641
|
+
}
|
1642
|
+
else {
|
1643
|
+
if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
|
1644
|
+
if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
|
1645
|
+
}
|
1646
|
+
}
|
1647
|
+
|
1162
1648
|
}
|
1163
1649
|
|
1164
1650
|
}
|
1165
1651
|
|
1652
|
+
/**
|
1653
|
+
* Updates the background elements to reflect the current
|
1654
|
+
* slide.
|
1655
|
+
*/
|
1656
|
+
function updateBackground() {
|
1657
|
+
|
1658
|
+
// Update the classes of all backgrounds to match the
|
1659
|
+
// states of their slides (past/present/future)
|
1660
|
+
toArray( dom.background.childNodes ).forEach( function( backgroundh, h ) {
|
1661
|
+
|
1662
|
+
// Reverse past/future classes when in RTL mode
|
1663
|
+
var horizontalPast = config.rtl ? 'future' : 'past',
|
1664
|
+
horizontalFuture = config.rtl ? 'past' : 'future';
|
1665
|
+
|
1666
|
+
backgroundh.className = 'slide-background ' + ( h < indexh ? horizontalPast : h > indexh ? horizontalFuture : 'present' );
|
1667
|
+
|
1668
|
+
toArray( backgroundh.childNodes ).forEach( function( backgroundv, v ) {
|
1669
|
+
|
1670
|
+
backgroundv.className = 'slide-background ' + ( v < indexv ? 'past' : v > indexv ? 'future' : 'present' );
|
1671
|
+
|
1672
|
+
} );
|
1673
|
+
|
1674
|
+
} );
|
1675
|
+
|
1676
|
+
// Allow the first background to apply without transition
|
1677
|
+
setTimeout( function() {
|
1678
|
+
dom.background.classList.remove( 'no-transition' );
|
1679
|
+
}, 1 );
|
1680
|
+
|
1681
|
+
}
|
1682
|
+
|
1166
1683
|
/**
|
1167
1684
|
* Determine what available routes there are for navigation.
|
1168
1685
|
*
|
@@ -1173,13 +1690,93 @@ var Reveal = (function(){
|
|
1173
1690
|
var horizontalSlides = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
|
1174
1691
|
verticalSlides = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
|
1175
1692
|
|
1176
|
-
|
1177
|
-
left: indexh > 0,
|
1178
|
-
right: indexh < horizontalSlides.length - 1,
|
1693
|
+
var routes = {
|
1694
|
+
left: indexh > 0 || config.loop,
|
1695
|
+
right: indexh < horizontalSlides.length - 1 || config.loop,
|
1179
1696
|
up: indexv > 0,
|
1180
1697
|
down: indexv < verticalSlides.length - 1
|
1181
1698
|
};
|
1182
1699
|
|
1700
|
+
// reverse horizontal controls for rtl
|
1701
|
+
if( config.rtl ) {
|
1702
|
+
var left = routes.left;
|
1703
|
+
routes.left = routes.right;
|
1704
|
+
routes.right = left;
|
1705
|
+
}
|
1706
|
+
|
1707
|
+
return routes;
|
1708
|
+
|
1709
|
+
}
|
1710
|
+
|
1711
|
+
/**
|
1712
|
+
* Returns an object describing the available fragment
|
1713
|
+
* directions.
|
1714
|
+
*
|
1715
|
+
* @return {Object} two boolean properties: prev/next
|
1716
|
+
*/
|
1717
|
+
function availableFragments() {
|
1718
|
+
|
1719
|
+
if( currentSlide && config.fragments ) {
|
1720
|
+
var fragments = currentSlide.querySelectorAll( '.fragment' );
|
1721
|
+
var hiddenFragments = currentSlide.querySelectorAll( '.fragment:not(.visible)' );
|
1722
|
+
|
1723
|
+
return {
|
1724
|
+
prev: fragments.length - hiddenFragments.length > 0,
|
1725
|
+
next: !!hiddenFragments.length
|
1726
|
+
};
|
1727
|
+
}
|
1728
|
+
else {
|
1729
|
+
return { prev: false, next: false };
|
1730
|
+
}
|
1731
|
+
|
1732
|
+
}
|
1733
|
+
|
1734
|
+
/**
|
1735
|
+
* Start playback of any embedded content inside of
|
1736
|
+
* the targeted slide.
|
1737
|
+
*/
|
1738
|
+
function startEmbeddedContent( slide ) {
|
1739
|
+
|
1740
|
+
if( slide ) {
|
1741
|
+
// HTML5 media elements
|
1742
|
+
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
1743
|
+
if( el.hasAttribute( 'data-autoplay' ) ) {
|
1744
|
+
el.play();
|
1745
|
+
}
|
1746
|
+
} );
|
1747
|
+
|
1748
|
+
// YouTube embeds
|
1749
|
+
toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
|
1750
|
+
if( el.hasAttribute( 'data-autoplay' ) ) {
|
1751
|
+
el.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
|
1752
|
+
}
|
1753
|
+
});
|
1754
|
+
}
|
1755
|
+
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
/**
|
1759
|
+
* Stop playback of any embedded content inside of
|
1760
|
+
* the targeted slide.
|
1761
|
+
*/
|
1762
|
+
function stopEmbeddedContent( slide ) {
|
1763
|
+
|
1764
|
+
if( slide ) {
|
1765
|
+
// HTML5 media elements
|
1766
|
+
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
1767
|
+
if( !el.hasAttribute( 'data-ignore' ) ) {
|
1768
|
+
el.pause();
|
1769
|
+
}
|
1770
|
+
} );
|
1771
|
+
|
1772
|
+
// YouTube embeds
|
1773
|
+
toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
|
1774
|
+
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
1775
|
+
el.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
|
1776
|
+
}
|
1777
|
+
});
|
1778
|
+
}
|
1779
|
+
|
1183
1780
|
}
|
1184
1781
|
|
1185
1782
|
/**
|
@@ -1264,17 +1861,18 @@ var Reveal = (function(){
|
|
1264
1861
|
* index will be for this slide rather than the currently
|
1265
1862
|
* active one
|
1266
1863
|
*
|
1267
|
-
* @return {Object} { h: <int>, v: <int> }
|
1864
|
+
* @return {Object} { h: <int>, v: <int>, f: <int> }
|
1268
1865
|
*/
|
1269
1866
|
function getIndices( slide ) {
|
1270
1867
|
|
1271
1868
|
// By default, return the current indices
|
1272
1869
|
var h = indexh,
|
1273
|
-
v = indexv
|
1870
|
+
v = indexv,
|
1871
|
+
f;
|
1274
1872
|
|
1275
1873
|
// If a slide is specified, return the indices of that slide
|
1276
1874
|
if( slide ) {
|
1277
|
-
var isVertical =
|
1875
|
+
var isVertical = isVerticalSlide( slide );
|
1278
1876
|
var slideh = isVertical ? slide.parentNode : slide;
|
1279
1877
|
|
1280
1878
|
// Select all horizontal slides
|
@@ -1289,7 +1887,14 @@ var Reveal = (function(){
|
|
1289
1887
|
}
|
1290
1888
|
}
|
1291
1889
|
|
1292
|
-
|
1890
|
+
if( !slide && currentSlide ) {
|
1891
|
+
var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );
|
1892
|
+
if( visibleFragments.length ) {
|
1893
|
+
f = visibleFragments.length;
|
1894
|
+
}
|
1895
|
+
}
|
1896
|
+
|
1897
|
+
return { h: h, v: v, f: f };
|
1293
1898
|
|
1294
1899
|
}
|
1295
1900
|
|
@@ -1301,25 +1906,24 @@ var Reveal = (function(){
|
|
1301
1906
|
*/
|
1302
1907
|
function nextFragment() {
|
1303
1908
|
|
1304
|
-
|
1305
|
-
|
1306
|
-
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
|
1307
|
-
if( verticalFragments.length ) {
|
1308
|
-
verticalFragments[0].classList.add( 'visible' );
|
1909
|
+
if( currentSlide && config.fragments ) {
|
1910
|
+
var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment:not(.visible)' ) );
|
1309
1911
|
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1912
|
+
if( fragments.length ) {
|
1913
|
+
// Find the index of the next fragment
|
1914
|
+
var index = fragments[0].getAttribute( 'data-fragment-index' );
|
1915
|
+
|
1916
|
+
// Find all fragments with the same index
|
1917
|
+
fragments = currentSlide.querySelectorAll( '.fragment[data-fragment-index="'+ index +'"]' );
|
1918
|
+
|
1919
|
+
toArray( fragments ).forEach( function( element ) {
|
1920
|
+
element.classList.add( 'visible' );
|
1921
|
+
} );
|
1320
1922
|
|
1321
1923
|
// Notify subscribers of the change
|
1322
|
-
dispatchEvent( 'fragmentshown', { fragment:
|
1924
|
+
dispatchEvent( 'fragmentshown', { fragment: fragments[0], fragments: fragments } );
|
1925
|
+
|
1926
|
+
updateControls();
|
1323
1927
|
return true;
|
1324
1928
|
}
|
1325
1929
|
}
|
@@ -1336,25 +1940,24 @@ var Reveal = (function(){
|
|
1336
1940
|
*/
|
1337
1941
|
function previousFragment() {
|
1338
1942
|
|
1339
|
-
|
1340
|
-
|
1341
|
-
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' );
|
1342
|
-
if( verticalFragments.length ) {
|
1343
|
-
verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
|
1943
|
+
if( currentSlide && config.fragments ) {
|
1944
|
+
var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment.visible' ) );
|
1344
1945
|
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1946
|
+
if( fragments.length ) {
|
1947
|
+
// Find the index of the previous fragment
|
1948
|
+
var index = fragments[ fragments.length - 1 ].getAttribute( 'data-fragment-index' );
|
1949
|
+
|
1950
|
+
// Find all fragments with the same index
|
1951
|
+
fragments = currentSlide.querySelectorAll( '.fragment[data-fragment-index="'+ index +'"]' );
|
1952
|
+
|
1953
|
+
toArray( fragments ).forEach( function( f ) {
|
1954
|
+
f.classList.remove( 'visible' );
|
1955
|
+
} );
|
1355
1956
|
|
1356
1957
|
// Notify subscribers of the change
|
1357
|
-
dispatchEvent( 'fragmenthidden', { fragment:
|
1958
|
+
dispatchEvent( 'fragmenthidden', { fragment: fragments[0], fragments: fragments } );
|
1959
|
+
|
1960
|
+
updateControls();
|
1358
1961
|
return true;
|
1359
1962
|
}
|
1360
1963
|
}
|
@@ -1371,16 +1974,31 @@ var Reveal = (function(){
|
|
1371
1974
|
clearTimeout( autoSlideTimeout );
|
1372
1975
|
|
1373
1976
|
// Cue the next auto-slide if enabled
|
1374
|
-
if( autoSlide ) {
|
1977
|
+
if( autoSlide && !isPaused() && !isOverview() ) {
|
1375
1978
|
autoSlideTimeout = setTimeout( navigateNext, autoSlide );
|
1376
1979
|
}
|
1377
1980
|
|
1378
1981
|
}
|
1379
1982
|
|
1983
|
+
/**
|
1984
|
+
* Cancels any ongoing request to auto-slide.
|
1985
|
+
*/
|
1986
|
+
function cancelAutoSlide() {
|
1987
|
+
|
1988
|
+
clearTimeout( autoSlideTimeout );
|
1989
|
+
|
1990
|
+
}
|
1991
|
+
|
1380
1992
|
function navigateLeft() {
|
1381
1993
|
|
1382
|
-
//
|
1383
|
-
if(
|
1994
|
+
// Reverse for RTL
|
1995
|
+
if( config.rtl ) {
|
1996
|
+
if( ( isOverview() || nextFragment() === false ) && availableRoutes().left ) {
|
1997
|
+
slide( indexh + 1 );
|
1998
|
+
}
|
1999
|
+
}
|
2000
|
+
// Normal navigation
|
2001
|
+
else if( ( isOverview() || previousFragment() === false ) && availableRoutes().left ) {
|
1384
2002
|
slide( indexh - 1 );
|
1385
2003
|
}
|
1386
2004
|
|
@@ -1388,8 +2006,14 @@ var Reveal = (function(){
|
|
1388
2006
|
|
1389
2007
|
function navigateRight() {
|
1390
2008
|
|
1391
|
-
//
|
1392
|
-
if(
|
2009
|
+
// Reverse for RTL
|
2010
|
+
if( config.rtl ) {
|
2011
|
+
if( ( isOverview() || previousFragment() === false ) && availableRoutes().right ) {
|
2012
|
+
slide( indexh - 1 );
|
2013
|
+
}
|
2014
|
+
}
|
2015
|
+
// Normal navigation
|
2016
|
+
else if( ( isOverview() || nextFragment() === false ) && availableRoutes().right ) {
|
1393
2017
|
slide( indexh + 1 );
|
1394
2018
|
}
|
1395
2019
|
|
@@ -1398,7 +2022,7 @@ var Reveal = (function(){
|
|
1398
2022
|
function navigateUp() {
|
1399
2023
|
|
1400
2024
|
// Prioritize hiding fragments
|
1401
|
-
if(
|
2025
|
+
if( ( isOverview() || previousFragment() === false ) && availableRoutes().up ) {
|
1402
2026
|
slide( indexh, indexv - 1 );
|
1403
2027
|
}
|
1404
2028
|
|
@@ -1407,7 +2031,7 @@ var Reveal = (function(){
|
|
1407
2031
|
function navigateDown() {
|
1408
2032
|
|
1409
2033
|
// Prioritize revealing fragments
|
1410
|
-
if(
|
2034
|
+
if( ( isOverview() || nextFragment() === false ) && availableRoutes().down ) {
|
1411
2035
|
slide( indexh, indexv + 1 );
|
1412
2036
|
}
|
1413
2037
|
|
@@ -1431,9 +2055,9 @@ var Reveal = (function(){
|
|
1431
2055
|
var previousSlide = document.querySelector( HORIZONTAL_SLIDES_SELECTOR + '.past:nth-child(' + indexh + ')' );
|
1432
2056
|
|
1433
2057
|
if( previousSlide ) {
|
1434
|
-
|
1435
|
-
indexh
|
1436
|
-
slide();
|
2058
|
+
var v = ( previousSlide.querySelectorAll( 'section' ).length - 1 ) || undefined;
|
2059
|
+
var h = indexh - 1;
|
2060
|
+
slide( h, v );
|
1437
2061
|
}
|
1438
2062
|
}
|
1439
2063
|
}
|
@@ -1476,37 +2100,77 @@ var Reveal = (function(){
|
|
1476
2100
|
|
1477
2101
|
// Disregard the event if there's a focused element or a
|
1478
2102
|
// keyboard modifier key is present
|
1479
|
-
if
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
2103
|
+
if( hasFocus || (event.shiftKey && event.keyCode !== 32) || event.altKey || event.ctrlKey || event.metaKey ) return;
|
2104
|
+
|
2105
|
+
// While paused only allow "unpausing" keyboard events (b and .)
|
2106
|
+
if( isPaused() && [66,190,191].indexOf( event.keyCode ) === -1 ) {
|
2107
|
+
return false;
|
2108
|
+
}
|
2109
|
+
|
2110
|
+
var triggered = false;
|
2111
|
+
|
2112
|
+
// 1. User defined key bindings
|
2113
|
+
if( typeof config.keyboard === 'object' ) {
|
2114
|
+
|
2115
|
+
for( var key in config.keyboard ) {
|
2116
|
+
|
2117
|
+
// Check if this binding matches the pressed key
|
2118
|
+
if( parseInt( key, 10 ) === event.keyCode ) {
|
2119
|
+
|
2120
|
+
var value = config.keyboard[ key ];
|
2121
|
+
|
2122
|
+
// Calback function
|
2123
|
+
if( typeof value === 'function' ) {
|
2124
|
+
value.apply( null, [ event ] );
|
2125
|
+
}
|
2126
|
+
// String shortcuts to reveal.js API
|
2127
|
+
else if( typeof value === 'string' && typeof Reveal[ value ] === 'function' ) {
|
2128
|
+
Reveal[ value ].call();
|
2129
|
+
}
|
2130
|
+
|
2131
|
+
triggered = true;
|
2132
|
+
|
2133
|
+
}
|
2134
|
+
|
2135
|
+
}
|
2136
|
+
|
2137
|
+
}
|
2138
|
+
|
2139
|
+
// 2. System defined key bindings
|
2140
|
+
if( triggered === false ) {
|
2141
|
+
|
2142
|
+
// Assume true and try to prove false
|
2143
|
+
triggered = true;
|
2144
|
+
|
2145
|
+
switch( event.keyCode ) {
|
2146
|
+
// p, page up
|
2147
|
+
case 80: case 33: navigatePrev(); break;
|
2148
|
+
// n, page down
|
2149
|
+
case 78: case 34: navigateNext(); break;
|
2150
|
+
// h, left
|
2151
|
+
case 72: case 37: navigateLeft(); break;
|
2152
|
+
// l, right
|
2153
|
+
case 76: case 39: navigateRight(); break;
|
2154
|
+
// k, up
|
2155
|
+
case 75: case 38: navigateUp(); break;
|
2156
|
+
// j, down
|
2157
|
+
case 74: case 40: navigateDown(); break;
|
2158
|
+
// home
|
2159
|
+
case 36: slide( 0 ); break;
|
2160
|
+
// end
|
2161
|
+
case 35: slide( Number.MAX_VALUE ); break;
|
2162
|
+
// space
|
2163
|
+
case 32: isOverview() ? deactivateOverview() : event.shiftKey ? navigatePrev() : navigateNext(); break;
|
2164
|
+
// return
|
2165
|
+
case 13: isOverview() ? deactivateOverview() : triggered = false; break;
|
2166
|
+
// b, period, Logitech presenter tools "black screen" button
|
2167
|
+
case 66: case 190: case 191: togglePause(); break;
|
2168
|
+
// f
|
2169
|
+
case 70: enterFullscreen(); break;
|
2170
|
+
default:
|
2171
|
+
triggered = false;
|
2172
|
+
}
|
2173
|
+
|
1510
2174
|
}
|
1511
2175
|
|
1512
2176
|
// If the input resulted in a triggered action we should prevent
|
@@ -1527,10 +2191,10 @@ var Reveal = (function(){
|
|
1527
2191
|
}
|
1528
2192
|
|
1529
2193
|
/**
|
1530
|
-
* Handler for the
|
1531
|
-
*
|
2194
|
+
* Handler for the 'touchstart' event, enables support for
|
2195
|
+
* swipe and pinch gestures.
|
1532
2196
|
*/
|
1533
|
-
function
|
2197
|
+
function onTouchStart( event ) {
|
1534
2198
|
|
1535
2199
|
touch.startX = event.touches[0].clientX;
|
1536
2200
|
touch.startY = event.touches[0].clientY;
|
@@ -1551,9 +2215,9 @@ var Reveal = (function(){
|
|
1551
2215
|
}
|
1552
2216
|
|
1553
2217
|
/**
|
1554
|
-
* Handler for the
|
2218
|
+
* Handler for the 'touchmove' event.
|
1555
2219
|
*/
|
1556
|
-
function
|
2220
|
+
function onTouchMove( event ) {
|
1557
2221
|
|
1558
2222
|
// Each touch should only trigger one action
|
1559
2223
|
if( !touch.handled ) {
|
@@ -1625,23 +2289,60 @@ var Reveal = (function(){
|
|
1625
2289
|
}
|
1626
2290
|
|
1627
2291
|
/**
|
1628
|
-
* Handler for the
|
2292
|
+
* Handler for the 'touchend' event.
|
1629
2293
|
*/
|
1630
|
-
function
|
2294
|
+
function onTouchEnd( event ) {
|
1631
2295
|
|
1632
2296
|
touch.handled = false;
|
1633
2297
|
|
1634
2298
|
}
|
1635
2299
|
|
2300
|
+
/**
|
2301
|
+
* Convert pointer down to touch start.
|
2302
|
+
*/
|
2303
|
+
function onPointerDown( event ) {
|
2304
|
+
|
2305
|
+
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH ) {
|
2306
|
+
event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
|
2307
|
+
onTouchStart( event );
|
2308
|
+
}
|
2309
|
+
|
2310
|
+
}
|
2311
|
+
|
2312
|
+
/**
|
2313
|
+
* Convert pointer move to touch move.
|
2314
|
+
*/
|
2315
|
+
function onPointerMove( event ) {
|
2316
|
+
|
2317
|
+
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH ) {
|
2318
|
+
event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
|
2319
|
+
onTouchMove( event );
|
2320
|
+
}
|
2321
|
+
|
2322
|
+
}
|
2323
|
+
|
2324
|
+
/**
|
2325
|
+
* Convert pointer up to touch end.
|
2326
|
+
*/
|
2327
|
+
function onPointerUp( event ) {
|
2328
|
+
|
2329
|
+
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH ) {
|
2330
|
+
event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
|
2331
|
+
onTouchEnd( event );
|
2332
|
+
}
|
2333
|
+
|
2334
|
+
}
|
2335
|
+
|
1636
2336
|
/**
|
1637
2337
|
* Handles mouse wheel scrolling, throttled to avoid skipping
|
1638
2338
|
* multiple slides.
|
1639
2339
|
*/
|
1640
2340
|
function onDocumentMouseScroll( event ) {
|
1641
2341
|
|
1642
|
-
|
2342
|
+
if( Date.now() - lastMouseWheelStep > 600 ) {
|
2343
|
+
|
2344
|
+
lastMouseWheelStep = Date.now();
|
1643
2345
|
|
1644
|
-
mouseWheelTimeout = setTimeout( function() {
|
1645
2346
|
var delta = event.detail || -event.wheelDelta;
|
1646
2347
|
if( delta > 0 ) {
|
1647
2348
|
navigateNext();
|
@@ -1649,7 +2350,8 @@ var Reveal = (function(){
|
|
1649
2350
|
else {
|
1650
2351
|
navigatePrev();
|
1651
2352
|
}
|
1652
|
-
|
2353
|
+
|
2354
|
+
}
|
1653
2355
|
|
1654
2356
|
}
|
1655
2357
|
|
@@ -1659,7 +2361,9 @@ var Reveal = (function(){
|
|
1659
2361
|
*
|
1660
2362
|
* ( clickX / presentationWidth ) * numberOfSlides
|
1661
2363
|
*/
|
1662
|
-
function
|
2364
|
+
function onProgressClicked( event ) {
|
2365
|
+
|
2366
|
+
event.preventDefault();
|
1663
2367
|
|
1664
2368
|
var slidesTotal = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).length;
|
1665
2369
|
var slideIndex = Math.floor( ( event.clientX / dom.wrapper.offsetWidth ) * slidesTotal );
|
@@ -1668,6 +2372,16 @@ var Reveal = (function(){
|
|
1668
2372
|
|
1669
2373
|
}
|
1670
2374
|
|
2375
|
+
/**
|
2376
|
+
* Event handler for navigation control buttons.
|
2377
|
+
*/
|
2378
|
+
function onNavigateLeftClicked( event ) { event.preventDefault(); navigateLeft(); }
|
2379
|
+
function onNavigateRightClicked( event ) { event.preventDefault(); navigateRight(); }
|
2380
|
+
function onNavigateUpClicked( event ) { event.preventDefault(); navigateUp(); }
|
2381
|
+
function onNavigateDownClicked( event ) { event.preventDefault(); navigateDown(); }
|
2382
|
+
function onNavigatePrevClicked( event ) { event.preventDefault(); navigatePrev(); }
|
2383
|
+
function onNavigateNextClicked( event ) { event.preventDefault(); navigateNext(); }
|
2384
|
+
|
1671
2385
|
/**
|
1672
2386
|
* Handler for the window level 'hashchange' event.
|
1673
2387
|
*/
|
@@ -1693,27 +2407,45 @@ var Reveal = (function(){
|
|
1693
2407
|
|
1694
2408
|
// TODO There's a bug here where the event listeners are not
|
1695
2409
|
// removed after deactivating the overview.
|
1696
|
-
if(
|
2410
|
+
if( eventsAreBound && isOverview() ) {
|
1697
2411
|
event.preventDefault();
|
1698
2412
|
|
1699
|
-
deactivateOverview();
|
1700
|
-
|
1701
2413
|
var element = event.target;
|
1702
2414
|
|
1703
2415
|
while( element && !element.nodeName.match( /section/gi ) ) {
|
1704
2416
|
element = element.parentNode;
|
1705
2417
|
}
|
1706
2418
|
|
1707
|
-
if( element.
|
1708
|
-
|
1709
|
-
|
2419
|
+
if( element && !element.classList.contains( 'disabled' ) ) {
|
2420
|
+
|
2421
|
+
deactivateOverview();
|
2422
|
+
|
2423
|
+
if( element.nodeName.match( /section/gi ) ) {
|
2424
|
+
var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
|
2425
|
+
v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
|
2426
|
+
|
2427
|
+
slide( h, v );
|
2428
|
+
}
|
1710
2429
|
|
1711
|
-
slide( h, v );
|
1712
2430
|
}
|
1713
2431
|
}
|
1714
2432
|
|
1715
2433
|
}
|
1716
2434
|
|
2435
|
+
/**
|
2436
|
+
* Handles clicks on links that are set to preview in the
|
2437
|
+
* iframe overlay.
|
2438
|
+
*/
|
2439
|
+
function onPreviewLinkClicked( event ) {
|
2440
|
+
|
2441
|
+
var url = event.target.getAttribute( 'href' );
|
2442
|
+
if( url ) {
|
2443
|
+
openPreview( url );
|
2444
|
+
event.preventDefault();
|
2445
|
+
}
|
2446
|
+
|
2447
|
+
}
|
2448
|
+
|
1717
2449
|
|
1718
2450
|
// --------------------------------------------------------------------//
|
1719
2451
|
// ------------------------------- API --------------------------------//
|
@@ -1722,6 +2454,8 @@ var Reveal = (function(){
|
|
1722
2454
|
|
1723
2455
|
return {
|
1724
2456
|
initialize: initialize,
|
2457
|
+
configure: configure,
|
2458
|
+
sync: sync,
|
1725
2459
|
|
1726
2460
|
// Navigation methods
|
1727
2461
|
slide: slide,
|
@@ -1746,12 +2480,22 @@ var Reveal = (function(){
|
|
1746
2480
|
// Forces an update in slide layout
|
1747
2481
|
layout: layout,
|
1748
2482
|
|
2483
|
+
// Returns an object with the available routes as booleans (left/right/top/bottom)
|
2484
|
+
availableRoutes: availableRoutes,
|
2485
|
+
|
2486
|
+
// Returns an object with the available fragments as booleans (prev/next)
|
2487
|
+
availableFragments: availableFragments,
|
2488
|
+
|
1749
2489
|
// Toggles the overview mode on/off
|
1750
2490
|
toggleOverview: toggleOverview,
|
1751
2491
|
|
1752
2492
|
// Toggles the "black screen" mode on/off
|
1753
2493
|
togglePause: togglePause,
|
1754
2494
|
|
2495
|
+
// State checks
|
2496
|
+
isOverview: isOverview,
|
2497
|
+
isPaused: isPaused,
|
2498
|
+
|
1755
2499
|
// Adds or removes all internal event listeners (such as keyboard)
|
1756
2500
|
addEventListeners: addEventListeners,
|
1757
2501
|
removeEventListeners: removeEventListeners,
|
@@ -1759,6 +2503,18 @@ var Reveal = (function(){
|
|
1759
2503
|
// Returns the indices of the current, or specified, slide
|
1760
2504
|
getIndices: getIndices,
|
1761
2505
|
|
2506
|
+
// Returns the slide at the specified index, y is optional
|
2507
|
+
getSlide: function( x, y ) {
|
2508
|
+
var horizontalSlide = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR )[ x ];
|
2509
|
+
var verticalSlides = horizontalSlide && horizontalSlide.querySelectorAll( 'section' );
|
2510
|
+
|
2511
|
+
if( typeof y !== 'undefined' ) {
|
2512
|
+
return verticalSlides ? verticalSlides[ y ] : undefined;
|
2513
|
+
}
|
2514
|
+
|
2515
|
+
return horizontalSlide;
|
2516
|
+
},
|
2517
|
+
|
1762
2518
|
// Returns the previous slide element, may be null
|
1763
2519
|
getPreviousSlide: function() {
|
1764
2520
|
return previousSlide;
|
@@ -1769,6 +2525,16 @@ var Reveal = (function(){
|
|
1769
2525
|
return currentSlide;
|
1770
2526
|
},
|
1771
2527
|
|
2528
|
+
// Returns the current scale of the presentation content
|
2529
|
+
getScale: function() {
|
2530
|
+
return scale;
|
2531
|
+
},
|
2532
|
+
|
2533
|
+
// Returns the current configuration object
|
2534
|
+
getConfig: function() {
|
2535
|
+
return config;
|
2536
|
+
},
|
2537
|
+
|
1772
2538
|
// Helper method, retrieves query string as a key/value hash
|
1773
2539
|
getQueryHash: function() {
|
1774
2540
|
var query = {};
|
@@ -1780,6 +2546,21 @@ var Reveal = (function(){
|
|
1780
2546
|
return query;
|
1781
2547
|
},
|
1782
2548
|
|
2549
|
+
// Returns true if we're currently on the first slide
|
2550
|
+
isFirstSlide: function() {
|
2551
|
+
return document.querySelector( SLIDES_SELECTOR + '.past' ) == null ? true : false;
|
2552
|
+
},
|
2553
|
+
|
2554
|
+
// Returns true if we're currently on the last slide
|
2555
|
+
isLastSlide: function() {
|
2556
|
+
if( currentSlide && currentSlide.classList.contains( '.stack' ) ) {
|
2557
|
+
return currentSlide.querySelector( SLIDES_SELECTOR + '.future' ) == null ? true : false;
|
2558
|
+
}
|
2559
|
+
else {
|
2560
|
+
return document.querySelector( SLIDES_SELECTOR + '.future' ) == null ? true : false;
|
2561
|
+
}
|
2562
|
+
},
|
2563
|
+
|
1783
2564
|
// Forward event binding to the reveal DOM element
|
1784
2565
|
addEventListener: function( type, listener, useCapture ) {
|
1785
2566
|
if( 'addEventListener' in window ) {
|
@@ -1793,4 +2574,4 @@ var Reveal = (function(){
|
|
1793
2574
|
}
|
1794
2575
|
};
|
1795
2576
|
|
1796
|
-
})();
|
2577
|
+
})();
|