slippery 0.4.1 → 0.4.2
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 +5 -5
- data/README.md +2 -2
- data/assets/LICENSE.md +21 -0
- data/assets/README.md +48 -0
- data/assets/highlight.js/CHANGES.md +693 -0
- data/assets/highlight.js/README.md +86 -37
- data/assets/highlight.js/README.ru.md +65 -24
- data/assets/highlight.js/highlight.pack.js +2 -1
- data/assets/highlight.js/styles/agate.css +108 -0
- data/assets/highlight.js/styles/androidstudio.css +66 -0
- data/assets/highlight.js/styles/arduino-light.css +88 -0
- data/assets/highlight.js/styles/arta.css +25 -93
- data/assets/highlight.js/styles/ascetic.css +20 -28
- data/assets/highlight.js/styles/atelier-cave-dark.css +83 -0
- data/assets/highlight.js/styles/atelier-cave-light.css +85 -0
- data/assets/highlight.js/styles/atelier-dune-dark.css +69 -0
- data/assets/highlight.js/styles/atelier-dune-light.css +69 -0
- data/assets/highlight.js/styles/atelier-estuary-dark.css +84 -0
- data/assets/highlight.js/styles/atelier-estuary-light.css +84 -0
- data/assets/highlight.js/styles/atelier-forest-dark.css +69 -0
- data/assets/highlight.js/styles/atelier-forest-light.css +69 -0
- data/assets/highlight.js/styles/atelier-heath-dark.css +69 -0
- data/assets/highlight.js/styles/atelier-heath-light.css +69 -0
- data/assets/highlight.js/styles/atelier-lakeside-dark.css +69 -0
- data/assets/highlight.js/styles/atelier-lakeside-light.css +69 -0
- data/assets/highlight.js/styles/atelier-plateau-dark.css +84 -0
- data/assets/highlight.js/styles/atelier-plateau-light.css +84 -0
- data/assets/highlight.js/styles/atelier-savanna-dark.css +84 -0
- data/assets/highlight.js/styles/atelier-savanna-light.css +84 -0
- data/assets/highlight.js/styles/atelier-seaside-dark.css +69 -0
- data/assets/highlight.js/styles/atelier-seaside-light.css +69 -0
- data/assets/highlight.js/styles/atelier-sulphurpool-dark.css +69 -0
- data/assets/highlight.js/styles/atelier-sulphurpool-light.css +69 -0
- data/assets/highlight.js/styles/atom-one-dark.css +96 -0
- data/assets/highlight.js/styles/atom-one-light.css +96 -0
- data/assets/highlight.js/styles/brown-paper.css +64 -0
- data/assets/highlight.js/styles/codepen-embed.css +22 -70
- data/assets/highlight.js/styles/color-brewer.css +20 -118
- data/assets/highlight.js/styles/darcula.css +77 -0
- data/assets/highlight.js/styles/dark.css +20 -62
- data/assets/highlight.js/styles/darkula.css +6 -0
- data/assets/highlight.js/styles/default.css +67 -121
- data/assets/highlight.js/styles/docco.css +22 -61
- data/assets/highlight.js/styles/dracula.css +76 -0
- data/assets/highlight.js/styles/far.css +26 -67
- data/assets/highlight.js/styles/foundation.css +22 -70
- data/assets/highlight.js/styles/github-gist.css +71 -0
- data/assets/highlight.js/styles/github.css +23 -51
- data/assets/highlight.js/styles/googlecode.css +29 -88
- data/assets/highlight.js/styles/grayscale.css +101 -0
- data/assets/highlight.js/styles/gruvbox-dark.css +108 -0
- data/assets/highlight.js/styles/gruvbox-light.css +108 -0
- data/assets/highlight.js/styles/hopscotch.css +83 -0
- data/assets/highlight.js/styles/hybrid.css +22 -91
- data/assets/highlight.js/styles/idea.css +24 -53
- data/assets/highlight.js/styles/ir-black.css +73 -0
- data/assets/highlight.js/styles/kimbie.dark.css +24 -46
- data/assets/highlight.js/styles/kimbie.light.css +24 -46
- data/assets/highlight.js/styles/magula.css +19 -71
- data/assets/highlight.js/styles/mono-blue.css +22 -33
- data/assets/highlight.js/styles/monokai-sublime.css +83 -0
- data/assets/highlight.js/styles/monokai.css +23 -80
- data/assets/highlight.js/styles/obsidian.css +26 -92
- data/assets/highlight.js/styles/ocean.css +74 -0
- data/assets/highlight.js/styles/paraiso-dark.css +72 -0
- data/assets/highlight.js/styles/paraiso-light.css +72 -0
- data/assets/highlight.js/styles/pojoaque.css +29 -54
- data/assets/highlight.js/styles/purebasic.css +96 -0
- data/assets/highlight.js/styles/qtcreator_dark.css +83 -0
- data/assets/highlight.js/styles/qtcreator_light.css +83 -0
- data/assets/highlight.js/styles/railscasts.css +32 -111
- data/assets/highlight.js/styles/rainbow.css +34 -58
- data/assets/highlight.js/styles/routeros.css +108 -0
- data/assets/highlight.js/styles/school-book.css +72 -0
- data/assets/highlight.js/styles/solarized-dark.css +84 -0
- data/assets/highlight.js/styles/solarized-light.css +84 -0
- data/assets/highlight.js/styles/sunburst.css +28 -91
- data/assets/highlight.js/styles/tomorrow-night-blue.css +23 -43
- data/assets/highlight.js/styles/tomorrow-night-bright.css +23 -43
- data/assets/highlight.js/styles/tomorrow-night-eighties.css +23 -43
- data/assets/highlight.js/styles/tomorrow-night.css +23 -43
- data/assets/highlight.js/styles/tomorrow.css +23 -43
- data/assets/highlight.js/styles/vs.css +33 -59
- data/assets/highlight.js/styles/vs2015.css +115 -0
- data/assets/highlight.js/styles/xcode.css +28 -94
- data/assets/highlight.js/styles/xt256.css +92 -0
- data/assets/highlight.js/styles/zenburn.css +26 -65
- data/assets/index.html +186 -0
- data/assets/pictures/cover.jpg +0 -0
- data/assets/pictures/logo.svg +3 -0
- data/assets/pictures/picture.jpg +0 -0
- data/assets/reveal.js/css/print/paper.css +193 -167
- data/assets/reveal.js/css/print/pdf.css +20 -53
- data/assets/reveal.js/css/reveal.css +953 -1663
- data/assets/reveal.js/css/reveal.min.css +3 -3
- data/assets/reveal.js/css/reveal.scss +1319 -0
- data/assets/reveal.js/css/theme/README.md +2 -4
- data/assets/reveal.js/css/theme/beige.css +183 -60
- data/assets/reveal.js/css/theme/black.css +267 -0
- data/assets/reveal.js/css/theme/blood.css +190 -80
- data/assets/reveal.js/css/theme/league.css +273 -0
- data/assets/reveal.js/css/theme/moon.css +174 -51
- data/assets/reveal.js/css/theme/night.css +171 -42
- data/assets/reveal.js/css/theme/serif.css +187 -58
- data/assets/reveal.js/css/theme/simple.css +179 -50
- data/assets/reveal.js/css/theme/sky.css +176 -47
- data/assets/reveal.js/css/theme/solarized.css +174 -51
- data/assets/reveal.js/css/theme/source/beige.scss +1 -12
- data/assets/reveal.js/css/theme/source/black.scss +49 -0
- data/assets/reveal.js/css/theme/source/blood.scss +3 -15
- data/assets/reveal.js/css/theme/source/{default.scss → league.scss} +5 -13
- data/assets/reveal.js/css/theme/source/moon.scss +1 -12
- data/assets/reveal.js/css/theme/source/serif.scss +1 -1
- data/assets/reveal.js/css/theme/source/sky.scss +1 -1
- data/assets/reveal.js/css/theme/source/solarized.scss +1 -12
- data/assets/reveal.js/css/theme/source/white.scss +49 -0
- data/assets/reveal.js/css/theme/template/settings.scss +13 -4
- data/assets/reveal.js/css/theme/template/theme.scss +193 -14
- data/assets/reveal.js/css/theme/white.css +267 -0
- data/assets/reveal.js/js/reveal.js +1572 -446
- data/assets/reveal.js/js/reveal.min.js +4 -4
- data/assets/reveal.js/lib/css/zenburn.css +74 -71
- data/assets/reveal.js/lib/font/league-gothic/league-gothic.css +10 -0
- data/assets/reveal.js/lib/font/league-gothic/league-gothic.eot +0 -0
- data/assets/reveal.js/lib/font/league-gothic/league-gothic.ttf +0 -0
- data/assets/reveal.js/lib/font/league-gothic/league-gothic.woff +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/LICENSE +45 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-italic.eot +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-italic.ttf +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-italic.woff +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-regular.eot +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-regular.ttf +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-regular.woff +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibold.eot +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibold.ttf +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibold.woff +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibolditalic.eot +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibolditalic.ttf +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibolditalic.woff +0 -0
- data/assets/reveal.js/lib/font/source-sans-pro/source-sans-pro.css +39 -0
- data/assets/reveal.js/plugin/highlight/highlight.js +2 -4
- data/assets/reveal.js/plugin/leap/leap.js +4 -2
- data/assets/reveal.js/plugin/markdown/example.html +3 -3
- data/assets/reveal.js/plugin/markdown/markdown.js +10 -9
- data/assets/reveal.js/plugin/markdown/marked.js +2 -33
- data/assets/reveal.js/plugin/math/math.js +1 -1
- data/assets/reveal.js/plugin/notes/notes.html +321 -182
- data/assets/reveal.js/plugin/notes/notes.js +89 -45
- data/assets/reveal.js/plugin/notes-server/client.js +49 -46
- data/assets/reveal.js/plugin/notes-server/index.js +28 -21
- data/assets/reveal.js/plugin/notes-server/notes.html +351 -97
- data/assets/reveal.js/plugin/print-pdf/print-pdf.js +24 -20
- data/assets/reveal.js/plugin/zoom-js/zoom.js +78 -58
- data/assets/shower/shower.min.js +8 -0
- data/assets/shower/themes/material/LICENSE.md +21 -0
- data/assets/shower/themes/material/README.md +45 -0
- data/assets/shower/themes/material/fonts/COPYRIGHT.txt +1 -0
- data/assets/shower/themes/material/fonts/LICENSE.txt +202 -0
- data/assets/shower/themes/material/fonts/roboto-bold-italic.woff2 +0 -0
- data/assets/shower/themes/material/fonts/roboto-bold.woff2 +0 -0
- data/assets/shower/themes/material/fonts/roboto-italic.woff2 +0 -0
- data/assets/shower/themes/material/fonts/roboto-light.woff2 +0 -0
- data/assets/shower/themes/material/fonts/roboto-mono-regular.woff2 +0 -0
- data/assets/shower/themes/material/fonts/roboto-regular.woff2 +0 -0
- data/assets/shower/themes/material/index.html +488 -0
- data/assets/shower/themes/material/pictures/canvas.png +0 -0
- data/assets/shower/themes/material/pictures/exact.svg +3 -0
- data/assets/shower/themes/material/pictures/picture-1.svg +3 -0
- data/assets/shower/themes/material/pictures/picture-2.svg +3 -0
- data/assets/shower/themes/material/pictures/picture-3.svg +3 -0
- data/assets/shower/themes/material/pictures/square.svg +3 -0
- data/assets/shower/themes/material/pictures/tall.svg +3 -0
- data/assets/shower/themes/material/pictures/wide.svg +3 -0
- data/assets/shower/themes/material/styles/blocks/badge.css +65 -0
- data/assets/shower/themes/material/styles/blocks/caption.css +67 -0
- data/assets/shower/themes/material/styles/blocks/progress.css +37 -0
- data/assets/shower/themes/material/styles/blocks/region.css +29 -0
- data/assets/shower/themes/material/styles/fonts.css +64 -0
- data/assets/shower/themes/material/styles/shower/grid.svg +50 -0
- data/assets/shower/themes/material/styles/shower/shower-full.css +13 -0
- data/assets/shower/themes/material/styles/shower/shower-grid.css +13 -0
- data/assets/shower/themes/material/styles/shower/shower-list.css +30 -0
- data/assets/shower/themes/material/styles/shower/shower-print.css +11 -0
- data/assets/shower/themes/material/styles/shower/shower.css +39 -0
- data/assets/shower/themes/material/styles/slide/content/basic.css +23 -0
- data/assets/shower/themes/material/styles/slide/content/code.css +80 -0
- data/assets/shower/themes/material/styles/slide/content/footer.css +29 -0
- data/assets/shower/themes/material/styles/slide/content/inline.css +49 -0
- data/assets/shower/themes/material/styles/slide/content/lists.css +54 -0
- data/assets/shower/themes/material/styles/slide/content/quote.css +24 -0
- data/assets/shower/themes/material/styles/slide/content/table.css +53 -0
- data/assets/shower/themes/material/styles/slide/elements/columns.css +19 -0
- data/assets/shower/themes/material/styles/slide/elements/copyright.css +38 -0
- data/assets/shower/themes/material/styles/slide/elements/cover.css +25 -0
- data/assets/shower/themes/material/styles/slide/elements/next.css +9 -0
- data/assets/shower/themes/material/styles/slide/elements/place.css +63 -0
- data/assets/shower/themes/material/styles/slide/elements/shout.css +53 -0
- data/assets/shower/themes/material/styles/slide/modifiers/black.css +5 -0
- data/assets/shower/themes/material/styles/slide/modifiers/clear.css +11 -0
- data/assets/shower/themes/material/styles/slide/modifiers/white.css +5 -0
- data/assets/shower/themes/material/styles/slide/slide-full.css +16 -0
- data/assets/shower/themes/material/styles/slide/slide-list.css +68 -0
- data/assets/shower/themes/material/styles/slide/slide.css +56 -0
- data/assets/shower/themes/material/styles/styles.css +9 -0
- data/assets/shower/themes/ribbon/LICENSE.md +21 -0
- data/assets/shower/themes/ribbon/README.md +41 -0
- data/assets/shower/themes/ribbon/fonts/LICENSE.txt +44 -0
- data/assets/shower/themes/ribbon/fonts/pt-mono-regular.woff2 +0 -0
- data/assets/shower/themes/ribbon/fonts/pt-sans-bold-italic.woff2 +0 -0
- data/assets/shower/themes/ribbon/fonts/pt-sans-bold.woff2 +0 -0
- data/assets/shower/themes/ribbon/fonts/pt-sans-italic.woff2 +0 -0
- data/assets/shower/themes/ribbon/fonts/pt-sans-narrow-bold.woff2 +0 -0
- data/assets/shower/themes/ribbon/fonts/pt-sans-regular.woff2 +0 -0
- data/assets/shower/themes/ribbon/index.html +490 -0
- data/assets/shower/themes/ribbon/pictures/canvas.png +0 -0
- data/assets/shower/themes/ribbon/pictures/exact.svg +3 -0
- data/assets/shower/themes/ribbon/pictures/picture-1.svg +3 -0
- data/assets/shower/themes/ribbon/pictures/picture-2.svg +3 -0
- data/assets/shower/themes/ribbon/pictures/picture-3.svg +3 -0
- data/assets/shower/themes/ribbon/pictures/square.svg +3 -0
- data/assets/shower/themes/ribbon/pictures/tall.svg +3 -0
- data/assets/shower/themes/ribbon/pictures/wide.svg +3 -0
- data/assets/shower/themes/ribbon/styles/blocks/badge.css +63 -0
- data/assets/shower/themes/ribbon/styles/blocks/caption.css +63 -0
- data/assets/shower/themes/ribbon/styles/blocks/progress.css +46 -0
- data/assets/shower/themes/ribbon/styles/blocks/region.css +29 -0
- data/assets/shower/themes/ribbon/styles/fonts.css +64 -0
- data/assets/shower/themes/ribbon/styles/shower/grid.svg +40 -0
- data/assets/shower/themes/ribbon/styles/shower/shower-full.css +13 -0
- data/assets/shower/themes/ribbon/styles/shower/shower-grid.css +13 -0
- data/assets/shower/themes/ribbon/styles/shower/shower-list.css +30 -0
- data/assets/shower/themes/ribbon/styles/shower/shower-print.css +11 -0
- data/assets/shower/themes/ribbon/styles/shower/shower.css +32 -0
- data/assets/shower/themes/ribbon/styles/slide/content/basic.css +21 -0
- data/assets/shower/themes/ribbon/styles/slide/content/code.css +82 -0
- data/assets/shower/themes/ribbon/styles/slide/content/footer.css +29 -0
- data/assets/shower/themes/ribbon/styles/slide/content/inline.css +50 -0
- data/assets/shower/themes/ribbon/styles/slide/content/lists.css +55 -0
- data/assets/shower/themes/ribbon/styles/slide/content/quote.css +23 -0
- data/assets/shower/themes/ribbon/styles/slide/content/table.css +53 -0
- data/assets/shower/themes/ribbon/styles/slide/elements/columns.css +19 -0
- data/assets/shower/themes/ribbon/styles/slide/elements/copyright.css +38 -0
- data/assets/shower/themes/ribbon/styles/slide/elements/cover.css +25 -0
- data/assets/shower/themes/ribbon/styles/slide/elements/next.css +9 -0
- data/assets/shower/themes/ribbon/styles/slide/elements/place.css +63 -0
- data/assets/shower/themes/ribbon/styles/slide/elements/shout.css +54 -0
- data/assets/shower/themes/ribbon/styles/slide/modifiers/black.css +5 -0
- data/assets/shower/themes/ribbon/styles/slide/modifiers/clear.css +11 -0
- data/assets/shower/themes/ribbon/styles/slide/modifiers/white.css +5 -0
- data/assets/shower/themes/ribbon/styles/slide/ribbon.svg +1 -0
- data/assets/shower/themes/ribbon/styles/slide/slide-full.css +16 -0
- data/assets/shower/themes/ribbon/styles/slide/slide-list.css +68 -0
- data/assets/shower/themes/ribbon/styles/slide/slide.css +60 -0
- data/assets/shower/themes/ribbon/styles/styles.css +9 -0
- data/lib/slippery/presentation.rb +4 -0
- data/lib/slippery/processors/add_highlight.rb +3 -8
- data/lib/slippery/processors/reveal_js/add_reveal_js.rb +1 -1
- data/lib/slippery/processors/shower.rb +76 -0
- data/lib/slippery/rake_tasks.rb +8 -3
- data/lib/slippery/version.rb +1 -1
- data/lib/slippery.rb +1 -0
- data/slippery.gemspec +3 -3
- metadata +194 -56
- data/assets/highlight.js/highlight-0.8.default.min.css +0 -1
- data/assets/highlight.js/highlight-0.8.min.js +0 -1
- data/assets/highlight.js/styles/atelier-dune.dark.css +0 -95
- data/assets/highlight.js/styles/atelier-dune.light.css +0 -95
- data/assets/highlight.js/styles/atelier-forest.dark.css +0 -95
- data/assets/highlight.js/styles/atelier-forest.light.css +0 -95
- data/assets/highlight.js/styles/atelier-heath.dark.css +0 -95
- data/assets/highlight.js/styles/atelier-heath.light.css +0 -95
- data/assets/highlight.js/styles/atelier-lakeside.dark.css +0 -95
- data/assets/highlight.js/styles/atelier-lakeside.light.css +0 -95
- data/assets/highlight.js/styles/atelier-seaside.dark.css +0 -95
- data/assets/highlight.js/styles/atelier-seaside.light.css +0 -95
- data/assets/highlight.js/styles/brown_paper.css +0 -105
- data/assets/highlight.js/styles/ir_black.css +0 -110
- data/assets/highlight.js/styles/monokai_sublime.css +0 -148
- data/assets/highlight.js/styles/paraiso.dark.css +0 -95
- data/assets/highlight.js/styles/paraiso.light.css +0 -95
- data/assets/highlight.js/styles/school_book.css +0 -113
- data/assets/highlight.js/styles/solarized_dark.css +0 -109
- data/assets/highlight.js/styles/solarized_light.css +0 -109
- data/assets/reveal.js/css/theme/default.css +0 -148
- data/assets/reveal.js/lib/font/league_gothic-webfont.eot +0 -0
- data/assets/reveal.js/lib/font/league_gothic-webfont.svg +0 -230
- data/assets/reveal.js/lib/font/league_gothic-webfont.ttf +0 -0
- data/assets/reveal.js/lib/font/league_gothic-webfont.woff +0 -0
- data/assets/reveal.js/plugin/postmessage/example.html +0 -39
- data/assets/reveal.js/plugin/postmessage/postmessage.js +0 -42
- /data/assets/highlight.js/styles/{brown_papersq.png → brown-papersq.png} +0 -0
- /data/assets/highlight.js/styles/{school_book.png → school-book.png} +0 -0
- /data/assets/reveal.js/lib/font/{league_gothic_license → league-gothic/LICENSE} +0 -0
|
@@ -3,18 +3,34 @@
|
|
|
3
3
|
* http://lab.hakim.se/reveal-js
|
|
4
4
|
* MIT licensed
|
|
5
5
|
*
|
|
6
|
-
* Copyright (C)
|
|
6
|
+
* Copyright (C) 2015 Hakim El Hattab, http://hakim.se
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
(function( root, factory ) {
|
|
9
|
+
if( typeof define === 'function' && define.amd ) {
|
|
10
|
+
// AMD. Register as an anonymous module.
|
|
11
|
+
define( function() {
|
|
12
|
+
root.Reveal = factory();
|
|
13
|
+
return root.Reveal;
|
|
14
|
+
} );
|
|
15
|
+
} else if( typeof exports === 'object' ) {
|
|
16
|
+
// Node. Does not work with strict CommonJS.
|
|
17
|
+
module.exports = factory();
|
|
18
|
+
} else {
|
|
19
|
+
// Browser globals.
|
|
20
|
+
root.Reveal = factory();
|
|
21
|
+
}
|
|
22
|
+
}( this, function() {
|
|
9
23
|
|
|
10
24
|
'use strict';
|
|
11
25
|
|
|
12
|
-
var
|
|
13
|
-
HORIZONTAL_SLIDES_SELECTOR = '.reveal .slides>section',
|
|
14
|
-
VERTICAL_SLIDES_SELECTOR = '.reveal .slides>section.present>section',
|
|
15
|
-
HOME_SLIDE_SELECTOR = '.reveal .slides>section:first-of-type',
|
|
26
|
+
var Reveal;
|
|
16
27
|
|
|
17
|
-
|
|
28
|
+
var SLIDES_SELECTOR = '.slides section',
|
|
29
|
+
HORIZONTAL_SLIDES_SELECTOR = '.slides>section',
|
|
30
|
+
VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section',
|
|
31
|
+
HOME_SLIDE_SELECTOR = '.slides>section:first-of-type',
|
|
32
|
+
|
|
33
|
+
// Configuration defaults, can be overridden at initialization time
|
|
18
34
|
config = {
|
|
19
35
|
|
|
20
36
|
// The "normal" size of the presentation, aspect ratio will be preserved
|
|
@@ -27,7 +43,7 @@ var Reveal = (function(){
|
|
|
27
43
|
|
|
28
44
|
// Bounds for smallest/largest possible scale to apply to content
|
|
29
45
|
minScale: 0.2,
|
|
30
|
-
maxScale: 1.
|
|
46
|
+
maxScale: 1.5,
|
|
31
47
|
|
|
32
48
|
// Display controls in the bottom right corner
|
|
33
49
|
controls: true,
|
|
@@ -44,6 +60,9 @@ var Reveal = (function(){
|
|
|
44
60
|
// Enable keyboard shortcuts for navigation
|
|
45
61
|
keyboard: true,
|
|
46
62
|
|
|
63
|
+
// Optional function that blocks keyboard events when retuning false
|
|
64
|
+
keyboardCondition: null,
|
|
65
|
+
|
|
47
66
|
// Enable the slide overview mode
|
|
48
67
|
overview: true,
|
|
49
68
|
|
|
@@ -66,6 +85,13 @@ var Reveal = (function(){
|
|
|
66
85
|
// i.e. contained within a limited portion of the screen
|
|
67
86
|
embedded: false,
|
|
68
87
|
|
|
88
|
+
// Flags if we should show a help overlay when the questionmark
|
|
89
|
+
// key is pressed
|
|
90
|
+
help: true,
|
|
91
|
+
|
|
92
|
+
// Flags if it should be possible to pause the presentation (blackout)
|
|
93
|
+
pause: true,
|
|
94
|
+
|
|
69
95
|
// Number of milliseconds between automatically proceeding to the
|
|
70
96
|
// next slide, disabled when set to 0, this value can be overwritten
|
|
71
97
|
// by using a data-autoslide attribute on your slides
|
|
@@ -86,20 +112,23 @@ var Reveal = (function(){
|
|
|
86
112
|
// Opens links in an iframe preview overlay
|
|
87
113
|
previewLinks: false,
|
|
88
114
|
|
|
89
|
-
//
|
|
90
|
-
|
|
115
|
+
// Exposes the reveal.js API through window.postMessage
|
|
116
|
+
postMessage: true,
|
|
91
117
|
|
|
92
|
-
//
|
|
93
|
-
|
|
118
|
+
// Dispatches all reveal.js events to the parent window through postMessage
|
|
119
|
+
postMessageEvents: false,
|
|
120
|
+
|
|
121
|
+
// Focuses body when page changes visiblity to ensure keyboard shortcuts work
|
|
122
|
+
focusBodyOnPageVisibilityChange: true,
|
|
94
123
|
|
|
95
124
|
// Transition style
|
|
96
|
-
transition: '
|
|
125
|
+
transition: 'slide', // none/fade/slide/convex/concave/zoom
|
|
97
126
|
|
|
98
127
|
// Transition speed
|
|
99
128
|
transitionSpeed: 'default', // default/fast/slow
|
|
100
129
|
|
|
101
130
|
// Transition style for full page slide backgrounds
|
|
102
|
-
backgroundTransition: '
|
|
131
|
+
backgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom
|
|
103
132
|
|
|
104
133
|
// Parallax background image
|
|
105
134
|
parallaxBackgroundImage: '', // CSS syntax, e.g. "a.jpg"
|
|
@@ -107,6 +136,10 @@ var Reveal = (function(){
|
|
|
107
136
|
// Parallax background size
|
|
108
137
|
parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px"
|
|
109
138
|
|
|
139
|
+
// Amount of pixels to move the parallax background per slide step
|
|
140
|
+
parallaxBackgroundHorizontal: null,
|
|
141
|
+
parallaxBackgroundVertical: null,
|
|
142
|
+
|
|
110
143
|
// Number of slides away from the current that are visible
|
|
111
144
|
viewDistance: 3,
|
|
112
145
|
|
|
@@ -118,6 +151,9 @@ var Reveal = (function(){
|
|
|
118
151
|
// Flags if reveal.js is loaded (has dispatched the 'ready' event)
|
|
119
152
|
loaded = false,
|
|
120
153
|
|
|
154
|
+
// Flags if the overview mode is currently active
|
|
155
|
+
overview = false,
|
|
156
|
+
|
|
121
157
|
// The horizontal and vertical index of the currently active slide
|
|
122
158
|
indexh,
|
|
123
159
|
indexv,
|
|
@@ -136,6 +172,10 @@ var Reveal = (function(){
|
|
|
136
172
|
// The current scale of the presentation (see width/height config)
|
|
137
173
|
scale = 1,
|
|
138
174
|
|
|
175
|
+
// CSS transform that is currently applied to the slides container,
|
|
176
|
+
// split into two groups
|
|
177
|
+
slidesTransform = { layout: '', overview: '' },
|
|
178
|
+
|
|
139
179
|
// Cached references to DOM elements
|
|
140
180
|
dom = {},
|
|
141
181
|
|
|
@@ -151,12 +191,6 @@ var Reveal = (function(){
|
|
|
151
191
|
// Delays updates to the URL due to a Chrome thumbnailer bug
|
|
152
192
|
writeURLTimeout = 0,
|
|
153
193
|
|
|
154
|
-
// A delay used to activate the overview mode
|
|
155
|
-
activateOverviewTimeout = 0,
|
|
156
|
-
|
|
157
|
-
// A delay used to deactivate the overview mode
|
|
158
|
-
deactivateOverviewTimeout = 0,
|
|
159
|
-
|
|
160
194
|
// Flags if the interaction event listeners are bound
|
|
161
195
|
eventsAreBound = false,
|
|
162
196
|
|
|
@@ -177,6 +211,21 @@ var Reveal = (function(){
|
|
|
177
211
|
startCount: 0,
|
|
178
212
|
captured: false,
|
|
179
213
|
threshold: 40
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
// Holds information about the keyboard shortcuts
|
|
217
|
+
keyboardShortcuts = {
|
|
218
|
+
'N , SPACE': 'Next slide',
|
|
219
|
+
'P': 'Previous slide',
|
|
220
|
+
'← , H': 'Navigate left',
|
|
221
|
+
'→ , L': 'Navigate right',
|
|
222
|
+
'↑ , K': 'Navigate up',
|
|
223
|
+
'↓ , J': 'Navigate down',
|
|
224
|
+
'Home': 'First slide',
|
|
225
|
+
'End': 'Last slide',
|
|
226
|
+
'B , .': 'Pause',
|
|
227
|
+
'F': 'Fullscreen',
|
|
228
|
+
'ESC, O': 'Slide overview'
|
|
180
229
|
};
|
|
181
230
|
|
|
182
231
|
/**
|
|
@@ -189,11 +238,30 @@ var Reveal = (function(){
|
|
|
189
238
|
if( !features.transforms2d && !features.transforms3d ) {
|
|
190
239
|
document.body.setAttribute( 'class', 'no-transforms' );
|
|
191
240
|
|
|
241
|
+
// Since JS won't be running any further, we load all lazy
|
|
242
|
+
// loading elements upfront
|
|
243
|
+
var images = toArray( document.getElementsByTagName( 'img' ) ),
|
|
244
|
+
iframes = toArray( document.getElementsByTagName( 'iframe' ) );
|
|
245
|
+
|
|
246
|
+
var lazyLoadable = images.concat( iframes );
|
|
247
|
+
|
|
248
|
+
for( var i = 0, len = lazyLoadable.length; i < len; i++ ) {
|
|
249
|
+
var element = lazyLoadable[i];
|
|
250
|
+
if( element.getAttribute( 'data-src' ) ) {
|
|
251
|
+
element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
|
|
252
|
+
element.removeAttribute( 'data-src' );
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
192
256
|
// If the browser doesn't support core features we won't be
|
|
193
257
|
// using JavaScript to control the presentation
|
|
194
258
|
return;
|
|
195
259
|
}
|
|
196
260
|
|
|
261
|
+
// Cache references to key DOM elements
|
|
262
|
+
dom.wrapper = document.querySelector( '.reveal' );
|
|
263
|
+
dom.slides = document.querySelector( '.reveal .slides' );
|
|
264
|
+
|
|
197
265
|
// Force a layout when the whole page, incl fonts, has loaded
|
|
198
266
|
window.addEventListener( 'load', layout, false );
|
|
199
267
|
|
|
@@ -238,10 +306,15 @@ var Reveal = (function(){
|
|
|
238
306
|
|
|
239
307
|
features.canvas = !!document.createElement( 'canvas' ).getContext;
|
|
240
308
|
|
|
241
|
-
|
|
309
|
+
features.touch = !!( 'ontouchstart' in window );
|
|
242
310
|
|
|
243
|
-
|
|
311
|
+
// Transitions in the overview are disabled in desktop and
|
|
312
|
+
// mobile Safari due to lag
|
|
313
|
+
features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( navigator.userAgent );
|
|
244
314
|
|
|
315
|
+
isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent );
|
|
316
|
+
|
|
317
|
+
}
|
|
245
318
|
|
|
246
319
|
/**
|
|
247
320
|
* Loads the dependencies of reveal.js. Dependencies are
|
|
@@ -316,6 +389,12 @@ var Reveal = (function(){
|
|
|
316
389
|
// Make sure we've got all the DOM elements we need
|
|
317
390
|
setupDOM();
|
|
318
391
|
|
|
392
|
+
// Listen to messages posted to this window
|
|
393
|
+
setupPostMessage();
|
|
394
|
+
|
|
395
|
+
// Prevent iframes from scrolling the slides out of view
|
|
396
|
+
setupIframeScrollPrevention();
|
|
397
|
+
|
|
319
398
|
// Resets all vertical slides so that only the first is visible
|
|
320
399
|
resetVerticalSlides();
|
|
321
400
|
|
|
@@ -343,6 +422,20 @@ var Reveal = (function(){
|
|
|
343
422
|
} );
|
|
344
423
|
}, 1 );
|
|
345
424
|
|
|
425
|
+
// Special setup and config is required when printing to PDF
|
|
426
|
+
if( isPrintingPDF() ) {
|
|
427
|
+
removeEventListeners();
|
|
428
|
+
|
|
429
|
+
// The document needs to have loaded for the PDF layout
|
|
430
|
+
// measurements to be accurate
|
|
431
|
+
if( document.readyState === 'complete' ) {
|
|
432
|
+
setupPDF();
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
window.addEventListener( 'load', setupPDF );
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
346
439
|
}
|
|
347
440
|
|
|
348
441
|
/**
|
|
@@ -352,11 +445,6 @@ var Reveal = (function(){
|
|
|
352
445
|
*/
|
|
353
446
|
function setupDOM() {
|
|
354
447
|
|
|
355
|
-
// Cache references to key DOM elements
|
|
356
|
-
dom.theme = document.querySelector( '#theme' );
|
|
357
|
-
dom.wrapper = document.querySelector( '.reveal' );
|
|
358
|
-
dom.slides = document.querySelector( '.reveal .slides' );
|
|
359
|
-
|
|
360
448
|
// Prevent transitions while we're loading
|
|
361
449
|
dom.slides.classList.add( 'no-transition' );
|
|
362
450
|
|
|
@@ -377,14 +465,14 @@ var Reveal = (function(){
|
|
|
377
465
|
// Slide number
|
|
378
466
|
dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' );
|
|
379
467
|
|
|
380
|
-
// State background element [DEPRECATED]
|
|
381
|
-
createSingletonNode( dom.wrapper, 'div', 'state-background', null );
|
|
382
|
-
|
|
383
468
|
// Overlay graphic which is displayed during the paused mode
|
|
384
469
|
createSingletonNode( dom.wrapper, 'div', 'pause-overlay', null );
|
|
385
470
|
|
|
386
471
|
// Cache references to elements
|
|
387
472
|
dom.controls = document.querySelector( '.reveal .controls' );
|
|
473
|
+
dom.theme = document.querySelector( '#theme' );
|
|
474
|
+
|
|
475
|
+
dom.wrapper.setAttribute( 'role', 'application' );
|
|
388
476
|
|
|
389
477
|
// There can be multiple instances of controls throughout the page
|
|
390
478
|
dom.controlsLeft = toArray( document.querySelectorAll( '.navigate-left' ) );
|
|
@@ -394,6 +482,120 @@ var Reveal = (function(){
|
|
|
394
482
|
dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) );
|
|
395
483
|
dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) );
|
|
396
484
|
|
|
485
|
+
dom.statusDiv = createStatusDiv();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Creates a hidden div with role aria-live to announce the
|
|
490
|
+
* current slide content. Hide the div off-screen to make it
|
|
491
|
+
* available only to Assistive Technologies.
|
|
492
|
+
*/
|
|
493
|
+
function createStatusDiv() {
|
|
494
|
+
|
|
495
|
+
var statusDiv = document.getElementById( 'aria-status-div' );
|
|
496
|
+
if( !statusDiv ) {
|
|
497
|
+
statusDiv = document.createElement( 'div' );
|
|
498
|
+
statusDiv.style.position = 'absolute';
|
|
499
|
+
statusDiv.style.height = '1px';
|
|
500
|
+
statusDiv.style.width = '1px';
|
|
501
|
+
statusDiv.style.overflow ='hidden';
|
|
502
|
+
statusDiv.style.clip = 'rect( 1px, 1px, 1px, 1px )';
|
|
503
|
+
statusDiv.setAttribute( 'id', 'aria-status-div' );
|
|
504
|
+
statusDiv.setAttribute( 'aria-live', 'polite' );
|
|
505
|
+
statusDiv.setAttribute( 'aria-atomic','true' );
|
|
506
|
+
dom.wrapper.appendChild( statusDiv );
|
|
507
|
+
}
|
|
508
|
+
return statusDiv;
|
|
509
|
+
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Configures the presentation for printing to a static
|
|
514
|
+
* PDF.
|
|
515
|
+
*/
|
|
516
|
+
function setupPDF() {
|
|
517
|
+
|
|
518
|
+
var slideSize = getComputedSlideSize( window.innerWidth, window.innerHeight );
|
|
519
|
+
|
|
520
|
+
// Dimensions of the PDF pages
|
|
521
|
+
var pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ),
|
|
522
|
+
pageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) );
|
|
523
|
+
|
|
524
|
+
// Dimensions of slides within the pages
|
|
525
|
+
var slideWidth = slideSize.width,
|
|
526
|
+
slideHeight = slideSize.height;
|
|
527
|
+
|
|
528
|
+
// Let the browser know what page size we want to print
|
|
529
|
+
injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0;}' );
|
|
530
|
+
|
|
531
|
+
// Limit the size of certain elements to the dimensions of the slide
|
|
532
|
+
injectStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );
|
|
533
|
+
|
|
534
|
+
document.body.classList.add( 'print-pdf' );
|
|
535
|
+
document.body.style.width = pageWidth + 'px';
|
|
536
|
+
document.body.style.height = pageHeight + 'px';
|
|
537
|
+
|
|
538
|
+
// Slide and slide background layout
|
|
539
|
+
toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
|
|
540
|
+
|
|
541
|
+
// Vertical stacks are not centred since their section
|
|
542
|
+
// children will be
|
|
543
|
+
if( slide.classList.contains( 'stack' ) === false ) {
|
|
544
|
+
// Center the slide inside of the page, giving the slide some margin
|
|
545
|
+
var left = ( pageWidth - slideWidth ) / 2,
|
|
546
|
+
top = ( pageHeight - slideHeight ) / 2;
|
|
547
|
+
|
|
548
|
+
var contentHeight = getAbsoluteHeight( slide );
|
|
549
|
+
var numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 );
|
|
550
|
+
|
|
551
|
+
// Center slides vertically
|
|
552
|
+
if( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) {
|
|
553
|
+
top = Math.max( ( pageHeight - contentHeight ) / 2, 0 );
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Position the slide inside of the page
|
|
557
|
+
slide.style.left = left + 'px';
|
|
558
|
+
slide.style.top = top + 'px';
|
|
559
|
+
slide.style.width = slideWidth + 'px';
|
|
560
|
+
|
|
561
|
+
// TODO Backgrounds need to be multiplied when the slide
|
|
562
|
+
// stretches over multiple pages
|
|
563
|
+
var background = slide.querySelector( '.slide-background' );
|
|
564
|
+
if( background ) {
|
|
565
|
+
background.style.width = pageWidth + 'px';
|
|
566
|
+
background.style.height = ( pageHeight * numberOfPages ) + 'px';
|
|
567
|
+
background.style.top = -top + 'px';
|
|
568
|
+
background.style.left = -left + 'px';
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
} );
|
|
573
|
+
|
|
574
|
+
// Show all fragments
|
|
575
|
+
toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' .fragment' ) ).forEach( function( fragment ) {
|
|
576
|
+
fragment.classList.add( 'visible' );
|
|
577
|
+
} );
|
|
578
|
+
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* This is an unfortunate necessity. Iframes can trigger the
|
|
583
|
+
* parent window to scroll, for example by focusing an input.
|
|
584
|
+
* This scrolling can not be prevented by hiding overflow in
|
|
585
|
+
* CSS so we have to resort to repeatedly checking if the
|
|
586
|
+
* browser has decided to offset our slides :(
|
|
587
|
+
*/
|
|
588
|
+
function setupIframeScrollPrevention() {
|
|
589
|
+
|
|
590
|
+
if( dom.slides.querySelector( 'iframe' ) ) {
|
|
591
|
+
setInterval( function() {
|
|
592
|
+
if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
|
|
593
|
+
dom.wrapper.scrollTop = 0;
|
|
594
|
+
dom.wrapper.scrollLeft = 0;
|
|
595
|
+
}
|
|
596
|
+
}, 500 );
|
|
597
|
+
}
|
|
598
|
+
|
|
397
599
|
}
|
|
398
600
|
|
|
399
601
|
/**
|
|
@@ -403,15 +605,26 @@ var Reveal = (function(){
|
|
|
403
605
|
*/
|
|
404
606
|
function createSingletonNode( container, tagname, classname, innerHTML ) {
|
|
405
607
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
608
|
+
// Find all nodes matching the description
|
|
609
|
+
var nodes = container.querySelectorAll( '.' + classname );
|
|
610
|
+
|
|
611
|
+
// Check all matches to find one which is a direct child of
|
|
612
|
+
// the specified container
|
|
613
|
+
for( var i = 0; i < nodes.length; i++ ) {
|
|
614
|
+
var testNode = nodes[i];
|
|
615
|
+
if( testNode.parentNode === container ) {
|
|
616
|
+
return testNode;
|
|
412
617
|
}
|
|
413
|
-
container.appendChild( node );
|
|
414
618
|
}
|
|
619
|
+
|
|
620
|
+
// If no node was found, create it now
|
|
621
|
+
var node = document.createElement( tagname );
|
|
622
|
+
node.classList.add( classname );
|
|
623
|
+
if( typeof innerHTML === 'string' ) {
|
|
624
|
+
node.innerHTML = innerHTML;
|
|
625
|
+
}
|
|
626
|
+
container.appendChild( node );
|
|
627
|
+
|
|
415
628
|
return node;
|
|
416
629
|
|
|
417
630
|
}
|
|
@@ -423,81 +636,36 @@ var Reveal = (function(){
|
|
|
423
636
|
*/
|
|
424
637
|
function createBackgrounds() {
|
|
425
638
|
|
|
426
|
-
|
|
427
|
-
document.body.classList.add( 'print-pdf' );
|
|
428
|
-
}
|
|
639
|
+
var printMode = isPrintingPDF();
|
|
429
640
|
|
|
430
641
|
// Clear prior backgrounds
|
|
431
642
|
dom.background.innerHTML = '';
|
|
432
643
|
dom.background.classList.add( 'no-transition' );
|
|
433
644
|
|
|
434
|
-
// Helper method for creating a background element for the
|
|
435
|
-
// given slide
|
|
436
|
-
function _createBackground( slide, container ) {
|
|
437
|
-
|
|
438
|
-
var data = {
|
|
439
|
-
background: slide.getAttribute( 'data-background' ),
|
|
440
|
-
backgroundSize: slide.getAttribute( 'data-background-size' ),
|
|
441
|
-
backgroundImage: slide.getAttribute( 'data-background-image' ),
|
|
442
|
-
backgroundColor: slide.getAttribute( 'data-background-color' ),
|
|
443
|
-
backgroundRepeat: slide.getAttribute( 'data-background-repeat' ),
|
|
444
|
-
backgroundPosition: slide.getAttribute( 'data-background-position' ),
|
|
445
|
-
backgroundTransition: slide.getAttribute( 'data-background-transition' )
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
var element = document.createElement( 'div' );
|
|
449
|
-
element.className = 'slide-background';
|
|
450
|
-
|
|
451
|
-
if( data.background ) {
|
|
452
|
-
// Auto-wrap image urls in url(...)
|
|
453
|
-
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) {
|
|
454
|
-
element.style.backgroundImage = 'url('+ data.background +')';
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
element.style.background = data.background;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
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
|
-
|
|
465
|
-
// Additional and optional background properties
|
|
466
|
-
if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
|
|
467
|
-
if( data.backgroundImage ) element.style.backgroundImage = 'url("' + data.backgroundImage + '")';
|
|
468
|
-
if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
|
|
469
|
-
if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat;
|
|
470
|
-
if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition;
|
|
471
|
-
if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );
|
|
472
|
-
|
|
473
|
-
container.appendChild( element );
|
|
474
|
-
|
|
475
|
-
return element;
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
645
|
// Iterate over all horizontal slides
|
|
480
|
-
toArray(
|
|
646
|
+
toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( slideh ) {
|
|
481
647
|
|
|
482
648
|
var backgroundStack;
|
|
483
649
|
|
|
484
|
-
if(
|
|
485
|
-
backgroundStack =
|
|
650
|
+
if( printMode ) {
|
|
651
|
+
backgroundStack = createBackground( slideh, slideh );
|
|
486
652
|
}
|
|
487
653
|
else {
|
|
488
|
-
backgroundStack =
|
|
654
|
+
backgroundStack = createBackground( slideh, dom.background );
|
|
489
655
|
}
|
|
490
656
|
|
|
491
657
|
// Iterate over all vertical slides
|
|
492
658
|
toArray( slideh.querySelectorAll( 'section' ) ).forEach( function( slidev ) {
|
|
493
659
|
|
|
494
|
-
if(
|
|
495
|
-
|
|
660
|
+
if( printMode ) {
|
|
661
|
+
createBackground( slidev, slidev );
|
|
496
662
|
}
|
|
497
663
|
else {
|
|
498
|
-
|
|
664
|
+
createBackground( slidev, backgroundStack );
|
|
499
665
|
}
|
|
500
666
|
|
|
667
|
+
backgroundStack.classList.add( 'stack' );
|
|
668
|
+
|
|
501
669
|
} );
|
|
502
670
|
|
|
503
671
|
} );
|
|
@@ -526,13 +694,131 @@ var Reveal = (function(){
|
|
|
526
694
|
|
|
527
695
|
}
|
|
528
696
|
|
|
697
|
+
/**
|
|
698
|
+
* Creates a background for the given slide.
|
|
699
|
+
*
|
|
700
|
+
* @param {HTMLElement} slide
|
|
701
|
+
* @param {HTMLElement} container The element that the background
|
|
702
|
+
* should be appended to
|
|
703
|
+
*/
|
|
704
|
+
function createBackground( slide, container ) {
|
|
705
|
+
|
|
706
|
+
var data = {
|
|
707
|
+
background: slide.getAttribute( 'data-background' ),
|
|
708
|
+
backgroundSize: slide.getAttribute( 'data-background-size' ),
|
|
709
|
+
backgroundImage: slide.getAttribute( 'data-background-image' ),
|
|
710
|
+
backgroundVideo: slide.getAttribute( 'data-background-video' ),
|
|
711
|
+
backgroundIframe: slide.getAttribute( 'data-background-iframe' ),
|
|
712
|
+
backgroundColor: slide.getAttribute( 'data-background-color' ),
|
|
713
|
+
backgroundRepeat: slide.getAttribute( 'data-background-repeat' ),
|
|
714
|
+
backgroundPosition: slide.getAttribute( 'data-background-position' ),
|
|
715
|
+
backgroundTransition: slide.getAttribute( 'data-background-transition' )
|
|
716
|
+
};
|
|
717
|
+
|
|
718
|
+
var element = document.createElement( 'div' );
|
|
719
|
+
|
|
720
|
+
// Carry over custom classes from the slide to the background
|
|
721
|
+
element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' );
|
|
722
|
+
|
|
723
|
+
if( data.background ) {
|
|
724
|
+
// Auto-wrap image urls in url(...)
|
|
725
|
+
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) {
|
|
726
|
+
slide.setAttribute( 'data-background-image', data.background );
|
|
727
|
+
}
|
|
728
|
+
else {
|
|
729
|
+
element.style.background = data.background;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// Create a hash for this combination of background settings.
|
|
734
|
+
// This is used to determine when two slide backgrounds are
|
|
735
|
+
// the same.
|
|
736
|
+
if( data.background || data.backgroundColor || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) {
|
|
737
|
+
element.setAttribute( 'data-background-hash', data.background +
|
|
738
|
+
data.backgroundSize +
|
|
739
|
+
data.backgroundImage +
|
|
740
|
+
data.backgroundVideo +
|
|
741
|
+
data.backgroundIframe +
|
|
742
|
+
data.backgroundColor +
|
|
743
|
+
data.backgroundRepeat +
|
|
744
|
+
data.backgroundPosition +
|
|
745
|
+
data.backgroundTransition );
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Additional and optional background properties
|
|
749
|
+
if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
|
|
750
|
+
if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
|
|
751
|
+
if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat;
|
|
752
|
+
if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition;
|
|
753
|
+
if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );
|
|
754
|
+
|
|
755
|
+
container.appendChild( element );
|
|
756
|
+
|
|
757
|
+
// If backgrounds are being recreated, clear old classes
|
|
758
|
+
slide.classList.remove( 'has-dark-background' );
|
|
759
|
+
slide.classList.remove( 'has-light-background' );
|
|
760
|
+
|
|
761
|
+
// If this slide has a background color, add a class that
|
|
762
|
+
// signals if it is light or dark. If the slide has no background
|
|
763
|
+
// color, no class will be set
|
|
764
|
+
var computedBackgroundColor = window.getComputedStyle( element ).backgroundColor;
|
|
765
|
+
if( computedBackgroundColor ) {
|
|
766
|
+
var rgb = colorToRgb( computedBackgroundColor );
|
|
767
|
+
|
|
768
|
+
// Ignore fully transparent backgrounds. Some browsers return
|
|
769
|
+
// rgba(0,0,0,0) when reading the computed background color of
|
|
770
|
+
// an element with no background
|
|
771
|
+
if( rgb && rgb.a !== 0 ) {
|
|
772
|
+
if( colorBrightness( computedBackgroundColor ) < 128 ) {
|
|
773
|
+
slide.classList.add( 'has-dark-background' );
|
|
774
|
+
}
|
|
775
|
+
else {
|
|
776
|
+
slide.classList.add( 'has-light-background' );
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
return element;
|
|
782
|
+
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Registers a listener to postMessage events, this makes it
|
|
787
|
+
* possible to call all reveal.js API methods from another
|
|
788
|
+
* window. For example:
|
|
789
|
+
*
|
|
790
|
+
* revealWindow.postMessage( JSON.stringify({
|
|
791
|
+
* method: 'slide',
|
|
792
|
+
* args: [ 2 ]
|
|
793
|
+
* }), '*' );
|
|
794
|
+
*/
|
|
795
|
+
function setupPostMessage() {
|
|
796
|
+
|
|
797
|
+
if( config.postMessage ) {
|
|
798
|
+
window.addEventListener( 'message', function ( event ) {
|
|
799
|
+
var data = event.data;
|
|
800
|
+
|
|
801
|
+
// Make sure we're dealing with JSON
|
|
802
|
+
if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) {
|
|
803
|
+
data = JSON.parse( data );
|
|
804
|
+
|
|
805
|
+
// Check if the requested method can be found
|
|
806
|
+
if( data.method && typeof Reveal[data.method] === 'function' ) {
|
|
807
|
+
Reveal[data.method].apply( Reveal, data.args );
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}, false );
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
}
|
|
814
|
+
|
|
529
815
|
/**
|
|
530
816
|
* Applies the configuration settings from the config
|
|
531
817
|
* object. May be called multiple times.
|
|
532
818
|
*/
|
|
533
819
|
function configure( options ) {
|
|
534
820
|
|
|
535
|
-
var numberOfSlides =
|
|
821
|
+
var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length;
|
|
536
822
|
|
|
537
823
|
dom.wrapper.classList.remove( config.transition );
|
|
538
824
|
|
|
@@ -565,6 +851,11 @@ var Reveal = (function(){
|
|
|
565
851
|
dom.wrapper.classList.remove( 'center' );
|
|
566
852
|
}
|
|
567
853
|
|
|
854
|
+
// Exit the paused mode if it was configured off
|
|
855
|
+
if( config.pause === false ) {
|
|
856
|
+
resume();
|
|
857
|
+
}
|
|
858
|
+
|
|
568
859
|
if( config.mouseWheel ) {
|
|
569
860
|
document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
|
|
570
861
|
document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
|
|
@@ -591,7 +882,13 @@ var Reveal = (function(){
|
|
|
591
882
|
enablePreviewLinks( '[data-preview-link]' );
|
|
592
883
|
}
|
|
593
884
|
|
|
594
|
-
//
|
|
885
|
+
// Remove existing auto-slide controls
|
|
886
|
+
if( autoSlidePlayer ) {
|
|
887
|
+
autoSlidePlayer.destroy();
|
|
888
|
+
autoSlidePlayer = null;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// Generate auto-slide controls if needed
|
|
595
892
|
if( numberOfSlides > 1 && config.autoSlide && config.autoSlideStoppable && features.canvas && features.requestAnimationFrame ) {
|
|
596
893
|
autoSlidePlayer = new Playback( dom.wrapper, function() {
|
|
597
894
|
return Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 );
|
|
@@ -600,21 +897,13 @@ var Reveal = (function(){
|
|
|
600
897
|
autoSlidePlayer.on( 'click', onAutoSlidePlayerClick );
|
|
601
898
|
autoSlidePaused = false;
|
|
602
899
|
}
|
|
603
|
-
else if( autoSlidePlayer ) {
|
|
604
|
-
autoSlidePlayer.destroy();
|
|
605
|
-
autoSlidePlayer = null;
|
|
606
|
-
}
|
|
607
900
|
|
|
608
|
-
//
|
|
609
|
-
if( config.
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
if( config.theme !== themeName ) {
|
|
615
|
-
themeURL = themeURL.replace(themeFinder, config.theme);
|
|
616
|
-
dom.theme.setAttribute( 'href', themeURL );
|
|
617
|
-
}
|
|
901
|
+
// When fragments are turned off they should be visible
|
|
902
|
+
if( config.fragments === false ) {
|
|
903
|
+
toArray( dom.slides.querySelectorAll( '.fragment' ) ).forEach( function( element ) {
|
|
904
|
+
element.classList.add( 'visible' );
|
|
905
|
+
element.classList.remove( 'current-fragment' );
|
|
906
|
+
} );
|
|
618
907
|
}
|
|
619
908
|
|
|
620
909
|
sync();
|
|
@@ -637,7 +926,14 @@ var Reveal = (function(){
|
|
|
637
926
|
dom.wrapper.addEventListener( 'touchend', onTouchEnd, false );
|
|
638
927
|
|
|
639
928
|
// Support pointer-style touch interaction as well
|
|
640
|
-
if( window.navigator.
|
|
929
|
+
if( window.navigator.pointerEnabled ) {
|
|
930
|
+
// IE 11 uses un-prefixed version of pointer events
|
|
931
|
+
dom.wrapper.addEventListener( 'pointerdown', onPointerDown, false );
|
|
932
|
+
dom.wrapper.addEventListener( 'pointermove', onPointerMove, false );
|
|
933
|
+
dom.wrapper.addEventListener( 'pointerup', onPointerUp, false );
|
|
934
|
+
}
|
|
935
|
+
else if( window.navigator.msPointerEnabled ) {
|
|
936
|
+
// IE 10 uses prefixed version of pointer events
|
|
641
937
|
dom.wrapper.addEventListener( 'MSPointerDown', onPointerDown, false );
|
|
642
938
|
dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false );
|
|
643
939
|
dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false );
|
|
@@ -646,13 +942,14 @@ var Reveal = (function(){
|
|
|
646
942
|
|
|
647
943
|
if( config.keyboard ) {
|
|
648
944
|
document.addEventListener( 'keydown', onDocumentKeyDown, false );
|
|
945
|
+
document.addEventListener( 'keypress', onDocumentKeyPress, false );
|
|
649
946
|
}
|
|
650
947
|
|
|
651
948
|
if( config.progress && dom.progress ) {
|
|
652
949
|
dom.progress.addEventListener( 'click', onProgressClicked, false );
|
|
653
950
|
}
|
|
654
951
|
|
|
655
|
-
if( config.
|
|
952
|
+
if( config.focusBodyOnPageVisibilityChange ) {
|
|
656
953
|
var visibilityChange;
|
|
657
954
|
|
|
658
955
|
if( 'hidden' in document ) {
|
|
@@ -670,7 +967,17 @@ var Reveal = (function(){
|
|
|
670
967
|
}
|
|
671
968
|
}
|
|
672
969
|
|
|
673
|
-
|
|
970
|
+
// Listen to both touch and click events, in case the device
|
|
971
|
+
// supports both
|
|
972
|
+
var pointerEvents = [ 'touchstart', 'click' ];
|
|
973
|
+
|
|
974
|
+
// Only support touch for Android, fixes double navigations in
|
|
975
|
+
// stock browser
|
|
976
|
+
if( navigator.userAgent.match( /android/gi ) ) {
|
|
977
|
+
pointerEvents = [ 'touchstart' ];
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
pointerEvents.forEach( function( eventName ) {
|
|
674
981
|
dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } );
|
|
675
982
|
dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } );
|
|
676
983
|
dom.controlsUp.forEach( function( el ) { el.addEventListener( eventName, onNavigateUpClicked, false ); } );
|
|
@@ -689,6 +996,7 @@ var Reveal = (function(){
|
|
|
689
996
|
eventsAreBound = false;
|
|
690
997
|
|
|
691
998
|
document.removeEventListener( 'keydown', onDocumentKeyDown, false );
|
|
999
|
+
document.removeEventListener( 'keypress', onDocumentKeyPress, false );
|
|
692
1000
|
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
|
693
1001
|
window.removeEventListener( 'resize', onWindowResize, false );
|
|
694
1002
|
|
|
@@ -696,7 +1004,14 @@ var Reveal = (function(){
|
|
|
696
1004
|
dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false );
|
|
697
1005
|
dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false );
|
|
698
1006
|
|
|
699
|
-
|
|
1007
|
+
// IE11
|
|
1008
|
+
if( window.navigator.pointerEnabled ) {
|
|
1009
|
+
dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false );
|
|
1010
|
+
dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false );
|
|
1011
|
+
dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false );
|
|
1012
|
+
}
|
|
1013
|
+
// IE10
|
|
1014
|
+
else if( window.navigator.msPointerEnabled ) {
|
|
700
1015
|
dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false );
|
|
701
1016
|
dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false );
|
|
702
1017
|
dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false );
|
|
@@ -738,6 +1053,22 @@ var Reveal = (function(){
|
|
|
738
1053
|
|
|
739
1054
|
}
|
|
740
1055
|
|
|
1056
|
+
/**
|
|
1057
|
+
* Utility for deserializing a value.
|
|
1058
|
+
*/
|
|
1059
|
+
function deserialize( value ) {
|
|
1060
|
+
|
|
1061
|
+
if( typeof value === 'string' ) {
|
|
1062
|
+
if( value === 'null' ) return null;
|
|
1063
|
+
else if( value === 'true' ) return true;
|
|
1064
|
+
else if( value === 'false' ) return false;
|
|
1065
|
+
else if( value.match( /^\d+$/ ) ) return parseFloat( value );
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
return value;
|
|
1069
|
+
|
|
1070
|
+
}
|
|
1071
|
+
|
|
741
1072
|
/**
|
|
742
1073
|
* Measures the distance in pixels between point a
|
|
743
1074
|
* and point b.
|
|
@@ -762,11 +1093,119 @@ var Reveal = (function(){
|
|
|
762
1093
|
element.style.WebkitTransform = transform;
|
|
763
1094
|
element.style.MozTransform = transform;
|
|
764
1095
|
element.style.msTransform = transform;
|
|
765
|
-
element.style.OTransform = transform;
|
|
766
1096
|
element.style.transform = transform;
|
|
767
1097
|
|
|
768
1098
|
}
|
|
769
1099
|
|
|
1100
|
+
/**
|
|
1101
|
+
* Applies CSS transforms to the slides container. The container
|
|
1102
|
+
* is transformed from two separate sources: layout and the overview
|
|
1103
|
+
* mode.
|
|
1104
|
+
*/
|
|
1105
|
+
function transformSlides( transforms ) {
|
|
1106
|
+
|
|
1107
|
+
// Pick up new transforms from arguments
|
|
1108
|
+
if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout;
|
|
1109
|
+
if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview;
|
|
1110
|
+
|
|
1111
|
+
// Apply the transforms to the slides container
|
|
1112
|
+
if( slidesTransform.layout ) {
|
|
1113
|
+
transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview );
|
|
1114
|
+
}
|
|
1115
|
+
else {
|
|
1116
|
+
transformElement( dom.slides, slidesTransform.overview );
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* Injects the given CSS styles into the DOM.
|
|
1123
|
+
*/
|
|
1124
|
+
function injectStyleSheet( value ) {
|
|
1125
|
+
|
|
1126
|
+
var tag = document.createElement( 'style' );
|
|
1127
|
+
tag.type = 'text/css';
|
|
1128
|
+
if( tag.styleSheet ) {
|
|
1129
|
+
tag.styleSheet.cssText = value;
|
|
1130
|
+
}
|
|
1131
|
+
else {
|
|
1132
|
+
tag.appendChild( document.createTextNode( value ) );
|
|
1133
|
+
}
|
|
1134
|
+
document.getElementsByTagName( 'head' )[0].appendChild( tag );
|
|
1135
|
+
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/**
|
|
1139
|
+
* Converts various color input formats to an {r:0,g:0,b:0} object.
|
|
1140
|
+
*
|
|
1141
|
+
* @param {String} color The string representation of a color,
|
|
1142
|
+
* the following formats are supported:
|
|
1143
|
+
* - #000
|
|
1144
|
+
* - #000000
|
|
1145
|
+
* - rgb(0,0,0)
|
|
1146
|
+
*/
|
|
1147
|
+
function colorToRgb( color ) {
|
|
1148
|
+
|
|
1149
|
+
var hex3 = color.match( /^#([0-9a-f]{3})$/i );
|
|
1150
|
+
if( hex3 && hex3[1] ) {
|
|
1151
|
+
hex3 = hex3[1];
|
|
1152
|
+
return {
|
|
1153
|
+
r: parseInt( hex3.charAt( 0 ), 16 ) * 0x11,
|
|
1154
|
+
g: parseInt( hex3.charAt( 1 ), 16 ) * 0x11,
|
|
1155
|
+
b: parseInt( hex3.charAt( 2 ), 16 ) * 0x11
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
var hex6 = color.match( /^#([0-9a-f]{6})$/i );
|
|
1160
|
+
if( hex6 && hex6[1] ) {
|
|
1161
|
+
hex6 = hex6[1];
|
|
1162
|
+
return {
|
|
1163
|
+
r: parseInt( hex6.substr( 0, 2 ), 16 ),
|
|
1164
|
+
g: parseInt( hex6.substr( 2, 2 ), 16 ),
|
|
1165
|
+
b: parseInt( hex6.substr( 4, 2 ), 16 )
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
var rgb = color.match( /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i );
|
|
1170
|
+
if( rgb ) {
|
|
1171
|
+
return {
|
|
1172
|
+
r: parseInt( rgb[1], 10 ),
|
|
1173
|
+
g: parseInt( rgb[2], 10 ),
|
|
1174
|
+
b: parseInt( rgb[3], 10 )
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
var rgba = color.match( /^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i );
|
|
1179
|
+
if( rgba ) {
|
|
1180
|
+
return {
|
|
1181
|
+
r: parseInt( rgba[1], 10 ),
|
|
1182
|
+
g: parseInt( rgba[2], 10 ),
|
|
1183
|
+
b: parseInt( rgba[3], 10 ),
|
|
1184
|
+
a: parseFloat( rgba[4] )
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
return null;
|
|
1189
|
+
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
/**
|
|
1193
|
+
* Calculates brightness on a scale of 0-255.
|
|
1194
|
+
*
|
|
1195
|
+
* @param color See colorStringToRgb for supported formats.
|
|
1196
|
+
*/
|
|
1197
|
+
function colorBrightness( color ) {
|
|
1198
|
+
|
|
1199
|
+
if( typeof color === 'string' ) color = colorToRgb( color );
|
|
1200
|
+
|
|
1201
|
+
if( color ) {
|
|
1202
|
+
return ( color.r * 299 + color.g * 587 + color.b * 114 ) / 1000;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
return null;
|
|
1206
|
+
|
|
1207
|
+
}
|
|
1208
|
+
|
|
770
1209
|
/**
|
|
771
1210
|
* Retrieves the height of the given element by looking
|
|
772
1211
|
* at the position and height of its immediate children.
|
|
@@ -782,7 +1221,7 @@ var Reveal = (function(){
|
|
|
782
1221
|
|
|
783
1222
|
if( typeof child.offsetTop === 'number' && child.style ) {
|
|
784
1223
|
// Count # of abs children
|
|
785
|
-
if( child.
|
|
1224
|
+
if( window.getComputedStyle( child ).position === 'absolute' ) {
|
|
786
1225
|
absoluteChildren += 1;
|
|
787
1226
|
}
|
|
788
1227
|
|
|
@@ -804,40 +1243,26 @@ var Reveal = (function(){
|
|
|
804
1243
|
|
|
805
1244
|
/**
|
|
806
1245
|
* Returns the remaining height within the parent of the
|
|
807
|
-
* target element
|
|
808
|
-
* siblings.
|
|
1246
|
+
* target element.
|
|
809
1247
|
*
|
|
810
|
-
* remaining height = [parent height] - [
|
|
1248
|
+
* remaining height = [ configured parent height ] - [ current parent height ]
|
|
811
1249
|
*/
|
|
812
1250
|
function getRemainingHeight( element, height ) {
|
|
813
1251
|
|
|
814
1252
|
height = height || 0;
|
|
815
1253
|
|
|
816
1254
|
if( element ) {
|
|
817
|
-
var
|
|
818
|
-
var siblings = parent.childNodes;
|
|
819
|
-
|
|
820
|
-
// Subtract the height of each sibling
|
|
821
|
-
toArray( siblings ).forEach( function( sibling ) {
|
|
822
|
-
|
|
823
|
-
if( typeof sibling.offsetHeight === 'number' && sibling !== element ) {
|
|
1255
|
+
var newHeight, oldHeight = element.style.height;
|
|
824
1256
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1257
|
+
// Change the .stretch element height to 0 in order find the height of all
|
|
1258
|
+
// the other elements
|
|
1259
|
+
element.style.height = '0px';
|
|
1260
|
+
newHeight = height - element.parentNode.offsetHeight;
|
|
828
1261
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
} );
|
|
834
|
-
|
|
835
|
-
var elementStyles = window.getComputedStyle( element );
|
|
836
|
-
|
|
837
|
-
// Subtract the margins of the target element
|
|
838
|
-
height -= parseInt( elementStyles.marginTop, 10 ) +
|
|
839
|
-
parseInt( elementStyles.marginBottom, 10 );
|
|
1262
|
+
// Restore the old height, just in case
|
|
1263
|
+
element.style.height = oldHeight + 'px';
|
|
840
1264
|
|
|
1265
|
+
return newHeight;
|
|
841
1266
|
}
|
|
842
1267
|
|
|
843
1268
|
return height;
|
|
@@ -882,13 +1307,19 @@ var Reveal = (function(){
|
|
|
882
1307
|
* Dispatches an event of the specified type from the
|
|
883
1308
|
* reveal DOM element.
|
|
884
1309
|
*/
|
|
885
|
-
function dispatchEvent( type,
|
|
1310
|
+
function dispatchEvent( type, args ) {
|
|
886
1311
|
|
|
887
|
-
var event = document.createEvent(
|
|
1312
|
+
var event = document.createEvent( 'HTMLEvents', 1, 2 );
|
|
888
1313
|
event.initEvent( type, true, true );
|
|
889
|
-
extend( event,
|
|
1314
|
+
extend( event, args );
|
|
890
1315
|
dom.wrapper.dispatchEvent( event );
|
|
891
1316
|
|
|
1317
|
+
// If we're in an iframe, post each reveal.js event to the
|
|
1318
|
+
// parent window. Used by the notes plugin
|
|
1319
|
+
if( config.postMessageEvents && window.parent !== window.self ) {
|
|
1320
|
+
window.parent.postMessage( JSON.stringify({ namespace: 'reveal', eventName: type, state: getState() }), '*' );
|
|
1321
|
+
}
|
|
1322
|
+
|
|
892
1323
|
}
|
|
893
1324
|
|
|
894
1325
|
/**
|
|
@@ -897,7 +1328,7 @@ var Reveal = (function(){
|
|
|
897
1328
|
function enableRollingLinks() {
|
|
898
1329
|
|
|
899
1330
|
if( features.transforms3d && !( 'msPerspective' in document.body.style ) ) {
|
|
900
|
-
var anchors =
|
|
1331
|
+
var anchors = dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' a' );
|
|
901
1332
|
|
|
902
1333
|
for( var i = 0, len = anchors.length; i < len; i++ ) {
|
|
903
1334
|
var anchor = anchors[i];
|
|
@@ -921,7 +1352,7 @@ var Reveal = (function(){
|
|
|
921
1352
|
*/
|
|
922
1353
|
function disableRollingLinks() {
|
|
923
1354
|
|
|
924
|
-
var anchors =
|
|
1355
|
+
var anchors = dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' a.roll' );
|
|
925
1356
|
|
|
926
1357
|
for( var i = 0, len = anchors.length; i < len; i++ ) {
|
|
927
1358
|
var anchor = anchors[i];
|
|
@@ -968,15 +1399,16 @@ var Reveal = (function(){
|
|
|
968
1399
|
/**
|
|
969
1400
|
* Opens a preview window for the target URL.
|
|
970
1401
|
*/
|
|
971
|
-
function
|
|
1402
|
+
function showPreview( url ) {
|
|
972
1403
|
|
|
973
|
-
|
|
1404
|
+
closeOverlay();
|
|
974
1405
|
|
|
975
|
-
dom.
|
|
976
|
-
dom.
|
|
977
|
-
dom.
|
|
1406
|
+
dom.overlay = document.createElement( 'div' );
|
|
1407
|
+
dom.overlay.classList.add( 'overlay' );
|
|
1408
|
+
dom.overlay.classList.add( 'overlay-preview' );
|
|
1409
|
+
dom.wrapper.appendChild( dom.overlay );
|
|
978
1410
|
|
|
979
|
-
dom.
|
|
1411
|
+
dom.overlay.innerHTML = [
|
|
980
1412
|
'<header>',
|
|
981
1413
|
'<a class="close" href="#"><span class="icon"></span></a>',
|
|
982
1414
|
'<a class="external" href="'+ url +'" target="_blank"><span class="icon"></span></a>',
|
|
@@ -987,34 +1419,78 @@ var Reveal = (function(){
|
|
|
987
1419
|
'</div>'
|
|
988
1420
|
].join('');
|
|
989
1421
|
|
|
990
|
-
dom.
|
|
991
|
-
dom.
|
|
1422
|
+
dom.overlay.querySelector( 'iframe' ).addEventListener( 'load', function( event ) {
|
|
1423
|
+
dom.overlay.classList.add( 'loaded' );
|
|
992
1424
|
}, false );
|
|
993
1425
|
|
|
994
|
-
dom.
|
|
995
|
-
|
|
1426
|
+
dom.overlay.querySelector( '.close' ).addEventListener( 'click', function( event ) {
|
|
1427
|
+
closeOverlay();
|
|
996
1428
|
event.preventDefault();
|
|
997
1429
|
}, false );
|
|
998
1430
|
|
|
999
|
-
dom.
|
|
1000
|
-
|
|
1431
|
+
dom.overlay.querySelector( '.external' ).addEventListener( 'click', function( event ) {
|
|
1432
|
+
closeOverlay();
|
|
1001
1433
|
}, false );
|
|
1002
1434
|
|
|
1003
1435
|
setTimeout( function() {
|
|
1004
|
-
dom.
|
|
1436
|
+
dom.overlay.classList.add( 'visible' );
|
|
1005
1437
|
}, 1 );
|
|
1006
1438
|
|
|
1007
1439
|
}
|
|
1008
1440
|
|
|
1009
1441
|
/**
|
|
1010
|
-
*
|
|
1442
|
+
* Opens a overlay window with help material.
|
|
1011
1443
|
*/
|
|
1012
|
-
function
|
|
1444
|
+
function showHelp() {
|
|
1445
|
+
|
|
1446
|
+
if( config.help ) {
|
|
1447
|
+
|
|
1448
|
+
closeOverlay();
|
|
1449
|
+
|
|
1450
|
+
dom.overlay = document.createElement( 'div' );
|
|
1451
|
+
dom.overlay.classList.add( 'overlay' );
|
|
1452
|
+
dom.overlay.classList.add( 'overlay-help' );
|
|
1453
|
+
dom.wrapper.appendChild( dom.overlay );
|
|
1454
|
+
|
|
1455
|
+
var html = '<p class="title">Keyboard Shortcuts</p><br/>';
|
|
1456
|
+
|
|
1457
|
+
html += '<table><th>KEY</th><th>ACTION</th>';
|
|
1458
|
+
for( var key in keyboardShortcuts ) {
|
|
1459
|
+
html += '<tr><td>' + key + '</td><td>' + keyboardShortcuts[ key ] + '</td></tr>';
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
html += '</table>';
|
|
1463
|
+
|
|
1464
|
+
dom.overlay.innerHTML = [
|
|
1465
|
+
'<header>',
|
|
1466
|
+
'<a class="close" href="#"><span class="icon"></span></a>',
|
|
1467
|
+
'</header>',
|
|
1468
|
+
'<div class="viewport">',
|
|
1469
|
+
'<div class="viewport-inner">'+ html +'</div>',
|
|
1470
|
+
'</div>'
|
|
1471
|
+
].join('');
|
|
1472
|
+
|
|
1473
|
+
dom.overlay.querySelector( '.close' ).addEventListener( 'click', function( event ) {
|
|
1474
|
+
closeOverlay();
|
|
1475
|
+
event.preventDefault();
|
|
1476
|
+
}, false );
|
|
1477
|
+
|
|
1478
|
+
setTimeout( function() {
|
|
1479
|
+
dom.overlay.classList.add( 'visible' );
|
|
1480
|
+
}, 1 );
|
|
1013
1481
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* Closes any currently open overlay.
|
|
1488
|
+
*/
|
|
1489
|
+
function closeOverlay() {
|
|
1490
|
+
|
|
1491
|
+
if( dom.overlay ) {
|
|
1492
|
+
dom.overlay.parentNode.removeChild( dom.overlay );
|
|
1493
|
+
dom.overlay = null;
|
|
1018
1494
|
}
|
|
1019
1495
|
|
|
1020
1496
|
}
|
|
@@ -1027,54 +1503,50 @@ var Reveal = (function(){
|
|
|
1027
1503
|
|
|
1028
1504
|
if( dom.wrapper && !isPrintingPDF() ) {
|
|
1029
1505
|
|
|
1030
|
-
|
|
1031
|
-
var availableWidth = dom.wrapper.offsetWidth,
|
|
1032
|
-
availableHeight = dom.wrapper.offsetHeight;
|
|
1506
|
+
var size = getComputedSlideSize();
|
|
1033
1507
|
|
|
1034
|
-
//
|
|
1035
|
-
availableWidth -= ( availableHeight * config.margin );
|
|
1036
|
-
availableHeight -= ( availableHeight * config.margin );
|
|
1037
|
-
|
|
1038
|
-
// Dimensions of the content
|
|
1039
|
-
var slideWidth = config.width,
|
|
1040
|
-
slideHeight = config.height,
|
|
1041
|
-
slidePadding = 20; // TODO Dig this out of DOM
|
|
1508
|
+
var slidePadding = 20; // TODO Dig this out of DOM
|
|
1042
1509
|
|
|
1043
1510
|
// Layout the contents of the slides
|
|
1044
1511
|
layoutSlideContents( config.width, config.height, slidePadding );
|
|
1045
1512
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
slideWidth = parseInt( slideWidth, 10 ) / 100 * availableWidth;
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
// Slide height may be a percentage of available height
|
|
1052
|
-
if( typeof slideHeight === 'string' && /%$/.test( slideHeight ) ) {
|
|
1053
|
-
slideHeight = parseInt( slideHeight, 10 ) / 100 * availableHeight;
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
dom.slides.style.width = slideWidth + 'px';
|
|
1057
|
-
dom.slides.style.height = slideHeight + 'px';
|
|
1513
|
+
dom.slides.style.width = size.width + 'px';
|
|
1514
|
+
dom.slides.style.height = size.height + 'px';
|
|
1058
1515
|
|
|
1059
1516
|
// Determine scale of content to fit within available space
|
|
1060
|
-
scale = Math.min(
|
|
1517
|
+
scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height );
|
|
1061
1518
|
|
|
1062
1519
|
// Respect max/min scale settings
|
|
1063
1520
|
scale = Math.max( scale, config.minScale );
|
|
1064
1521
|
scale = Math.min( scale, config.maxScale );
|
|
1065
1522
|
|
|
1066
|
-
//
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
dom.slides.style.
|
|
1523
|
+
// Don't apply any scaling styles if scale is 1
|
|
1524
|
+
if( scale === 1 ) {
|
|
1525
|
+
dom.slides.style.zoom = '';
|
|
1526
|
+
dom.slides.style.left = '';
|
|
1527
|
+
dom.slides.style.top = '';
|
|
1528
|
+
dom.slides.style.bottom = '';
|
|
1529
|
+
dom.slides.style.right = '';
|
|
1530
|
+
transformSlides( { layout: '' } );
|
|
1070
1531
|
}
|
|
1071
|
-
// Apply scale transform as a fallback
|
|
1072
1532
|
else {
|
|
1073
|
-
|
|
1533
|
+
// Prefer zooming in desktop Chrome so that content remains crisp
|
|
1534
|
+
if( !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) {
|
|
1535
|
+
dom.slides.style.zoom = scale;
|
|
1536
|
+
transformSlides( { layout: '' } );
|
|
1537
|
+
}
|
|
1538
|
+
// Apply scale transform as a fallback
|
|
1539
|
+
else {
|
|
1540
|
+
dom.slides.style.left = '50%';
|
|
1541
|
+
dom.slides.style.top = '50%';
|
|
1542
|
+
dom.slides.style.bottom = 'auto';
|
|
1543
|
+
dom.slides.style.right = 'auto';
|
|
1544
|
+
transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
|
|
1545
|
+
}
|
|
1074
1546
|
}
|
|
1075
1547
|
|
|
1076
1548
|
// Select all slides, vertical and horizontal
|
|
1077
|
-
var slides = toArray(
|
|
1549
|
+
var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) );
|
|
1078
1550
|
|
|
1079
1551
|
for( var i = 0, len = slides.length; i < len; i++ ) {
|
|
1080
1552
|
var slide = slides[ i ];
|
|
@@ -1091,7 +1563,7 @@ var Reveal = (function(){
|
|
|
1091
1563
|
slide.style.top = 0;
|
|
1092
1564
|
}
|
|
1093
1565
|
else {
|
|
1094
|
-
slide.style.top = Math.max(
|
|
1566
|
+
slide.style.top = Math.max( ( ( size.height - getAbsoluteHeight( slide ) ) / 2 ) - slidePadding, 0 ) + 'px';
|
|
1095
1567
|
}
|
|
1096
1568
|
}
|
|
1097
1569
|
else {
|
|
@@ -1117,7 +1589,7 @@ var Reveal = (function(){
|
|
|
1117
1589
|
toArray( dom.slides.querySelectorAll( 'section > .stretch' ) ).forEach( function( element ) {
|
|
1118
1590
|
|
|
1119
1591
|
// Determine how much vertical space we can use
|
|
1120
|
-
var remainingHeight = getRemainingHeight( element,
|
|
1592
|
+
var remainingHeight = getRemainingHeight( element, height );
|
|
1121
1593
|
|
|
1122
1594
|
// Consider the aspect ratio of media elements
|
|
1123
1595
|
if( /(img|video)/gi.test( element.nodeName ) ) {
|
|
@@ -1139,6 +1611,41 @@ var Reveal = (function(){
|
|
|
1139
1611
|
|
|
1140
1612
|
}
|
|
1141
1613
|
|
|
1614
|
+
/**
|
|
1615
|
+
* Calculates the computed pixel size of our slides. These
|
|
1616
|
+
* values are based on the width and height configuration
|
|
1617
|
+
* options.
|
|
1618
|
+
*/
|
|
1619
|
+
function getComputedSlideSize( presentationWidth, presentationHeight ) {
|
|
1620
|
+
|
|
1621
|
+
var size = {
|
|
1622
|
+
// Slide size
|
|
1623
|
+
width: config.width,
|
|
1624
|
+
height: config.height,
|
|
1625
|
+
|
|
1626
|
+
// Presentation size
|
|
1627
|
+
presentationWidth: presentationWidth || dom.wrapper.offsetWidth,
|
|
1628
|
+
presentationHeight: presentationHeight || dom.wrapper.offsetHeight
|
|
1629
|
+
};
|
|
1630
|
+
|
|
1631
|
+
// Reduce available space by margin
|
|
1632
|
+
size.presentationWidth -= ( size.presentationWidth * config.margin );
|
|
1633
|
+
size.presentationHeight -= ( size.presentationHeight * config.margin );
|
|
1634
|
+
|
|
1635
|
+
// Slide width may be a percentage of available width
|
|
1636
|
+
if( typeof size.width === 'string' && /%$/.test( size.width ) ) {
|
|
1637
|
+
size.width = parseInt( size.width, 10 ) / 100 * size.presentationWidth;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
// Slide height may be a percentage of available height
|
|
1641
|
+
if( typeof size.height === 'string' && /%$/.test( size.height ) ) {
|
|
1642
|
+
size.height = parseInt( size.height, 10 ) / 100 * size.presentationHeight;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
return size;
|
|
1646
|
+
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1142
1649
|
/**
|
|
1143
1650
|
* Stores the vertical index of a stack so that the same
|
|
1144
1651
|
* vertical slide can be selected when navigating to and
|
|
@@ -1176,92 +1683,122 @@ var Reveal = (function(){
|
|
|
1176
1683
|
}
|
|
1177
1684
|
|
|
1178
1685
|
/**
|
|
1179
|
-
* Displays the overview of slides (quick nav) by
|
|
1180
|
-
*
|
|
1181
|
-
*
|
|
1182
|
-
* Experimental feature, might be dropped if perf
|
|
1183
|
-
* can't be improved.
|
|
1686
|
+
* Displays the overview of slides (quick nav) by scaling
|
|
1687
|
+
* down and arranging all slide elements.
|
|
1184
1688
|
*/
|
|
1185
1689
|
function activateOverview() {
|
|
1186
1690
|
|
|
1187
1691
|
// Only proceed if enabled in config
|
|
1188
|
-
if( config.overview ) {
|
|
1692
|
+
if( config.overview && !isOverview() ) {
|
|
1189
1693
|
|
|
1190
|
-
|
|
1191
|
-
cancelAutoSlide();
|
|
1192
|
-
|
|
1193
|
-
var wasActive = dom.wrapper.classList.contains( 'overview' );
|
|
1194
|
-
|
|
1195
|
-
// Vary the depth of the overview based on screen size
|
|
1196
|
-
var depth = window.innerWidth < 400 ? 1000 : 2500;
|
|
1694
|
+
overview = true;
|
|
1197
1695
|
|
|
1198
1696
|
dom.wrapper.classList.add( 'overview' );
|
|
1199
1697
|
dom.wrapper.classList.remove( 'overview-deactivating' );
|
|
1200
1698
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1699
|
+
if( features.overviewTransitions ) {
|
|
1700
|
+
setTimeout( function() {
|
|
1701
|
+
dom.wrapper.classList.add( 'overview-animated' );
|
|
1702
|
+
}, 1 );
|
|
1703
|
+
}
|
|
1203
1704
|
|
|
1204
|
-
//
|
|
1205
|
-
|
|
1206
|
-
// before we can position them
|
|
1207
|
-
activateOverviewTimeout = setTimeout( function() {
|
|
1705
|
+
// Don't auto-slide while in overview mode
|
|
1706
|
+
cancelAutoSlide();
|
|
1208
1707
|
|
|
1209
|
-
|
|
1708
|
+
// Move the backgrounds element into the slide container to
|
|
1709
|
+
// that the same scaling is applied
|
|
1710
|
+
dom.slides.appendChild( dom.background );
|
|
1210
1711
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1712
|
+
// Clicking on an overview slide navigates to it
|
|
1713
|
+
toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
|
|
1714
|
+
if( !slide.classList.contains( 'stack' ) ) {
|
|
1715
|
+
slide.addEventListener( 'click', onOverviewSlideClicked, true );
|
|
1716
|
+
}
|
|
1717
|
+
} );
|
|
1214
1718
|
|
|
1215
|
-
|
|
1719
|
+
updateSlidesVisibility();
|
|
1720
|
+
layoutOverview();
|
|
1721
|
+
updateOverview();
|
|
1216
1722
|
|
|
1217
|
-
|
|
1218
|
-
transformElement( hslide, 'translateZ(-'+ depth +'px) translate(' + ( ( i - indexh ) * hoffset ) + '%, 0%)' );
|
|
1723
|
+
layout();
|
|
1219
1724
|
|
|
1220
|
-
|
|
1725
|
+
// Notify observers of the overview showing
|
|
1726
|
+
dispatchEvent( 'overviewshown', {
|
|
1727
|
+
'indexh': indexh,
|
|
1728
|
+
'indexv': indexv,
|
|
1729
|
+
'currentSlide': currentSlide
|
|
1730
|
+
} );
|
|
1221
1731
|
|
|
1222
|
-
|
|
1732
|
+
}
|
|
1223
1733
|
|
|
1224
|
-
|
|
1225
|
-
var verticalIndex = i === indexh ? indexv : getPreviousVerticalIndex( hslide );
|
|
1734
|
+
}
|
|
1226
1735
|
|
|
1227
|
-
|
|
1736
|
+
/**
|
|
1737
|
+
* Uses CSS transforms to position all slides in a grid for
|
|
1738
|
+
* display inside of the overview mode.
|
|
1739
|
+
*/
|
|
1740
|
+
function layoutOverview() {
|
|
1228
1741
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1742
|
+
var margin = 70;
|
|
1743
|
+
var slideWidth = config.width + margin,
|
|
1744
|
+
slideHeight = config.height + margin;
|
|
1231
1745
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1746
|
+
// Reverse in RTL mode
|
|
1747
|
+
if( config.rtl ) {
|
|
1748
|
+
slideWidth = -slideWidth;
|
|
1749
|
+
}
|
|
1234
1750
|
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1751
|
+
// Layout slides
|
|
1752
|
+
toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) {
|
|
1753
|
+
hslide.setAttribute( 'data-index-h', h );
|
|
1754
|
+
transformElement( hslide, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' );
|
|
1238
1755
|
|
|
1239
|
-
|
|
1240
|
-
else {
|
|
1756
|
+
if( hslide.classList.contains( 'stack' ) ) {
|
|
1241
1757
|
|
|
1242
|
-
|
|
1243
|
-
|
|
1758
|
+
toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) {
|
|
1759
|
+
vslide.setAttribute( 'data-index-h', h );
|
|
1760
|
+
vslide.setAttribute( 'data-index-v', v );
|
|
1244
1761
|
|
|
1245
|
-
|
|
1246
|
-
}
|
|
1762
|
+
transformElement( vslide, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' );
|
|
1763
|
+
} );
|
|
1764
|
+
|
|
1765
|
+
}
|
|
1766
|
+
} );
|
|
1247
1767
|
|
|
1248
|
-
|
|
1768
|
+
// Layout slide backgrounds
|
|
1769
|
+
toArray( dom.background.childNodes ).forEach( function( hbackground, h ) {
|
|
1770
|
+
transformElement( hbackground, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' );
|
|
1249
1771
|
|
|
1250
|
-
|
|
1772
|
+
toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) {
|
|
1773
|
+
transformElement( vbackground, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' );
|
|
1774
|
+
} );
|
|
1775
|
+
} );
|
|
1251
1776
|
|
|
1252
|
-
|
|
1253
|
-
// Notify observers of the overview showing
|
|
1254
|
-
dispatchEvent( 'overviewshown', {
|
|
1255
|
-
'indexh': indexh,
|
|
1256
|
-
'indexv': indexv,
|
|
1257
|
-
'currentSlide': currentSlide
|
|
1258
|
-
} );
|
|
1259
|
-
}
|
|
1777
|
+
}
|
|
1260
1778
|
|
|
1261
|
-
|
|
1779
|
+
/**
|
|
1780
|
+
* Moves the overview viewport to the current slides.
|
|
1781
|
+
* Called each time the current slide changes.
|
|
1782
|
+
*/
|
|
1783
|
+
function updateOverview() {
|
|
1262
1784
|
|
|
1785
|
+
var margin = 70;
|
|
1786
|
+
var slideWidth = config.width + margin,
|
|
1787
|
+
slideHeight = config.height + margin;
|
|
1788
|
+
|
|
1789
|
+
// Reverse in RTL mode
|
|
1790
|
+
if( config.rtl ) {
|
|
1791
|
+
slideWidth = -slideWidth;
|
|
1263
1792
|
}
|
|
1264
1793
|
|
|
1794
|
+
transformSlides( {
|
|
1795
|
+
overview: [
|
|
1796
|
+
'translateX('+ ( -indexh * slideWidth ) +'px)',
|
|
1797
|
+
'translateY('+ ( -indexv * slideHeight ) +'px)',
|
|
1798
|
+
'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)'
|
|
1799
|
+
].join( ' ' )
|
|
1800
|
+
} );
|
|
1801
|
+
|
|
1265
1802
|
}
|
|
1266
1803
|
|
|
1267
1804
|
/**
|
|
@@ -1273,30 +1810,41 @@ var Reveal = (function(){
|
|
|
1273
1810
|
// Only proceed if enabled in config
|
|
1274
1811
|
if( config.overview ) {
|
|
1275
1812
|
|
|
1276
|
-
|
|
1277
|
-
clearTimeout( deactivateOverviewTimeout );
|
|
1813
|
+
overview = false;
|
|
1278
1814
|
|
|
1279
1815
|
dom.wrapper.classList.remove( 'overview' );
|
|
1816
|
+
dom.wrapper.classList.remove( 'overview-animated' );
|
|
1280
1817
|
|
|
1281
1818
|
// Temporarily add a class so that transitions can do different things
|
|
1282
1819
|
// depending on whether they are exiting/entering overview, or just
|
|
1283
1820
|
// moving from slide to slide
|
|
1284
1821
|
dom.wrapper.classList.add( 'overview-deactivating' );
|
|
1285
1822
|
|
|
1286
|
-
|
|
1823
|
+
setTimeout( function () {
|
|
1287
1824
|
dom.wrapper.classList.remove( 'overview-deactivating' );
|
|
1288
1825
|
}, 1 );
|
|
1289
1826
|
|
|
1290
|
-
//
|
|
1291
|
-
|
|
1292
|
-
|
|
1827
|
+
// Move the background element back out
|
|
1828
|
+
dom.wrapper.appendChild( dom.background );
|
|
1829
|
+
|
|
1830
|
+
// Clean up changes made to slides
|
|
1831
|
+
toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
|
|
1293
1832
|
transformElement( slide, '' );
|
|
1294
1833
|
|
|
1295
1834
|
slide.removeEventListener( 'click', onOverviewSlideClicked, true );
|
|
1296
1835
|
} );
|
|
1297
1836
|
|
|
1837
|
+
// Clean up changes made to backgrounds
|
|
1838
|
+
toArray( dom.background.querySelectorAll( '.slide-background' ) ).forEach( function( background ) {
|
|
1839
|
+
transformElement( background, '' );
|
|
1840
|
+
} );
|
|
1841
|
+
|
|
1842
|
+
transformSlides( { overview: '' } );
|
|
1843
|
+
|
|
1298
1844
|
slide( indexh, indexv );
|
|
1299
1845
|
|
|
1846
|
+
layout();
|
|
1847
|
+
|
|
1300
1848
|
cueAutoSlide();
|
|
1301
1849
|
|
|
1302
1850
|
// Notify observers of the overview hiding
|
|
@@ -1335,7 +1883,7 @@ var Reveal = (function(){
|
|
|
1335
1883
|
*/
|
|
1336
1884
|
function isOverview() {
|
|
1337
1885
|
|
|
1338
|
-
return
|
|
1886
|
+
return overview;
|
|
1339
1887
|
|
|
1340
1888
|
}
|
|
1341
1889
|
|
|
@@ -1370,7 +1918,7 @@ var Reveal = (function(){
|
|
|
1370
1918
|
element.webkitRequestFullscreen ||
|
|
1371
1919
|
element.webkitRequestFullScreen ||
|
|
1372
1920
|
element.mozRequestFullScreen ||
|
|
1373
|
-
element.
|
|
1921
|
+
element.msRequestFullscreen;
|
|
1374
1922
|
|
|
1375
1923
|
if( requestMethod ) {
|
|
1376
1924
|
requestMethod.apply( element );
|
|
@@ -1384,13 +1932,15 @@ var Reveal = (function(){
|
|
|
1384
1932
|
*/
|
|
1385
1933
|
function pause() {
|
|
1386
1934
|
|
|
1387
|
-
|
|
1935
|
+
if( config.pause ) {
|
|
1936
|
+
var wasPaused = dom.wrapper.classList.contains( 'paused' );
|
|
1388
1937
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1938
|
+
cancelAutoSlide();
|
|
1939
|
+
dom.wrapper.classList.add( 'paused' );
|
|
1391
1940
|
|
|
1392
|
-
|
|
1393
|
-
|
|
1941
|
+
if( wasPaused === false ) {
|
|
1942
|
+
dispatchEvent( 'paused' );
|
|
1943
|
+
}
|
|
1394
1944
|
}
|
|
1395
1945
|
|
|
1396
1946
|
}
|
|
@@ -1414,13 +1964,13 @@ var Reveal = (function(){
|
|
|
1414
1964
|
/**
|
|
1415
1965
|
* Toggles the paused mode on and off.
|
|
1416
1966
|
*/
|
|
1417
|
-
function togglePause() {
|
|
1967
|
+
function togglePause( override ) {
|
|
1418
1968
|
|
|
1419
|
-
if(
|
|
1420
|
-
resume();
|
|
1969
|
+
if( typeof override === 'boolean' ) {
|
|
1970
|
+
override ? pause() : resume();
|
|
1421
1971
|
}
|
|
1422
1972
|
else {
|
|
1423
|
-
pause();
|
|
1973
|
+
isPaused() ? resume() : pause();
|
|
1424
1974
|
}
|
|
1425
1975
|
|
|
1426
1976
|
}
|
|
@@ -1434,6 +1984,34 @@ var Reveal = (function(){
|
|
|
1434
1984
|
|
|
1435
1985
|
}
|
|
1436
1986
|
|
|
1987
|
+
/**
|
|
1988
|
+
* Toggles the auto slide mode on and off.
|
|
1989
|
+
*
|
|
1990
|
+
* @param {Boolean} override Optional flag which sets the desired state.
|
|
1991
|
+
* True means autoplay starts, false means it stops.
|
|
1992
|
+
*/
|
|
1993
|
+
|
|
1994
|
+
function toggleAutoSlide( override ) {
|
|
1995
|
+
|
|
1996
|
+
if( typeof override === 'boolean' ) {
|
|
1997
|
+
override ? resumeAutoSlide() : pauseAutoSlide();
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
else {
|
|
2001
|
+
autoSlidePaused ? resumeAutoSlide() : pauseAutoSlide();
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
/**
|
|
2007
|
+
* Checks if the auto slide mode is currently on.
|
|
2008
|
+
*/
|
|
2009
|
+
function isAutoSliding() {
|
|
2010
|
+
|
|
2011
|
+
return !!( autoSlide && !autoSlidePaused );
|
|
2012
|
+
|
|
2013
|
+
}
|
|
2014
|
+
|
|
1437
2015
|
/**
|
|
1438
2016
|
* Steps from the current point in the presentation to the
|
|
1439
2017
|
* slide which matches the specified horizontal and vertical
|
|
@@ -1451,11 +2029,11 @@ var Reveal = (function(){
|
|
|
1451
2029
|
previousSlide = currentSlide;
|
|
1452
2030
|
|
|
1453
2031
|
// Query all horizontal slides in the deck
|
|
1454
|
-
var horizontalSlides =
|
|
2032
|
+
var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );
|
|
1455
2033
|
|
|
1456
2034
|
// If no vertical index is specified and the upcoming slide is a
|
|
1457
2035
|
// stack, resume at its previous vertical index
|
|
1458
|
-
if( v === undefined ) {
|
|
2036
|
+
if( v === undefined && !isOverview() ) {
|
|
1459
2037
|
v = getPreviousVerticalIndex( horizontalSlides[ h ] );
|
|
1460
2038
|
}
|
|
1461
2039
|
|
|
@@ -1505,9 +2083,9 @@ var Reveal = (function(){
|
|
|
1505
2083
|
document.documentElement.classList.remove( stateBefore.pop() );
|
|
1506
2084
|
}
|
|
1507
2085
|
|
|
1508
|
-
//
|
|
2086
|
+
// Update the overview if it's currently active
|
|
1509
2087
|
if( isOverview() ) {
|
|
1510
|
-
|
|
2088
|
+
updateOverview();
|
|
1511
2089
|
}
|
|
1512
2090
|
|
|
1513
2091
|
// Find the current horizontal slide and any possible vertical slides
|
|
@@ -1544,13 +2122,14 @@ var Reveal = (function(){
|
|
|
1544
2122
|
// stacks
|
|
1545
2123
|
if( previousSlide ) {
|
|
1546
2124
|
previousSlide.classList.remove( 'present' );
|
|
2125
|
+
previousSlide.setAttribute( 'aria-hidden', 'true' );
|
|
1547
2126
|
|
|
1548
2127
|
// Reset all slides upon navigate to home
|
|
1549
2128
|
// Issue: #285
|
|
1550
|
-
if (
|
|
2129
|
+
if ( dom.wrapper.querySelector( HOME_SLIDE_SELECTOR ).classList.contains( 'present' ) ) {
|
|
1551
2130
|
// Launch async task
|
|
1552
2131
|
setTimeout( function () {
|
|
1553
|
-
var slides = toArray(
|
|
2132
|
+
var slides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.stack') ), i;
|
|
1554
2133
|
for( i in slides ) {
|
|
1555
2134
|
if( slides[i] ) {
|
|
1556
2135
|
// Reset stack
|
|
@@ -1562,11 +2141,14 @@ var Reveal = (function(){
|
|
|
1562
2141
|
}
|
|
1563
2142
|
|
|
1564
2143
|
// Handle embedded content
|
|
1565
|
-
if( slideChanged ) {
|
|
2144
|
+
if( slideChanged || !previousSlide ) {
|
|
1566
2145
|
stopEmbeddedContent( previousSlide );
|
|
1567
2146
|
startEmbeddedContent( currentSlide );
|
|
1568
2147
|
}
|
|
1569
2148
|
|
|
2149
|
+
// Announce the current slide contents, for screen readers
|
|
2150
|
+
dom.statusDiv.textContent = currentSlide.textContent;
|
|
2151
|
+
|
|
1570
2152
|
updateControls();
|
|
1571
2153
|
updateProgress();
|
|
1572
2154
|
updateBackground();
|
|
@@ -1603,12 +2185,23 @@ var Reveal = (function(){
|
|
|
1603
2185
|
// Re-create the slide backgrounds
|
|
1604
2186
|
createBackgrounds();
|
|
1605
2187
|
|
|
2188
|
+
// Write the current hash to the URL
|
|
2189
|
+
writeURL();
|
|
2190
|
+
|
|
1606
2191
|
sortAllFragments();
|
|
1607
2192
|
|
|
1608
2193
|
updateControls();
|
|
1609
2194
|
updateProgress();
|
|
1610
2195
|
updateBackground( true );
|
|
1611
2196
|
updateSlideNumber();
|
|
2197
|
+
updateSlidesVisibility();
|
|
2198
|
+
|
|
2199
|
+
formatEmbeddedContent();
|
|
2200
|
+
startEmbeddedContent( currentSlide );
|
|
2201
|
+
|
|
2202
|
+
if( isOverview() ) {
|
|
2203
|
+
layoutOverview();
|
|
2204
|
+
}
|
|
1612
2205
|
|
|
1613
2206
|
}
|
|
1614
2207
|
|
|
@@ -1618,7 +2211,7 @@ var Reveal = (function(){
|
|
|
1618
2211
|
*/
|
|
1619
2212
|
function resetVerticalSlides() {
|
|
1620
2213
|
|
|
1621
|
-
var horizontalSlides = toArray(
|
|
2214
|
+
var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
|
1622
2215
|
horizontalSlides.forEach( function( horizontalSlide ) {
|
|
1623
2216
|
|
|
1624
2217
|
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
|
@@ -1628,6 +2221,7 @@ var Reveal = (function(){
|
|
|
1628
2221
|
verticalSlide.classList.remove( 'present' );
|
|
1629
2222
|
verticalSlide.classList.remove( 'past' );
|
|
1630
2223
|
verticalSlide.classList.add( 'future' );
|
|
2224
|
+
verticalSlide.setAttribute( 'aria-hidden', 'true' );
|
|
1631
2225
|
}
|
|
1632
2226
|
|
|
1633
2227
|
} );
|
|
@@ -1642,7 +2236,7 @@ var Reveal = (function(){
|
|
|
1642
2236
|
*/
|
|
1643
2237
|
function sortAllFragments() {
|
|
1644
2238
|
|
|
1645
|
-
var horizontalSlides = toArray(
|
|
2239
|
+
var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
|
1646
2240
|
horizontalSlides.forEach( function( horizontalSlide ) {
|
|
1647
2241
|
|
|
1648
2242
|
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
|
@@ -1675,9 +2269,11 @@ var Reveal = (function(){
|
|
|
1675
2269
|
|
|
1676
2270
|
// Select all slides and convert the NodeList result to
|
|
1677
2271
|
// an array
|
|
1678
|
-
var slides = toArray(
|
|
2272
|
+
var slides = toArray( dom.wrapper.querySelectorAll( selector ) ),
|
|
1679
2273
|
slidesLength = slides.length;
|
|
1680
2274
|
|
|
2275
|
+
var printMode = isPrintingPDF();
|
|
2276
|
+
|
|
1681
2277
|
if( slidesLength ) {
|
|
1682
2278
|
|
|
1683
2279
|
// Should the index loop?
|
|
@@ -1703,43 +2299,55 @@ var Reveal = (function(){
|
|
|
1703
2299
|
|
|
1704
2300
|
// http://www.w3.org/html/wg/drafts/html/master/editing.html#the-hidden-attribute
|
|
1705
2301
|
element.setAttribute( 'hidden', '' );
|
|
2302
|
+
element.setAttribute( 'aria-hidden', 'true' );
|
|
2303
|
+
|
|
2304
|
+
// If this element contains vertical slides
|
|
2305
|
+
if( element.querySelector( 'section' ) ) {
|
|
2306
|
+
element.classList.add( 'stack' );
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
// If we're printing static slides, all slides are "present"
|
|
2310
|
+
if( printMode ) {
|
|
2311
|
+
element.classList.add( 'present' );
|
|
2312
|
+
continue;
|
|
2313
|
+
}
|
|
1706
2314
|
|
|
1707
2315
|
if( i < index ) {
|
|
1708
2316
|
// Any element previous to index is given the 'past' class
|
|
1709
2317
|
element.classList.add( reverse ? 'future' : 'past' );
|
|
1710
2318
|
|
|
1711
|
-
|
|
2319
|
+
if( config.fragments ) {
|
|
2320
|
+
var pastFragments = toArray( element.querySelectorAll( '.fragment' ) );
|
|
1712
2321
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
2322
|
+
// Show all fragments on prior slides
|
|
2323
|
+
while( pastFragments.length ) {
|
|
2324
|
+
var pastFragment = pastFragments.pop();
|
|
2325
|
+
pastFragment.classList.add( 'visible' );
|
|
2326
|
+
pastFragment.classList.remove( 'current-fragment' );
|
|
2327
|
+
}
|
|
1718
2328
|
}
|
|
1719
2329
|
}
|
|
1720
2330
|
else if( i > index ) {
|
|
1721
2331
|
// Any element subsequent to index is given the 'future' class
|
|
1722
2332
|
element.classList.add( reverse ? 'past' : 'future' );
|
|
1723
2333
|
|
|
1724
|
-
|
|
2334
|
+
if( config.fragments ) {
|
|
2335
|
+
var futureFragments = toArray( element.querySelectorAll( '.fragment.visible' ) );
|
|
1725
2336
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
2337
|
+
// No fragments in future slides should be visible ahead of time
|
|
2338
|
+
while( futureFragments.length ) {
|
|
2339
|
+
var futureFragment = futureFragments.pop();
|
|
2340
|
+
futureFragment.classList.remove( 'visible' );
|
|
2341
|
+
futureFragment.classList.remove( 'current-fragment' );
|
|
2342
|
+
}
|
|
1731
2343
|
}
|
|
1732
2344
|
}
|
|
1733
|
-
|
|
1734
|
-
// If this element contains vertical slides
|
|
1735
|
-
if( element.querySelector( 'section' ) ) {
|
|
1736
|
-
element.classList.add( 'stack' );
|
|
1737
|
-
}
|
|
1738
2345
|
}
|
|
1739
2346
|
|
|
1740
2347
|
// Mark the current slide as present
|
|
1741
2348
|
slides[index].classList.add( 'present' );
|
|
1742
2349
|
slides[index].removeAttribute( 'hidden' );
|
|
2350
|
+
slides[index].removeAttribute( 'aria-hidden' );
|
|
1743
2351
|
|
|
1744
2352
|
// If this slide has a state associated with it, add it
|
|
1745
2353
|
// onto the current state of the deck
|
|
@@ -1767,12 +2375,12 @@ var Reveal = (function(){
|
|
|
1767
2375
|
|
|
1768
2376
|
// Select all slides and convert the NodeList result to
|
|
1769
2377
|
// an array
|
|
1770
|
-
var horizontalSlides = toArray(
|
|
2378
|
+
var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ),
|
|
1771
2379
|
horizontalSlidesLength = horizontalSlides.length,
|
|
1772
2380
|
distanceX,
|
|
1773
2381
|
distanceY;
|
|
1774
2382
|
|
|
1775
|
-
if( horizontalSlidesLength ) {
|
|
2383
|
+
if( horizontalSlidesLength && typeof indexh !== 'undefined' ) {
|
|
1776
2384
|
|
|
1777
2385
|
// The number of steps away from the present slide that will
|
|
1778
2386
|
// be visible
|
|
@@ -1780,7 +2388,12 @@ var Reveal = (function(){
|
|
|
1780
2388
|
|
|
1781
2389
|
// Limit view distance on weaker devices
|
|
1782
2390
|
if( isMobileDevice ) {
|
|
1783
|
-
viewDistance = isOverview() ? 6 :
|
|
2391
|
+
viewDistance = isOverview() ? 6 : 2;
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2394
|
+
// All slides need to be visible when exporting to PDF
|
|
2395
|
+
if( isPrintingPDF() ) {
|
|
2396
|
+
viewDistance = Number.MAX_VALUE;
|
|
1784
2397
|
}
|
|
1785
2398
|
|
|
1786
2399
|
for( var x = 0; x < horizontalSlidesLength; x++ ) {
|
|
@@ -1789,11 +2402,22 @@ var Reveal = (function(){
|
|
|
1789
2402
|
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ),
|
|
1790
2403
|
verticalSlidesLength = verticalSlides.length;
|
|
1791
2404
|
|
|
1792
|
-
//
|
|
1793
|
-
distanceX = Math.abs( ( indexh
|
|
2405
|
+
// Determine how far away this slide is from the present
|
|
2406
|
+
distanceX = Math.abs( ( indexh || 0 ) - x ) || 0;
|
|
2407
|
+
|
|
2408
|
+
// If the presentation is looped, distance should measure
|
|
2409
|
+
// 1 between the first and last slides
|
|
2410
|
+
if( config.loop ) {
|
|
2411
|
+
distanceX = Math.abs( ( ( indexh || 0 ) - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0;
|
|
2412
|
+
}
|
|
1794
2413
|
|
|
1795
2414
|
// Show the horizontal slide if it's within the view distance
|
|
1796
|
-
|
|
2415
|
+
if( distanceX < viewDistance ) {
|
|
2416
|
+
showSlide( horizontalSlide );
|
|
2417
|
+
}
|
|
2418
|
+
else {
|
|
2419
|
+
hideSlide( horizontalSlide );
|
|
2420
|
+
}
|
|
1797
2421
|
|
|
1798
2422
|
if( verticalSlidesLength ) {
|
|
1799
2423
|
|
|
@@ -1802,9 +2426,14 @@ var Reveal = (function(){
|
|
|
1802
2426
|
for( var y = 0; y < verticalSlidesLength; y++ ) {
|
|
1803
2427
|
var verticalSlide = verticalSlides[y];
|
|
1804
2428
|
|
|
1805
|
-
distanceY = x === indexh ? Math.abs( indexv - y ) : Math.abs( y - oy );
|
|
2429
|
+
distanceY = x === ( indexh || 0 ) ? Math.abs( ( indexv || 0 ) - y ) : Math.abs( y - oy );
|
|
1806
2430
|
|
|
1807
|
-
|
|
2431
|
+
if( distanceX + distanceY < viewDistance ) {
|
|
2432
|
+
showSlide( verticalSlide );
|
|
2433
|
+
}
|
|
2434
|
+
else {
|
|
2435
|
+
hideSlide( verticalSlide );
|
|
2436
|
+
}
|
|
1808
2437
|
}
|
|
1809
2438
|
|
|
1810
2439
|
}
|
|
@@ -1820,44 +2449,9 @@ var Reveal = (function(){
|
|
|
1820
2449
|
function updateProgress() {
|
|
1821
2450
|
|
|
1822
2451
|
// Update progress if enabled
|
|
1823
|
-
if( config.progress && dom.
|
|
1824
|
-
|
|
1825
|
-
var horizontalSlides = toArray( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
|
1826
|
-
|
|
1827
|
-
// The number of past and total slides
|
|
1828
|
-
var totalCount = document.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' ).length;
|
|
1829
|
-
var pastCount = 0;
|
|
2452
|
+
if( config.progress && dom.progressbar ) {
|
|
1830
2453
|
|
|
1831
|
-
|
|
1832
|
-
mainLoop: for( var i = 0; i < horizontalSlides.length; i++ ) {
|
|
1833
|
-
|
|
1834
|
-
var horizontalSlide = horizontalSlides[i];
|
|
1835
|
-
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
|
1836
|
-
|
|
1837
|
-
for( var j = 0; j < verticalSlides.length; j++ ) {
|
|
1838
|
-
|
|
1839
|
-
// Stop as soon as we arrive at the present
|
|
1840
|
-
if( verticalSlides[j].classList.contains( 'present' ) ) {
|
|
1841
|
-
break mainLoop;
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
pastCount++;
|
|
1845
|
-
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
// Stop as soon as we arrive at the present
|
|
1849
|
-
if( horizontalSlide.classList.contains( 'present' ) ) {
|
|
1850
|
-
break;
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
|
-
// Don't count the wrapping section for vertical slides
|
|
1854
|
-
if( horizontalSlide.classList.contains( 'stack' ) === false ) {
|
|
1855
|
-
pastCount++;
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
}
|
|
1859
|
-
|
|
1860
|
-
dom.progressbar.style.width = ( pastCount / ( totalCount - 1 ) ) * window.innerWidth + 'px';
|
|
2454
|
+
dom.progressbar.style.width = getProgress() * dom.wrapper.offsetWidth + 'px';
|
|
1861
2455
|
|
|
1862
2456
|
}
|
|
1863
2457
|
|
|
@@ -1865,19 +2459,31 @@ var Reveal = (function(){
|
|
|
1865
2459
|
|
|
1866
2460
|
/**
|
|
1867
2461
|
* Updates the slide number div to reflect the current slide.
|
|
2462
|
+
*
|
|
2463
|
+
* Slide number format can be defined as a string using the
|
|
2464
|
+
* following variables:
|
|
2465
|
+
* h: current slide's horizontal index
|
|
2466
|
+
* v: current slide's vertical index
|
|
2467
|
+
* c: current slide index (flattened)
|
|
2468
|
+
* t: total number of slides (flattened)
|
|
1868
2469
|
*/
|
|
1869
2470
|
function updateSlideNumber() {
|
|
1870
2471
|
|
|
1871
2472
|
// Update slide number if enabled
|
|
1872
2473
|
if( config.slideNumber && dom.slideNumber) {
|
|
1873
2474
|
|
|
1874
|
-
//
|
|
1875
|
-
var
|
|
1876
|
-
|
|
1877
|
-
|
|
2475
|
+
// Default to only showing the current slide number
|
|
2476
|
+
var format = 'c';
|
|
2477
|
+
|
|
2478
|
+
// Check if a custom slide number format is available
|
|
2479
|
+
if( typeof config.slideNumber === 'string' ) {
|
|
2480
|
+
format = config.slideNumber;
|
|
1878
2481
|
}
|
|
1879
2482
|
|
|
1880
|
-
dom.slideNumber.innerHTML =
|
|
2483
|
+
dom.slideNumber.innerHTML = format.replace( /h/g, indexh )
|
|
2484
|
+
.replace( /v/g, indexv )
|
|
2485
|
+
.replace( /c/g, getSlidePastCount() + 1 )
|
|
2486
|
+
.replace( /t/g, getTotalSlides() );
|
|
1881
2487
|
}
|
|
1882
2488
|
|
|
1883
2489
|
}
|
|
@@ -1951,43 +2557,76 @@ var Reveal = (function(){
|
|
|
1951
2557
|
// states of their slides (past/present/future)
|
|
1952
2558
|
toArray( dom.background.childNodes ).forEach( function( backgroundh, h ) {
|
|
1953
2559
|
|
|
2560
|
+
backgroundh.classList.remove( 'past' );
|
|
2561
|
+
backgroundh.classList.remove( 'present' );
|
|
2562
|
+
backgroundh.classList.remove( 'future' );
|
|
2563
|
+
|
|
1954
2564
|
if( h < indexh ) {
|
|
1955
|
-
backgroundh.
|
|
2565
|
+
backgroundh.classList.add( horizontalPast );
|
|
1956
2566
|
}
|
|
1957
2567
|
else if ( h > indexh ) {
|
|
1958
|
-
backgroundh.
|
|
2568
|
+
backgroundh.classList.add( horizontalFuture );
|
|
1959
2569
|
}
|
|
1960
2570
|
else {
|
|
1961
|
-
backgroundh.
|
|
2571
|
+
backgroundh.classList.add( 'present' );
|
|
1962
2572
|
|
|
1963
2573
|
// Store a reference to the current background element
|
|
1964
2574
|
currentBackground = backgroundh;
|
|
1965
2575
|
}
|
|
1966
2576
|
|
|
1967
2577
|
if( includeAll || h === indexh ) {
|
|
1968
|
-
toArray( backgroundh.
|
|
2578
|
+
toArray( backgroundh.querySelectorAll( '.slide-background' ) ).forEach( function( backgroundv, v ) {
|
|
2579
|
+
|
|
2580
|
+
backgroundv.classList.remove( 'past' );
|
|
2581
|
+
backgroundv.classList.remove( 'present' );
|
|
2582
|
+
backgroundv.classList.remove( 'future' );
|
|
1969
2583
|
|
|
1970
2584
|
if( v < indexv ) {
|
|
1971
|
-
backgroundv.
|
|
2585
|
+
backgroundv.classList.add( 'past' );
|
|
1972
2586
|
}
|
|
1973
2587
|
else if ( v > indexv ) {
|
|
1974
|
-
backgroundv.
|
|
2588
|
+
backgroundv.classList.add( 'future' );
|
|
1975
2589
|
}
|
|
1976
2590
|
else {
|
|
1977
|
-
backgroundv.
|
|
2591
|
+
backgroundv.classList.add( 'present' );
|
|
1978
2592
|
|
|
1979
2593
|
// Only if this is the present horizontal and vertical slide
|
|
1980
2594
|
if( h === indexh ) currentBackground = backgroundv;
|
|
1981
2595
|
}
|
|
1982
2596
|
|
|
1983
|
-
} );
|
|
2597
|
+
} );
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
} );
|
|
2601
|
+
|
|
2602
|
+
// Stop any currently playing video background
|
|
2603
|
+
if( previousBackground ) {
|
|
2604
|
+
|
|
2605
|
+
var previousVideo = previousBackground.querySelector( 'video' );
|
|
2606
|
+
if( previousVideo ) previousVideo.pause();
|
|
2607
|
+
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
if( currentBackground ) {
|
|
2611
|
+
|
|
2612
|
+
// Start video playback
|
|
2613
|
+
var currentVideo = currentBackground.querySelector( 'video' );
|
|
2614
|
+
if( currentVideo ) {
|
|
2615
|
+
currentVideo.currentTime = 0;
|
|
2616
|
+
currentVideo.play();
|
|
1984
2617
|
}
|
|
1985
2618
|
|
|
1986
|
-
|
|
2619
|
+
var backgroundImageURL = currentBackground.style.backgroundImage || '';
|
|
1987
2620
|
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
2621
|
+
// Restart GIFs (doesn't work in Firefox)
|
|
2622
|
+
if( /\.gif/i.test( backgroundImageURL ) ) {
|
|
2623
|
+
currentBackground.style.backgroundImage = '';
|
|
2624
|
+
window.getComputedStyle( currentBackground ).opacity;
|
|
2625
|
+
currentBackground.style.backgroundImage = backgroundImageURL;
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
// Don't transition between identical backgrounds. This
|
|
2629
|
+
// prevents unwanted flicker.
|
|
1991
2630
|
var previousBackgroundHash = previousBackground ? previousBackground.getAttribute( 'data-background-hash' ) : null;
|
|
1992
2631
|
var currentBackgroundHash = currentBackground.getAttribute( 'data-background-hash' );
|
|
1993
2632
|
if( currentBackgroundHash && currentBackgroundHash === previousBackgroundHash && currentBackground !== previousBackground ) {
|
|
@@ -1995,6 +2634,20 @@ var Reveal = (function(){
|
|
|
1995
2634
|
}
|
|
1996
2635
|
|
|
1997
2636
|
previousBackground = currentBackground;
|
|
2637
|
+
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
// If there's a background brightness flag for this slide,
|
|
2641
|
+
// bubble it to the .reveal container
|
|
2642
|
+
if( currentSlide ) {
|
|
2643
|
+
[ 'has-light-background', 'has-dark-background' ].forEach( function( classToBubble ) {
|
|
2644
|
+
if( currentSlide.classList.contains( classToBubble ) ) {
|
|
2645
|
+
dom.wrapper.classList.add( classToBubble );
|
|
2646
|
+
}
|
|
2647
|
+
else {
|
|
2648
|
+
dom.wrapper.classList.remove( classToBubble );
|
|
2649
|
+
}
|
|
2650
|
+
} );
|
|
1998
2651
|
}
|
|
1999
2652
|
|
|
2000
2653
|
// Allow the first background to apply without transition
|
|
@@ -2012,8 +2665,8 @@ var Reveal = (function(){
|
|
|
2012
2665
|
|
|
2013
2666
|
if( config.parallaxBackgroundImage ) {
|
|
2014
2667
|
|
|
2015
|
-
var horizontalSlides =
|
|
2016
|
-
verticalSlides =
|
|
2668
|
+
var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
|
|
2669
|
+
verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
|
|
2017
2670
|
|
|
2018
2671
|
var backgroundSize = dom.background.style.backgroundSize.split( ' ' ),
|
|
2019
2672
|
backgroundWidth, backgroundHeight;
|
|
@@ -2026,16 +2679,138 @@ var Reveal = (function(){
|
|
|
2026
2679
|
backgroundHeight = parseInt( backgroundSize[1], 10 );
|
|
2027
2680
|
}
|
|
2028
2681
|
|
|
2029
|
-
var slideWidth = dom.background.offsetWidth
|
|
2030
|
-
|
|
2031
|
-
|
|
2682
|
+
var slideWidth = dom.background.offsetWidth,
|
|
2683
|
+
horizontalSlideCount = horizontalSlides.length,
|
|
2684
|
+
horizontalOffsetMultiplier,
|
|
2685
|
+
horizontalOffset;
|
|
2686
|
+
|
|
2687
|
+
if( typeof config.parallaxBackgroundHorizontal === 'number' ) {
|
|
2688
|
+
horizontalOffsetMultiplier = config.parallaxBackgroundHorizontal;
|
|
2689
|
+
}
|
|
2690
|
+
else {
|
|
2691
|
+
horizontalOffsetMultiplier = ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 );
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
horizontalOffset = horizontalOffsetMultiplier * indexh * -1;
|
|
2695
|
+
|
|
2696
|
+
var slideHeight = dom.background.offsetHeight,
|
|
2697
|
+
verticalSlideCount = verticalSlides.length,
|
|
2698
|
+
verticalOffsetMultiplier,
|
|
2699
|
+
verticalOffset;
|
|
2700
|
+
|
|
2701
|
+
if( typeof config.parallaxBackgroundVertical === 'number' ) {
|
|
2702
|
+
verticalOffsetMultiplier = config.parallaxBackgroundVertical;
|
|
2703
|
+
}
|
|
2704
|
+
else {
|
|
2705
|
+
verticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 );
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
verticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indexv * 1 : 0;
|
|
2709
|
+
|
|
2710
|
+
dom.background.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px';
|
|
2711
|
+
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
/**
|
|
2717
|
+
* Called when the given slide is within the configured view
|
|
2718
|
+
* distance. Shows the slide element and loads any content
|
|
2719
|
+
* that is set to load lazily (data-src).
|
|
2720
|
+
*/
|
|
2721
|
+
function showSlide( slide ) {
|
|
2722
|
+
|
|
2723
|
+
// Show the slide element
|
|
2724
|
+
slide.style.display = 'block';
|
|
2725
|
+
|
|
2726
|
+
// Media elements with data-src attributes
|
|
2727
|
+
toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) {
|
|
2728
|
+
element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
|
|
2729
|
+
element.removeAttribute( 'data-src' );
|
|
2730
|
+
} );
|
|
2731
|
+
|
|
2732
|
+
// Media elements with <source> children
|
|
2733
|
+
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( media ) {
|
|
2734
|
+
var sources = 0;
|
|
2735
|
+
|
|
2736
|
+
toArray( media.querySelectorAll( 'source[data-src]' ) ).forEach( function( source ) {
|
|
2737
|
+
source.setAttribute( 'src', source.getAttribute( 'data-src' ) );
|
|
2738
|
+
source.removeAttribute( 'data-src' );
|
|
2739
|
+
sources += 1;
|
|
2740
|
+
} );
|
|
2741
|
+
|
|
2742
|
+
// If we rewrote sources for this video/audio element, we need
|
|
2743
|
+
// to manually tell it to load from its new origin
|
|
2744
|
+
if( sources > 0 ) {
|
|
2745
|
+
media.load();
|
|
2746
|
+
}
|
|
2747
|
+
} );
|
|
2748
|
+
|
|
2749
|
+
|
|
2750
|
+
// Show the corresponding background element
|
|
2751
|
+
var indices = getIndices( slide );
|
|
2752
|
+
var background = getSlideBackground( indices.h, indices.v );
|
|
2753
|
+
if( background ) {
|
|
2754
|
+
background.style.display = 'block';
|
|
2755
|
+
|
|
2756
|
+
// If the background contains media, load it
|
|
2757
|
+
if( background.hasAttribute( 'data-loaded' ) === false ) {
|
|
2758
|
+
background.setAttribute( 'data-loaded', 'true' );
|
|
2759
|
+
|
|
2760
|
+
var backgroundImage = slide.getAttribute( 'data-background-image' ),
|
|
2761
|
+
backgroundVideo = slide.getAttribute( 'data-background-video' ),
|
|
2762
|
+
backgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ),
|
|
2763
|
+
backgroundIframe = slide.getAttribute( 'data-background-iframe' );
|
|
2764
|
+
|
|
2765
|
+
// Images
|
|
2766
|
+
if( backgroundImage ) {
|
|
2767
|
+
background.style.backgroundImage = 'url('+ backgroundImage +')';
|
|
2768
|
+
}
|
|
2769
|
+
// Videos
|
|
2770
|
+
else if ( backgroundVideo && !isSpeakerNotes() ) {
|
|
2771
|
+
var video = document.createElement( 'video' );
|
|
2772
|
+
|
|
2773
|
+
if( backgroundVideoLoop ) {
|
|
2774
|
+
video.setAttribute( 'loop', '' );
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
// Support comma separated lists of video sources
|
|
2778
|
+
backgroundVideo.split( ',' ).forEach( function( source ) {
|
|
2779
|
+
video.innerHTML += '<source src="'+ source +'">';
|
|
2780
|
+
} );
|
|
2781
|
+
|
|
2782
|
+
background.appendChild( video );
|
|
2783
|
+
}
|
|
2784
|
+
// Iframes
|
|
2785
|
+
else if( backgroundIframe ) {
|
|
2786
|
+
var iframe = document.createElement( 'iframe' );
|
|
2787
|
+
iframe.setAttribute( 'src', backgroundIframe );
|
|
2788
|
+
iframe.style.width = '100%';
|
|
2789
|
+
iframe.style.height = '100%';
|
|
2790
|
+
iframe.style.maxHeight = '100%';
|
|
2791
|
+
iframe.style.maxWidth = '100%';
|
|
2792
|
+
|
|
2793
|
+
background.appendChild( iframe );
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
}
|
|
2032
2799
|
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2800
|
+
/**
|
|
2801
|
+
* Called when the given slide is moved outside of the
|
|
2802
|
+
* configured view distance.
|
|
2803
|
+
*/
|
|
2804
|
+
function hideSlide( slide ) {
|
|
2036
2805
|
|
|
2037
|
-
|
|
2806
|
+
// Hide the slide element
|
|
2807
|
+
slide.style.display = 'none';
|
|
2038
2808
|
|
|
2809
|
+
// Hide the corresponding background element
|
|
2810
|
+
var indices = getIndices( slide );
|
|
2811
|
+
var background = getSlideBackground( indices.h, indices.v );
|
|
2812
|
+
if( background ) {
|
|
2813
|
+
background.style.display = 'none';
|
|
2039
2814
|
}
|
|
2040
2815
|
|
|
2041
2816
|
}
|
|
@@ -2047,8 +2822,8 @@ var Reveal = (function(){
|
|
|
2047
2822
|
*/
|
|
2048
2823
|
function availableRoutes() {
|
|
2049
2824
|
|
|
2050
|
-
var horizontalSlides =
|
|
2051
|
-
verticalSlides =
|
|
2825
|
+
var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
|
|
2826
|
+
verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
|
|
2052
2827
|
|
|
2053
2828
|
var routes = {
|
|
2054
2829
|
left: indexh > 0 || config.loop,
|
|
@@ -2091,6 +2866,30 @@ var Reveal = (function(){
|
|
|
2091
2866
|
|
|
2092
2867
|
}
|
|
2093
2868
|
|
|
2869
|
+
/**
|
|
2870
|
+
* Enforces origin-specific format rules for embedded media.
|
|
2871
|
+
*/
|
|
2872
|
+
function formatEmbeddedContent() {
|
|
2873
|
+
|
|
2874
|
+
var _appendParamToIframeSource = function( sourceAttribute, sourceURL, param ) {
|
|
2875
|
+
toArray( dom.slides.querySelectorAll( 'iframe['+ sourceAttribute +'*="'+ sourceURL +'"]' ) ).forEach( function( el ) {
|
|
2876
|
+
var src = el.getAttribute( sourceAttribute );
|
|
2877
|
+
if( src && src.indexOf( param ) === -1 ) {
|
|
2878
|
+
el.setAttribute( sourceAttribute, src + ( !/\?/.test( src ) ? '?' : '&' ) + param );
|
|
2879
|
+
}
|
|
2880
|
+
});
|
|
2881
|
+
};
|
|
2882
|
+
|
|
2883
|
+
// YouTube frames must include "?enablejsapi=1"
|
|
2884
|
+
_appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' );
|
|
2885
|
+
_appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' );
|
|
2886
|
+
|
|
2887
|
+
// Vimeo frames must include "?api=1"
|
|
2888
|
+
_appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' );
|
|
2889
|
+
_appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' );
|
|
2890
|
+
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2094
2893
|
/**
|
|
2095
2894
|
* Start playback of any embedded content inside of
|
|
2096
2895
|
* the targeted slide.
|
|
@@ -2098,24 +2897,56 @@ var Reveal = (function(){
|
|
|
2098
2897
|
function startEmbeddedContent( slide ) {
|
|
2099
2898
|
|
|
2100
2899
|
if( slide && !isSpeakerNotes() ) {
|
|
2900
|
+
// Restart GIFs
|
|
2901
|
+
toArray( slide.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) {
|
|
2902
|
+
// Setting the same unchanged source like this was confirmed
|
|
2903
|
+
// to work in Chrome, FF & Safari
|
|
2904
|
+
el.setAttribute( 'src', el.getAttribute( 'src' ) );
|
|
2905
|
+
} );
|
|
2906
|
+
|
|
2101
2907
|
// HTML5 media elements
|
|
2102
2908
|
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
|
2103
|
-
if( el.hasAttribute( 'data-autoplay' ) ) {
|
|
2909
|
+
if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) {
|
|
2104
2910
|
el.play();
|
|
2105
2911
|
}
|
|
2106
2912
|
} );
|
|
2107
2913
|
|
|
2108
|
-
//
|
|
2109
|
-
toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
|
|
2110
|
-
|
|
2111
|
-
});
|
|
2914
|
+
// Normal iframes
|
|
2915
|
+
toArray( slide.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) {
|
|
2916
|
+
startEmbeddedIframe( { target: el } );
|
|
2917
|
+
} );
|
|
2112
2918
|
|
|
2113
|
-
//
|
|
2114
|
-
toArray( slide.querySelectorAll( 'iframe[src
|
|
2115
|
-
if( el.
|
|
2116
|
-
el.
|
|
2919
|
+
// Lazy loading iframes
|
|
2920
|
+
toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
|
|
2921
|
+
if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) {
|
|
2922
|
+
el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes
|
|
2923
|
+
el.addEventListener( 'load', startEmbeddedIframe );
|
|
2924
|
+
el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
|
|
2117
2925
|
}
|
|
2118
|
-
});
|
|
2926
|
+
} );
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
}
|
|
2930
|
+
|
|
2931
|
+
/**
|
|
2932
|
+
* "Starts" the content of an embedded iframe using the
|
|
2933
|
+
* postmessage API.
|
|
2934
|
+
*/
|
|
2935
|
+
function startEmbeddedIframe( event ) {
|
|
2936
|
+
|
|
2937
|
+
var iframe = event.target;
|
|
2938
|
+
|
|
2939
|
+
// YouTube postMessage API
|
|
2940
|
+
if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) {
|
|
2941
|
+
iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
|
|
2942
|
+
}
|
|
2943
|
+
// Vimeo postMessage API
|
|
2944
|
+
else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) {
|
|
2945
|
+
iframe.contentWindow.postMessage( '{"method":"play"}', '*' );
|
|
2946
|
+
}
|
|
2947
|
+
// Generic postMessage API
|
|
2948
|
+
else {
|
|
2949
|
+
iframe.contentWindow.postMessage( 'slide:start', '*' );
|
|
2119
2950
|
}
|
|
2120
2951
|
|
|
2121
2952
|
}
|
|
@@ -2126,27 +2957,120 @@ var Reveal = (function(){
|
|
|
2126
2957
|
*/
|
|
2127
2958
|
function stopEmbeddedContent( slide ) {
|
|
2128
2959
|
|
|
2129
|
-
if( slide ) {
|
|
2960
|
+
if( slide && slide.parentNode ) {
|
|
2130
2961
|
// HTML5 media elements
|
|
2131
2962
|
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
|
2132
|
-
if( !el.hasAttribute( 'data-ignore' ) ) {
|
|
2963
|
+
if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
|
|
2133
2964
|
el.pause();
|
|
2134
2965
|
}
|
|
2135
2966
|
} );
|
|
2136
2967
|
|
|
2137
|
-
//
|
|
2968
|
+
// Generic postMessage API for non-lazy loaded iframes
|
|
2138
2969
|
toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
|
|
2139
2970
|
el.contentWindow.postMessage( 'slide:stop', '*' );
|
|
2971
|
+
el.removeEventListener( 'load', startEmbeddedIframe );
|
|
2140
2972
|
});
|
|
2141
2973
|
|
|
2142
|
-
// YouTube
|
|
2974
|
+
// YouTube postMessage API
|
|
2143
2975
|
toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
|
|
2144
2976
|
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
|
2145
2977
|
el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' );
|
|
2146
2978
|
}
|
|
2147
2979
|
});
|
|
2980
|
+
|
|
2981
|
+
// Vimeo postMessage API
|
|
2982
|
+
toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
|
|
2983
|
+
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
|
2984
|
+
el.contentWindow.postMessage( '{"method":"pause"}', '*' );
|
|
2985
|
+
}
|
|
2986
|
+
});
|
|
2987
|
+
|
|
2988
|
+
// Lazy loading iframes
|
|
2989
|
+
toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
|
|
2990
|
+
// Only removing the src doesn't actually unload the frame
|
|
2991
|
+
// in all browsers (Firefox) so we set it to blank first
|
|
2992
|
+
el.setAttribute( 'src', 'about:blank' );
|
|
2993
|
+
el.removeAttribute( 'src' );
|
|
2994
|
+
} );
|
|
2995
|
+
}
|
|
2996
|
+
|
|
2997
|
+
}
|
|
2998
|
+
|
|
2999
|
+
/**
|
|
3000
|
+
* Returns the number of past slides. This can be used as a global
|
|
3001
|
+
* flattened index for slides.
|
|
3002
|
+
*/
|
|
3003
|
+
function getSlidePastCount() {
|
|
3004
|
+
|
|
3005
|
+
var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
|
3006
|
+
|
|
3007
|
+
// The number of past slides
|
|
3008
|
+
var pastCount = 0;
|
|
3009
|
+
|
|
3010
|
+
// Step through all slides and count the past ones
|
|
3011
|
+
mainLoop: for( var i = 0; i < horizontalSlides.length; i++ ) {
|
|
3012
|
+
|
|
3013
|
+
var horizontalSlide = horizontalSlides[i];
|
|
3014
|
+
var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) );
|
|
3015
|
+
|
|
3016
|
+
for( var j = 0; j < verticalSlides.length; j++ ) {
|
|
3017
|
+
|
|
3018
|
+
// Stop as soon as we arrive at the present
|
|
3019
|
+
if( verticalSlides[j].classList.contains( 'present' ) ) {
|
|
3020
|
+
break mainLoop;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
pastCount++;
|
|
3024
|
+
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
// Stop as soon as we arrive at the present
|
|
3028
|
+
if( horizontalSlide.classList.contains( 'present' ) ) {
|
|
3029
|
+
break;
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
// Don't count the wrapping section for vertical slides
|
|
3033
|
+
if( horizontalSlide.classList.contains( 'stack' ) === false ) {
|
|
3034
|
+
pastCount++;
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
return pastCount;
|
|
3040
|
+
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
/**
|
|
3044
|
+
* Returns a value ranging from 0-1 that represents
|
|
3045
|
+
* how far into the presentation we have navigated.
|
|
3046
|
+
*/
|
|
3047
|
+
function getProgress() {
|
|
3048
|
+
|
|
3049
|
+
// The number of past and total slides
|
|
3050
|
+
var totalCount = getTotalSlides();
|
|
3051
|
+
var pastCount = getSlidePastCount();
|
|
3052
|
+
|
|
3053
|
+
if( currentSlide ) {
|
|
3054
|
+
|
|
3055
|
+
var allFragments = currentSlide.querySelectorAll( '.fragment' );
|
|
3056
|
+
|
|
3057
|
+
// If there are fragments in the current slide those should be
|
|
3058
|
+
// accounted for in the progress.
|
|
3059
|
+
if( allFragments.length > 0 ) {
|
|
3060
|
+
var visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );
|
|
3061
|
+
|
|
3062
|
+
// This value represents how big a portion of the slide progress
|
|
3063
|
+
// that is made up by its fragments (0-1)
|
|
3064
|
+
var fragmentWeight = 0.9;
|
|
3065
|
+
|
|
3066
|
+
// Add fragment progress to the past slide count
|
|
3067
|
+
pastCount += ( visibleFragments.length / allFragments.length ) * fragmentWeight;
|
|
3068
|
+
}
|
|
3069
|
+
|
|
2148
3070
|
}
|
|
2149
3071
|
|
|
3072
|
+
return pastCount / ( totalCount - 1 );
|
|
3073
|
+
|
|
2150
3074
|
}
|
|
2151
3075
|
|
|
2152
3076
|
/**
|
|
@@ -2173,8 +3097,13 @@ var Reveal = (function(){
|
|
|
2173
3097
|
// If the first bit is invalid and there is a name we can
|
|
2174
3098
|
// assume that this is a named link
|
|
2175
3099
|
if( isNaN( parseInt( bits[0], 10 ) ) && name.length ) {
|
|
2176
|
-
|
|
2177
|
-
|
|
3100
|
+
var element;
|
|
3101
|
+
|
|
3102
|
+
// Ensure the named link is a valid HTML ID attribute
|
|
3103
|
+
if( /^[a-zA-Z][\w:.-]*$/.test( name ) ) {
|
|
3104
|
+
// Find the slide with the specified ID
|
|
3105
|
+
element = document.getElementById( name );
|
|
3106
|
+
}
|
|
2178
3107
|
|
|
2179
3108
|
if( element ) {
|
|
2180
3109
|
// Find the position of the named slide and navigate to it
|
|
@@ -2216,12 +3145,19 @@ var Reveal = (function(){
|
|
|
2216
3145
|
if( typeof delay === 'number' ) {
|
|
2217
3146
|
writeURLTimeout = setTimeout( writeURL, delay );
|
|
2218
3147
|
}
|
|
2219
|
-
else {
|
|
3148
|
+
else if( currentSlide ) {
|
|
2220
3149
|
var url = '/';
|
|
2221
3150
|
|
|
3151
|
+
// Attempt to create a named link based on the slide's ID
|
|
3152
|
+
var id = currentSlide.getAttribute( 'id' );
|
|
3153
|
+
if( id ) {
|
|
3154
|
+
id = id.toLowerCase();
|
|
3155
|
+
id = id.replace( /[^a-zA-Z0-9\-\_\:\.]/g, '' );
|
|
3156
|
+
}
|
|
3157
|
+
|
|
2222
3158
|
// If the current slide has an ID, use that as a named link
|
|
2223
|
-
if(
|
|
2224
|
-
url = '/' +
|
|
3159
|
+
if( typeof id === 'string' && id.length ) {
|
|
3160
|
+
url = '/' + id;
|
|
2225
3161
|
}
|
|
2226
3162
|
// Otherwise use the /h/v index
|
|
2227
3163
|
else {
|
|
@@ -2258,11 +3194,14 @@ var Reveal = (function(){
|
|
|
2258
3194
|
var slideh = isVertical ? slide.parentNode : slide;
|
|
2259
3195
|
|
|
2260
3196
|
// Select all horizontal slides
|
|
2261
|
-
var horizontalSlides = toArray(
|
|
3197
|
+
var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
|
|
2262
3198
|
|
|
2263
3199
|
// Now that we know which the horizontal slide is, get its index
|
|
2264
3200
|
h = Math.max( horizontalSlides.indexOf( slideh ), 0 );
|
|
2265
3201
|
|
|
3202
|
+
// Assume we're not vertical
|
|
3203
|
+
v = undefined;
|
|
3204
|
+
|
|
2266
3205
|
// If this is a vertical slide, grab the vertical index
|
|
2267
3206
|
if( isVertical ) {
|
|
2268
3207
|
v = Math.max( toArray( slide.parentNode.querySelectorAll( 'section' ) ).indexOf( slide ), 0 );
|
|
@@ -2272,8 +3211,13 @@ var Reveal = (function(){
|
|
|
2272
3211
|
if( !slide && currentSlide ) {
|
|
2273
3212
|
var hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0;
|
|
2274
3213
|
if( hasFragments ) {
|
|
2275
|
-
var
|
|
2276
|
-
|
|
3214
|
+
var currentFragment = currentSlide.querySelector( '.current-fragment' );
|
|
3215
|
+
if( currentFragment && currentFragment.hasAttribute( 'data-fragment-index' ) ) {
|
|
3216
|
+
f = parseInt( currentFragment.getAttribute( 'data-fragment-index' ), 10 );
|
|
3217
|
+
}
|
|
3218
|
+
else {
|
|
3219
|
+
f = currentSlide.querySelectorAll( '.fragment.visible' ).length - 1;
|
|
3220
|
+
}
|
|
2277
3221
|
}
|
|
2278
3222
|
}
|
|
2279
3223
|
|
|
@@ -2281,6 +3225,107 @@ var Reveal = (function(){
|
|
|
2281
3225
|
|
|
2282
3226
|
}
|
|
2283
3227
|
|
|
3228
|
+
/**
|
|
3229
|
+
* Retrieves the total number of slides in this presentation.
|
|
3230
|
+
*/
|
|
3231
|
+
function getTotalSlides() {
|
|
3232
|
+
|
|
3233
|
+
return dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' ).length;
|
|
3234
|
+
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
/**
|
|
3238
|
+
* Returns the slide element matching the specified index.
|
|
3239
|
+
*/
|
|
3240
|
+
function getSlide( x, y ) {
|
|
3241
|
+
|
|
3242
|
+
var horizontalSlide = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR )[ x ];
|
|
3243
|
+
var verticalSlides = horizontalSlide && horizontalSlide.querySelectorAll( 'section' );
|
|
3244
|
+
|
|
3245
|
+
if( verticalSlides && verticalSlides.length && typeof y === 'number' ) {
|
|
3246
|
+
return verticalSlides ? verticalSlides[ y ] : undefined;
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3249
|
+
return horizontalSlide;
|
|
3250
|
+
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
/**
|
|
3254
|
+
* Returns the background element for the given slide.
|
|
3255
|
+
* All slides, even the ones with no background properties
|
|
3256
|
+
* defined, have a background element so as long as the
|
|
3257
|
+
* index is valid an element will be returned.
|
|
3258
|
+
*/
|
|
3259
|
+
function getSlideBackground( x, y ) {
|
|
3260
|
+
|
|
3261
|
+
// When printing to PDF the slide backgrounds are nested
|
|
3262
|
+
// inside of the slides
|
|
3263
|
+
if( isPrintingPDF() ) {
|
|
3264
|
+
var slide = getSlide( x, y );
|
|
3265
|
+
if( slide ) {
|
|
3266
|
+
var background = slide.querySelector( '.slide-background' );
|
|
3267
|
+
if( background && background.parentNode === slide ) {
|
|
3268
|
+
return background;
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
return undefined;
|
|
3273
|
+
}
|
|
3274
|
+
|
|
3275
|
+
var horizontalBackground = dom.wrapper.querySelectorAll( '.backgrounds>.slide-background' )[ x ];
|
|
3276
|
+
var verticalBackgrounds = horizontalBackground && horizontalBackground.querySelectorAll( '.slide-background' );
|
|
3277
|
+
|
|
3278
|
+
if( verticalBackgrounds && verticalBackgrounds.length && typeof y === 'number' ) {
|
|
3279
|
+
return verticalBackgrounds ? verticalBackgrounds[ y ] : undefined;
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
return horizontalBackground;
|
|
3283
|
+
|
|
3284
|
+
}
|
|
3285
|
+
|
|
3286
|
+
/**
|
|
3287
|
+
* Retrieves the current state of the presentation as
|
|
3288
|
+
* an object. This state can then be restored at any
|
|
3289
|
+
* time.
|
|
3290
|
+
*/
|
|
3291
|
+
function getState() {
|
|
3292
|
+
|
|
3293
|
+
var indices = getIndices();
|
|
3294
|
+
|
|
3295
|
+
return {
|
|
3296
|
+
indexh: indices.h,
|
|
3297
|
+
indexv: indices.v,
|
|
3298
|
+
indexf: indices.f,
|
|
3299
|
+
paused: isPaused(),
|
|
3300
|
+
overview: isOverview()
|
|
3301
|
+
};
|
|
3302
|
+
|
|
3303
|
+
}
|
|
3304
|
+
|
|
3305
|
+
/**
|
|
3306
|
+
* Restores the presentation to the given state.
|
|
3307
|
+
*
|
|
3308
|
+
* @param {Object} state As generated by getState()
|
|
3309
|
+
*/
|
|
3310
|
+
function setState( state ) {
|
|
3311
|
+
|
|
3312
|
+
if( typeof state === 'object' ) {
|
|
3313
|
+
slide( deserialize( state.indexh ), deserialize( state.indexv ), deserialize( state.indexf ) );
|
|
3314
|
+
|
|
3315
|
+
var pausedFlag = deserialize( state.paused ),
|
|
3316
|
+
overviewFlag = deserialize( state.overview );
|
|
3317
|
+
|
|
3318
|
+
if( typeof pausedFlag === 'boolean' && pausedFlag !== isPaused() ) {
|
|
3319
|
+
togglePause( pausedFlag );
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
if( typeof overviewFlag === 'boolean' && overviewFlag !== isOverview() ) {
|
|
3323
|
+
toggleOverview( overviewFlag );
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
|
|
3327
|
+
}
|
|
3328
|
+
|
|
2284
3329
|
/**
|
|
2285
3330
|
* Return a sorted fragments list, ordered by an increasing
|
|
2286
3331
|
* "data-fragment-index" attribute.
|
|
@@ -2392,6 +3437,9 @@ var Reveal = (function(){
|
|
|
2392
3437
|
element.classList.add( 'visible' );
|
|
2393
3438
|
element.classList.remove( 'current-fragment' );
|
|
2394
3439
|
|
|
3440
|
+
// Announce the fragments one by one to the Screen Reader
|
|
3441
|
+
dom.statusDiv.textContent = element.textContent;
|
|
3442
|
+
|
|
2395
3443
|
if( i === index ) {
|
|
2396
3444
|
element.classList.add( 'current-fragment' );
|
|
2397
3445
|
}
|
|
@@ -2415,6 +3463,7 @@ var Reveal = (function(){
|
|
|
2415
3463
|
}
|
|
2416
3464
|
|
|
2417
3465
|
updateControls();
|
|
3466
|
+
updateProgress();
|
|
2418
3467
|
|
|
2419
3468
|
return !!( fragmentsShown.length || fragmentsHidden.length );
|
|
2420
3469
|
|
|
@@ -2459,14 +3508,21 @@ var Reveal = (function(){
|
|
|
2459
3508
|
|
|
2460
3509
|
if( currentSlide ) {
|
|
2461
3510
|
|
|
3511
|
+
var currentFragment = currentSlide.querySelector( '.current-fragment' );
|
|
3512
|
+
|
|
3513
|
+
var fragmentAutoSlide = currentFragment ? currentFragment.getAttribute( 'data-autoslide' ) : null;
|
|
2462
3514
|
var parentAutoSlide = currentSlide.parentNode ? currentSlide.parentNode.getAttribute( 'data-autoslide' ) : null;
|
|
2463
3515
|
var slideAutoSlide = currentSlide.getAttribute( 'data-autoslide' );
|
|
2464
3516
|
|
|
2465
3517
|
// Pick value in the following priority order:
|
|
2466
|
-
// 1. Current
|
|
2467
|
-
// 2.
|
|
2468
|
-
// 3.
|
|
2469
|
-
|
|
3518
|
+
// 1. Current fragment's data-autoslide
|
|
3519
|
+
// 2. Current slide's data-autoslide
|
|
3520
|
+
// 3. Parent slide's data-autoslide
|
|
3521
|
+
// 4. Global autoSlide setting
|
|
3522
|
+
if( fragmentAutoSlide ) {
|
|
3523
|
+
autoSlide = parseInt( fragmentAutoSlide, 10 );
|
|
3524
|
+
}
|
|
3525
|
+
else if( slideAutoSlide ) {
|
|
2470
3526
|
autoSlide = parseInt( slideAutoSlide, 10 );
|
|
2471
3527
|
}
|
|
2472
3528
|
else if( parentAutoSlide ) {
|
|
@@ -2478,14 +3534,17 @@ var Reveal = (function(){
|
|
|
2478
3534
|
|
|
2479
3535
|
// If there are media elements with data-autoplay,
|
|
2480
3536
|
// automatically set the autoSlide duration to the
|
|
2481
|
-
// length of that media
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
3537
|
+
// length of that media. Not applicable if the slide
|
|
3538
|
+
// is divided up into fragments.
|
|
3539
|
+
if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
|
|
3540
|
+
toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
|
3541
|
+
if( el.hasAttribute( 'data-autoplay' ) ) {
|
|
3542
|
+
if( autoSlide && el.duration * 1000 > autoSlide ) {
|
|
3543
|
+
autoSlide = ( el.duration * 1000 ) + 1000;
|
|
3544
|
+
}
|
|
2486
3545
|
}
|
|
2487
|
-
}
|
|
2488
|
-
}
|
|
3546
|
+
} );
|
|
3547
|
+
}
|
|
2489
3548
|
|
|
2490
3549
|
// Cue the next auto-slide if:
|
|
2491
3550
|
// - There is an autoSlide value
|
|
@@ -2493,7 +3552,7 @@ var Reveal = (function(){
|
|
|
2493
3552
|
// - The presentation isn't paused
|
|
2494
3553
|
// - The overview isn't active
|
|
2495
3554
|
// - The presentation isn't over
|
|
2496
|
-
if( autoSlide && !autoSlidePaused && !isPaused() && !isOverview() && ( !Reveal.isLastSlide() || config.loop === true ) ) {
|
|
3555
|
+
if( autoSlide && !autoSlidePaused && !isPaused() && !isOverview() && ( !Reveal.isLastSlide() || availableFragments().next || config.loop === true ) ) {
|
|
2497
3556
|
autoSlideTimeout = setTimeout( navigateNext, autoSlide );
|
|
2498
3557
|
autoSlideStartTime = Date.now();
|
|
2499
3558
|
}
|
|
@@ -2518,19 +3577,25 @@ var Reveal = (function(){
|
|
|
2518
3577
|
|
|
2519
3578
|
function pauseAutoSlide() {
|
|
2520
3579
|
|
|
2521
|
-
autoSlidePaused
|
|
2522
|
-
|
|
3580
|
+
if( autoSlide && !autoSlidePaused ) {
|
|
3581
|
+
autoSlidePaused = true;
|
|
3582
|
+
dispatchEvent( 'autoslidepaused' );
|
|
3583
|
+
clearTimeout( autoSlideTimeout );
|
|
2523
3584
|
|
|
2524
|
-
|
|
2525
|
-
|
|
3585
|
+
if( autoSlidePlayer ) {
|
|
3586
|
+
autoSlidePlayer.setPlaying( false );
|
|
3587
|
+
}
|
|
2526
3588
|
}
|
|
2527
3589
|
|
|
2528
3590
|
}
|
|
2529
3591
|
|
|
2530
3592
|
function resumeAutoSlide() {
|
|
2531
3593
|
|
|
2532
|
-
autoSlidePaused
|
|
2533
|
-
|
|
3594
|
+
if( autoSlide && autoSlidePaused ) {
|
|
3595
|
+
autoSlidePaused = false;
|
|
3596
|
+
dispatchEvent( 'autoslideresumed' );
|
|
3597
|
+
cueAutoSlide();
|
|
3598
|
+
}
|
|
2534
3599
|
|
|
2535
3600
|
}
|
|
2536
3601
|
|
|
@@ -2597,7 +3662,14 @@ var Reveal = (function(){
|
|
|
2597
3662
|
}
|
|
2598
3663
|
else {
|
|
2599
3664
|
// Fetch the previous horizontal slide, if there is one
|
|
2600
|
-
var previousSlide
|
|
3665
|
+
var previousSlide;
|
|
3666
|
+
|
|
3667
|
+
if( config.rtl ) {
|
|
3668
|
+
previousSlide = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.future' ) ).pop();
|
|
3669
|
+
}
|
|
3670
|
+
else {
|
|
3671
|
+
previousSlide = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.past' ) ).pop();
|
|
3672
|
+
}
|
|
2601
3673
|
|
|
2602
3674
|
if( previousSlide ) {
|
|
2603
3675
|
var v = ( previousSlide.querySelectorAll( 'section' ).length - 1 ) || undefined;
|
|
@@ -2610,13 +3682,21 @@ var Reveal = (function(){
|
|
|
2610
3682
|
}
|
|
2611
3683
|
|
|
2612
3684
|
/**
|
|
2613
|
-
*
|
|
3685
|
+
* The reverse of #navigatePrev().
|
|
2614
3686
|
*/
|
|
2615
3687
|
function navigateNext() {
|
|
2616
3688
|
|
|
2617
3689
|
// Prioritize revealing fragments
|
|
2618
3690
|
if( nextFragment() === false ) {
|
|
2619
|
-
availableRoutes().down
|
|
3691
|
+
if( availableRoutes().down ) {
|
|
3692
|
+
navigateDown();
|
|
3693
|
+
}
|
|
3694
|
+
else if( config.rtl ) {
|
|
3695
|
+
navigateLeft();
|
|
3696
|
+
}
|
|
3697
|
+
else {
|
|
3698
|
+
navigateRight();
|
|
3699
|
+
}
|
|
2620
3700
|
}
|
|
2621
3701
|
|
|
2622
3702
|
// If auto-sliding is enabled we need to cue up
|
|
@@ -2642,21 +3722,47 @@ var Reveal = (function(){
|
|
|
2642
3722
|
|
|
2643
3723
|
}
|
|
2644
3724
|
|
|
3725
|
+
/**
|
|
3726
|
+
* Handler for the document level 'keypress' event.
|
|
3727
|
+
*/
|
|
3728
|
+
function onDocumentKeyPress( event ) {
|
|
3729
|
+
|
|
3730
|
+
// Check if the pressed key is question mark
|
|
3731
|
+
if( event.shiftKey && event.charCode === 63 ) {
|
|
3732
|
+
if( dom.overlay ) {
|
|
3733
|
+
closeOverlay();
|
|
3734
|
+
}
|
|
3735
|
+
else {
|
|
3736
|
+
showHelp( true );
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
|
|
3740
|
+
}
|
|
3741
|
+
|
|
2645
3742
|
/**
|
|
2646
3743
|
* Handler for the document level 'keydown' event.
|
|
2647
3744
|
*/
|
|
2648
3745
|
function onDocumentKeyDown( event ) {
|
|
2649
3746
|
|
|
3747
|
+
// If there's a condition specified and it returns false,
|
|
3748
|
+
// ignore this event
|
|
3749
|
+
if( typeof config.keyboardCondition === 'function' && config.keyboardCondition() === false ) {
|
|
3750
|
+
return true;
|
|
3751
|
+
}
|
|
3752
|
+
|
|
3753
|
+
// Remember if auto-sliding was paused so we can toggle it
|
|
3754
|
+
var autoSlideWasPaused = autoSlidePaused;
|
|
3755
|
+
|
|
2650
3756
|
onUserInput( event );
|
|
2651
3757
|
|
|
2652
3758
|
// Check if there's a focused element that could be using
|
|
2653
3759
|
// the keyboard
|
|
2654
|
-
var
|
|
2655
|
-
var
|
|
3760
|
+
var activeElementIsCE = document.activeElement && document.activeElement.contentEditable !== 'inherit';
|
|
3761
|
+
var activeElementIsInput = document.activeElement && document.activeElement.tagName && /input|textarea/i.test( document.activeElement.tagName );
|
|
2656
3762
|
|
|
2657
3763
|
// Disregard the event if there's a focused element or a
|
|
2658
3764
|
// keyboard modifier key is present
|
|
2659
|
-
if(
|
|
3765
|
+
if( activeElementIsCE || activeElementIsInput || (event.shiftKey && event.keyCode !== 32) || event.altKey || event.ctrlKey || event.metaKey ) return;
|
|
2660
3766
|
|
|
2661
3767
|
// While paused only allow "unpausing" keyboard events (b and .)
|
|
2662
3768
|
if( isPaused() && [66,190,191].indexOf( event.keyCode ) === -1 ) {
|
|
@@ -2719,10 +3825,12 @@ var Reveal = (function(){
|
|
|
2719
3825
|
case 32: isOverview() ? deactivateOverview() : event.shiftKey ? navigatePrev() : navigateNext(); break;
|
|
2720
3826
|
// return
|
|
2721
3827
|
case 13: isOverview() ? deactivateOverview() : triggered = false; break;
|
|
2722
|
-
// b, period, Logitech presenter tools "black screen" button
|
|
2723
|
-
case 66: case 190: case 191: togglePause(); break;
|
|
3828
|
+
// two-spot, semicolon, b, period, Logitech presenter tools "black screen" button
|
|
3829
|
+
case 58: case 59: case 66: case 190: case 191: togglePause(); break;
|
|
2724
3830
|
// f
|
|
2725
3831
|
case 70: enterFullscreen(); break;
|
|
3832
|
+
// a
|
|
3833
|
+
case 65: if ( config.autoSlideStoppable ) toggleAutoSlide( autoSlideWasPaused ); break;
|
|
2726
3834
|
default:
|
|
2727
3835
|
triggered = false;
|
|
2728
3836
|
}
|
|
@@ -2732,18 +3840,18 @@ var Reveal = (function(){
|
|
|
2732
3840
|
// If the input resulted in a triggered action we should prevent
|
|
2733
3841
|
// the browsers default behavior
|
|
2734
3842
|
if( triggered ) {
|
|
2735
|
-
event.preventDefault();
|
|
3843
|
+
event.preventDefault && event.preventDefault();
|
|
2736
3844
|
}
|
|
2737
3845
|
// ESC or O key
|
|
2738
3846
|
else if ( ( event.keyCode === 27 || event.keyCode === 79 ) && features.transforms3d ) {
|
|
2739
|
-
if( dom.
|
|
2740
|
-
|
|
3847
|
+
if( dom.overlay ) {
|
|
3848
|
+
closeOverlay();
|
|
2741
3849
|
}
|
|
2742
3850
|
else {
|
|
2743
3851
|
toggleOverview();
|
|
2744
3852
|
}
|
|
2745
3853
|
|
|
2746
|
-
event.preventDefault();
|
|
3854
|
+
event.preventDefault && event.preventDefault();
|
|
2747
3855
|
}
|
|
2748
3856
|
|
|
2749
3857
|
// If auto-sliding is enabled we need to cue up
|
|
@@ -2877,7 +3985,7 @@ var Reveal = (function(){
|
|
|
2877
3985
|
*/
|
|
2878
3986
|
function onPointerDown( event ) {
|
|
2879
3987
|
|
|
2880
|
-
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH ) {
|
|
3988
|
+
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) {
|
|
2881
3989
|
event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
|
|
2882
3990
|
onTouchStart( event );
|
|
2883
3991
|
}
|
|
@@ -2889,7 +3997,7 @@ var Reveal = (function(){
|
|
|
2889
3997
|
*/
|
|
2890
3998
|
function onPointerMove( event ) {
|
|
2891
3999
|
|
|
2892
|
-
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH )
|
|
4000
|
+
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) {
|
|
2893
4001
|
event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
|
|
2894
4002
|
onTouchMove( event );
|
|
2895
4003
|
}
|
|
@@ -2901,7 +4009,7 @@ var Reveal = (function(){
|
|
|
2901
4009
|
*/
|
|
2902
4010
|
function onPointerUp( event ) {
|
|
2903
4011
|
|
|
2904
|
-
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH )
|
|
4012
|
+
if( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === "touch" ) {
|
|
2905
4013
|
event.touches = [{ clientX: event.clientX, clientY: event.clientY }];
|
|
2906
4014
|
onTouchEnd( event );
|
|
2907
4015
|
}
|
|
@@ -2942,9 +4050,13 @@ var Reveal = (function(){
|
|
|
2942
4050
|
|
|
2943
4051
|
event.preventDefault();
|
|
2944
4052
|
|
|
2945
|
-
var slidesTotal = toArray(
|
|
4053
|
+
var slidesTotal = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).length;
|
|
2946
4054
|
var slideIndex = Math.floor( ( event.clientX / dom.wrapper.offsetWidth ) * slidesTotal );
|
|
2947
4055
|
|
|
4056
|
+
if( config.rtl ) {
|
|
4057
|
+
slideIndex = slidesTotal - slideIndex;
|
|
4058
|
+
}
|
|
4059
|
+
|
|
2948
4060
|
slide( slideIndex );
|
|
2949
4061
|
|
|
2950
4062
|
}
|
|
@@ -2989,7 +4101,10 @@ var Reveal = (function(){
|
|
|
2989
4101
|
// If, after clicking a link or similar and we're coming back,
|
|
2990
4102
|
// focus the document.body to ensure we can use keyboard shortcuts
|
|
2991
4103
|
if( isHidden === false && document.activeElement !== document.body ) {
|
|
2992
|
-
|
|
4104
|
+
// Not all elements support .blur() - SVGs among them.
|
|
4105
|
+
if( typeof document.activeElement.blur === 'function' ) {
|
|
4106
|
+
document.activeElement.blur();
|
|
4107
|
+
}
|
|
2993
4108
|
document.body.focus();
|
|
2994
4109
|
}
|
|
2995
4110
|
|
|
@@ -3033,10 +4148,12 @@ var Reveal = (function(){
|
|
|
3033
4148
|
*/
|
|
3034
4149
|
function onPreviewLinkClicked( event ) {
|
|
3035
4150
|
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
4151
|
+
if( event.currentTarget && event.currentTarget.hasAttribute( 'href' ) ) {
|
|
4152
|
+
var url = event.currentTarget.getAttribute( 'href' );
|
|
4153
|
+
if( url ) {
|
|
4154
|
+
showPreview( url );
|
|
4155
|
+
event.preventDefault();
|
|
4156
|
+
}
|
|
3040
4157
|
}
|
|
3041
4158
|
|
|
3042
4159
|
}
|
|
@@ -3232,7 +4349,7 @@ var Reveal = (function(){
|
|
|
3232
4349
|
// --------------------------------------------------------------------//
|
|
3233
4350
|
|
|
3234
4351
|
|
|
3235
|
-
|
|
4352
|
+
Reveal = {
|
|
3236
4353
|
initialize: initialize,
|
|
3237
4354
|
configure: configure,
|
|
3238
4355
|
sync: sync,
|
|
@@ -3275,28 +4392,35 @@ var Reveal = (function(){
|
|
|
3275
4392
|
// Toggles the "black screen" mode on/off
|
|
3276
4393
|
togglePause: togglePause,
|
|
3277
4394
|
|
|
4395
|
+
// Toggles the auto slide mode on/off
|
|
4396
|
+
toggleAutoSlide: toggleAutoSlide,
|
|
4397
|
+
|
|
3278
4398
|
// State checks
|
|
3279
4399
|
isOverview: isOverview,
|
|
3280
4400
|
isPaused: isPaused,
|
|
4401
|
+
isAutoSliding: isAutoSliding,
|
|
3281
4402
|
|
|
3282
4403
|
// Adds or removes all internal event listeners (such as keyboard)
|
|
3283
4404
|
addEventListeners: addEventListeners,
|
|
3284
4405
|
removeEventListeners: removeEventListeners,
|
|
3285
4406
|
|
|
4407
|
+
// Facility for persisting and restoring the presentation state
|
|
4408
|
+
getState: getState,
|
|
4409
|
+
setState: setState,
|
|
4410
|
+
|
|
4411
|
+
// Presentation progress on range of 0-1
|
|
4412
|
+
getProgress: getProgress,
|
|
4413
|
+
|
|
3286
4414
|
// Returns the indices of the current, or specified, slide
|
|
3287
4415
|
getIndices: getIndices,
|
|
3288
4416
|
|
|
3289
|
-
|
|
3290
|
-
getSlide: function( x, y ) {
|
|
3291
|
-
var horizontalSlide = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR )[ x ];
|
|
3292
|
-
var verticalSlides = horizontalSlide && horizontalSlide.querySelectorAll( 'section' );
|
|
4417
|
+
getTotalSlides: getTotalSlides,
|
|
3293
4418
|
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
}
|
|
4419
|
+
// Returns the slide element at the specified index
|
|
4420
|
+
getSlide: getSlide,
|
|
3297
4421
|
|
|
3298
|
-
|
|
3299
|
-
|
|
4422
|
+
// Returns the slide background element at the specified index
|
|
4423
|
+
getSlideBackground: getSlideBackground,
|
|
3300
4424
|
|
|
3301
4425
|
// Returns the previous slide element, may be null
|
|
3302
4426
|
getPreviousSlide: function() {
|
|
@@ -3330,12 +4454,7 @@ var Reveal = (function(){
|
|
|
3330
4454
|
for( var i in query ) {
|
|
3331
4455
|
var value = query[ i ];
|
|
3332
4456
|
|
|
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 );
|
|
4457
|
+
query[ i ] = deserialize( unescape( value ) );
|
|
3339
4458
|
}
|
|
3340
4459
|
|
|
3341
4460
|
return query;
|
|
@@ -3343,7 +4462,7 @@ var Reveal = (function(){
|
|
|
3343
4462
|
|
|
3344
4463
|
// Returns true if we're currently on the first slide
|
|
3345
4464
|
isFirstSlide: function() {
|
|
3346
|
-
return
|
|
4465
|
+
return ( indexh === 0 && indexv === 0 );
|
|
3347
4466
|
},
|
|
3348
4467
|
|
|
3349
4468
|
// Returns true if we're currently on the last slide
|
|
@@ -3376,7 +4495,14 @@ var Reveal = (function(){
|
|
|
3376
4495
|
if( 'addEventListener' in window ) {
|
|
3377
4496
|
( dom.wrapper || document.querySelector( '.reveal' ) ).removeEventListener( type, listener, useCapture );
|
|
3378
4497
|
}
|
|
4498
|
+
},
|
|
4499
|
+
|
|
4500
|
+
// Programatically triggers a keyboard event
|
|
4501
|
+
triggerKey: function( keyCode ) {
|
|
4502
|
+
onDocumentKeyDown( { keyCode: keyCode } );
|
|
3379
4503
|
}
|
|
3380
4504
|
};
|
|
3381
4505
|
|
|
3382
|
-
|
|
4506
|
+
return Reveal;
|
|
4507
|
+
|
|
4508
|
+
}));
|