diff options
-rw-r--r-- | Gruntfile.js | 38 | ||||
-rw-r--r-- | README.md | 26 | ||||
-rw-r--r-- | css/reveal.css | 110 | ||||
-rw-r--r-- | css/reveal.scss | 130 | ||||
-rw-r--r-- | css/theme/README.md | 4 | ||||
-rw-r--r-- | css/theme/beige.css | 6 | ||||
-rw-r--r-- | css/theme/black.css | 6 | ||||
-rw-r--r-- | css/theme/blood.css | 20 | ||||
-rw-r--r-- | css/theme/league.css | 6 | ||||
-rw-r--r-- | css/theme/moon.css | 6 | ||||
-rw-r--r-- | css/theme/night.css | 6 | ||||
-rw-r--r-- | css/theme/serif.css | 6 | ||||
-rw-r--r-- | css/theme/simple.css | 6 | ||||
-rw-r--r-- | css/theme/sky.css | 6 | ||||
-rw-r--r-- | css/theme/solarized.css | 6 | ||||
-rw-r--r-- | css/theme/source/blood.scss | 18 | ||||
-rw-r--r-- | css/theme/template/theme.scss | 14 | ||||
-rw-r--r-- | css/theme/white.css | 6 | ||||
-rw-r--r-- | index.html | 4 | ||||
-rw-r--r-- | js/reveal.js | 335 | ||||
-rw-r--r-- | plugin/markdown/example.html | 2 | ||||
-rwxr-xr-x | plugin/markdown/markdown.js | 2 | ||||
-rwxr-xr-x | plugin/math/math.js | 2 |
23 files changed, 512 insertions, 253 deletions
diff --git a/Gruntfile.js b/Gruntfile.js index 3e67b9f..46385f4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -36,19 +36,15 @@ module.exports = function(grunt) { } }, themes: { - files: { - 'css/theme/black.css': 'css/theme/source/black.scss', - 'css/theme/white.css': 'css/theme/source/white.scss', - 'css/theme/league.css': 'css/theme/source/league.scss', - 'css/theme/beige.css': 'css/theme/source/beige.scss', - 'css/theme/night.css': 'css/theme/source/night.scss', - 'css/theme/serif.css': 'css/theme/source/serif.scss', - 'css/theme/simple.css': 'css/theme/source/simple.scss', - 'css/theme/sky.css': 'css/theme/source/sky.scss', - 'css/theme/moon.css': 'css/theme/source/moon.scss', - 'css/theme/solarized.css': 'css/theme/source/solarized.scss', - 'css/theme/blood.css': 'css/theme/source/blood.scss' - } + files: [ + { + expand: true, + cwd: 'css/theme/source', + src: ['*.scss'], + dest: 'css/theme', + ext: '.css' + } + ] } }, @@ -96,8 +92,8 @@ module.exports = function(grunt) { options: { port: port, base: '.', - livereload: true, - open: true + livereload: true, + open: true } } }, @@ -114,9 +110,9 @@ module.exports = function(grunt) { }, watch: { - options: { - livereload: true - }, + options: { + livereload: true + }, js: { files: [ 'Gruntfile.js', 'js/reveal.js' ], tasks: 'js' @@ -129,9 +125,9 @@ module.exports = function(grunt) { files: [ 'css/reveal.scss' ], tasks: 'css-core' }, - html: { - files: [ 'index.html'] - } + html: { + files: [ 'index.html'] + } } }); @@ -176,6 +176,10 @@ Reveal.initialize({ // Parallax background size parallaxBackgroundSize: '' // CSS syntax, e.g. "2100px 900px" + // Amount to move parallax background (horizontal and vertical) on slide change + // Number, e.g. 100 + parallaxBackgroundHorizontal: '', + parallaxBackgroundVertical: '' }); ``` @@ -428,8 +432,8 @@ Slides are contained within a limited portion of the screen by default to allow <section data-background="http://example.com/image.png" data-background-size="100px" data-background-repeat="repeat"> <h2>This background image will be sized to 100px and repeated.</h2> </section> -<section data-background-video="https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.mp4,https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.webm"> - <h2>Video. Multiple sources can be defined using a comma separated list.</h2> +<section data-background-video="https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.mp4,https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.webm" data-background-video-loop> + <h2>Video. Multiple sources can be defined using a comma separated list. Video will loop when the data-background-video-loop attribute is provided.</h2> </section> <section data-background-iframe="https://slides.com"> <h2>Embeds a web page as a background. Note that the page won't be interactive.</h2> @@ -441,7 +445,7 @@ Backgrounds transition using a fade animation by default. This can be changed to ### Parallax Background -If you want to use a parallax scrolling background, set the two following config properties when initializing reveal.js (the third one is optional). +If you want to use a parallax scrolling background, set the first two config properties below when initializing reveal.js (the other two are optional). ```javascript Reveal.initialize({ @@ -452,8 +456,11 @@ Reveal.initialize({ // Parallax background size parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px" - currently only pixels are supported (don't use % or auto) - // This slide transition gives best results: - transition: 'slide' + // Amount of pixels to move the parallax background per slide step, + // a value of 0 disables movement along the given axis + // These are optional, if they aren't specified they'll be calculated automatically + parallaxBackgroundHorizontal: 200, + parallaxBackgroundVertical: 50 }); ``` @@ -573,7 +580,16 @@ By default, Reveal is configured with [highlight.js](http://softwaremaniacs.org/ If you would like to display the page number of the current slide you can do so using the ```slideNumber``` configuration value. ```javascript +// Shows the slide number using default formatting Reveal.configure({ slideNumber: true }); + +// Slide number formatting can be configured using these variables: +// h: current slide's horizontal index +// v: current slide's vertical index +// c: current slide index (flattened) +// t: total number of slides (flattened) +Reveal.configure({ slideNumber: 'c / t' }); + ``` diff --git a/css/reveal.css b/css/reveal.css index 05bfd2d..15696d3 100644 --- a/css/reveal.css +++ b/css/reveal.css @@ -33,16 +33,6 @@ body { background-color: #fff; color: #000; } -::-moz-selection { - background: #FF5E99; - color: #fff; - text-shadow: none; } - -::selection { - background: #FF5E99; - color: #fff; - text-shadow: none; } - /********************************************* * VIEW FRAGMENTS *********************************************/ @@ -275,6 +265,7 @@ body { position: relative; width: 100%; height: 100%; + overflow: hidden; -ms-touch-action: none; touch-action: none; } @@ -625,51 +616,6 @@ body { transition: none; } /********************************************* - * OVERVIEW - *********************************************/ -.reveal.overview .slides { - -webkit-perspective-origin: 50% 50%; - perspective-origin: 50% 50%; - -webkit-perspective: 700px; - perspective: 700px; } - -.reveal.overview .slides section { - height: 700px; - overflow: hidden; - opacity: 1 !important; - visibility: visible !important; - cursor: pointer; - background: rgba(0, 0, 0, 0.1); - -moz-box-sizing: border-box; - box-sizing: border-box; } - -.reveal.overview .slides section, .reveal.overview-deactivating .slides section { - -webkit-transition: none !important; - transition: none !important; } - -.reveal.overview .slides section .fragment { - opacity: 1; } - -.reveal.overview .slides section:after, .reveal.overview .slides section:before { - display: none !important; } - -.reveal.overview .slides section > section { - opacity: 1; - cursor: pointer; } - -.reveal.overview .slides section:hover { - background: rgba(0, 0, 0, 0.3); } - -.reveal.overview .slides section.present { - background: rgba(0, 0, 0, 0.3); } - -.reveal.overview .slides > section.stack { - padding: 0; - top: 0 !important; - background: none; - overflow: visible; } - -/********************************************* * PAUSED MODE *********************************************/ .reveal .pause-overlay { @@ -730,7 +676,7 @@ body { /********************************************* * PER-SLIDE BACKGROUNDS *********************************************/ -.reveal > .backgrounds { +.reveal .backgrounds { position: absolute; width: 100%; height: 100%; @@ -890,6 +836,58 @@ body { transition-duration: 1200ms; } /********************************************* + * OVERVIEW + *********************************************/ +.reveal.overview { + -webkit-perspective-origin: 50% 50%; + perspective-origin: 50% 50%; + -webkit-perspective: 700px; + perspective: 700px; } + .reveal.overview .slides section { + height: 700px; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .reveal.overview .slides section:hover, .reveal.overview .slides section.present { + outline: 10px solid rgba(150, 150, 150, 0.4); + outline-offset: 10px; } + .reveal.overview .slides section .fragment { + opacity: 1; + -webkit-transition: none; + transition: none; } + .reveal.overview .slides section:after, .reveal.overview .slides section:before { + display: none !important; } + .reveal.overview .slides > section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; } + .reveal.overview .backgrounds { + -webkit-perspective: inherit; + perspective: inherit; } + .reveal.overview .backgrounds .slide-background { + opacity: 1; + visibility: visible; + outline: 10px solid rgba(150, 150, 150, 0.1); + outline-offset: 10px; } + +.reveal.overview .slides section, .reveal.overview-deactivating .slides section { + -webkit-transition: none; + transition: none; } + +.reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background { + -webkit-transition: none; + transition: none; } + +.reveal.overview-animated .slides { + -webkit-transition: -webkit-transform 0.4s ease; + transition: transform 0.4s ease; } + +/********************************************* * RTL SUPPORT *********************************************/ .reveal.rtl .slides, .reveal.rtl .slides h1, .reveal.rtl .slides h2, .reveal.rtl .slides h3, .reveal.rtl .slides h4, .reveal.rtl .slides h5, .reveal.rtl .slides h6 { diff --git a/css/reveal.scss b/css/reveal.scss index 6cc21ba..f0d269f 100644 --- a/css/reveal.scss +++ b/css/reveal.scss @@ -57,18 +57,6 @@ body { color: #000; } -::-moz-selection { - background: #FF5E99; - color: #fff; - text-shadow: none; -} - -::selection { - background: #FF5E99; - color: #fff; - text-shadow: none; -} - /********************************************* * VIEW FRAGMENTS @@ -352,6 +340,7 @@ body { position: relative; width: 100%; height: 100%; + overflow: hidden; touch-action: none; } @@ -740,53 +729,6 @@ body { /********************************************* - * OVERVIEW - *********************************************/ - -.reveal.overview .slides { - perspective-origin: 50% 50%; - perspective: 700px; -} - -.reveal.overview .slides section { - height: 700px; - overflow: hidden; - opacity: 1 !important; - visibility: visible !important; - cursor: pointer; - background: rgba(0,0,0,0.1); - box-sizing: border-box; -} -.reveal.overview .slides section, -.reveal.overview-deactivating .slides section { - transition: none !important; -} -.reveal.overview .slides section .fragment { - opacity: 1; -} -.reveal.overview .slides section:after, -.reveal.overview .slides section:before { - display: none !important; -} -.reveal.overview .slides section>section { - opacity: 1; - cursor: pointer; -} - .reveal.overview .slides section:hover { - background: rgba(0,0,0,0.3); - } - .reveal.overview .slides section.present { - background: rgba(0,0,0,0.3); - } -.reveal.overview .slides>section.stack { - padding: 0; - top: 0 !important; - background: none; - overflow: visible; -} - - -/********************************************* * PAUSED MODE *********************************************/ @@ -857,7 +799,7 @@ body { * PER-SLIDE BACKGROUNDS *********************************************/ -.reveal>.backgrounds { +.reveal .backgrounds { position: absolute; width: 100%; height: 100%; @@ -1027,6 +969,74 @@ body { /********************************************* + * OVERVIEW + *********************************************/ + +.reveal.overview { + perspective-origin: 50% 50%; + perspective: 700px; + + .slides section { + height: 700px; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + box-sizing: border-box; + } + .slides section:hover, + .slides section.present { + outline: 10px solid rgba(150,150,150,0.4); + outline-offset: 10px; + } + .slides section .fragment { + opacity: 1; + transition: none; + } + .slides section:after, + .slides section:before { + display: none !important; + } + .slides>section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; + } + + .backgrounds { + perspective: inherit; + } + + .backgrounds .slide-background { + opacity: 1; + visibility: visible; + + // This can't be applied to the slide itself in Safari + outline: 10px solid rgba(150,150,150,0.1); + outline-offset: 10px; + } +} + +// Disable transitions transitions while we're activating +// or deactivating the overview mode. +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; +} + +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; +} + +.reveal.overview-animated .slides { + transition: transform 0.4s ease; +} + + +/********************************************* * RTL SUPPORT *********************************************/ diff --git a/css/theme/README.md b/css/theme/README.md index 90dc149..753e0c0 100644 --- a/css/theme/README.md +++ b/css/theme/README.md @@ -2,8 +2,6 @@ Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceding: https://github.com/hakimel/reveal.js#full-setup -You also need to install Ruby and then Sass (with `gem install sass`). - ## Creating a Theme To create your own theme, start by duplicating any ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source) and adding it to the compilation list in the [Gruntfile](https://github.com/hakimel/reveal.js/blob/master/Gruntfile.js). @@ -17,7 +15,7 @@ Shared utility functions. Declares a set of custom variables that the template file (step 4) expects. Can be overridden in step 3. 3. **Override** -This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding full selectors with hardcoded styles. +This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding any selectors and styles you please. 4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)** The template theme file which will generate final CSS output based on the currently defined variables. diff --git a/css/theme/beige.css b/css/theme/beige.css index 514427c..944dbd8 100644 --- a/css/theme/beige.css +++ b/css/theme/beige.css @@ -163,6 +163,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/black.css b/css/theme/black.css index 7d3bee4..ee2ead8 100644 --- a/css/theme/black.css +++ b/css/theme/black.css @@ -159,6 +159,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/blood.css b/css/theme/blood.css index 768d2a3..952fdf2 100644 --- a/css/theme/blood.css +++ b/css/theme/blood.css @@ -15,13 +15,7 @@ *********************************************/ body { background: #222; - background: -moz-radial-gradient(center, circle cover, #626262 0%, #222 100%); - background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #626262), color-stop(100%, #222)); - background: -webkit-radial-gradient(center, circle cover, #626262 0%, #222 100%); - background: -o-radial-gradient(center, circle cover, #626262 0%, #222 100%); - background: -ms-radial-gradient(center, circle cover, #626262 0%, #222 100%); - background: radial-gradient(center, circle cover, #626262 0%, #222 100%); - background-color: #2b2b2b; } + background-color: #222; } .reveal { font-family: Ubuntu, 'sans-serif'; @@ -168,6 +162,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } @@ -276,12 +276,6 @@ body { .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { font-weight: 700; } -.reveal a, .reveal a:hover { - text-shadow: 2px 2px 2px #000; } - -.reveal small a, .reveal small a:hover { - text-shadow: 1px 1px 1px #000; } - .reveal p code { background-color: #23241f; display: inline-block; diff --git a/css/theme/league.css b/css/theme/league.css index c6d07f6..41967d2 100644 --- a/css/theme/league.css +++ b/css/theme/league.css @@ -165,6 +165,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/moon.css b/css/theme/moon.css index 4817c18..ac93638 100644 --- a/css/theme/moon.css +++ b/css/theme/moon.css @@ -163,6 +163,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/night.css b/css/theme/night.css index 71319b2..6a5ed31 100644 --- a/css/theme/night.css +++ b/css/theme/night.css @@ -157,6 +157,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/serif.css b/css/theme/serif.css index ed85db6..fc83e5d 100644 --- a/css/theme/serif.css +++ b/css/theme/serif.css @@ -159,6 +159,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/simple.css b/css/theme/simple.css index d9153d7..ea08a27 100644 --- a/css/theme/simple.css +++ b/css/theme/simple.css @@ -159,6 +159,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/sky.css b/css/theme/sky.css index f7e8402..83842c4 100644 --- a/css/theme/sky.css +++ b/css/theme/sky.css @@ -166,6 +166,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/solarized.css b/css/theme/solarized.css index 583201a..649f7a9 100644 --- a/css/theme/solarized.css +++ b/css/theme/solarized.css @@ -163,6 +163,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } diff --git a/css/theme/source/blood.scss b/css/theme/source/blood.scss index f2e3a09..d22b53d 100644 --- a/css/theme/source/blood.scss +++ b/css/theme/source/blood.scss @@ -24,6 +24,8 @@ $blood: #a23; $coal: #222; $codeBackground: #23241f; +$backgroundColor: $coal; + // Main text $mainFont: Ubuntu, 'sans-serif'; $mainFontSize: 36px; @@ -45,10 +47,6 @@ $linkColorHover: lighten( $linkColor, 20% ); $selectionBackgroundColor: $blood; $selectionColor: #fff; -// Background generator -@mixin bodyBackground() { - @include radial-gradient( $coal, lighten( $coal, 25% ) ); -} // Theme template ------------------------------ @import "../template/theme"; @@ -61,7 +59,7 @@ $selectionColor: #fff; text-shadow: 1px 1px $coal; } -.reveal h1, +.reveal h1, .reveal h2, .reveal h3, .reveal h4, @@ -70,16 +68,6 @@ $selectionColor: #fff; font-weight: 700; } -.reveal a, -.reveal a:hover { - text-shadow: 2px 2px 2px #000; -} - -.reveal small a, -.reveal small a:hover { - text-shadow: 1px 1px 1px #000; -} - .reveal p code { background-color: $codeBackground; display: inline-block; diff --git a/css/theme/template/theme.scss b/css/theme/template/theme.scss index d1be10a..bd89d31 100644 --- a/css/theme/template/theme.scss +++ b/css/theme/template/theme.scss @@ -199,8 +199,18 @@ body { border-bottom: 1px solid; } +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; +} + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; +} + .reveal table tr:last-child td { - border-bottom: none; + border-bottom: none; } .reveal sup { @@ -333,7 +343,7 @@ body { * SLIDE NUMBER *********************************************/ .reveal .slide-number { - color: $linkColor; + color: $linkColor; } diff --git a/css/theme/white.css b/css/theme/white.css index 5fdb2fc..c77d5ab 100644 --- a/css/theme/white.css +++ b/css/theme/white.css @@ -159,6 +159,12 @@ body { padding: 0.2em 0.5em 0.2em 0.5em; border-bottom: 1px solid; } +.reveal table th[align="center"], .reveal table td[align="center"] { + text-align: center; } + +.reveal table th[align="right"], .reveal table td[align="right"] { + text-align: right; } + .reveal table tr:last-child td { border-bottom: none; } @@ -171,6 +171,7 @@ <a href="#" onclick="document.getElementById('theme').setAttribute('href','css/theme/beige.css'); return false;">Beige</a> - <a href="#" onclick="document.getElementById('theme').setAttribute('href','css/theme/simple.css'); return false;">Simple</a> <br> <a href="#" onclick="document.getElementById('theme').setAttribute('href','css/theme/serif.css'); return false;">Serif</a> - + <a href="#" onclick="document.getElementById('theme').setAttribute('href','css/theme/blood.css'); return false;">Blood</a> - <a href="#" onclick="document.getElementById('theme').setAttribute('href','css/theme/night.css'); return false;">Night</a> - <a href="#" onclick="document.getElementById('theme').setAttribute('href','css/theme/moon.css'); return false;">Moon</a> - <a href="#" onclick="document.getElementById('theme').setAttribute('href','css/theme/solarized.css'); return false;">Solarized</a> @@ -201,6 +202,9 @@ <pre><code style="word-wrap: break-word;"><section data-background-video="video.mp4,video.webm"></code></pre> </div> </section> + <section data-background="http://i.giphy.com/90F8aUepslB84.gif"> + <h2>... and GIFs!</h2> + </section> </section> <section data-transition="slide" data-background="#4d7e65" data-background-transition="zoom"> diff --git a/js/reveal.js b/js/reveal.js index 65ac29f..3edd301 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -136,6 +136,10 @@ // Parallax background size parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px" + // Amount of pixels to move the parallax background per slide step + parallaxBackgroundHorizontal: null, + parallaxBackgroundVertical: null, + // Number of slides away from the current that are visible viewDistance: 3, @@ -147,6 +151,9 @@ // Flags if reveal.js is loaded (has dispatched the 'ready' event) loaded = false, + // Flags if the overview mode is currently active + overview = false, + // The horizontal and vertical index of the currently active slide indexh, indexv, @@ -165,6 +172,10 @@ // The current scale of the presentation (see width/height config) scale = 1, + // CSS transform that is currently applied to the slides container, + // split into two groups + slidesTransform = { layout: '', overview: '' }, + // Cached references to DOM elements dom = {}, @@ -293,7 +304,11 @@ features.touch = !!( 'ontouchstart' in window ); - isMobileDevice = navigator.userAgent.match( /(iphone|ipod|ipad|android)/gi ); + // Transitions in the overview are disabled in desktop and + // mobile Safari due to lag + features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( navigator.userAgent ); + + isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent ); } @@ -373,6 +388,9 @@ // Listen to messages posted to this window setupPostMessage(); + // Prevent iframes from scrolling the slides out of view + setupIframeScrollPrevention(); + // Resets all vertical slides so that only the first is visible resetVerticalSlides(); @@ -557,6 +575,26 @@ } /** + * This is an unfortunate necessity. Iframes can trigger the + * parent window to scroll, for example by focusing an input. + * This scrolling can not be prevented by hiding overflow in + * CSS so we have to resort to repeatedly checking if the + * browser has decided to offset our slides :( + */ + function setupIframeScrollPrevention() { + + if( dom.slides.querySelector( 'iframe' ) ) { + setInterval( function() { + if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) { + dom.wrapper.scrollTop = 0; + dom.wrapper.scrollLeft = 0; + } + }, 500 ); + } + + } + + /** * Creates an HTML element and returns a reference to it. * If the element already exists the existing instance will * be returned. @@ -757,7 +795,7 @@ var data = event.data; // Make sure we're dealing with JSON - if( data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) { + if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) { data = JSON.parse( data ); // Check if the requested method can be found @@ -1051,12 +1089,32 @@ element.style.WebkitTransform = transform; element.style.MozTransform = transform; element.style.msTransform = transform; - element.style.OTransform = transform; element.style.transform = transform; } /** + * Applies CSS transforms to the slides container. The container + * is transformed from two separate sources: layout and the overview + * mode. + */ + function transformSlides( transforms ) { + + // Pick up new transforms from arguments + if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout; + if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview; + + // Apply the transforms to the slides container + if( slidesTransform.layout ) { + transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview ); + } + else { + transformElement( dom.slides, slidesTransform.overview ); + } + + } + + /** * Injects the given CSS styles into the DOM. */ function injectStyleSheet( value ) { @@ -1465,12 +1523,13 @@ dom.slides.style.top = ''; dom.slides.style.bottom = ''; dom.slides.style.right = ''; - transformElement( dom.slides, '' ); + transformSlides( { layout: '' } ); } else { // Prefer zooming in desktop Chrome so that content remains crisp if( !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) { dom.slides.style.zoom = scale; + transformSlides( { layout: '' } ); } // Apply scale transform as a fallback else { @@ -1478,7 +1537,7 @@ dom.slides.style.top = '50%'; dom.slides.style.bottom = 'auto'; dom.slides.style.right = 'auto'; - transformElement( dom.slides, 'translate(-50%, -50%) scale('+ scale +')' ); + transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } ); } } @@ -1620,82 +1679,122 @@ } /** - * Displays the overview of slides (quick nav) by - * scaling down and arranging all slide elements. - * - * Experimental feature, might be dropped if perf - * can't be improved. + * Displays the overview of slides (quick nav) by scaling + * down and arranging all slide elements. */ function activateOverview() { // Only proceed if enabled in config - if( config.overview ) { + if( config.overview && !isOverview() ) { + + overview = true; + + dom.wrapper.classList.add( 'overview' ); + dom.wrapper.classList.remove( 'overview-deactivating' ); + + if( features.overviewTransitions ) { + setTimeout( function() { + dom.wrapper.classList.add( 'overview-animated' ); + }, 1 ); + } // Don't auto-slide while in overview mode cancelAutoSlide(); - var wasActive = dom.wrapper.classList.contains( 'overview' ); + // Move the backgrounds element into the slide container to + // that the same scaling is applied + dom.slides.appendChild( dom.background ); - // Vary the depth of the overview based on screen size - var depth = window.innerWidth < 400 ? 1000 : 2500; + // Clicking on an overview slide navigates to it + toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { + if( !slide.classList.contains( 'stack' ) ) { + slide.addEventListener( 'click', onOverviewSlideClicked, true ); + } + } ); - dom.wrapper.classList.add( 'overview' ); - dom.wrapper.classList.remove( 'overview-deactivating' ); + updateSlidesVisibility(); + layoutOverview(); + updateOverview(); - var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ); + layout(); - for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) { - var hslide = horizontalSlides[i], - hoffset = config.rtl ? -105 : 105; + // Notify observers of the overview showing + dispatchEvent( 'overviewshown', { + 'indexh': indexh, + 'indexv': indexv, + 'currentSlide': currentSlide + } ); - hslide.setAttribute( 'data-index-h', i ); + } - // Apply CSS transform - transformElement( hslide, 'translateZ(-'+ depth +'px) translate(' + ( ( i - indexh ) * hoffset ) + '%, 0%)' ); + } - if( hslide.classList.contains( 'stack' ) ) { + /** + * Uses CSS transforms to position all slides in a grid for + * display inside of the overview mode. + */ + function layoutOverview() { - var verticalSlides = hslide.querySelectorAll( 'section' ); + var margin = 70; + var slideWidth = config.width + margin, + slideHeight = config.height + margin; - for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) { - var verticalIndex = i === indexh ? indexv : getPreviousVerticalIndex( hslide ); + // Reverse in RTL mode + if( config.rtl ) { + slideWidth = -slideWidth; + } - var vslide = verticalSlides[j]; + // Layout slides + toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { + hslide.setAttribute( 'data-index-h', h ); + transformElement( hslide, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' ); - vslide.setAttribute( 'data-index-h', i ); - vslide.setAttribute( 'data-index-v', j ); + if( hslide.classList.contains( 'stack' ) ) { - // Apply CSS transform - transformElement( vslide, 'translate(0%, ' + ( ( j - verticalIndex ) * 105 ) + '%)' ); + toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { + vslide.setAttribute( 'data-index-h', h ); + vslide.setAttribute( 'data-index-v', v ); - // Navigate to this slide on click - vslide.addEventListener( 'click', onOverviewSlideClicked, true ); - } + transformElement( vslide, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' ); + } ); - } - else { + } + } ); - // Navigate to this slide on click - hslide.addEventListener( 'click', onOverviewSlideClicked, true ); + // Layout slide backgrounds + toArray( dom.background.childNodes ).forEach( function( hbackground, h ) { + transformElement( hbackground, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' ); - } - } + toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) { + transformElement( vbackground, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' ); + } ); + } ); - updateSlidesVisibility(); + } - layout(); + /** + * Moves the overview viewport to the current slides. + * Called each time the current slide changes. + */ + function updateOverview() { - if( !wasActive ) { - // Notify observers of the overview showing - dispatchEvent( 'overviewshown', { - 'indexh': indexh, - 'indexv': indexv, - 'currentSlide': currentSlide - } ); - } + var margin = 70; + var slideWidth = config.width + margin, + slideHeight = config.height + margin; + // Reverse in RTL mode + if( config.rtl ) { + slideWidth = -slideWidth; } + transformSlides( { + overview: [ + 'translateX('+ ( -indexh * slideWidth ) +'px)', + 'translateY('+ ( -indexv * slideHeight ) +'px)', + 'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)' + ].join( ' ' ) + } ); + } /** @@ -1707,7 +1806,10 @@ // Only proceed if enabled in config if( config.overview ) { + overview = false; + dom.wrapper.classList.remove( 'overview' ); + dom.wrapper.classList.remove( 'overview-animated' ); // Temporarily add a class so that transitions can do different things // depending on whether they are exiting/entering overview, or just @@ -1718,16 +1820,27 @@ dom.wrapper.classList.remove( 'overview-deactivating' ); }, 1 ); - // Select all slides + // Move the background element back out + dom.wrapper.appendChild( dom.background ); + + // Clean up changes made to slides toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { - // Resets all transforms to use the external styles transformElement( slide, '' ); slide.removeEventListener( 'click', onOverviewSlideClicked, true ); } ); + // Clean up changes made to backgrounds + toArray( dom.background.querySelectorAll( '.slide-background' ) ).forEach( function( background ) { + transformElement( background, '' ); + } ); + + transformSlides( { overview: '' } ); + slide( indexh, indexv ); + layout(); + cueAutoSlide(); // Notify observers of the overview hiding @@ -1766,7 +1879,7 @@ */ function isOverview() { - return dom.wrapper.classList.contains( 'overview' ); + return overview; } @@ -1916,7 +2029,7 @@ // If no vertical index is specified and the upcoming slide is a // stack, resume at its previous vertical index - if( v === undefined ) { + if( v === undefined && !isOverview() ) { v = getPreviousVerticalIndex( horizontalSlides[ h ] ); } @@ -1966,9 +2079,9 @@ document.documentElement.classList.remove( stateBefore.pop() ); } - // If the overview is active, re-activate it to update positions + // Update the overview if it's currently active if( isOverview() ) { - activateOverview(); + updateOverview(); } // Find the current horizontal slide and any possible vertical slides @@ -2081,6 +2194,10 @@ formatEmbeddedContent(); + if( isOverview() ) { + layoutOverview(); + } + } /** @@ -2269,7 +2386,7 @@ viewDistance = isOverview() ? 6 : 2; } - // Limit view distance on weaker devices + // All slides need to be visible when exporting to PDF if( isPrintingPDF() ) { viewDistance = Number.MAX_VALUE; } @@ -2280,8 +2397,14 @@ var verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ), verticalSlidesLength = verticalSlides.length; - // Loops so that it measures 1 between the first and last slides - distanceX = Math.abs( ( ( indexh || 0 ) - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0; + // Determine how far away this slide is from the present + distanceX = Math.abs( ( indexh || 0 ) - x ) || 0; + + // If the presentation is looped, distance should measure + // 1 between the first and last slides + if( config.loop ) { + distanceX = Math.abs( ( ( indexh || 0 ) - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0; + } // Show the horizontal slide if it's within the view distance if( distanceX < viewDistance ) { @@ -2331,19 +2454,33 @@ /** * Updates the slide number div to reflect the current slide. + * + * Slide number format can be defined as a string using the + * following variables: + * h: current slide's horizontal index + * v: current slide's vertical index + * c: current slide index (flattened) + * t: total number of slides (flattened) */ function updateSlideNumber() { // Update slide number if enabled if( config.slideNumber && dom.slideNumber) { - // Display the number of the page using 'indexh - indexv' format - var indexString = indexh; - if( indexv > 0 ) { - indexString += ' - ' + indexv; + // Default to only showing the current slide number + var format = 'c'; + + // Check if a custom slide number format is available + if( typeof config.slideNumber === 'string' ) { + format = config.slideNumber; } - dom.slideNumber.innerHTML = indexString; + var totalSlides = getTotalSlides(); + + dom.slideNumber.innerHTML = format.replace( /h/g, indexh ) + .replace( /v/g, indexv ) + .replace( /c/g, Math.round( getProgress() * totalSlides ) + 1 ) + .replace( /t/g, totalSlides + 1 ); } } @@ -2476,6 +2613,15 @@ currentVideo.play(); } + var backgroundImageURL = currentBackground.style.backgroundImage || ''; + + // Restart GIFs (doesn't work in Firefox) + if( /\.gif/i.test( backgroundImageURL ) ) { + currentBackground.style.backgroundImage = ''; + window.getComputedStyle( currentBackground ).opacity; + currentBackground.style.backgroundImage = backgroundImageURL; + } + // Don't transition between identical backgrounds. This // prevents unwanted flicker. var previousBackgroundHash = previousBackground ? previousBackground.getAttribute( 'data-background-hash' ) : null; @@ -2530,15 +2676,35 @@ backgroundHeight = parseInt( backgroundSize[1], 10 ); } - var slideWidth = dom.background.offsetWidth; - var horizontalSlideCount = horizontalSlides.length; - var horizontalOffset = -( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ) * indexh; + var slideWidth = dom.background.offsetWidth, + horizontalSlideCount = horizontalSlides.length, + horizontalOffsetMultiplier, + horizontalOffset; + + if( typeof config.parallaxBackgroundHorizontal === 'number' ) { + horizontalOffsetMultiplier = config.parallaxBackgroundHorizontal; + } + else { + horizontalOffsetMultiplier = ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ); + } + + horizontalOffset = horizontalOffsetMultiplier * indexh * -1; - var slideHeight = dom.background.offsetHeight; - var verticalSlideCount = verticalSlides.length; - var verticalOffset = verticalSlideCount > 1 ? -( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 ) * indexv : 0; + var slideHeight = dom.background.offsetHeight, + verticalSlideCount = verticalSlides.length, + verticalOffsetMultiplier, + verticalOffset; - dom.background.style.backgroundPosition = horizontalOffset + 'px ' + verticalOffset + 'px'; + if( typeof config.parallaxBackgroundVertical === 'number' ) { + verticalOffsetMultiplier = config.parallaxBackgroundVertical; + } + else { + verticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 ); + } + + verticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indexv * 1 : 0; + + dom.background.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px'; } @@ -2590,6 +2756,7 @@ var backgroundImage = slide.getAttribute( 'data-background-image' ), backgroundVideo = slide.getAttribute( 'data-background-video' ), + backgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ), backgroundIframe = slide.getAttribute( 'data-background-iframe' ); // Images @@ -2600,6 +2767,10 @@ else if ( backgroundVideo && !isSpeakerNotes() ) { var video = document.createElement( 'video' ); + if( backgroundVideoLoop ) { + video.setAttribute( 'loop', '' ); + } + // Support comma separated lists of video sources backgroundVideo.split( ',' ).forEach( function( source ) { video.innerHTML += '<source src="'+ source +'">'; @@ -2608,7 +2779,7 @@ background.appendChild( video ); } // Iframes - else if ( backgroundIframe ) { + else if( backgroundIframe ) { var iframe = document.createElement( 'iframe' ); iframe.setAttribute( 'src', backgroundIframe ); iframe.style.width = '100%'; @@ -2722,6 +2893,13 @@ function startEmbeddedContent( slide ) { if( slide && !isSpeakerNotes() ) { + // Restart GIFs + toArray( slide.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) { + // Setting the same unchanged source like this was confirmed + // to work in Chrome, FF & Safari + el.setAttribute( 'src', el.getAttribute( 'src' ) ); + } ); + // HTML5 media elements toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { if( el.hasAttribute( 'data-autoplay' ) ) { @@ -2880,7 +3058,7 @@ // Ensure the named link is a valid HTML ID attribute if( /^[a-zA-Z][\w:.-]*$/.test( name ) ) { // Find the slide with the specified ID - element = document.querySelector( '#' + name ); + element = document.getElementById( name ); } if( element ) { @@ -3828,6 +4006,10 @@ var slidesTotal = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).length; var slideIndex = Math.floor( ( event.clientX / dom.wrapper.offsetWidth ) * slidesTotal ); + if( config.rtl ) { + slideIndex = slidesTotal - slideIndex; + } + slide( slideIndex ); } @@ -3872,7 +4054,10 @@ // If, after clicking a link or similar and we're coming back, // focus the document.body to ensure we can use keyboard shortcuts if( isHidden === false && document.activeElement !== document.body ) { - document.activeElement.blur(); + // Not all elements support .blur() - SVGs among them. + if( typeof document.activeElement.blur === 'function' ) { + document.activeElement.blur(); + } document.body.focus(); } diff --git a/plugin/markdown/example.html b/plugin/markdown/example.html index 364e866..36f6a51 100644 --- a/plugin/markdown/example.html +++ b/plugin/markdown/example.html @@ -7,7 +7,7 @@ <title>reveal.js - Markdown Demo</title> <link rel="stylesheet" href="../../css/reveal.css"> - <link rel="stylesheet" href="../../css/theme/default.css" id="theme"> + <link rel="stylesheet" href="../../css/theme/white.css" id="theme"> <link rel="stylesheet" href="../../lib/css/zenburn.css"> </head> diff --git a/plugin/markdown/markdown.js b/plugin/markdown/markdown.js index 9afee06..4847c7a 100755 --- a/plugin/markdown/markdown.js +++ b/plugin/markdown/markdown.js @@ -50,7 +50,7 @@ text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' ); } else if( leadingWs > 1 ) { - text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' ); + text = text.replace( new RegExp('\\n? {' + leadingWs + '}', 'g'), '\n' ); } return text; diff --git a/plugin/math/math.js b/plugin/math/math.js index d55d9d1..25b7516 100755 --- a/plugin/math/math.js +++ b/plugin/math/math.js @@ -7,7 +7,7 @@ var RevealMath = window.RevealMath || (function(){ var options = Reveal.getConfig().math || {}; - options.mathjax = options.mathjax || 'http://cdn.mathjax.org/mathjax/latest/MathJax.js'; + options.mathjax = options.mathjax || 'https://cdn.mathjax.org/mathjax/latest/MathJax.js'; options.config = options.config || 'TeX-AMS_HTML-full'; loadScript( options.mathjax + '?config=' + options.config, function() { |