reveal-ck 0.1.8 → 0.2.0
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 +3 -11
- data/bin/reveal-ck +38 -3
- data/lib/reveal-ck.rb +2 -0
- data/lib/reveal-ck/markdown.rb +2 -0
- data/lib/reveal-ck/markdown/slide_markdown.rb +22 -0
- data/lib/reveal-ck/markdown/slide_markdown_template.rb +22 -0
- data/lib/reveal-ck/tilt/config.rb +2 -0
- data/lib/reveal-ck/version.rb +1 -1
- data/reveal.js/Gruntfile.js +4 -3
- data/reveal.js/README.md +135 -13
- data/reveal.js/css/print/pdf.css +1 -1
- data/reveal.js/css/reveal.css +242 -15
- data/reveal.js/css/reveal.min.css +1 -1
- data/reveal.js/css/theme/beige.css +7 -1
- data/reveal.js/css/theme/blood.css +175 -0
- data/reveal.js/css/theme/default.css +7 -1
- data/reveal.js/css/theme/moon.css +7 -1
- data/reveal.js/css/theme/night.css +7 -1
- data/reveal.js/css/theme/serif.css +7 -1
- data/reveal.js/css/theme/simple.css +7 -1
- data/reveal.js/css/theme/sky.css +7 -1
- data/reveal.js/css/theme/solarized.css +7 -1
- data/reveal.js/css/theme/source/blood.scss +91 -0
- data/reveal.js/css/theme/template/theme.scss +8 -1
- data/reveal.js/index.html +9 -4
- data/reveal.js/js/reveal.js +804 -199
- data/reveal.js/js/reveal.min.js +3 -2
- data/reveal.js/package.json +1 -1
- data/reveal.js/plugin/highlight/highlight.js +3 -2
- data/reveal.js/plugin/markdown/example.html +34 -3
- data/reveal.js/plugin/markdown/markdown.js +75 -3
- data/reveal.js/plugin/notes/notes.html +10 -6
- data/reveal.js/plugin/remotes/remotes.js +1 -1
- data/reveal.js/plugin/zoom-js/zoom.js +3 -1
- data/reveal.js/test/examples/barebones.html +0 -1
- data/reveal.js/test/examples/slide-backgrounds.html +22 -1
- data/reveal.js/test/test-markdown-element-attributes.html +134 -0
- data/reveal.js/test/test-markdown-element-attributes.js +46 -0
- data/reveal.js/test/test-markdown-slide-attributes.html +128 -0
- data/reveal.js/test/test-markdown-slide-attributes.js +47 -0
- data/reveal.js/test/test.html +26 -7
- data/reveal.js/test/test.js +95 -10
- data/spec/lib/reveal-ck/markdown/slide_markdown_spec.rb +76 -0
- data/spec/lib/reveal-ck/markdown/slide_markdown_template_spec.rb +29 -0
- data/spec/lib/reveal-ck/tilt/config_spec.rb +9 -0
- metadata +34 -4
@@ -27,7 +27,7 @@ body {
|
|
27
27
|
.reveal {
|
28
28
|
font-family: "Lato", sans-serif;
|
29
29
|
font-size: 36px;
|
30
|
-
font-weight:
|
30
|
+
font-weight: normal;
|
31
31
|
letter-spacing: -0.02em;
|
32
32
|
color: #eeeeee; }
|
33
33
|
|
@@ -140,3 +140,9 @@ body {
|
|
140
140
|
-ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
141
141
|
-o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
142
142
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
143
|
+
|
144
|
+
/*********************************************
|
145
|
+
* SLIDE NUMBER
|
146
|
+
*********************************************/
|
147
|
+
.reveal .slide-number {
|
148
|
+
color: #13daec; }
|
@@ -27,7 +27,7 @@ body {
|
|
27
27
|
.reveal {
|
28
28
|
font-family: "Lato", sans-serif;
|
29
29
|
font-size: 36px;
|
30
|
-
font-weight:
|
30
|
+
font-weight: normal;
|
31
31
|
letter-spacing: -0.02em;
|
32
32
|
color: #93a1a1; }
|
33
33
|
|
@@ -140,3 +140,9 @@ body {
|
|
140
140
|
-ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
141
141
|
-o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
142
142
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
143
|
+
|
144
|
+
/*********************************************
|
145
|
+
* SLIDE NUMBER
|
146
|
+
*********************************************/
|
147
|
+
.reveal .slide-number {
|
148
|
+
color: #268bd2; }
|
@@ -15,7 +15,7 @@ body {
|
|
15
15
|
.reveal {
|
16
16
|
font-family: "Open Sans", sans-serif;
|
17
17
|
font-size: 30px;
|
18
|
-
font-weight:
|
18
|
+
font-weight: normal;
|
19
19
|
letter-spacing: -0.02em;
|
20
20
|
color: #eeeeee; }
|
21
21
|
|
@@ -128,3 +128,9 @@ body {
|
|
128
128
|
-ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
129
129
|
-o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
130
130
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
131
|
+
|
132
|
+
/*********************************************
|
133
|
+
* SLIDE NUMBER
|
134
|
+
*********************************************/
|
135
|
+
.reveal .slide-number {
|
136
|
+
color: #e7ad52; }
|
@@ -17,7 +17,7 @@ body {
|
|
17
17
|
.reveal {
|
18
18
|
font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
|
19
19
|
font-size: 36px;
|
20
|
-
font-weight:
|
20
|
+
font-weight: normal;
|
21
21
|
letter-spacing: -0.02em;
|
22
22
|
color: black; }
|
23
23
|
|
@@ -130,3 +130,9 @@ body {
|
|
130
130
|
-ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
131
131
|
-o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
132
132
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
133
|
+
|
134
|
+
/*********************************************
|
135
|
+
* SLIDE NUMBER
|
136
|
+
*********************************************/
|
137
|
+
.reveal .slide-number {
|
138
|
+
color: #51483d; }
|
@@ -17,7 +17,7 @@ body {
|
|
17
17
|
.reveal {
|
18
18
|
font-family: "Lato", sans-serif;
|
19
19
|
font-size: 36px;
|
20
|
-
font-weight:
|
20
|
+
font-weight: normal;
|
21
21
|
letter-spacing: -0.02em;
|
22
22
|
color: black; }
|
23
23
|
|
@@ -130,3 +130,9 @@ body {
|
|
130
130
|
-ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
131
131
|
-o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
132
132
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
133
|
+
|
134
|
+
/*********************************************
|
135
|
+
* SLIDE NUMBER
|
136
|
+
*********************************************/
|
137
|
+
.reveal .slide-number {
|
138
|
+
color: darkblue; }
|
data/reveal.js/css/theme/sky.css
CHANGED
@@ -24,7 +24,7 @@ body {
|
|
24
24
|
.reveal {
|
25
25
|
font-family: "Open Sans", sans-serif;
|
26
26
|
font-size: 36px;
|
27
|
-
font-weight:
|
27
|
+
font-weight: normal;
|
28
28
|
letter-spacing: -0.02em;
|
29
29
|
color: #333333; }
|
30
30
|
|
@@ -137,3 +137,9 @@ body {
|
|
137
137
|
-ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
138
138
|
-o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
139
139
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
140
|
+
|
141
|
+
/*********************************************
|
142
|
+
* SLIDE NUMBER
|
143
|
+
*********************************************/
|
144
|
+
.reveal .slide-number {
|
145
|
+
color: #3b759e; }
|
@@ -27,7 +27,7 @@ body {
|
|
27
27
|
.reveal {
|
28
28
|
font-family: "Lato", sans-serif;
|
29
29
|
font-size: 36px;
|
30
|
-
font-weight:
|
30
|
+
font-weight: normal;
|
31
31
|
letter-spacing: -0.02em;
|
32
32
|
color: #657b83; }
|
33
33
|
|
@@ -140,3 +140,9 @@ body {
|
|
140
140
|
-ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
141
141
|
-o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
|
142
142
|
transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
|
143
|
+
|
144
|
+
/*********************************************
|
145
|
+
* SLIDE NUMBER
|
146
|
+
*********************************************/
|
147
|
+
.reveal .slide-number {
|
148
|
+
color: #268bd2; }
|
@@ -0,0 +1,91 @@
|
|
1
|
+
/**
|
2
|
+
* Blood theme for reveal.js
|
3
|
+
* Author: Walther http://github.com/Walther
|
4
|
+
*
|
5
|
+
* Designed to be used with highlight.js theme
|
6
|
+
* "monokai_sublime.css" available from
|
7
|
+
* https://github.com/isagalaev/highlight.js/
|
8
|
+
*
|
9
|
+
* For other themes, change $codeBackground accordingly.
|
10
|
+
*
|
11
|
+
*/
|
12
|
+
|
13
|
+
// Default mixins and settings -----------------
|
14
|
+
@import "../template/mixins";
|
15
|
+
@import "../template/settings";
|
16
|
+
// ---------------------------------------------
|
17
|
+
|
18
|
+
// Include theme-specific fonts
|
19
|
+
|
20
|
+
@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic);
|
21
|
+
|
22
|
+
// Colors used in the theme
|
23
|
+
$blood: #a23;
|
24
|
+
$coal: #222;
|
25
|
+
$codeBackground: #23241f;
|
26
|
+
|
27
|
+
// Main text
|
28
|
+
$mainFont: Ubuntu, 'sans-serif';
|
29
|
+
$mainFontSize: 36px;
|
30
|
+
$mainColor: #eee;
|
31
|
+
|
32
|
+
// Headings
|
33
|
+
$headingFont: Ubuntu, 'sans-serif';
|
34
|
+
$headingTextShadow: 2px 2px 2px $coal;
|
35
|
+
|
36
|
+
// h1 shadow, borrowed humbly from
|
37
|
+
// (c) Default theme by Hakim El Hattab
|
38
|
+
$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
|
39
|
+
|
40
|
+
// Links
|
41
|
+
$linkColor: $blood;
|
42
|
+
$linkColorHover: lighten( $linkColor, 20% );
|
43
|
+
|
44
|
+
// Text selection
|
45
|
+
$selectionBackgroundColor: $blood;
|
46
|
+
$selectionColor: #fff;
|
47
|
+
|
48
|
+
// Background generator
|
49
|
+
@mixin bodyBackground() {
|
50
|
+
@include radial-gradient( $coal, lighten( $coal, 25% ) );
|
51
|
+
}
|
52
|
+
|
53
|
+
// Theme template ------------------------------
|
54
|
+
@import "../template/theme";
|
55
|
+
// ---------------------------------------------
|
56
|
+
|
57
|
+
// some overrides after theme template import
|
58
|
+
|
59
|
+
.reveal p {
|
60
|
+
font-weight: 300;
|
61
|
+
text-shadow: 1px 1px $coal;
|
62
|
+
}
|
63
|
+
|
64
|
+
.reveal h1,
|
65
|
+
.reveal h2,
|
66
|
+
.reveal h3,
|
67
|
+
.reveal h4,
|
68
|
+
.reveal h5,
|
69
|
+
.reveal h6 {
|
70
|
+
font-weight: 700;
|
71
|
+
}
|
72
|
+
|
73
|
+
.reveal a:not(.image),
|
74
|
+
.reveal a:not(.image):hover {
|
75
|
+
text-shadow: 2px 2px 2px #000;
|
76
|
+
}
|
77
|
+
|
78
|
+
.reveal small a:not(.image),
|
79
|
+
.reveal small a:not(.image):hover {
|
80
|
+
text-shadow: 1px 1px 1px #000;
|
81
|
+
}
|
82
|
+
|
83
|
+
.reveal p code {
|
84
|
+
background-color: $codeBackground;
|
85
|
+
display: inline-block;
|
86
|
+
border-radius: 7px;
|
87
|
+
}
|
88
|
+
|
89
|
+
.reveal small code {
|
90
|
+
vertical-align: baseline;
|
91
|
+
}
|
@@ -12,7 +12,7 @@ body {
|
|
12
12
|
.reveal {
|
13
13
|
font-family: $mainFont;
|
14
14
|
font-size: $mainFontSize;
|
15
|
-
font-weight:
|
15
|
+
font-weight: normal;
|
16
16
|
letter-spacing: -0.02em;
|
17
17
|
color: $mainColor;
|
18
18
|
}
|
@@ -160,4 +160,11 @@ body {
|
|
160
160
|
transition: width 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985);
|
161
161
|
}
|
162
162
|
|
163
|
+
/*********************************************
|
164
|
+
* SLIDE NUMBER
|
165
|
+
*********************************************/
|
166
|
+
.reveal .slide-number {
|
167
|
+
color: $linkColor;
|
168
|
+
}
|
169
|
+
|
163
170
|
|
data/reveal.js/index.html
CHANGED
@@ -173,9 +173,8 @@
|
|
173
173
|
<a href="?theme=simple#/themes">Simple</a> -
|
174
174
|
<a href="?theme=serif#/themes">Serif</a> -
|
175
175
|
<a href="?theme=night#/themes">Night</a> <br>
|
176
|
-
<a href="?theme=moon
|
177
|
-
<a href="?theme=
|
178
|
-
<a href="?theme=solarized.css#/themes">Solarized</a>
|
176
|
+
<a href="?theme=moon#/themes">Moon</a> -
|
177
|
+
<a href="?theme=solarized#/themes">Solarized</a>
|
179
178
|
</p>
|
180
179
|
<p>
|
181
180
|
<small>
|
@@ -281,7 +280,7 @@ function linkify( selector ) {
|
|
281
280
|
</section>
|
282
281
|
|
283
282
|
<section>
|
284
|
-
<section>
|
283
|
+
<section id="fragments">
|
285
284
|
<h2>Fragmented Views</h2>
|
286
285
|
<p>Hit the next arrow...</p>
|
287
286
|
<p class="fragment">... to step through ...</p>
|
@@ -305,6 +304,8 @@ function linkify( selector ) {
|
|
305
304
|
<p class="fragment highlight-red">highlight-red</p>
|
306
305
|
<p class="fragment highlight-green">highlight-green</p>
|
307
306
|
<p class="fragment highlight-blue">highlight-blue</p>
|
307
|
+
<p class="fragment current-visible">current-visible</p>
|
308
|
+
<p class="fragment highlight-current-blue">highlight-current-blue</p>
|
308
309
|
</section>
|
309
310
|
</section>
|
310
311
|
|
@@ -366,6 +367,10 @@ function linkify( selector ) {
|
|
366
367
|
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
|
367
368
|
transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
|
368
369
|
|
370
|
+
// Parallax scrolling
|
371
|
+
// parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg',
|
372
|
+
// parallaxBackgroundSize: '2100px 900px',
|
373
|
+
|
369
374
|
// Optional libraries used to extend on reveal.js
|
370
375
|
dependencies: [
|
371
376
|
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
data/reveal.js/js/reveal.js
CHANGED
@@ -12,7 +12,7 @@ var Reveal = (function(){
|
|
12
12
|
var SLIDES_SELECTOR = '.reveal .slides section',
|
13
13
|
HORIZONTAL_SLIDES_SELECTOR = '.reveal .slides>section',
|
14
14
|
VERTICAL_SLIDES_SELECTOR = '.reveal .slides>section.present>section',
|
15
|
-
HOME_SLIDE_SELECTOR = '.reveal .slides>section:first-
|
15
|
+
HOME_SLIDE_SELECTOR = '.reveal .slides>section:first-of-type',
|
16
16
|
|
17
17
|
// Configurations defaults, can be overridden at initialization time
|
18
18
|
config = {
|
@@ -35,6 +35,9 @@ var Reveal = (function(){
|
|
35
35
|
// Display a presentation progress bar
|
36
36
|
progress: true,
|
37
37
|
|
38
|
+
// Display the page number of the current slide
|
39
|
+
slideNumber: false,
|
40
|
+
|
38
41
|
// Push each slide change to the browser history
|
39
42
|
history: false,
|
40
43
|
|
@@ -44,7 +47,7 @@ var Reveal = (function(){
|
|
44
47
|
// Enable the slide overview mode
|
45
48
|
overview: true,
|
46
49
|
|
47
|
-
// Vertical
|
50
|
+
// Vertical centering of slides
|
48
51
|
center: true,
|
49
52
|
|
50
53
|
// Enables touch navigation on devices with touch input
|
@@ -68,6 +71,9 @@ var Reveal = (function(){
|
|
68
71
|
// by using a data-autoslide attribute on your slides
|
69
72
|
autoSlide: 0,
|
70
73
|
|
74
|
+
// Stop auto-sliding after user input
|
75
|
+
autoSlideStoppable: true,
|
76
|
+
|
71
77
|
// Enable slide navigation via mouse wheel
|
72
78
|
mouseWheel: false,
|
73
79
|
|
@@ -80,6 +86,9 @@ var Reveal = (function(){
|
|
80
86
|
// Opens links in an iframe preview overlay
|
81
87
|
previewLinks: false,
|
82
88
|
|
89
|
+
// Focuses body when page changes visiblity to ensure keyboard shortcuts work
|
90
|
+
focusBodyOnPageVisiblityChange: true,
|
91
|
+
|
83
92
|
// Theme (see /css/theme)
|
84
93
|
theme: null,
|
85
94
|
|
@@ -92,19 +101,23 @@ var Reveal = (function(){
|
|
92
101
|
// Transition style for full page slide backgrounds
|
93
102
|
backgroundTransition: 'default', // default/linear/none
|
94
103
|
|
104
|
+
// Parallax background image
|
105
|
+
parallaxBackgroundImage: '', // CSS syntax, e.g. "a.jpg"
|
106
|
+
|
107
|
+
// Parallax background size
|
108
|
+
parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px"
|
109
|
+
|
95
110
|
// Number of slides away from the current that are visible
|
96
111
|
viewDistance: 3,
|
97
112
|
|
98
113
|
// Script dependencies to load
|
99
114
|
dependencies: []
|
115
|
+
|
100
116
|
},
|
101
117
|
|
102
118
|
// Flags if reveal.js is loaded (has dispatched the 'ready' event)
|
103
119
|
loaded = false,
|
104
120
|
|
105
|
-
// The current auto-slide duration
|
106
|
-
autoSlide = 0,
|
107
|
-
|
108
121
|
// The horizontal and vertical index of the currently active slide
|
109
122
|
indexh,
|
110
123
|
indexv,
|
@@ -113,6 +126,8 @@ var Reveal = (function(){
|
|
113
126
|
previousSlide,
|
114
127
|
currentSlide,
|
115
128
|
|
129
|
+
previousBackground,
|
130
|
+
|
116
131
|
// Slides may hold a data-state attribute which we pick up and apply
|
117
132
|
// as a class to the body. This list contains the combined state of
|
118
133
|
// all current slides.
|
@@ -124,11 +139,8 @@ var Reveal = (function(){
|
|
124
139
|
// Cached references to DOM elements
|
125
140
|
dom = {},
|
126
141
|
|
127
|
-
//
|
128
|
-
|
129
|
-
|
130
|
-
// Client support for CSS 2D transforms, see #checkCapabilities()
|
131
|
-
supports2DTransforms,
|
142
|
+
// Features supported by the browser, see #checkCapabilities()
|
143
|
+
features = {},
|
132
144
|
|
133
145
|
// Client is a mobile device, see #checkCapabilities()
|
134
146
|
isMobileDevice,
|
@@ -136,9 +148,6 @@ var Reveal = (function(){
|
|
136
148
|
// Throttles mouse wheel navigation
|
137
149
|
lastMouseWheelStep = 0,
|
138
150
|
|
139
|
-
// An interval used to automatically move on to the next slide
|
140
|
-
autoSlideTimeout = 0,
|
141
|
-
|
142
151
|
// Delays updates to the URL due to a Chrome thumbnailer bug
|
143
152
|
writeURLTimeout = 0,
|
144
153
|
|
@@ -151,6 +160,15 @@ var Reveal = (function(){
|
|
151
160
|
// Flags if the interaction event listeners are bound
|
152
161
|
eventsAreBound = false,
|
153
162
|
|
163
|
+
// The current auto-slide duration
|
164
|
+
autoSlide = 0,
|
165
|
+
|
166
|
+
// Auto slide properties
|
167
|
+
autoSlidePlayer,
|
168
|
+
autoSlideTimeout = 0,
|
169
|
+
autoSlideStartTime = -1,
|
170
|
+
autoSlidePaused = false,
|
171
|
+
|
154
172
|
// Holds information about the currently ongoing touch input
|
155
173
|
touch = {
|
156
174
|
startX: 0,
|
@@ -168,7 +186,7 @@ var Reveal = (function(){
|
|
168
186
|
|
169
187
|
checkCapabilities();
|
170
188
|
|
171
|
-
if( !
|
189
|
+
if( !features.transforms2d && !features.transforms3d ) {
|
172
190
|
document.body.setAttribute( 'class', 'no-transforms' );
|
173
191
|
|
174
192
|
// If the browser doesn't support core features we won't be
|
@@ -179,8 +197,15 @@ var Reveal = (function(){
|
|
179
197
|
// Force a layout when the whole page, incl fonts, has loaded
|
180
198
|
window.addEventListener( 'load', layout, false );
|
181
199
|
|
200
|
+
var query = Reveal.getQueryHash();
|
201
|
+
|
202
|
+
// Do not accept new dependencies via query config to avoid
|
203
|
+
// the potential of malicious script injection
|
204
|
+
if( typeof query['dependencies'] !== 'undefined' ) delete query['dependencies'];
|
205
|
+
|
182
206
|
// Copy options over to our config object
|
183
207
|
extend( config, options );
|
208
|
+
extend( config, query );
|
184
209
|
|
185
210
|
// Hide the address bar in mobile browsers
|
186
211
|
hideAddressBar();
|
@@ -196,33 +221,63 @@ var Reveal = (function(){
|
|
196
221
|
*/
|
197
222
|
function checkCapabilities() {
|
198
223
|
|
199
|
-
|
224
|
+
features.transforms3d = 'WebkitPerspective' in document.body.style ||
|
200
225
|
'MozPerspective' in document.body.style ||
|
201
226
|
'msPerspective' in document.body.style ||
|
202
227
|
'OPerspective' in document.body.style ||
|
203
228
|
'perspective' in document.body.style;
|
204
229
|
|
205
|
-
|
230
|
+
features.transforms2d = 'WebkitTransform' in document.body.style ||
|
206
231
|
'MozTransform' in document.body.style ||
|
207
232
|
'msTransform' in document.body.style ||
|
208
233
|
'OTransform' in document.body.style ||
|
209
234
|
'transform' in document.body.style;
|
210
235
|
|
236
|
+
features.requestAnimationFrameMethod = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
|
237
|
+
features.requestAnimationFrame = typeof features.requestAnimationFrameMethod === 'function';
|
238
|
+
|
239
|
+
features.canvas = !!document.createElement( 'canvas' ).getContext;
|
240
|
+
|
211
241
|
isMobileDevice = navigator.userAgent.match( /(iphone|ipod|android)/gi );
|
212
242
|
|
213
243
|
}
|
214
244
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
245
|
+
|
246
|
+
/**
|
247
|
+
* Loads the dependencies of reveal.js. Dependencies are
|
248
|
+
* defined via the configuration option 'dependencies'
|
249
|
+
* and will be loaded prior to starting/binding reveal.js.
|
250
|
+
* Some dependencies may have an 'async' flag, if so they
|
251
|
+
* will load after reveal.js has been started up.
|
252
|
+
*/
|
222
253
|
function load() {
|
223
254
|
|
224
255
|
var scripts = [],
|
225
|
-
scriptsAsync = []
|
256
|
+
scriptsAsync = [],
|
257
|
+
scriptsToPreload = 0;
|
258
|
+
|
259
|
+
// Called once synchronous scripts finish loading
|
260
|
+
function proceed() {
|
261
|
+
if( scriptsAsync.length ) {
|
262
|
+
// Load asynchronous scripts
|
263
|
+
head.js.apply( null, scriptsAsync );
|
264
|
+
}
|
265
|
+
|
266
|
+
start();
|
267
|
+
}
|
268
|
+
|
269
|
+
function loadScript( s ) {
|
270
|
+
head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], function() {
|
271
|
+
// Extension may contain callback functions
|
272
|
+
if( typeof s.callback === 'function' ) {
|
273
|
+
s.callback.apply( this );
|
274
|
+
}
|
275
|
+
|
276
|
+
if( --scriptsToPreload === 0 ) {
|
277
|
+
proceed();
|
278
|
+
}
|
279
|
+
});
|
280
|
+
}
|
226
281
|
|
227
282
|
for( var i = 0, len = config.dependencies.length; i < len; i++ ) {
|
228
283
|
var s = config.dependencies[i];
|
@@ -236,25 +291,12 @@ var Reveal = (function(){
|
|
236
291
|
scripts.push( s.src );
|
237
292
|
}
|
238
293
|
|
239
|
-
|
240
|
-
if( typeof s.callback === 'function' ) {
|
241
|
-
head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], s.callback );
|
242
|
-
}
|
243
|
-
}
|
244
|
-
}
|
245
|
-
|
246
|
-
// Called once synchronous scripts finish loading
|
247
|
-
function proceed() {
|
248
|
-
if( scriptsAsync.length ) {
|
249
|
-
// Load asynchronous scripts
|
250
|
-
head.js.apply( null, scriptsAsync );
|
294
|
+
loadScript( s );
|
251
295
|
}
|
252
|
-
|
253
|
-
start();
|
254
296
|
}
|
255
297
|
|
256
298
|
if( scripts.length ) {
|
257
|
-
|
299
|
+
scriptsToPreload = scripts.length;
|
258
300
|
|
259
301
|
// Load synchronous scripts
|
260
302
|
head.js.apply( null, scripts );
|
@@ -274,8 +316,8 @@ var Reveal = (function(){
|
|
274
316
|
// Make sure we've got all the DOM elements we need
|
275
317
|
setupDOM();
|
276
318
|
|
277
|
-
//
|
278
|
-
|
319
|
+
// Resets all vertical slides so that only the first is visible
|
320
|
+
resetVerticalSlides();
|
279
321
|
|
280
322
|
// Updates the presentation to match the current configuration values
|
281
323
|
configure();
|
@@ -283,6 +325,9 @@ var Reveal = (function(){
|
|
283
325
|
// Read the initial hash
|
284
326
|
readURL();
|
285
327
|
|
328
|
+
// Update all backgrounds
|
329
|
+
updateBackground( true );
|
330
|
+
|
286
331
|
// Notify listeners that the presentation is ready but use a 1ms
|
287
332
|
// timeout to ensure it's not fired synchronously after #initialize()
|
288
333
|
setTimeout( function() {
|
@@ -300,26 +345,6 @@ var Reveal = (function(){
|
|
300
345
|
|
301
346
|
}
|
302
347
|
|
303
|
-
/**
|
304
|
-
* Iterates through and decorates slides DOM elements with
|
305
|
-
* appropriate classes.
|
306
|
-
*/
|
307
|
-
function setupSlides() {
|
308
|
-
|
309
|
-
var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
310
|
-
horizontalSlides.forEach( function( horizontalSlide ) {
|
311
|
-
|
312
|
-
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
313
|
-
verticalSlides.forEach( function( verticalSlide, y ) {
|
314
|
-
|
315
|
-
if( y > 0 ) verticalSlide.classList.add( 'future' );
|
316
|
-
|
317
|
-
} );
|
318
|
-
|
319
|
-
} );
|
320
|
-
|
321
|
-
}
|
322
|
-
|
323
348
|
/**
|
324
349
|
* Finds and stores references to DOM elements which are
|
325
350
|
* required by the presentation. If a required element is
|
@@ -349,6 +374,9 @@ var Reveal = (function(){
|
|
349
374
|
'<div class="navigate-up"></div>' +
|
350
375
|
'<div class="navigate-down"></div>' );
|
351
376
|
|
377
|
+
// Slide number
|
378
|
+
dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' );
|
379
|
+
|
352
380
|
// State background element [DEPRECATED]
|
353
381
|
createSingletonNode( dom.wrapper, 'div', 'state-background', null );
|
354
382
|
|
@@ -422,7 +450,7 @@ var Reveal = (function(){
|
|
422
450
|
|
423
451
|
if( data.background ) {
|
424
452
|
// Auto-wrap image urls in url(...)
|
425
|
-
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) {
|
453
|
+
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) {
|
426
454
|
element.style.backgroundImage = 'url('+ data.background +')';
|
427
455
|
}
|
428
456
|
else {
|
@@ -430,6 +458,10 @@ var Reveal = (function(){
|
|
430
458
|
}
|
431
459
|
}
|
432
460
|
|
461
|
+
if( data.background || data.backgroundColor || data.backgroundImage ) {
|
462
|
+
element.setAttribute( 'data-background-hash', data.background + data.backgroundSize + data.backgroundImage + data.backgroundColor + data.backgroundRepeat + data.backgroundPosition + data.backgroundTransition );
|
463
|
+
}
|
464
|
+
|
433
465
|
// Additional and optional background properties
|
434
466
|
if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
|
435
467
|
if( data.backgroundImage ) element.style.backgroundImage = 'url("' + data.backgroundImage + '")';
|
@@ -470,6 +502,28 @@ var Reveal = (function(){
|
|
470
502
|
|
471
503
|
} );
|
472
504
|
|
505
|
+
// Add parallax background if specified
|
506
|
+
if( config.parallaxBackgroundImage ) {
|
507
|
+
|
508
|
+
dom.background.style.backgroundImage = 'url("' + config.parallaxBackgroundImage + '")';
|
509
|
+
dom.background.style.backgroundSize = config.parallaxBackgroundSize;
|
510
|
+
|
511
|
+
// Make sure the below properties are set on the element - these properties are
|
512
|
+
// needed for proper transitions to be set on the element via CSS. To remove
|
513
|
+
// annoying background slide-in effect when the presentation starts, apply
|
514
|
+
// these properties after short time delay
|
515
|
+
setTimeout( function() {
|
516
|
+
dom.wrapper.classList.add( 'has-parallax-background' );
|
517
|
+
}, 1 );
|
518
|
+
|
519
|
+
}
|
520
|
+
else {
|
521
|
+
|
522
|
+
dom.background.style.backgroundImage = '';
|
523
|
+
dom.wrapper.classList.remove( 'has-parallax-background' );
|
524
|
+
|
525
|
+
}
|
526
|
+
|
473
527
|
}
|
474
528
|
|
475
529
|
/**
|
@@ -478,6 +532,8 @@ var Reveal = (function(){
|
|
478
532
|
*/
|
479
533
|
function configure( options ) {
|
480
534
|
|
535
|
+
var numberOfSlides = document.querySelectorAll( SLIDES_SELECTOR ).length;
|
536
|
+
|
481
537
|
dom.wrapper.classList.remove( config.transition );
|
482
538
|
|
483
539
|
// New config options may be passed when this method
|
@@ -485,7 +541,7 @@ var Reveal = (function(){
|
|
485
541
|
if( typeof options === 'object' ) extend( config, options );
|
486
542
|
|
487
543
|
// Force linear transition based on browser capabilities
|
488
|
-
if(
|
544
|
+
if( features.transforms3d === false ) config.transition = 'linear';
|
489
545
|
|
490
546
|
dom.wrapper.classList.add( config.transition );
|
491
547
|
|
@@ -535,6 +591,20 @@ var Reveal = (function(){
|
|
535
591
|
enablePreviewLinks( '[data-preview-link]' );
|
536
592
|
}
|
537
593
|
|
594
|
+
// Auto-slide playback controls
|
595
|
+
if( numberOfSlides > 1 && config.autoSlide && config.autoSlideStoppable && features.canvas && features.requestAnimationFrame ) {
|
596
|
+
autoSlidePlayer = new Playback( dom.wrapper, function() {
|
597
|
+
return Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 );
|
598
|
+
} );
|
599
|
+
|
600
|
+
autoSlidePlayer.on( 'click', onAutoSlidePlayerClick );
|
601
|
+
autoSlidePaused = false;
|
602
|
+
}
|
603
|
+
else if( autoSlidePlayer ) {
|
604
|
+
autoSlidePlayer.destroy();
|
605
|
+
autoSlidePlayer = null;
|
606
|
+
}
|
607
|
+
|
538
608
|
// Load the theme in the config, if it's not already loaded
|
539
609
|
if( config.theme && dom.theme ) {
|
540
610
|
var themeURL = dom.theme.getAttribute( 'href' );
|
@@ -578,10 +648,28 @@ var Reveal = (function(){
|
|
578
648
|
document.addEventListener( 'keydown', onDocumentKeyDown, false );
|
579
649
|
}
|
580
650
|
|
581
|
-
if
|
651
|
+
if( config.progress && dom.progress ) {
|
582
652
|
dom.progress.addEventListener( 'click', onProgressClicked, false );
|
583
653
|
}
|
584
654
|
|
655
|
+
if( config.focusBodyOnPageVisiblityChange ) {
|
656
|
+
var visibilityChange;
|
657
|
+
|
658
|
+
if( 'hidden' in document ) {
|
659
|
+
visibilityChange = 'visibilitychange';
|
660
|
+
}
|
661
|
+
else if( 'msHidden' in document ) {
|
662
|
+
visibilityChange = 'msvisibilitychange';
|
663
|
+
}
|
664
|
+
else if( 'webkitHidden' in document ) {
|
665
|
+
visibilityChange = 'webkitvisibilitychange';
|
666
|
+
}
|
667
|
+
|
668
|
+
if( visibilityChange ) {
|
669
|
+
document.addEventListener( visibilityChange, onPageVisibilityChange, false );
|
670
|
+
}
|
671
|
+
}
|
672
|
+
|
585
673
|
[ 'touchstart', 'click' ].forEach( function( eventName ) {
|
586
674
|
dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } );
|
587
675
|
dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } );
|
@@ -784,16 +872,6 @@ var Reveal = (function(){
|
|
784
872
|
*/
|
785
873
|
function removeAddressBar() {
|
786
874
|
|
787
|
-
// Portrait and not Chrome for iOS
|
788
|
-
if( window.orientation === 0 && !/crios/gi.test( navigator.userAgent ) ) {
|
789
|
-
document.documentElement.style.overflow = 'scroll';
|
790
|
-
document.body.style.height = '120%';
|
791
|
-
}
|
792
|
-
else {
|
793
|
-
document.documentElement.style.overflow = '';
|
794
|
-
document.body.style.height = '100%';
|
795
|
-
}
|
796
|
-
|
797
875
|
setTimeout( function() {
|
798
876
|
window.scrollTo( 0, 1 );
|
799
877
|
}, 10 );
|
@@ -818,7 +896,7 @@ var Reveal = (function(){
|
|
818
896
|
*/
|
819
897
|
function enableRollingLinks() {
|
820
898
|
|
821
|
-
if(
|
899
|
+
if( features.transforms3d && !( 'msPerspective' in document.body.style ) ) {
|
822
900
|
var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' );
|
823
901
|
|
824
902
|
for( var i = 0, len = anchors.length; i < len; i++ ) {
|
@@ -941,38 +1019,6 @@ var Reveal = (function(){
|
|
941
1019
|
|
942
1020
|
}
|
943
1021
|
|
944
|
-
/**
|
945
|
-
* Return a sorted fragments list, ordered by an increasing
|
946
|
-
* "data-fragment-index" attribute.
|
947
|
-
*
|
948
|
-
* Fragments will be revealed in the order that they are returned by
|
949
|
-
* this function, so you can use the index attributes to control the
|
950
|
-
* order of fragment appearance.
|
951
|
-
*
|
952
|
-
* To maintain a sensible default fragment order, fragments are presumed
|
953
|
-
* to be passed in document order. This function adds a "fragment-index"
|
954
|
-
* attribute to each node if such an attribute is not already present,
|
955
|
-
* and sets that attribute to an integer value which is the position of
|
956
|
-
* the fragment within the fragments list.
|
957
|
-
*/
|
958
|
-
function sortFragments( fragments ) {
|
959
|
-
|
960
|
-
var a = toArray( fragments );
|
961
|
-
|
962
|
-
a.forEach( function( el, idx ) {
|
963
|
-
if( !el.hasAttribute( 'data-fragment-index' ) ) {
|
964
|
-
el.setAttribute( 'data-fragment-index', idx );
|
965
|
-
}
|
966
|
-
} );
|
967
|
-
|
968
|
-
a.sort( function( l, r ) {
|
969
|
-
return l.getAttribute( 'data-fragment-index' ) - r.getAttribute( 'data-fragment-index');
|
970
|
-
} );
|
971
|
-
|
972
|
-
return a;
|
973
|
-
|
974
|
-
}
|
975
|
-
|
976
1022
|
/**
|
977
1023
|
* Applies JavaScript-controlled layout rules to the
|
978
1024
|
* presentation.
|
@@ -1038,7 +1084,7 @@ var Reveal = (function(){
|
|
1038
1084
|
continue;
|
1039
1085
|
}
|
1040
1086
|
|
1041
|
-
if( config.center ) {
|
1087
|
+
if( config.center || slide.classList.contains( 'center' ) ) {
|
1042
1088
|
// Vertical stacks are not centred since their section
|
1043
1089
|
// children will be
|
1044
1090
|
if( slide.classList.contains( 'stack' ) ) {
|
@@ -1055,6 +1101,7 @@ var Reveal = (function(){
|
|
1055
1101
|
}
|
1056
1102
|
|
1057
1103
|
updateProgress();
|
1104
|
+
updateParallax();
|
1058
1105
|
|
1059
1106
|
}
|
1060
1107
|
|
@@ -1471,19 +1518,9 @@ var Reveal = (function(){
|
|
1471
1518
|
// Store references to the previous and current slides
|
1472
1519
|
currentSlide = currentVerticalSlides[ indexv ] || currentHorizontalSlide;
|
1473
1520
|
|
1474
|
-
|
1475
1521
|
// Show fragment, if specified
|
1476
1522
|
if( typeof f !== 'undefined' ) {
|
1477
|
-
|
1478
|
-
|
1479
|
-
toArray( fragments ).forEach( function( fragment, indexf ) {
|
1480
|
-
if( indexf < f ) {
|
1481
|
-
fragment.classList.add( 'visible' );
|
1482
|
-
}
|
1483
|
-
else {
|
1484
|
-
fragment.classList.remove( 'visible' );
|
1485
|
-
}
|
1486
|
-
} );
|
1523
|
+
navigateFragment( f );
|
1487
1524
|
}
|
1488
1525
|
|
1489
1526
|
// Dispatch an event if the slide changed
|
@@ -1533,10 +1570,14 @@ var Reveal = (function(){
|
|
1533
1570
|
updateControls();
|
1534
1571
|
updateProgress();
|
1535
1572
|
updateBackground();
|
1573
|
+
updateParallax();
|
1574
|
+
updateSlideNumber();
|
1536
1575
|
|
1537
1576
|
// Update the URL hash
|
1538
1577
|
writeURL();
|
1539
1578
|
|
1579
|
+
cueAutoSlide();
|
1580
|
+
|
1540
1581
|
}
|
1541
1582
|
|
1542
1583
|
/**
|
@@ -1562,9 +1603,58 @@ var Reveal = (function(){
|
|
1562
1603
|
// Re-create the slide backgrounds
|
1563
1604
|
createBackgrounds();
|
1564
1605
|
|
1606
|
+
sortAllFragments();
|
1607
|
+
|
1565
1608
|
updateControls();
|
1566
1609
|
updateProgress();
|
1567
|
-
updateBackground();
|
1610
|
+
updateBackground( true );
|
1611
|
+
updateSlideNumber();
|
1612
|
+
|
1613
|
+
}
|
1614
|
+
|
1615
|
+
/**
|
1616
|
+
* Resets all vertical slides so that only the first
|
1617
|
+
* is visible.
|
1618
|
+
*/
|
1619
|
+
function resetVerticalSlides() {
|
1620
|
+
|
1621
|
+
var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
1622
|
+
horizontalSlides.forEach( function( horizontalSlide ) {
|
1623
|
+
|
1624
|
+
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
1625
|
+
verticalSlides.forEach( function( verticalSlide, y ) {
|
1626
|
+
|
1627
|
+
if( y > 0 ) {
|
1628
|
+
verticalSlide.classList.remove( 'present' );
|
1629
|
+
verticalSlide.classList.remove( 'past' );
|
1630
|
+
verticalSlide.classList.add( 'future' );
|
1631
|
+
}
|
1632
|
+
|
1633
|
+
} );
|
1634
|
+
|
1635
|
+
} );
|
1636
|
+
|
1637
|
+
}
|
1638
|
+
|
1639
|
+
/**
|
1640
|
+
* Sorts and formats all of fragments in the
|
1641
|
+
* presentation.
|
1642
|
+
*/
|
1643
|
+
function sortAllFragments() {
|
1644
|
+
|
1645
|
+
var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
1646
|
+
horizontalSlides.forEach( function( horizontalSlide ) {
|
1647
|
+
|
1648
|
+
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
1649
|
+
verticalSlides.forEach( function( verticalSlide, y ) {
|
1650
|
+
|
1651
|
+
sortFragments( verticalSlide.querySelectorAll( '.fragment' ) );
|
1652
|
+
|
1653
|
+
} );
|
1654
|
+
|
1655
|
+
if( verticalSlides.length === 0 ) sortFragments( horizontalSlide.querySelectorAll( '.fragment' ) );
|
1656
|
+
|
1657
|
+
} );
|
1568
1658
|
|
1569
1659
|
}
|
1570
1660
|
|
@@ -1617,16 +1707,27 @@ var Reveal = (function(){
|
|
1617
1707
|
if( i < index ) {
|
1618
1708
|
// Any element previous to index is given the 'past' class
|
1619
1709
|
element.classList.add( reverse ? 'future' : 'past' );
|
1710
|
+
|
1711
|
+
var pastFragments = toArray( element.querySelectorAll( '.fragment' ) );
|
1712
|
+
|
1713
|
+
// Show all fragments on prior slides
|
1714
|
+
while( pastFragments.length ) {
|
1715
|
+
var pastFragment = pastFragments.pop();
|
1716
|
+
pastFragment.classList.add( 'visible' );
|
1717
|
+
pastFragment.classList.remove( 'current-fragment' );
|
1718
|
+
}
|
1620
1719
|
}
|
1621
1720
|
else if( i > index ) {
|
1622
1721
|
// Any element subsequent to index is given the 'future' class
|
1623
1722
|
element.classList.add( reverse ? 'past' : 'future' );
|
1624
1723
|
|
1625
|
-
var
|
1724
|
+
var futureFragments = toArray( element.querySelectorAll( '.fragment.visible' ) );
|
1626
1725
|
|
1627
1726
|
// No fragments in future slides should be visible ahead of time
|
1628
|
-
while(
|
1629
|
-
|
1727
|
+
while( futureFragments.length ) {
|
1728
|
+
var futureFragment = futureFragments.pop();
|
1729
|
+
futureFragment.classList.remove( 'visible' );
|
1730
|
+
futureFragment.classList.remove( 'current-fragment' );
|
1630
1731
|
}
|
1631
1732
|
}
|
1632
1733
|
|
@@ -1647,18 +1748,6 @@ var Reveal = (function(){
|
|
1647
1748
|
state = state.concat( slideState.split( ' ' ) );
|
1648
1749
|
}
|
1649
1750
|
|
1650
|
-
// If this slide has a data-autoslide attribute associated use this as
|
1651
|
-
// autoSlide value otherwise use the global configured time
|
1652
|
-
var slideAutoSlide = slides[index].getAttribute( 'data-autoslide' );
|
1653
|
-
if( slideAutoSlide ) {
|
1654
|
-
autoSlide = parseInt( slideAutoSlide, 10 );
|
1655
|
-
}
|
1656
|
-
else {
|
1657
|
-
autoSlide = config.autoSlide;
|
1658
|
-
}
|
1659
|
-
|
1660
|
-
cueAutoSlide();
|
1661
|
-
|
1662
1751
|
}
|
1663
1752
|
else {
|
1664
1753
|
// Since there are no slides we can't be anywhere beyond the
|
@@ -1774,6 +1863,25 @@ var Reveal = (function(){
|
|
1774
1863
|
|
1775
1864
|
}
|
1776
1865
|
|
1866
|
+
/**
|
1867
|
+
* Updates the slide number div to reflect the current slide.
|
1868
|
+
*/
|
1869
|
+
function updateSlideNumber() {
|
1870
|
+
|
1871
|
+
// Update slide number if enabled
|
1872
|
+
if( config.slideNumber && dom.slideNumber) {
|
1873
|
+
|
1874
|
+
// Display the number of the page using 'indexh - indexv' format
|
1875
|
+
var indexString = indexh;
|
1876
|
+
if( indexv > 0 ) {
|
1877
|
+
indexString += ' - ' + indexv;
|
1878
|
+
}
|
1879
|
+
|
1880
|
+
dom.slideNumber.innerHTML = indexString;
|
1881
|
+
}
|
1882
|
+
|
1883
|
+
}
|
1884
|
+
|
1777
1885
|
/**
|
1778
1886
|
* Updates the state of all control/navigation arrows.
|
1779
1887
|
*/
|
@@ -1825,29 +1933,70 @@ var Reveal = (function(){
|
|
1825
1933
|
}
|
1826
1934
|
|
1827
1935
|
/**
|
1828
|
-
* Updates the background elements to reflect the current
|
1936
|
+
* Updates the background elements to reflect the current
|
1829
1937
|
* slide.
|
1938
|
+
*
|
1939
|
+
* @param {Boolean} includeAll If true, the backgrounds of
|
1940
|
+
* all vertical slides (not just the present) will be updated.
|
1830
1941
|
*/
|
1831
|
-
function updateBackground() {
|
1942
|
+
function updateBackground( includeAll ) {
|
1943
|
+
|
1944
|
+
var currentBackground = null;
|
1832
1945
|
|
1833
|
-
//
|
1946
|
+
// Reverse past/future classes when in RTL mode
|
1947
|
+
var horizontalPast = config.rtl ? 'future' : 'past',
|
1948
|
+
horizontalFuture = config.rtl ? 'past' : 'future';
|
1949
|
+
|
1950
|
+
// Update the classes of all backgrounds to match the
|
1834
1951
|
// states of their slides (past/present/future)
|
1835
1952
|
toArray( dom.background.childNodes ).forEach( function( backgroundh, h ) {
|
1836
1953
|
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1954
|
+
if( h < indexh ) {
|
1955
|
+
backgroundh.className = 'slide-background ' + horizontalPast;
|
1956
|
+
}
|
1957
|
+
else if ( h > indexh ) {
|
1958
|
+
backgroundh.className = 'slide-background ' + horizontalFuture;
|
1959
|
+
}
|
1960
|
+
else {
|
1961
|
+
backgroundh.className = 'slide-background present';
|
1962
|
+
|
1963
|
+
// Store a reference to the current background element
|
1964
|
+
currentBackground = backgroundh;
|
1965
|
+
}
|
1840
1966
|
|
1841
|
-
|
1967
|
+
if( includeAll || h === indexh ) {
|
1968
|
+
toArray( backgroundh.childNodes ).forEach( function( backgroundv, v ) {
|
1842
1969
|
|
1843
|
-
|
1970
|
+
if( v < indexv ) {
|
1971
|
+
backgroundv.className = 'slide-background past';
|
1972
|
+
}
|
1973
|
+
else if ( v > indexv ) {
|
1974
|
+
backgroundv.className = 'slide-background future';
|
1975
|
+
}
|
1976
|
+
else {
|
1977
|
+
backgroundv.className = 'slide-background present';
|
1844
1978
|
|
1845
|
-
|
1979
|
+
// Only if this is the present horizontal and vertical slide
|
1980
|
+
if( h === indexh ) currentBackground = backgroundv;
|
1981
|
+
}
|
1846
1982
|
|
1847
|
-
|
1983
|
+
} );
|
1984
|
+
}
|
1848
1985
|
|
1849
1986
|
} );
|
1850
1987
|
|
1988
|
+
// Don't transition between identical backgrounds. This
|
1989
|
+
// prevents unwanted flicker.
|
1990
|
+
if( currentBackground ) {
|
1991
|
+
var previousBackgroundHash = previousBackground ? previousBackground.getAttribute( 'data-background-hash' ) : null;
|
1992
|
+
var currentBackgroundHash = currentBackground.getAttribute( 'data-background-hash' );
|
1993
|
+
if( currentBackgroundHash && currentBackgroundHash === previousBackgroundHash && currentBackground !== previousBackground ) {
|
1994
|
+
dom.background.classList.add( 'no-transition' );
|
1995
|
+
}
|
1996
|
+
|
1997
|
+
previousBackground = currentBackground;
|
1998
|
+
}
|
1999
|
+
|
1851
2000
|
// Allow the first background to apply without transition
|
1852
2001
|
setTimeout( function() {
|
1853
2002
|
dom.background.classList.remove( 'no-transition' );
|
@@ -1855,6 +2004,42 @@ var Reveal = (function(){
|
|
1855
2004
|
|
1856
2005
|
}
|
1857
2006
|
|
2007
|
+
/**
|
2008
|
+
* Updates the position of the parallax background based
|
2009
|
+
* on the current slide index.
|
2010
|
+
*/
|
2011
|
+
function updateParallax() {
|
2012
|
+
|
2013
|
+
if( config.parallaxBackgroundImage ) {
|
2014
|
+
|
2015
|
+
var horizontalSlides = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
|
2016
|
+
verticalSlides = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
|
2017
|
+
|
2018
|
+
var backgroundSize = dom.background.style.backgroundSize.split( ' ' ),
|
2019
|
+
backgroundWidth, backgroundHeight;
|
2020
|
+
|
2021
|
+
if( backgroundSize.length === 1 ) {
|
2022
|
+
backgroundWidth = backgroundHeight = parseInt( backgroundSize[0], 10 );
|
2023
|
+
}
|
2024
|
+
else {
|
2025
|
+
backgroundWidth = parseInt( backgroundSize[0], 10 );
|
2026
|
+
backgroundHeight = parseInt( backgroundSize[1], 10 );
|
2027
|
+
}
|
2028
|
+
|
2029
|
+
var slideWidth = dom.background.offsetWidth;
|
2030
|
+
var horizontalSlideCount = horizontalSlides.length;
|
2031
|
+
var horizontalOffset = -( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ) * indexh;
|
2032
|
+
|
2033
|
+
var slideHeight = dom.background.offsetHeight;
|
2034
|
+
var verticalSlideCount = verticalSlides.length;
|
2035
|
+
var verticalOffset = verticalSlideCount > 0 ? -( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 ) * indexv : 0;
|
2036
|
+
|
2037
|
+
dom.background.style.backgroundPosition = horizontalOffset + 'px ' + verticalOffset + 'px';
|
2038
|
+
|
2039
|
+
}
|
2040
|
+
|
2041
|
+
}
|
2042
|
+
|
1858
2043
|
/**
|
1859
2044
|
* Determine what available routes there are for navigation.
|
1860
2045
|
*
|
@@ -1912,7 +2097,7 @@ var Reveal = (function(){
|
|
1912
2097
|
*/
|
1913
2098
|
function startEmbeddedContent( slide ) {
|
1914
2099
|
|
1915
|
-
if( slide ) {
|
2100
|
+
if( slide && !isSpeakerNotes() ) {
|
1916
2101
|
// HTML5 media elements
|
1917
2102
|
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
1918
2103
|
if( el.hasAttribute( 'data-autoplay' ) ) {
|
@@ -1920,10 +2105,15 @@ var Reveal = (function(){
|
|
1920
2105
|
}
|
1921
2106
|
} );
|
1922
2107
|
|
2108
|
+
// iframe embeds
|
2109
|
+
toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
|
2110
|
+
el.contentWindow.postMessage( 'slide:start', '*' );
|
2111
|
+
});
|
2112
|
+
|
1923
2113
|
// YouTube embeds
|
1924
2114
|
toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
|
1925
2115
|
if( el.hasAttribute( 'data-autoplay' ) ) {
|
1926
|
-
el.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
|
2116
|
+
el.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
|
1927
2117
|
}
|
1928
2118
|
});
|
1929
2119
|
}
|
@@ -1944,16 +2134,31 @@ var Reveal = (function(){
|
|
1944
2134
|
}
|
1945
2135
|
} );
|
1946
2136
|
|
2137
|
+
// iframe embeds
|
2138
|
+
toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
|
2139
|
+
el.contentWindow.postMessage( 'slide:stop', '*' );
|
2140
|
+
});
|
2141
|
+
|
1947
2142
|
// YouTube embeds
|
1948
2143
|
toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
|
1949
2144
|
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
1950
|
-
el.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
|
2145
|
+
el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' );
|
1951
2146
|
}
|
1952
2147
|
});
|
1953
2148
|
}
|
1954
2149
|
|
1955
2150
|
}
|
1956
2151
|
|
2152
|
+
/**
|
2153
|
+
* Checks if this presentation is running inside of the
|
2154
|
+
* speaker notes window.
|
2155
|
+
*/
|
2156
|
+
function isSpeakerNotes() {
|
2157
|
+
|
2158
|
+
return !!window.location.search.match( /receiver/gi );
|
2159
|
+
|
2160
|
+
}
|
2161
|
+
|
1957
2162
|
/**
|
1958
2163
|
* Reads the current URL (hash) and navigates accordingly.
|
1959
2164
|
*/
|
@@ -2068,7 +2273,7 @@ var Reveal = (function(){
|
|
2068
2273
|
var hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0;
|
2069
2274
|
if( hasFragments ) {
|
2070
2275
|
var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );
|
2071
|
-
f = visibleFragments.length;
|
2276
|
+
f = visibleFragments.length - 1;
|
2072
2277
|
}
|
2073
2278
|
}
|
2074
2279
|
|
@@ -2077,83 +2282,226 @@ var Reveal = (function(){
|
|
2077
2282
|
}
|
2078
2283
|
|
2079
2284
|
/**
|
2080
|
-
*
|
2285
|
+
* Return a sorted fragments list, ordered by an increasing
|
2286
|
+
* "data-fragment-index" attribute.
|
2081
2287
|
*
|
2082
|
-
*
|
2083
|
-
*
|
2288
|
+
* Fragments will be revealed in the order that they are returned by
|
2289
|
+
* this function, so you can use the index attributes to control the
|
2290
|
+
* order of fragment appearance.
|
2291
|
+
*
|
2292
|
+
* To maintain a sensible default fragment order, fragments are presumed
|
2293
|
+
* to be passed in document order. This function adds a "fragment-index"
|
2294
|
+
* attribute to each node if such an attribute is not already present,
|
2295
|
+
* and sets that attribute to an integer value which is the position of
|
2296
|
+
* the fragment within the fragments list.
|
2084
2297
|
*/
|
2085
|
-
function
|
2298
|
+
function sortFragments( fragments ) {
|
2086
2299
|
|
2087
|
-
|
2088
|
-
var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment:not(.visible)' ) );
|
2300
|
+
fragments = toArray( fragments );
|
2089
2301
|
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2302
|
+
var ordered = [],
|
2303
|
+
unordered = [],
|
2304
|
+
sorted = [];
|
2093
2305
|
|
2094
|
-
|
2095
|
-
|
2306
|
+
// Group ordered and unordered elements
|
2307
|
+
fragments.forEach( function( fragment, i ) {
|
2308
|
+
if( fragment.hasAttribute( 'data-fragment-index' ) ) {
|
2309
|
+
var index = parseInt( fragment.getAttribute( 'data-fragment-index' ), 10 );
|
2096
2310
|
|
2097
|
-
|
2098
|
-
|
2099
|
-
}
|
2100
|
-
|
2101
|
-
// Notify subscribers of the change
|
2102
|
-
dispatchEvent( 'fragmentshown', { fragment: fragments[0], fragments: fragments } );
|
2311
|
+
if( !ordered[index] ) {
|
2312
|
+
ordered[index] = [];
|
2313
|
+
}
|
2103
2314
|
|
2104
|
-
|
2105
|
-
return true;
|
2315
|
+
ordered[index].push( fragment );
|
2106
2316
|
}
|
2107
|
-
|
2317
|
+
else {
|
2318
|
+
unordered.push( [ fragment ] );
|
2319
|
+
}
|
2320
|
+
} );
|
2108
2321
|
|
2109
|
-
|
2322
|
+
// Append fragments without explicit indices in their
|
2323
|
+
// DOM order
|
2324
|
+
ordered = ordered.concat( unordered );
|
2325
|
+
|
2326
|
+
// Manually count the index up per group to ensure there
|
2327
|
+
// are no gaps
|
2328
|
+
var index = 0;
|
2329
|
+
|
2330
|
+
// Push all fragments in their sorted order to an array,
|
2331
|
+
// this flattens the groups
|
2332
|
+
ordered.forEach( function( group ) {
|
2333
|
+
group.forEach( function( fragment ) {
|
2334
|
+
sorted.push( fragment );
|
2335
|
+
fragment.setAttribute( 'data-fragment-index', index );
|
2336
|
+
} );
|
2337
|
+
|
2338
|
+
index ++;
|
2339
|
+
} );
|
2340
|
+
|
2341
|
+
return sorted;
|
2110
2342
|
|
2111
2343
|
}
|
2112
2344
|
|
2113
2345
|
/**
|
2114
|
-
* Navigate to the
|
2346
|
+
* Navigate to the specified slide fragment.
|
2115
2347
|
*
|
2116
|
-
* @
|
2117
|
-
*
|
2348
|
+
* @param {Number} index The index of the fragment that
|
2349
|
+
* should be shown, -1 means all are invisible
|
2350
|
+
* @param {Number} offset Integer offset to apply to the
|
2351
|
+
* fragment index
|
2352
|
+
*
|
2353
|
+
* @return {Boolean} true if a change was made in any
|
2354
|
+
* fragments visibility as part of this call
|
2118
2355
|
*/
|
2119
|
-
function
|
2356
|
+
function navigateFragment( index, offset ) {
|
2120
2357
|
|
2121
2358
|
if( currentSlide && config.fragments ) {
|
2122
|
-
var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment.visible' ) );
|
2123
2359
|
|
2360
|
+
var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
|
2124
2361
|
if( fragments.length ) {
|
2125
|
-
// Find the index of the previous fragment
|
2126
|
-
var index = fragments[ fragments.length - 1 ].getAttribute( 'data-fragment-index' );
|
2127
2362
|
|
2128
|
-
//
|
2129
|
-
|
2363
|
+
// If no index is specified, find the current
|
2364
|
+
if( typeof index !== 'number' ) {
|
2365
|
+
var lastVisibleFragment = sortFragments( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop();
|
2366
|
+
|
2367
|
+
if( lastVisibleFragment ) {
|
2368
|
+
index = parseInt( lastVisibleFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );
|
2369
|
+
}
|
2370
|
+
else {
|
2371
|
+
index = -1;
|
2372
|
+
}
|
2373
|
+
}
|
2374
|
+
|
2375
|
+
// If an offset is specified, apply it to the index
|
2376
|
+
if( typeof offset === 'number' ) {
|
2377
|
+
index += offset;
|
2378
|
+
}
|
2379
|
+
|
2380
|
+
var fragmentsShown = [],
|
2381
|
+
fragmentsHidden = [];
|
2382
|
+
|
2383
|
+
toArray( fragments ).forEach( function( element, i ) {
|
2384
|
+
|
2385
|
+
if( element.hasAttribute( 'data-fragment-index' ) ) {
|
2386
|
+
i = parseInt( element.getAttribute( 'data-fragment-index' ), 10 );
|
2387
|
+
}
|
2388
|
+
|
2389
|
+
// Visible fragments
|
2390
|
+
if( i <= index ) {
|
2391
|
+
if( !element.classList.contains( 'visible' ) ) fragmentsShown.push( element );
|
2392
|
+
element.classList.add( 'visible' );
|
2393
|
+
element.classList.remove( 'current-fragment' );
|
2394
|
+
|
2395
|
+
if( i === index ) {
|
2396
|
+
element.classList.add( 'current-fragment' );
|
2397
|
+
}
|
2398
|
+
}
|
2399
|
+
// Hidden fragments
|
2400
|
+
else {
|
2401
|
+
if( element.classList.contains( 'visible' ) ) fragmentsHidden.push( element );
|
2402
|
+
element.classList.remove( 'visible' );
|
2403
|
+
element.classList.remove( 'current-fragment' );
|
2404
|
+
}
|
2405
|
+
|
2130
2406
|
|
2131
|
-
toArray( fragments ).forEach( function( f ) {
|
2132
|
-
f.classList.remove( 'visible' );
|
2133
2407
|
} );
|
2134
2408
|
|
2135
|
-
|
2136
|
-
|
2409
|
+
if( fragmentsHidden.length ) {
|
2410
|
+
dispatchEvent( 'fragmenthidden', { fragment: fragmentsHidden[0], fragments: fragmentsHidden } );
|
2411
|
+
}
|
2412
|
+
|
2413
|
+
if( fragmentsShown.length ) {
|
2414
|
+
dispatchEvent( 'fragmentshown', { fragment: fragmentsShown[0], fragments: fragmentsShown } );
|
2415
|
+
}
|
2137
2416
|
|
2138
2417
|
updateControls();
|
2139
|
-
|
2418
|
+
|
2419
|
+
return !!( fragmentsShown.length || fragmentsHidden.length );
|
2420
|
+
|
2140
2421
|
}
|
2422
|
+
|
2141
2423
|
}
|
2142
2424
|
|
2143
2425
|
return false;
|
2144
2426
|
|
2145
2427
|
}
|
2146
2428
|
|
2429
|
+
/**
|
2430
|
+
* Navigate to the next slide fragment.
|
2431
|
+
*
|
2432
|
+
* @return {Boolean} true if there was a next fragment,
|
2433
|
+
* false otherwise
|
2434
|
+
*/
|
2435
|
+
function nextFragment() {
|
2436
|
+
|
2437
|
+
return navigateFragment( null, 1 );
|
2438
|
+
|
2439
|
+
}
|
2440
|
+
|
2441
|
+
/**
|
2442
|
+
* Navigate to the previous slide fragment.
|
2443
|
+
*
|
2444
|
+
* @return {Boolean} true if there was a previous fragment,
|
2445
|
+
* false otherwise
|
2446
|
+
*/
|
2447
|
+
function previousFragment() {
|
2448
|
+
|
2449
|
+
return navigateFragment( null, -1 );
|
2450
|
+
|
2451
|
+
}
|
2452
|
+
|
2147
2453
|
/**
|
2148
2454
|
* Cues a new automated slide if enabled in the config.
|
2149
2455
|
*/
|
2150
2456
|
function cueAutoSlide() {
|
2151
2457
|
|
2152
|
-
|
2458
|
+
cancelAutoSlide();
|
2459
|
+
|
2460
|
+
if( currentSlide ) {
|
2461
|
+
|
2462
|
+
var parentAutoSlide = currentSlide.parentNode ? currentSlide.parentNode.getAttribute( 'data-autoslide' ) : null;
|
2463
|
+
var slideAutoSlide = currentSlide.getAttribute( 'data-autoslide' );
|
2464
|
+
|
2465
|
+
// Pick value in the following priority order:
|
2466
|
+
// 1. Current slide's data-autoslide
|
2467
|
+
// 2. Parent slide's data-autoslide
|
2468
|
+
// 3. Global autoSlide setting
|
2469
|
+
if( slideAutoSlide ) {
|
2470
|
+
autoSlide = parseInt( slideAutoSlide, 10 );
|
2471
|
+
}
|
2472
|
+
else if( parentAutoSlide ) {
|
2473
|
+
autoSlide = parseInt( parentAutoSlide, 10 );
|
2474
|
+
}
|
2475
|
+
else {
|
2476
|
+
autoSlide = config.autoSlide;
|
2477
|
+
}
|
2478
|
+
|
2479
|
+
// If there are media elements with data-autoplay,
|
2480
|
+
// automatically set the autoSlide duration to the
|
2481
|
+
// length of that media
|
2482
|
+
toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
2483
|
+
if( el.hasAttribute( 'data-autoplay' ) ) {
|
2484
|
+
if( autoSlide && el.duration * 1000 > autoSlide ) {
|
2485
|
+
autoSlide = ( el.duration * 1000 ) + 1000;
|
2486
|
+
}
|
2487
|
+
}
|
2488
|
+
} );
|
2489
|
+
|
2490
|
+
// Cue the next auto-slide if:
|
2491
|
+
// - There is an autoSlide value
|
2492
|
+
// - Auto-sliding isn't paused by the user
|
2493
|
+
// - The presentation isn't paused
|
2494
|
+
// - The overview isn't active
|
2495
|
+
// - The presentation isn't over
|
2496
|
+
if( autoSlide && !autoSlidePaused && !isPaused() && !isOverview() && ( !Reveal.isLastSlide() || config.loop === true ) ) {
|
2497
|
+
autoSlideTimeout = setTimeout( navigateNext, autoSlide );
|
2498
|
+
autoSlideStartTime = Date.now();
|
2499
|
+
}
|
2500
|
+
|
2501
|
+
if( autoSlidePlayer ) {
|
2502
|
+
autoSlidePlayer.setPlaying( autoSlideTimeout !== -1 );
|
2503
|
+
}
|
2153
2504
|
|
2154
|
-
// Cue the next auto-slide if enabled
|
2155
|
-
if( autoSlide && !isPaused() && !isOverview() ) {
|
2156
|
-
autoSlideTimeout = setTimeout( navigateNext, autoSlide );
|
2157
2505
|
}
|
2158
2506
|
|
2159
2507
|
}
|
@@ -2164,6 +2512,25 @@ var Reveal = (function(){
|
|
2164
2512
|
function cancelAutoSlide() {
|
2165
2513
|
|
2166
2514
|
clearTimeout( autoSlideTimeout );
|
2515
|
+
autoSlideTimeout = -1;
|
2516
|
+
|
2517
|
+
}
|
2518
|
+
|
2519
|
+
function pauseAutoSlide() {
|
2520
|
+
|
2521
|
+
autoSlidePaused = true;
|
2522
|
+
clearTimeout( autoSlideTimeout );
|
2523
|
+
|
2524
|
+
if( autoSlidePlayer ) {
|
2525
|
+
autoSlidePlayer.setPlaying( false );
|
2526
|
+
}
|
2527
|
+
|
2528
|
+
}
|
2529
|
+
|
2530
|
+
function resumeAutoSlide() {
|
2531
|
+
|
2532
|
+
autoSlidePaused = false;
|
2533
|
+
cueAutoSlide();
|
2167
2534
|
|
2168
2535
|
}
|
2169
2536
|
|
@@ -2263,14 +2630,25 @@ var Reveal = (function(){
|
|
2263
2630
|
// ----------------------------- EVENTS -------------------------------//
|
2264
2631
|
// --------------------------------------------------------------------//
|
2265
2632
|
|
2633
|
+
/**
|
2634
|
+
* Called by all event handlers that are based on user
|
2635
|
+
* input.
|
2636
|
+
*/
|
2637
|
+
function onUserInput( event ) {
|
2638
|
+
|
2639
|
+
if( config.autoSlideStoppable ) {
|
2640
|
+
pauseAutoSlide();
|
2641
|
+
}
|
2642
|
+
|
2643
|
+
}
|
2266
2644
|
|
2267
2645
|
/**
|
2268
2646
|
* Handler for the document level 'keydown' event.
|
2269
|
-
*
|
2270
|
-
* @param {Object} event
|
2271
2647
|
*/
|
2272
2648
|
function onDocumentKeyDown( event ) {
|
2273
2649
|
|
2650
|
+
onUserInput( event );
|
2651
|
+
|
2274
2652
|
// Check if there's a focused element that could be using
|
2275
2653
|
// the keyboard
|
2276
2654
|
var activeElement = document.activeElement;
|
@@ -2357,8 +2735,13 @@ var Reveal = (function(){
|
|
2357
2735
|
event.preventDefault();
|
2358
2736
|
}
|
2359
2737
|
// ESC or O key
|
2360
|
-
else if ( ( event.keyCode === 27 || event.keyCode === 79 ) &&
|
2361
|
-
|
2738
|
+
else if ( ( event.keyCode === 27 || event.keyCode === 79 ) && features.transforms3d ) {
|
2739
|
+
if( dom.preview ) {
|
2740
|
+
closePreview();
|
2741
|
+
}
|
2742
|
+
else {
|
2743
|
+
toggleOverview();
|
2744
|
+
}
|
2362
2745
|
|
2363
2746
|
event.preventDefault();
|
2364
2747
|
}
|
@@ -2400,6 +2783,8 @@ var Reveal = (function(){
|
|
2400
2783
|
|
2401
2784
|
// Each touch should only trigger one action
|
2402
2785
|
if( !touch.captured ) {
|
2786
|
+
onUserInput( event );
|
2787
|
+
|
2403
2788
|
var currentX = event.touches[0].clientX;
|
2404
2789
|
var currentY = event.touches[0].clientY;
|
2405
2790
|
|
@@ -2553,6 +2938,8 @@ var Reveal = (function(){
|
|
2553
2938
|
*/
|
2554
2939
|
function onProgressClicked( event ) {
|
2555
2940
|
|
2941
|
+
onUserInput( event );
|
2942
|
+
|
2556
2943
|
event.preventDefault();
|
2557
2944
|
|
2558
2945
|
var slidesTotal = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).length;
|
@@ -2565,12 +2952,12 @@ var Reveal = (function(){
|
|
2565
2952
|
/**
|
2566
2953
|
* Event handler for navigation control buttons.
|
2567
2954
|
*/
|
2568
|
-
function onNavigateLeftClicked( event ) { event.preventDefault(); navigateLeft(); }
|
2569
|
-
function onNavigateRightClicked( event ) { event.preventDefault(); navigateRight(); }
|
2570
|
-
function onNavigateUpClicked( event ) { event.preventDefault(); navigateUp(); }
|
2571
|
-
function onNavigateDownClicked( event ) { event.preventDefault(); navigateDown(); }
|
2572
|
-
function onNavigatePrevClicked( event ) { event.preventDefault(); navigatePrev(); }
|
2573
|
-
function onNavigateNextClicked( event ) { event.preventDefault(); navigateNext(); }
|
2955
|
+
function onNavigateLeftClicked( event ) { event.preventDefault(); onUserInput(); navigateLeft(); }
|
2956
|
+
function onNavigateRightClicked( event ) { event.preventDefault(); onUserInput(); navigateRight(); }
|
2957
|
+
function onNavigateUpClicked( event ) { event.preventDefault(); onUserInput(); navigateUp(); }
|
2958
|
+
function onNavigateDownClicked( event ) { event.preventDefault(); onUserInput(); navigateDown(); }
|
2959
|
+
function onNavigatePrevClicked( event ) { event.preventDefault(); onUserInput(); navigatePrev(); }
|
2960
|
+
function onNavigateNextClicked( event ) { event.preventDefault(); onUserInput(); navigateNext(); }
|
2574
2961
|
|
2575
2962
|
/**
|
2576
2963
|
* Handler for the window level 'hashchange' event.
|
@@ -2590,6 +2977,24 @@ var Reveal = (function(){
|
|
2590
2977
|
|
2591
2978
|
}
|
2592
2979
|
|
2980
|
+
/**
|
2981
|
+
* Handle for the window level 'visibilitychange' event.
|
2982
|
+
*/
|
2983
|
+
function onPageVisibilityChange( event ) {
|
2984
|
+
|
2985
|
+
var isHidden = document.webkitHidden ||
|
2986
|
+
document.msHidden ||
|
2987
|
+
document.hidden;
|
2988
|
+
|
2989
|
+
// If, after clicking a link or similar and we're coming back,
|
2990
|
+
// focus the document.body to ensure we can use keyboard shortcuts
|
2991
|
+
if( isHidden === false && document.activeElement !== document.body ) {
|
2992
|
+
document.activeElement.blur();
|
2993
|
+
document.body.focus();
|
2994
|
+
}
|
2995
|
+
|
2996
|
+
}
|
2997
|
+
|
2593
2998
|
/**
|
2594
2999
|
* Invoked when a slide is and we're in the overview.
|
2595
3000
|
*/
|
@@ -2636,6 +3041,191 @@ var Reveal = (function(){
|
|
2636
3041
|
|
2637
3042
|
}
|
2638
3043
|
|
3044
|
+
/**
|
3045
|
+
* Handles click on the auto-sliding controls element.
|
3046
|
+
*/
|
3047
|
+
function onAutoSlidePlayerClick( event ) {
|
3048
|
+
|
3049
|
+
// Replay
|
3050
|
+
if( Reveal.isLastSlide() && config.loop === false ) {
|
3051
|
+
slide( 0, 0 );
|
3052
|
+
resumeAutoSlide();
|
3053
|
+
}
|
3054
|
+
// Resume
|
3055
|
+
else if( autoSlidePaused ) {
|
3056
|
+
resumeAutoSlide();
|
3057
|
+
}
|
3058
|
+
// Pause
|
3059
|
+
else {
|
3060
|
+
pauseAutoSlide();
|
3061
|
+
}
|
3062
|
+
|
3063
|
+
}
|
3064
|
+
|
3065
|
+
|
3066
|
+
// --------------------------------------------------------------------//
|
3067
|
+
// ------------------------ PLAYBACK COMPONENT ------------------------//
|
3068
|
+
// --------------------------------------------------------------------//
|
3069
|
+
|
3070
|
+
|
3071
|
+
/**
|
3072
|
+
* Constructor for the playback component, which displays
|
3073
|
+
* play/pause/progress controls.
|
3074
|
+
*
|
3075
|
+
* @param {HTMLElement} container The component will append
|
3076
|
+
* itself to this
|
3077
|
+
* @param {Function} progressCheck A method which will be
|
3078
|
+
* called frequently to get the current progress on a range
|
3079
|
+
* of 0-1
|
3080
|
+
*/
|
3081
|
+
function Playback( container, progressCheck ) {
|
3082
|
+
|
3083
|
+
// Cosmetics
|
3084
|
+
this.diameter = 50;
|
3085
|
+
this.thickness = 3;
|
3086
|
+
|
3087
|
+
// Flags if we are currently playing
|
3088
|
+
this.playing = false;
|
3089
|
+
|
3090
|
+
// Current progress on a 0-1 range
|
3091
|
+
this.progress = 0;
|
3092
|
+
|
3093
|
+
// Used to loop the animation smoothly
|
3094
|
+
this.progressOffset = 1;
|
3095
|
+
|
3096
|
+
this.container = container;
|
3097
|
+
this.progressCheck = progressCheck;
|
3098
|
+
|
3099
|
+
this.canvas = document.createElement( 'canvas' );
|
3100
|
+
this.canvas.className = 'playback';
|
3101
|
+
this.canvas.width = this.diameter;
|
3102
|
+
this.canvas.height = this.diameter;
|
3103
|
+
this.context = this.canvas.getContext( '2d' );
|
3104
|
+
|
3105
|
+
this.container.appendChild( this.canvas );
|
3106
|
+
|
3107
|
+
this.render();
|
3108
|
+
|
3109
|
+
}
|
3110
|
+
|
3111
|
+
Playback.prototype.setPlaying = function( value ) {
|
3112
|
+
|
3113
|
+
var wasPlaying = this.playing;
|
3114
|
+
|
3115
|
+
this.playing = value;
|
3116
|
+
|
3117
|
+
// Start repainting if we weren't already
|
3118
|
+
if( !wasPlaying && this.playing ) {
|
3119
|
+
this.animate();
|
3120
|
+
}
|
3121
|
+
else {
|
3122
|
+
this.render();
|
3123
|
+
}
|
3124
|
+
|
3125
|
+
};
|
3126
|
+
|
3127
|
+
Playback.prototype.animate = function() {
|
3128
|
+
|
3129
|
+
var progressBefore = this.progress;
|
3130
|
+
|
3131
|
+
this.progress = this.progressCheck();
|
3132
|
+
|
3133
|
+
// When we loop, offset the progress so that it eases
|
3134
|
+
// smoothly rather than immediately resetting
|
3135
|
+
if( progressBefore > 0.8 && this.progress < 0.2 ) {
|
3136
|
+
this.progressOffset = this.progress;
|
3137
|
+
}
|
3138
|
+
|
3139
|
+
this.render();
|
3140
|
+
|
3141
|
+
if( this.playing ) {
|
3142
|
+
features.requestAnimationFrameMethod.call( window, this.animate.bind( this ) );
|
3143
|
+
}
|
3144
|
+
|
3145
|
+
};
|
3146
|
+
|
3147
|
+
/**
|
3148
|
+
* Renders the current progress and playback state.
|
3149
|
+
*/
|
3150
|
+
Playback.prototype.render = function() {
|
3151
|
+
|
3152
|
+
var progress = this.playing ? this.progress : 0,
|
3153
|
+
radius = ( this.diameter / 2 ) - this.thickness,
|
3154
|
+
x = this.diameter / 2,
|
3155
|
+
y = this.diameter / 2,
|
3156
|
+
iconSize = 14;
|
3157
|
+
|
3158
|
+
// Ease towards 1
|
3159
|
+
this.progressOffset += ( 1 - this.progressOffset ) * 0.1;
|
3160
|
+
|
3161
|
+
var endAngle = ( - Math.PI / 2 ) + ( progress * ( Math.PI * 2 ) );
|
3162
|
+
var startAngle = ( - Math.PI / 2 ) + ( this.progressOffset * ( Math.PI * 2 ) );
|
3163
|
+
|
3164
|
+
this.context.save();
|
3165
|
+
this.context.clearRect( 0, 0, this.diameter, this.diameter );
|
3166
|
+
|
3167
|
+
// Solid background color
|
3168
|
+
this.context.beginPath();
|
3169
|
+
this.context.arc( x, y, radius + 2, 0, Math.PI * 2, false );
|
3170
|
+
this.context.fillStyle = 'rgba( 0, 0, 0, 0.4 )';
|
3171
|
+
this.context.fill();
|
3172
|
+
|
3173
|
+
// Draw progress track
|
3174
|
+
this.context.beginPath();
|
3175
|
+
this.context.arc( x, y, radius, 0, Math.PI * 2, false );
|
3176
|
+
this.context.lineWidth = this.thickness;
|
3177
|
+
this.context.strokeStyle = '#666';
|
3178
|
+
this.context.stroke();
|
3179
|
+
|
3180
|
+
if( this.playing ) {
|
3181
|
+
// Draw progress on top of track
|
3182
|
+
this.context.beginPath();
|
3183
|
+
this.context.arc( x, y, radius, startAngle, endAngle, false );
|
3184
|
+
this.context.lineWidth = this.thickness;
|
3185
|
+
this.context.strokeStyle = '#fff';
|
3186
|
+
this.context.stroke();
|
3187
|
+
}
|
3188
|
+
|
3189
|
+
this.context.translate( x - ( iconSize / 2 ), y - ( iconSize / 2 ) );
|
3190
|
+
|
3191
|
+
// Draw play/pause icons
|
3192
|
+
if( this.playing ) {
|
3193
|
+
this.context.fillStyle = '#fff';
|
3194
|
+
this.context.fillRect( 0, 0, iconSize / 2 - 2, iconSize );
|
3195
|
+
this.context.fillRect( iconSize / 2 + 2, 0, iconSize / 2 - 2, iconSize );
|
3196
|
+
}
|
3197
|
+
else {
|
3198
|
+
this.context.beginPath();
|
3199
|
+
this.context.translate( 2, 0 );
|
3200
|
+
this.context.moveTo( 0, 0 );
|
3201
|
+
this.context.lineTo( iconSize - 2, iconSize / 2 );
|
3202
|
+
this.context.lineTo( 0, iconSize );
|
3203
|
+
this.context.fillStyle = '#fff';
|
3204
|
+
this.context.fill();
|
3205
|
+
}
|
3206
|
+
|
3207
|
+
this.context.restore();
|
3208
|
+
|
3209
|
+
};
|
3210
|
+
|
3211
|
+
Playback.prototype.on = function( type, listener ) {
|
3212
|
+
this.canvas.addEventListener( type, listener, false );
|
3213
|
+
};
|
3214
|
+
|
3215
|
+
Playback.prototype.off = function( type, listener ) {
|
3216
|
+
this.canvas.removeEventListener( type, listener, false );
|
3217
|
+
};
|
3218
|
+
|
3219
|
+
Playback.prototype.destroy = function() {
|
3220
|
+
|
3221
|
+
this.playing = false;
|
3222
|
+
|
3223
|
+
if( this.canvas.parentNode ) {
|
3224
|
+
this.container.removeChild( this.canvas );
|
3225
|
+
}
|
3226
|
+
|
3227
|
+
};
|
3228
|
+
|
2639
3229
|
|
2640
3230
|
// --------------------------------------------------------------------//
|
2641
3231
|
// ------------------------------- API --------------------------------//
|
@@ -2655,6 +3245,9 @@ var Reveal = (function(){
|
|
2655
3245
|
down: navigateDown,
|
2656
3246
|
prev: navigatePrev,
|
2657
3247
|
next: navigateNext,
|
3248
|
+
|
3249
|
+
// Fragment methods
|
3250
|
+
navigateFragment: navigateFragment,
|
2658
3251
|
prevFragment: previousFragment,
|
2659
3252
|
nextFragment: nextFragment,
|
2660
3253
|
|
@@ -2729,10 +3322,22 @@ var Reveal = (function(){
|
|
2729
3322
|
getQueryHash: function() {
|
2730
3323
|
var query = {};
|
2731
3324
|
|
2732
|
-
location.search.replace( /[A-Z0-9]+?=(\w*)/gi, function(a) {
|
3325
|
+
location.search.replace( /[A-Z0-9]+?=([\w\.%-]*)/gi, function(a) {
|
2733
3326
|
query[ a.split( '=' ).shift() ] = a.split( '=' ).pop();
|
2734
3327
|
} );
|
2735
3328
|
|
3329
|
+
// Basic deserialization
|
3330
|
+
for( var i in query ) {
|
3331
|
+
var value = query[ i ];
|
3332
|
+
|
3333
|
+
query[ i ] = unescape( value );
|
3334
|
+
|
3335
|
+
if( value === 'null' ) query[ i ] = null;
|
3336
|
+
else if( value === 'true' ) query[ i ] = true;
|
3337
|
+
else if( value === 'false' ) query[ i ] = false;
|
3338
|
+
else if( value.match( /^\d+$/ ) ) query[ i ] = parseFloat( value );
|
3339
|
+
}
|
3340
|
+
|
2736
3341
|
return query;
|
2737
3342
|
},
|
2738
3343
|
|