diff options
32 files changed, 914 insertions, 470 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'] + } } }); @@ -174,8 +174,12 @@ Reveal.initialize({ parallaxBackgroundImage: '', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'" // Parallax background size - parallaxBackgroundSize: '' // CSS syntax, e.g. "2100px 900px" + parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px" + // Amount to move parallax background (horizontal and vertical) on slide change + // Number, e.g. 100 + parallaxBackgroundHorizontal: '', + parallaxBackgroundVertical: '' }); ``` @@ -313,12 +317,12 @@ Reveal.configure({ When working on presentation with a lot of media or iframe content it's important to load lazily. Lazy loading means that reveal.js will only load content for the few slides nearest to the current slide. The number of slides that are preloaded is determined by the `viewDistance` configuration option. -To enable lazy loading all you need to do is change your "src" attributes to "data-src" as shown below. This is supported for image, video, audio and iframe elements. +To enable lazy loading all you need to do is change your "src" attributes to "data-src" as shown below. This is supported for image, video, audio and iframe elements. Lazy loaded iframes will also unload when the containing slide is no longer visible. ```html <section> <img data-src="image.png"> - <iframe data-src="http://slides.com"></iframe> + <iframe data-src="http://hakim.se"></iframe> <video> <source data-src="video.webm" type="video/webm" /> <source data-src="video.mp4" type="video/mp4" /> @@ -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 }); ``` @@ -475,6 +482,27 @@ The global presentation transition is set using the ```transition``` config valu </section> ``` +You can also use different in and out transitions for the same slide: + +```html +<section data-transition="slide"> + The train goes on … +</section> +<section data-transition="slide"> + and on … +</section> +<section data-transition="slide-in fade-out"> + and stops. +</section> +<section data-transition="fade-in slide-out"> + (Passengers entering and leaving) +</section> +<section data-transition="slide"> + And it starts again. +</section> +``` + + Note that this does not work with the page and cube transitions. @@ -508,7 +536,6 @@ The default fragment style is to start out invisible and fade in. This style can <section> <p class="fragment grow">grow</p> <p class="fragment shrink">shrink</p> - <p class="fragment roll-in">roll-in</p> <p class="fragment fade-out">fade-out</p> <p class="fragment current-visible">visible only once</p> <p class="fragment highlight-current-blue">blue only once</p> @@ -573,7 +600,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' }); + ``` @@ -676,7 +712,7 @@ The framework comes with a few different themes included: - white: White background, black text, blue links - league: Gray background, white text, blue links (default theme for reveal.js < 3.0.0) - beige: Beige background, dark text, brown links -- sky: Blue background, thin white text, blue links +- sky: Blue background, thin dark text, blue links - night: Black background, thick white text, orange links - serif: Cappuccino background, gray text, brown links - simple: White background, black text, blue links diff --git a/css/reveal.css b/css/reveal.css index 05bfd2d..258e975 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 *********************************************/ @@ -76,16 +66,9 @@ body { -ms-transform: scale(0.1); transform: scale(0.1); } .reveal .slides section .fragment.zoom-in.visible { - -webkit-transform: scale(1); - -ms-transform: scale(1); - transform: scale(1); } - -.reveal .slides section .fragment.roll-in { - -webkit-transform: rotateX(90deg); - transform: rotateX(90deg); } - .reveal .slides section .fragment.roll-in.visible { - -webkit-transform: rotateX(0); - transform: rotateX(0); } + -webkit-transform: none; + -ms-transform: none; + transform: none; } .reveal .slides section .fragment.fade-out { opacity: 1; @@ -275,6 +258,7 @@ body { position: relative; width: 100%; height: 100%; + overflow: hidden; -ms-touch-action: none; touch-action: none; } @@ -351,29 +335,56 @@ body { opacity: 0; } /********************************************* + * Mixins for readability of transitions + *********************************************/ +/********************************************* * SLIDE TRANSITION * Aliased 'linear' for backwards compatibility *********************************************/ -.reveal.slide section, .reveal.linear section { +.reveal.slide section { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; } + +.reveal .slides > section[data-transition=slide].past, .reveal .slides > section[data-transition~=slide-out].past, .reveal.slide .slides > section:not([data-transition]).past { + -webkit-transform: translate(-150%, 0); + -ms-transform: translate(-150%, 0); + transform: translate(-150%, 0); } + +.reveal .slides > section[data-transition=slide].future, .reveal .slides > section[data-transition~=slide-in].future, .reveal.slide .slides > section:not([data-transition]).future { + -webkit-transform: translate(150%, 0); + -ms-transform: translate(150%, 0); + transform: translate(150%, 0); } + +.reveal .slides > section > section[data-transition=slide].past, .reveal .slides > section > section[data-transition~=slide-out].past, .reveal.slide .slides > section > section:not([data-transition]).past { + -webkit-transform: translate(0, -150%); + -ms-transform: translate(0, -150%); + transform: translate(0, -150%); } + +.reveal .slides > section > section[data-transition=slide].future, .reveal .slides > section > section[data-transition~=slide-in].future, .reveal.slide .slides > section > section:not([data-transition]).future { + -webkit-transform: translate(0, 150%); + -ms-transform: translate(0, 150%); + transform: translate(0, 150%); } + +.reveal.linear section { -webkit-backface-visibility: hidden; backface-visibility: hidden; } -.reveal .slides > section[data-transition=slide].past, .reveal.slide .slides > section:not([data-transition]).past, .reveal .slides > section[data-transition=linear].past, .reveal.linear .slides > section:not([data-transition]).past { +.reveal .slides > section[data-transition=linear].past, .reveal .slides > section[data-transition~=linear-out].past, .reveal.linear .slides > section:not([data-transition]).past { -webkit-transform: translate(-150%, 0); -ms-transform: translate(-150%, 0); transform: translate(-150%, 0); } -.reveal .slides > section[data-transition=slide].future, .reveal.slide .slides > section:not([data-transition]).future, .reveal .slides > section[data-transition=linear].future, .reveal.linear .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=linear].future, .reveal .slides > section[data-transition~=linear-in].future, .reveal.linear .slides > section:not([data-transition]).future { -webkit-transform: translate(150%, 0); -ms-transform: translate(150%, 0); transform: translate(150%, 0); } -.reveal .slides > section > section[data-transition=slide].past, .reveal.slide .slides > section > section:not([data-transition]).past, .reveal .slides > section > section[data-transition=linear].past, .reveal.linear .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=linear].past, .reveal .slides > section > section[data-transition~=linear-out].past, .reveal.linear .slides > section > section:not([data-transition]).past { -webkit-transform: translate(0, -150%); -ms-transform: translate(0, -150%); transform: translate(0, -150%); } -.reveal .slides > section > section[data-transition=slide].future, .reveal.slide .slides > section > section:not([data-transition]).future, .reveal .slides > section > section[data-transition=linear].future, .reveal.linear .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=linear].future, .reveal .slides > section > section[data-transition~=linear-in].future, .reveal.linear .slides > section > section:not([data-transition]).future { -webkit-transform: translate(0, 150%); -ms-transform: translate(0, 150%); transform: translate(0, 150%); } @@ -382,38 +393,54 @@ body { * CONVEX TRANSITION * Aliased 'default' for backwards compatibility *********************************************/ -.reveal .slides > section[data-transition=default].past, .reveal.default .slides > section:not([data-transition]).past, .reveal .slides > section[data-transition=convex].past, .reveal.convex .slides > section:not([data-transition]).past { +.reveal .slides > section[data-transition=default].past, .reveal .slides > section[data-transition~=default-out].past, .reveal.default .slides > section:not([data-transition]).past { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=default].future, .reveal .slides > section[data-transition~=default-in].future, .reveal.default .slides > section:not([data-transition]).future { + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=default].past, .reveal .slides > section > section[data-transition~=default-out].past, .reveal.default .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } + +.reveal .slides > section > section[data-transition=default].future, .reveal .slides > section > section[data-transition~=default-in].future, .reveal.default .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } + +.reveal .slides > section[data-transition=convex].past, .reveal .slides > section[data-transition~=convex-out].past, .reveal.convex .slides > section:not([data-transition]).past { -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } -.reveal .slides > section[data-transition=default].future, .reveal.default .slides > section:not([data-transition]).future, .reveal .slides > section[data-transition=convex].future, .reveal.convex .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=convex].future, .reveal .slides > section[data-transition~=convex-in].future, .reveal.convex .slides > section:not([data-transition]).future { -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } -.reveal .slides > section > section[data-transition=default].past, .reveal.default .slides > section > section:not([data-transition]).past, .reveal .slides > section > section[data-transition=convex].past, .reveal.convex .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=convex].past, .reveal .slides > section > section[data-transition~=convex-out].past, .reveal.convex .slides > section > section:not([data-transition]).past { -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } -.reveal .slides > section > section[data-transition=default].future, .reveal.default .slides > section > section:not([data-transition]).future, .reveal .slides > section > section[data-transition=convex].future, .reveal.convex .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=convex].future, .reveal .slides > section > section[data-transition~=convex-in].future, .reveal.convex .slides > section > section:not([data-transition]).future { -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } /********************************************* * CONCAVE TRANSITION *********************************************/ -.reveal .slides > section[data-transition=concave].past, .reveal.concave .slides > section:not([data-transition]).past { +.reveal .slides > section[data-transition=concave].past, .reveal .slides > section[data-transition~=concave-out].past, .reveal.concave .slides > section:not([data-transition]).past { -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } -.reveal .slides > section[data-transition=concave].future, .reveal.concave .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=concave].future, .reveal .slides > section[data-transition~=concave-in].future, .reveal.concave .slides > section:not([data-transition]).future { -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } -.reveal .slides > section > section[data-transition=concave].past, .reveal.concave .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=concave].past, .reveal .slides > section > section[data-transition~=concave-out].past, .reveal.concave .slides > section > section:not([data-transition]).past { -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); } -.reveal .slides > section > section[data-transition=concave].future, .reveal.concave .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=concave].future, .reveal .slides > section > section[data-transition~=concave-in].future, .reveal.concave .slides > section > section:not([data-transition]).future { -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); } @@ -424,24 +451,24 @@ body { -webkit-transition-timing-function: ease; transition-timing-function: ease; } -.reveal .slides > section[data-transition=zoom].past, .reveal.zoom .slides > section:not([data-transition]).past { +.reveal .slides > section[data-transition=zoom].past, .reveal .slides > section[data-transition~=zoom-out].past, .reveal.zoom .slides > section:not([data-transition]).past { visibility: hidden; -webkit-transform: scale(16); -ms-transform: scale(16); transform: scale(16); } -.reveal .slides > section[data-transition=zoom].future, .reveal.zoom .slides > section:not([data-transition]).future { +.reveal .slides > section[data-transition=zoom].future, .reveal .slides > section[data-transition~=zoom-in].future, .reveal.zoom .slides > section:not([data-transition]).future { visibility: hidden; -webkit-transform: scale(0.2); -ms-transform: scale(0.2); transform: scale(0.2); } -.reveal .slides > section > section[data-transition=zoom].past, .reveal.zoom .slides > section > section:not([data-transition]).past { +.reveal .slides > section > section[data-transition=zoom].past, .reveal .slides > section > section[data-transition~=zoom-out].past, .reveal.zoom .slides > section > section:not([data-transition]).past { -webkit-transform: translate(0, -150%); -ms-transform: translate(0, -150%); transform: translate(0, -150%); } -.reveal .slides > section > section[data-transition=zoom].future, .reveal.zoom .slides > section > section:not([data-transition]).future { +.reveal .slides > section > section[data-transition=zoom].future, .reveal .slides > section > section[data-transition~=zoom-in].future, .reveal.zoom .slides > section > section:not([data-transition]).future { -webkit-transform: translate(0, 150%); -ms-transform: translate(0, 150%); transform: translate(0, 150%); } @@ -617,7 +644,7 @@ body { /********************************************* * NO TRANSITION *********************************************/ -.reveal .slides section[data-transition=none], .reveal.none .slides section:not([data-transition]) { +.reveal .slides > section[data-transition=none], .reveal.none .slides > section:not([data-transition]) { -webkit-transform: none; -ms-transform: none; transform: none; @@ -625,51 +652,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 +712,7 @@ body { /********************************************* * PER-SLIDE BACKGROUNDS *********************************************/ -.reveal > .backgrounds { +.reveal .backgrounds { position: absolute; width: 100%; height: 100%; @@ -890,6 +872,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..3321c98 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 @@ -107,15 +95,7 @@ body { transform: scale( 0.1 ); &.visible { - transform: scale( 1 ); - } -} - -.reveal .slides section .fragment.roll-in { - transform: rotateX( 90deg ); - - &.visible { - transform: rotateX( 0 ); + transform: none; } } @@ -352,6 +332,7 @@ body { position: relative; width: 100%; height: 100%; + overflow: hidden; touch-action: none; } @@ -447,93 +428,102 @@ body { /********************************************* - * SLIDE TRANSITION - * Aliased 'linear' for backwards compatibility + * Mixins for readability of transitions *********************************************/ -.reveal.slide section, -.reveal.linear section { - backface-visibility: hidden; +@mixin transition-global($style) { + .reveal .slides>section[data-transition=#{$style}], + .reveal.#{$style} .slides>section:not([data-transition]) { + @content; + } } - -.reveal .slides>section[data-transition=slide].past, -.reveal.slide .slides>section:not([data-transition]).past, -.reveal .slides>section[data-transition=linear].past, -.reveal.linear .slides>section:not([data-transition]).past { - transform: translate(-150%, 0); +@mixin transition-horizontal-past($style) { + .reveal .slides>section[data-transition=#{$style}].past, + .reveal .slides>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section:not([data-transition]).past { + @content; + } } -.reveal .slides>section[data-transition=slide].future, -.reveal.slide .slides>section:not([data-transition]).future, -.reveal .slides>section[data-transition=linear].future, -.reveal.linear .slides>section:not([data-transition]).future { - transform: translate(150%, 0); +@mixin transition-horizontal-future($style) { + .reveal .slides>section[data-transition=#{$style}].future, + .reveal .slides>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section:not([data-transition]).future { + @content; + } } -.reveal .slides>section>section[data-transition=slide].past, -.reveal.slide .slides>section>section:not([data-transition]).past, -.reveal .slides>section>section[data-transition=linear].past, -.reveal.linear .slides>section>section:not([data-transition]).past { - transform: translate(0, -150%); +@mixin transition-vertical-past($style) { + .reveal .slides>section>section[data-transition=#{$style}].past, + .reveal .slides>section>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section>section:not([data-transition]).past { + @content; + } } -.reveal .slides>section>section[data-transition=slide].future, -.reveal.slide .slides>section>section:not([data-transition]).future, -.reveal .slides>section>section[data-transition=linear].future, -.reveal.linear .slides>section>section:not([data-transition]).future { - transform: translate(0, 150%); +@mixin transition-vertical-future($style) { + .reveal .slides>section>section[data-transition=#{$style}].future, + .reveal .slides>section>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section>section:not([data-transition]).future { + @content; + } } +/********************************************* + * SLIDE TRANSITION + * Aliased 'linear' for backwards compatibility + *********************************************/ + +@each $stylename in slide, linear { + .reveal.#{$stylename} section { + backface-visibility: hidden; + } + @include transition-horizontal-past(#{$stylename}) { + transform: translate(-150%, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate(150%, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate(0, -150%); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate(0, 150%); + } +} /********************************************* * CONVEX TRANSITION * Aliased 'default' for backwards compatibility *********************************************/ -.reveal .slides>section[data-transition=default].past, -.reveal.default .slides>section:not([data-transition]).past, -.reveal .slides>section[data-transition=convex].past, -.reveal.convex .slides>section:not([data-transition]).past { - transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); -} -.reveal .slides>section[data-transition=default].future, -.reveal.default .slides>section:not([data-transition]).future, -.reveal .slides>section[data-transition=convex].future, -.reveal.convex .slides>section:not([data-transition]).future { - transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); -} - -.reveal .slides>section>section[data-transition=default].past, -.reveal.default .slides>section>section:not([data-transition]).past, -.reveal .slides>section>section[data-transition=convex].past, -.reveal.convex .slides>section>section:not([data-transition]).past { - transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); -} -.reveal .slides>section>section[data-transition=default].future, -.reveal.default .slides>section>section:not([data-transition]).future, -.reveal .slides>section>section[data-transition=convex].future, -.reveal.convex .slides>section>section:not([data-transition]).future { - transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); +@each $stylename in default, convex { + @include transition-horizontal-past(#{$stylename}) { + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + } } - /********************************************* * CONCAVE TRANSITION *********************************************/ -.reveal .slides>section[data-transition=concave].past, -.reveal.concave .slides>section:not([data-transition]).past { +@include transition-horizontal-past(concave) { transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } -.reveal .slides>section[data-transition=concave].future, -.reveal.concave .slides>section:not([data-transition]).future { +@include transition-horizontal-future(concave) { transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } - -.reveal .slides>section>section[data-transition=concave].past, -.reveal.concave .slides>section>section:not([data-transition]).past { +@include transition-vertical-past(concave) { transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); } -.reveal .slides>section>section[data-transition=concave].future, -.reveal.concave .slides>section>section:not([data-transition]).future { +@include transition-vertical-future(concave) { transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); } @@ -542,28 +532,21 @@ body { * ZOOM TRANSITION *********************************************/ -.reveal .slides>section[data-transition=zoom], -.reveal.zoom .slides>section:not([data-transition]) { +@include transition-global(zoom) { transition-timing-function: ease; } - -.reveal .slides>section[data-transition=zoom].past, -.reveal.zoom .slides>section:not([data-transition]).past { +@include transition-horizontal-past(zoom) { visibility: hidden; transform: scale(16); } -.reveal .slides>section[data-transition=zoom].future, -.reveal.zoom .slides>section:not([data-transition]).future { +@include transition-horizontal-future(zoom) { visibility: hidden; transform: scale(0.2); } - -.reveal .slides>section>section[data-transition=zoom].past, -.reveal.zoom .slides>section>section:not([data-transition]).past { +@include transition-vertical-past(zoom) { transform: translate(0, -150%); } -.reveal .slides>section>section[data-transition=zoom].future, -.reveal.zoom .slides>section>section:not([data-transition]).future { +@include transition-vertical-future(zoom) { transform: translate(0, 150%); } @@ -732,61 +715,13 @@ body { * NO TRANSITION *********************************************/ -.reveal .slides section[data-transition=none], -.reveal.none .slides section:not([data-transition]) { +@include transition-global(none) { transform: none; transition: none; } /********************************************* - * 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 +792,7 @@ body { * PER-SLIDE BACKGROUNDS *********************************************/ -.reveal>.backgrounds { +.reveal .backgrounds { position: absolute; width: 100%; height: 100%; @@ -1027,6 +962,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; } @@ -75,7 +75,7 @@ <p>That's it, time to go back up.</p> <br> <a href="#/2"> - <img width="178" height="238" data-src="https://s3.amazonaws.com/hakim-static/reveal-js/arrow.png" alt="Up arrow" style="-webkit-transform: rotate(180deg);"> + <img width="178" height="238" data-src="https://s3.amazonaws.com/hakim-static/reveal-js/arrow.png" alt="Up arrow" style="transform: rotate(180deg); -webkit-transform: rotate(180deg);"> </a> </section> </section> @@ -138,7 +138,6 @@ <p>There's different types of fragments, like:</p> <p class="fragment grow">grow</p> <p class="fragment shrink">shrink</p> - <p class="fragment roll-in">roll-in</p> <p class="fragment fade-out">fade-out</p> <p class="fragment current-visible">current-visible</p> <p class="fragment highlight-red">highlight-red</p> @@ -171,6 +170,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 +201,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..ff5ea53 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -30,7 +30,7 @@ VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section', HOME_SLIDE_SELECTOR = '.slides>section:first-of-type', - // Configurations defaults, can be overridden at initialization time + // Configuration defaults, can be overridden at initialization time config = { // The "normal" size of the presentation, aspect ratio will be preserved @@ -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 = {}, @@ -227,14 +238,18 @@ if( !features.transforms2d && !features.transforms3d ) { document.body.setAttribute( 'class', 'no-transforms' ); - // Since JS won't be running any further, we need to load all - // images that were intended to lazy load now - var images = document.getElementsByTagName( 'img' ); - for( var i = 0, len = images.length; i < len; i++ ) { - var image = images[i]; - if( image.getAttribute( 'data-src' ) ) { - image.setAttribute( 'src', image.getAttribute( 'data-src' ) ); - image.removeAttribute( 'data-src' ); + // Since JS won't be running any further, we load all lazy + // loading elements upfront + var images = toArray( document.getElementsByTagName( 'img' ) ), + iframes = toArray( document.getElementsByTagName( 'iframe' ) ); + + var lazyLoadable = images.concat( iframes ); + + for( var i = 0, len = lazyLoadable.length; i < len; i++ ) { + var element = lazyLoadable[i]; + if( element.getAttribute( 'data-src' ) ) { + element.setAttribute( 'src', element.getAttribute( 'data-src' ) ); + element.removeAttribute( 'data-src' ); } } @@ -293,7 +308,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 +392,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 +579,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 +799,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 +1093,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 ) { @@ -1074,7 +1136,7 @@ } /** - * Measures the distance in pixels between point a and point b. + * Converts various color input formats to an {r:0,g:0,b:0} object. * * @param {String} color The string representation of a color, * the following formats are supported: @@ -1465,12 +1527,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 +1541,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 +')' } ); } } @@ -1566,7 +1629,7 @@ }; // Reduce available space by margin - size.presentationWidth -= ( size.presentationHeight * config.margin ); + size.presentationWidth -= ( size.presentationWidth * config.margin ); size.presentationHeight -= ( size.presentationHeight * config.margin ); // Slide width may be a percentage of available width @@ -1620,82 +1683,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 +1810,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 +1824,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 +1883,7 @@ */ function isOverview() { - return dom.wrapper.classList.contains( 'overview' ); + return overview; } @@ -1916,7 +2033,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 +2083,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 @@ -2080,6 +2197,11 @@ updateSlidesVisibility(); formatEmbeddedContent(); + startEmbeddedContent( currentSlide ); + + if( isOverview() ) { + layoutOverview(); + } } @@ -2269,7 +2391,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 +2402,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 +2459,31 @@ /** * 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; + dom.slideNumber.innerHTML = format.replace( /h/g, indexh ) + .replace( /v/g, indexv ) + .replace( /c/g, getSlidePastCount() + 1 ) + .replace( /t/g, getTotalSlides() ); } } @@ -2476,6 +2616,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 +2679,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, + verticalSlideCount = verticalSlides.length, + verticalOffsetMultiplier, + verticalOffset; + + if( typeof config.parallaxBackgroundVertical === 'number' ) { + verticalOffsetMultiplier = config.parallaxBackgroundVertical; + } + else { + verticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 ); + } - var slideHeight = dom.background.offsetHeight; - var verticalSlideCount = verticalSlides.length; - var verticalOffset = verticalSlideCount > 1 ? -( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 ) * indexv : 0; + verticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indexv * 1 : 0; - dom.background.style.backgroundPosition = horizontalOffset + 'px ' + verticalOffset + 'px'; + dom.background.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px'; } @@ -2555,7 +2724,7 @@ slide.style.display = 'block'; // Media elements with data-src attributes - toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ) ).forEach( function( element ) { + toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) { element.setAttribute( 'src', element.getAttribute( 'data-src' ) ); element.removeAttribute( 'data-src' ); } ); @@ -2590,6 +2759,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 +2770,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 +2782,7 @@ background.appendChild( video ); } // Iframes - else if ( backgroundIframe ) { + else if( backgroundIframe ) { var iframe = document.createElement( 'iframe' ); iframe.setAttribute( 'src', backgroundIframe ); iframe.style.width = '100%'; @@ -2697,21 +2871,22 @@ */ function formatEmbeddedContent() { + var _appendParamToIframeSource = function( sourceAttribute, sourceURL, param ) { + toArray( dom.slides.querySelectorAll( 'iframe['+ sourceAttribute +'*="'+ sourceURL +'"]' ) ).forEach( function( el ) { + var src = el.getAttribute( sourceAttribute ); + if( src && src.indexOf( param ) === -1 ) { + el.setAttribute( sourceAttribute, src + ( !/\?/.test( src ) ? '?' : '&' ) + param ); + } + }); + }; + // YouTube frames must include "?enablejsapi=1" - toArray( dom.slides.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) { - var src = el.getAttribute( 'src' ); - if( !/enablejsapi\=1/gi.test( src ) ) { - el.setAttribute( 'src', src + ( !/\?/.test( src ) ? '?' : '&' ) + 'enablejsapi=1' ); - } - }); + _appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' ); + _appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' ); // Vimeo frames must include "?api=1" - toArray( dom.slides.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) { - var src = el.getAttribute( 'src' ); - if( !/api\=1/gi.test( src ) ) { - el.setAttribute( 'src', src + ( !/\?/.test( src ) ? '?' : '&' ) + 'api=1' ); - } - }); + _appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' ); + _appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' ); } @@ -2722,31 +2897,56 @@ 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' ) ) { + if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) { el.play(); } } ); - // iframe embeds - toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) { - el.contentWindow.postMessage( 'slide:start', '*' ); - }); + // Normal iframes + toArray( slide.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) { + startEmbeddedIframe( { target: el } ); + } ); - // YouTube embeds - toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) { - if( el.hasAttribute( 'data-autoplay' ) ) { - el.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' ); + // Lazy loading iframes + toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { + if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) { + el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes + el.addEventListener( 'load', startEmbeddedIframe ); + el.setAttribute( 'src', el.getAttribute( 'data-src' ) ); } - }); + } ); + } - // Vimeo embeds - toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) { - if( el.hasAttribute( 'data-autoplay' ) ) { - el.contentWindow.postMessage( '{"method":"play"}', '*' ); - } - }); + } + + /** + * "Starts" the content of an embedded iframe using the + * postmessage API. + */ + function startEmbeddedIframe( event ) { + + var iframe = event.target; + + // YouTube postMessage API + if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) { + iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' ); + } + // Vimeo postMessage API + else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) { + iframe.contentWindow.postMessage( '{"method":"play"}', '*' ); + } + // Generic postMessage API + else { + iframe.contentWindow.postMessage( 'slide:start', '*' ); } } @@ -2760,43 +2960,51 @@ if( slide && slide.parentNode ) { // HTML5 media elements toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { - if( !el.hasAttribute( 'data-ignore' ) ) { + if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) { el.pause(); } } ); - // iframe embeds + // Generic postMessage API for non-lazy loaded iframes toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) { el.contentWindow.postMessage( 'slide:stop', '*' ); + el.removeEventListener( 'load', startEmbeddedIframe ); }); - // YouTube embeds + // YouTube postMessage API toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) { if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) { el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' ); } }); - // Vimeo embeds + // Vimeo postMessage API toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) { if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) { el.contentWindow.postMessage( '{"method":"pause"}', '*' ); } }); + + // Lazy loading iframes + toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { + // Only removing the src doesn't actually unload the frame + // in all browsers (Firefox) so we set it to blank first + el.setAttribute( 'src', 'about:blank' ); + el.removeAttribute( 'src' ); + } ); } } /** - * Returns a value ranging from 0-1 that represents - * how far into the presentation we have navigated. + * Returns the number of past slides. This can be used as a global + * flattened index for slides. */ - function getProgress() { + function getSlidePastCount() { var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ); - // The number of past and total slides - var totalCount = getTotalSlides(); + // The number of past slides var pastCount = 0; // Step through all slides and count the past ones @@ -2828,6 +3036,20 @@ } + return pastCount; + + } + + /** + * Returns a value ranging from 0-1 that represents + * how far into the presentation we have navigated. + */ + function getProgress() { + + // The number of past and total slides + var totalCount = getTotalSlides(); + var pastCount = getSlidePastCount(); + if( currentSlide ) { var allFragments = currentSlide.querySelectorAll( '.fragment' ); @@ -2880,7 +3102,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 ) { @@ -3312,14 +3534,17 @@ // If there are media elements with data-autoplay, // automatically set the autoSlide duration to the - // length of that media - toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { - if( el.hasAttribute( 'data-autoplay' ) ) { - if( autoSlide && el.duration * 1000 > autoSlide ) { - autoSlide = ( el.duration * 1000 ) + 1000; + // length of that media. Not applicable if the slide + // is divided up into fragments. + if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) { + toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { + if( el.hasAttribute( 'data-autoplay' ) ) { + if( autoSlide && el.duration * 1000 > autoSlide ) { + autoSlide = ( el.duration * 1000 ) + 1000; + } } - } - } ); + } ); + } // Cue the next auto-slide if: // - There is an autoSlide value @@ -3828,6 +4053,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 +4101,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/package.json b/package.json index afe21f2..201c6bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reveal.js", - "version": "3.0.0", + "version": "3.1.0", "description": "The HTML Presentation Framework", "homepage": "http://lab.hakim.se/reveal-js", "subdomain": "revealjs", @@ -30,7 +30,7 @@ "devDependencies": { "grunt-contrib-qunit": "~0.5.2", "grunt-contrib-jshint": "~0.6.4", - "grunt-contrib-cssmin": "~0.4.1", + "grunt-contrib-cssmin": "~0.12.2", "grunt-contrib-uglify": "~0.2.4", "grunt-contrib-watch": "~0.5.3", "grunt-sass": "~0.14.0", 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..15e3b40 100755 --- a/plugin/markdown/markdown.js +++ b/plugin/markdown/markdown.js @@ -26,7 +26,7 @@ }); } - var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$', + var DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$', DEFAULT_NOTES_SEPARATOR = 'note:', DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$', DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$'; @@ -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; @@ -76,7 +76,7 @@ if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue; if( value ) { - result.push( name + '=' + value ); + result.push( name + '="' + value + '"' ); } else { result.push( name ); diff --git a/plugin/markdown/marked.js b/plugin/markdown/marked.js index ca558fb..70af29b 100644 --- a/plugin/markdown/marked.js +++ b/plugin/markdown/marked.js @@ -1,37 +1,6 @@ /** * marked - a markdown parser - * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed) + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) * https://github.com/chjj/marked */ - -(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, -text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr",/\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b";block.html=replace(block.html)("comment",/\x3c!--[\s\S]*?--\x3e/)("closed", -/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1", -"\\2")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm)if(this.options.tables)this.rules=block.tables;else this.rules=block.gfm}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)}; -Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1)this.tokens.push({type:"space"})}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm, -"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g, -"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++)if(/^ *-+: *$/.test(item.align[i]))item.align[i]="right";else if(/^ *:-+: *$/.test(item.align[i]))item.align[i]="center";else if(/^ *:-+ *$/.test(item.align[i]))item.align[i]="left";else item.align[i]=null;for(i=0;i<item.cells.length;i++)item.cells[i]=item.cells[i].split(/ *\| */);this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src= -src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length); -bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+ -1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item[item.length-1]==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script",text:cap[0]});continue}if(top&& -(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++)if(/^ *-+: *$/.test(item.align[i]))item.align[i]="right";else if(/^ *:-+: *$/.test(item.align[i]))item.align[i]= -"center";else if(/^ *:-+ *$/.test(item.align[i]))item.align[i]="left";else item.align[i]=null;for(i=0;i<item.cells.length;i++)item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */);this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1][cap[1].length-1]==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text", -text:cap[0]});continue}if(src)throw new Error("Infinite loop on byte: "+src.charCodeAt(0));}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^\x3c!--[\s\S]*?--\x3e|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, -code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, -em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal; -if(!this.links)throw new Error("Tokens array requires a `links` property.");if(this.options.gfm)if(this.options.breaks)this.rules=inline.breaks;else this.rules=inline.gfm;else if(this.options.pedantic)this.rules=inline.pedantic}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length); -out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1][6]===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+='<a href="'+href+'">'+text+"</a>";continue}if(cap=this.rules.url.exec(src)){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+='<a href="'+href+'">'+text+"</a>";continue}if(cap=this.rules.tag.exec(src)){src=src.substring(cap[0].length); -out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);out+=this.outputLink(cap,{href:cap[2],title:cap[3]});continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0][0];src=cap[0].substring(1)+src;continue}out+=this.outputLink(cap,link);continue}if(cap=this.rules.strong.exec(src)){src= -src.substring(cap[0].length);out+="<strong>"+this.output(cap[2]||cap[1])+"</strong>";continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+="<em>"+this.output(cap[2]||cap[1])+"</em>";continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+="<code>"+escape(cap[2],true)+"</code>";continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+="<br>";continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+="<del>"+ -this.output(cap[1])+"</del>";continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(cap[0]);continue}if(src)throw new Error("Infinite loop on byte: "+src.charCodeAt(0));}return out};InlineLexer.prototype.outputLink=function(cap,link){if(cap[0][0]!=="!")return'<a href="'+escape(link.href)+'"'+(link.title?' title="'+escape(link.title)+'"':"")+">"+this.output(cap[1])+"</a>";else return'<img src="'+escape(link.href)+'" alt="'+escape(cap[1])+'"'+(link.title?' title="'+ -escape(link.title)+'"':"")+">"};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"\u2014").replace(/'([^']*)'/g,"\u2018$1\u2019").replace(/"([^"]*)"/g,"\u201c$1\u201d").replace(/\.{3}/g,"\u2026")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>0.5)ch="x"+ch.toString(16);out+="&#"+ch+";"}return out};function Parser(options){this.tokens=[];this.token=null; -this.options=options||marked.defaults}Parser.parse=function(src,options){var parser=new Parser(options);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options);this.tokens=src.reverse();var out="";while(this.next())out+=this.tok();return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text; -while(this.peek().type==="text")body+="\n"+this.next().text;return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case "space":return"";case "hr":return"<hr>\n";case "heading":return"<h"+this.token.depth+">"+this.inline.output(this.token.text)+"</h"+this.token.depth+">\n";case "code":if(this.options.highlight){var code=this.options.highlight(this.token.text,this.token.lang);if(code!=null&&code!==this.token.text){this.token.escaped=true;this.token.text=code}}if(!this.token.escaped)this.token.text= -escape(this.token.text,true);return"<pre><code"+(this.token.lang?' class="'+this.options.langPrefix+this.token.lang+'"':"")+">"+this.token.text+"</code></pre>\n";case "table":var body="",heading,i,row,cell,j;body+="<thead>\n<tr>\n";for(i=0;i<this.token.header.length;i++){heading=this.inline.output(this.token.header[i]);body+=this.token.align[i]?'<th align="'+this.token.align[i]+'">'+heading+"</th>\n":"<th>"+heading+"</th>\n"}body+="</tr>\n</thead>\n";body+="<tbody>\n";for(i=0;i<this.token.cells.length;i++){row= -this.token.cells[i];body+="<tr>\n";for(j=0;j<row.length;j++){cell=this.inline.output(row[j]);body+=this.token.align[j]?'<td align="'+this.token.align[j]+'">'+cell+"</td>\n":"<td>"+cell+"</td>\n"}body+="</tr>\n"}body+="</tbody>\n";return"<table>\n"+body+"</table>\n";case "blockquote_start":var body="";while(this.next().type!=="blockquote_end")body+=this.tok();return"<blockquote>\n"+body+"</blockquote>\n";case "list_start":var type=this.token.ordered?"ol":"ul",body="";while(this.next().type!=="list_end")body+= -this.tok();return"<"+type+">\n"+body+"</"+type+">\n";case "list_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.token.type==="text"?this.parseText():this.tok();return"<li>"+body+"</li>\n";case "loose_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.tok();return"<li>"+body+"</li>\n";case "html":return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case "paragraph":return"<p>"+this.inline.output(this.token.text)+ -"</p>\n";case "text":return"<p>"+this.parseText()+"</p>\n"}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i= -1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target)if(Object.prototype.hasOwnProperty.call(target,key))obj[key]=target[key]}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}if(opt)opt=merge({},marked.defaults,opt);var tokens=Lexer.lex(tokens,opt),highlight=opt.highlight,pending=0,l=tokens.length,i=0;if(!highlight||highlight.length<3)return callback(null,Parser.parse(tokens,opt));var done=function(){delete opt.highlight; -var out=Parser.parse(tokens,opt);opt.highlight=highlight;return callback(null,out)};for(;i<l;i++)(function(token){if(token.type!=="code")return;pending++;return highlight(token.text,token.lang,function(err,code){if(code==null||code===token.text)return--pending||done();token.text=code;token.escaped=true;--pending||done()})})(tokens[i]);return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked."; -if((opt||marked.defaults).silent)return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>";throw e;}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:""};marked.Parser=Parser;marked.parser=Parser.parse;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output; -marked.parse=marked;if(typeof exports==="object")module.exports=marked;else if(typeof define==="function"&&define.amd)define(function(){return marked});else this.marked=marked}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); +(function(){function e(e){this.tokens=[],this.tokens.links={},this.options=e||a.defaults,this.rules=p.normal,this.options.gfm&&(this.rules=this.options.tables?p.tables:p.gfm)}function t(e,t){if(this.options=t||a.defaults,this.links=e,this.rules=u.normal,this.renderer=this.options.renderer||new n,this.renderer.options=this.options,!this.links)throw new Error("Tokens array requires a `links` property.");this.options.gfm?this.rules=this.options.breaks?u.breaks:u.gfm:this.options.pedantic&&(this.rules=u.pedantic)}function n(e){this.options=e||{}}function r(e){this.tokens=[],this.token=null,this.options=e||a.defaults,this.options.renderer=this.options.renderer||new n,this.renderer=this.options.renderer,this.renderer.options=this.options}function s(e,t){return e.replace(t?/&/g:/&(?!#?\w+;)/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function i(e){return e.replace(/&([#\w]+);/g,function(e,t){return t=t.toLowerCase(),"colon"===t?":":"#"===t.charAt(0)?String.fromCharCode("x"===t.charAt(1)?parseInt(t.substring(2),16):+t.substring(1)):""})}function l(e,t){return e=e.source,t=t||"",function n(r,s){return r?(s=s.source||s,s=s.replace(/(^|[^\[])\^/g,"$1"),e=e.replace(r,s),n):new RegExp(e,t)}}function o(){}function h(e){for(var t,n,r=1;r<arguments.length;r++){t=arguments[r];for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e}function a(t,n,i){if(i||"function"==typeof n){i||(i=n,n=null),n=h({},a.defaults,n||{});var l,o,p=n.highlight,u=0;try{l=e.lex(t,n)}catch(c){return i(c)}o=l.length;var g=function(e){if(e)return n.highlight=p,i(e);var t;try{t=r.parse(l,n)}catch(s){e=s}return n.highlight=p,e?i(e):i(null,t)};if(!p||p.length<3)return g();if(delete n.highlight,!o)return g();for(;u<l.length;u++)!function(e){return"code"!==e.type?--o||g():p(e.text,e.lang,function(t,n){return t?g(t):null==n||n===e.text?--o||g():(e.text=n,e.escaped=!0,void(--o||g()))})}(l[u])}else try{return n&&(n=h({},a.defaults,n)),r.parse(e.lex(t,n),n)}catch(c){if(c.message+="\nPlease report this to https://github.com/chjj/marked.",(n||a.defaults).silent)return"<p>An error occured:</p><pre>"+s(c.message+"",!0)+"</pre>";throw c}}var p={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:o,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:o,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:o,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};p.bullet=/(?:[*+-]|\d+\.)/,p.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,p.item=l(p.item,"gm")(/bull/g,p.bullet)(),p.list=l(p.list)(/bull/g,p.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+p.def.source+")")(),p.blockquote=l(p.blockquote)("def",p.def)(),p._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b",p.html=l(p.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,p._tag)(),p.paragraph=l(p.paragraph)("hr",p.hr)("heading",p.heading)("lheading",p.lheading)("blockquote",p.blockquote)("tag","<"+p._tag)("def",p.def)(),p.normal=h({},p),p.gfm=h({},p.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/}),p.gfm.paragraph=l(p.paragraph)("(?!","(?!"+p.gfm.fences.source.replace("\\1","\\2")+"|"+p.list.source.replace("\\1","\\3")+"|")(),p.tables=h({},p.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),e.rules=p,e.lex=function(t,n){var r=new e(n);return r.lex(t)},e.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},e.prototype.token=function(e,t,n){for(var r,s,i,l,o,h,a,u,c,e=e.replace(/^ +$/gm,"");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:"space"})),i=this.rules.code.exec(e))e=e.substring(i[0].length),i=i[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?i:i.replace(/\n+$/,"")});else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"code",lang:i[2],text:i[3]});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:i[1].length,text:i[2]});else if(t&&(i=this.rules.nptable.exec(e))){for(e=e.substring(i[0].length),h={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/\n$/,"").split("\n")},u=0;u<h.align.length;u++)h.align[u]=/^ *-+: *$/.test(h.align[u])?"right":/^ *:-+: *$/.test(h.align[u])?"center":/^ *:-+ *$/.test(h.align[u])?"left":null;for(u=0;u<h.cells.length;u++)h.cells[u]=h.cells[u].split(/ *\| */);this.tokens.push(h)}else if(i=this.rules.lheading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"heading",depth:"="===i[2]?1:2,text:i[1]});else if(i=this.rules.hr.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"hr"});else if(i=this.rules.blockquote.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"blockquote_start"}),i=i[0].replace(/^ *> ?/gm,""),this.token(i,t,!0),this.tokens.push({type:"blockquote_end"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),l=i[2],this.tokens.push({type:"list_start",ordered:l.length>1}),i=i[0].match(this.rules.item),r=!1,c=i.length,u=0;c>u;u++)h=i[u],a=h.length,h=h.replace(/^ *([*+-]|\d+\.) +/,""),~h.indexOf("\n ")&&(a-=h.length,h=this.options.pedantic?h.replace(/^ {1,4}/gm,""):h.replace(new RegExp("^ {1,"+a+"}","gm"),"")),this.options.smartLists&&u!==c-1&&(o=p.bullet.exec(i[u+1])[0],l===o||l.length>1&&o.length>1||(e=i.slice(u+1).join("\n")+e,u=c-1)),s=r||/\n\n(?!\s*$)/.test(h),u!==c-1&&(r="\n"===h.charAt(h.length-1),s||(s=r)),this.tokens.push({type:s?"loose_item_start":"list_item_start"}),this.token(h,!1,n),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(i=this.rules.html.exec(e))e=e.substring(i[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:"pre"===i[1]||"script"===i[1]||"style"===i[1],text:i[0]});else if(!n&&t&&(i=this.rules.def.exec(e)))e=e.substring(i[0].length),this.tokens.links[i[1].toLowerCase()]={href:i[2],title:i[3]};else if(t&&(i=this.rules.table.exec(e))){for(e=e.substring(i[0].length),h={type:"table",header:i[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:i[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:i[3].replace(/(?: *\| *)?\n$/,"").split("\n")},u=0;u<h.align.length;u++)h.align[u]=/^ *-+: *$/.test(h.align[u])?"right":/^ *:-+: *$/.test(h.align[u])?"center":/^ *:-+ *$/.test(h.align[u])?"left":null;for(u=0;u<h.cells.length;u++)h.cells[u]=h.cells[u].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */);this.tokens.push(h)}else if(t&&(i=this.rules.paragraph.exec(e)))e=e.substring(i[0].length),this.tokens.push({type:"paragraph",text:"\n"===i[1].charAt(i[1].length-1)?i[1].slice(0,-1):i[1]});else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),this.tokens.push({type:"text",text:i[0]});else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0));return this.tokens};var u={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:o,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:o,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};u._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/,u._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/,u.link=l(u.link)("inside",u._inside)("href",u._href)(),u.reflink=l(u.reflink)("inside",u._inside)(),u.normal=h({},u),u.pedantic=h({},u.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/}),u.gfm=h({},u.normal,{escape:l(u.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:l(u.text)("]|","~]|")("|","|https?://|")()}),u.breaks=h({},u.gfm,{br:l(u.br)("{2,}","*")(),text:l(u.gfm.text)("{2,}","*")()}),t.rules=u,t.output=function(e,n,r){var s=new t(n,r);return s.output(e)},t.prototype.output=function(e){for(var t,n,r,i,l="";e;)if(i=this.rules.escape.exec(e))e=e.substring(i[0].length),l+=i[1];else if(i=this.rules.autolink.exec(e))e=e.substring(i[0].length),"@"===i[2]?(n=this.mangle(":"===i[1].charAt(6)?i[1].substring(7):i[1]),r=this.mangle("mailto:")+n):(n=s(i[1]),r=n),l+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(e))){if(i=this.rules.tag.exec(e))!this.inLink&&/^<a /i.test(i[0])?this.inLink=!0:this.inLink&&/^<\/a>/i.test(i[0])&&(this.inLink=!1),e=e.substring(i[0].length),l+=this.options.sanitize?s(i[0]):i[0];else if(i=this.rules.link.exec(e))e=e.substring(i[0].length),this.inLink=!0,l+=this.outputLink(i,{href:i[2],title:i[3]}),this.inLink=!1;else if((i=this.rules.reflink.exec(e))||(i=this.rules.nolink.exec(e))){if(e=e.substring(i[0].length),t=(i[2]||i[1]).replace(/\s+/g," "),t=this.links[t.toLowerCase()],!t||!t.href){l+=i[0].charAt(0),e=i[0].substring(1)+e;continue}this.inLink=!0,l+=this.outputLink(i,t),this.inLink=!1}else if(i=this.rules.strong.exec(e))e=e.substring(i[0].length),l+=this.renderer.strong(this.output(i[2]||i[1]));else if(i=this.rules.em.exec(e))e=e.substring(i[0].length),l+=this.renderer.em(this.output(i[2]||i[1]));else if(i=this.rules.code.exec(e))e=e.substring(i[0].length),l+=this.renderer.codespan(s(i[2],!0));else if(i=this.rules.br.exec(e))e=e.substring(i[0].length),l+=this.renderer.br();else if(i=this.rules.del.exec(e))e=e.substring(i[0].length),l+=this.renderer.del(this.output(i[1]));else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),l+=s(this.smartypants(i[0]));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else e=e.substring(i[0].length),n=s(i[1]),r=n,l+=this.renderer.link(r,null,n);return l},t.prototype.outputLink=function(e,t){var n=s(t.href),r=t.title?s(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,s(e[1]))},t.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/--/g,"—").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},t.prototype.mangle=function(e){for(var t,n="",r=e.length,s=0;r>s;s++)t=e.charCodeAt(s),Math.random()>.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},n.prototype.code=function(e,t,n){if(this.options.highlight){var r=this.options.highlight(e,t);null!=r&&r!==e&&(n=!0,e=r)}return t?'<pre><code class="'+this.options.langPrefix+s(t,!0)+'">'+(n?e:s(e,!0))+"\n</code></pre>\n":"<pre><code>"+(n?e:s(e,!0))+"\n</code></pre>"},n.prototype.blockquote=function(e){return"<blockquote>\n"+e+"</blockquote>\n"},n.prototype.html=function(e){return e},n.prototype.heading=function(e,t,n){return"<h"+t+' id="'+this.options.headerPrefix+n.toLowerCase().replace(/[^\w]+/g,"-")+'">'+e+"</h"+t+">\n"},n.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"},n.prototype.list=function(e,t){var n=t?"ol":"ul";return"<"+n+">\n"+e+"</"+n+">\n"},n.prototype.listitem=function(e){return"<li>"+e+"</li>\n"},n.prototype.paragraph=function(e){return"<p>"+e+"</p>\n"},n.prototype.table=function(e,t){return"<table>\n<thead>\n"+e+"</thead>\n<tbody>\n"+t+"</tbody>\n</table>\n"},n.prototype.tablerow=function(e){return"<tr>\n"+e+"</tr>\n"},n.prototype.tablecell=function(e,t){var n=t.header?"th":"td",r=t.align?"<"+n+' style="text-align:'+t.align+'">':"<"+n+">";return r+e+"</"+n+">\n"},n.prototype.strong=function(e){return"<strong>"+e+"</strong>"},n.prototype.em=function(e){return"<em>"+e+"</em>"},n.prototype.codespan=function(e){return"<code>"+e+"</code>"},n.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"},n.prototype.del=function(e){return"<del>"+e+"</del>"},n.prototype.link=function(e,t,n){if(this.options.sanitize){try{var r=decodeURIComponent(i(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(s){return""}if(0===r.indexOf("javascript:")||0===r.indexOf("vbscript:"))return""}var l='<a href="'+e+'"';return t&&(l+=' title="'+t+'"'),l+=">"+n+"</a>"},n.prototype.image=function(e,t,n){var r='<img src="'+e+'" alt="'+n+'"';return t&&(r+=' title="'+t+'"'),r+=this.options.xhtml?"/>":">"},r.parse=function(e,t,n){var s=new r(t,n);return s.parse(e)},r.prototype.parse=function(e){this.inline=new t(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var n="";this.next();)n+=this.tok();return n},r.prototype.next=function(){return this.token=this.tokens.pop()},r.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},r.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},r.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s,i="",l="";for(n="",e=0;e<this.token.header.length;e++)r={header:!0,align:this.token.align[e]},n+=this.renderer.tablecell(this.inline.output(this.token.header[e]),{header:!0,align:this.token.align[e]});for(i+=this.renderer.tablerow(n),e=0;e<this.token.cells.length;e++){for(t=this.token.cells[e],n="",s=0;s<t.length;s++)n+=this.renderer.tablecell(this.inline.output(t[s]),{header:!1,align:this.token.align[s]});l+=this.renderer.tablerow(n)}return this.renderer.table(i,l);case"blockquote_start":for(var l="";"blockquote_end"!==this.next().type;)l+=this.tok();return this.renderer.blockquote(l);case"list_start":for(var l="",o=this.token.ordered;"list_end"!==this.next().type;)l+=this.tok();return this.renderer.list(l,o);case"list_item_start":for(var l="";"list_item_end"!==this.next().type;)l+="text"===this.token.type?this.parseText():this.tok();return this.renderer.listitem(l);case"loose_item_start":for(var l="";"list_item_end"!==this.next().type;)l+=this.tok();return this.renderer.listitem(l);case"html":var h=this.token.pre||this.options.pedantic?this.token.text:this.inline.output(this.token.text);return this.renderer.html(h);case"paragraph":return this.renderer.paragraph(this.inline.output(this.token.text));case"text":return this.renderer.paragraph(this.parseText())}},o.exec=o,a.options=a.setOptions=function(e){return h(a.defaults,e),a},a.defaults={gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!1,smartLists:!1,silent:!1,highlight:null,langPrefix:"lang-",smartypants:!1,headerPrefix:"",renderer:new n,xhtml:!1},a.Parser=r,a.parser=r.parse,a.Renderer=n,a.Lexer=e,a.lexer=e.lex,a.InlineLexer=t,a.inlineLexer=t.output,a.parse=a,"undefined"!=typeof module&&"object"==typeof exports?module.exports=a:"function"==typeof define&&define.amd?define(function(){return a}):this.marked=a}).call(function(){return this||("undefined"!=typeof window?window:global)}());
\ No newline at end of file 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() { diff --git a/plugin/notes/notes.js b/plugin/notes/notes.js index 27199af..e42329d 100644 --- a/plugin/notes/notes.js +++ b/plugin/notes/notes.js @@ -28,7 +28,7 @@ var RevealNotes = (function() { notesPopup.postMessage( JSON.stringify( { namespace: 'reveal-notes', type: 'connect', - url: window.location.protocol + '//' + window.location.host + window.location.pathname, + url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search, state: Reveal.getState() } ), '*' ); }, 500 ); diff --git a/plugin/zoom-js/zoom.js b/plugin/zoom-js/zoom.js index da2c10a..95093e0 100644 --- a/plugin/zoom-js/zoom.js +++ b/plugin/zoom-js/zoom.js @@ -2,7 +2,7 @@ (function(){ var isEnabled = true; - document.querySelector( '.reveal' ).addEventListener( 'mousedown', function( event ) { + document.querySelector( '.reveal .slides' ).addEventListener( 'mousedown', function( event ) { var modifier = ( Reveal.getConfig().zoomKey ? Reveal.getConfig().zoomKey : 'alt' ) + 'Key'; var zoomPadding = 20; diff --git a/test/examples/slide-transitions.html b/test/examples/slide-transitions.html new file mode 100644 index 0000000..88119dc --- /dev/null +++ b/test/examples/slide-transitions.html @@ -0,0 +1,101 @@ +<!doctype html> +<html lang="en"> + + <head> + <meta charset="utf-8"> + + <title>reveal.js - Slide Transitions</title> + + <link rel="stylesheet" href="../../css/reveal.css"> + <link rel="stylesheet" href="../../css/theme/white.css" id="theme"> + <style type="text/css" media="screen"> + .slides section.has-dark-background, + .slides section.has-dark-background h3 { + color: #fff; + } + .slides section.has-light-background, + .slides section.has-light-background h3 { + color: #222; + } + </style> + </head> + + <body> + + <div class="reveal"> + + <div class="slides"> + + <section> + <h3>Default</h3> + </section> + + <section> + <h3>Default</h3> + </section> + + <section data-transition="zoom"> + <h3>data-transition: zoom</h3> + </section> + + <section data-transition="zoom-in fade-out"> + <h3>data-transition: zoom-in fade-out</h3> + </section> + + <section> + <h3>Default</h3> + </section> + + <section data-transition="convex"> + <h3>data-transition: convex</h3> + </section> + + <section data-transition="convex-in concave-out"> + <h3>data-transition: convex-in concave-out</h3> + </section> + + <section> + <section data-transition="zoom"> + <h3>Default</h3> + </section> + <section data-transition="concave"> + <h3>data-transition: concave</h3> + </section> + <section data-transition="convex-in fade-out"> + <h3>data-transition: convex-in fade-out</h3> + </section> + <section> + <h3>Default</h3> + </section> + </section> + + <section data-transition="none"> + <h3>data-transition: none</h3> + </section> + + <section> + <h3>Default</h3> + </section> + + </div> + + </div> + + <script src="../../lib/js/head.min.js"></script> + <script src="../../js/reveal.js"></script> + + <script> + + Reveal.initialize({ + center: true, + history: true, + + // transition: 'slide', + // transitionSpeed: 'slow', + // backgroundTransition: 'slide' + }); + + </script> + + </body> +</html> diff --git a/test/test-markdown-element-attributes.html b/test/test-markdown-element-attributes.html index 5dba085..6edf95e 100644 --- a/test/test-markdown-element-attributes.html +++ b/test/test-markdown-element-attributes.html @@ -38,9 +38,9 @@ Paragraph 2 <!-- {_class="fragment grow"} --> - - list item 1 <!-- {_class="fragment roll-in"} --> - - list item 2 <!-- {_class="fragment roll-in"} --> - - list item 3 <!-- {_class="fragment roll-in"} --> + - list item 1 <!-- {_class="fragment grow"} --> + - list item 2 <!-- {_class="fragment grow"} --> + - list item 3 <!-- {_class="fragment grow"} --> --- diff --git a/test/test-markdown-element-attributes.js b/test/test-markdown-element-attributes.js index 4541077..10a2503 100644 --- a/test/test-markdown-element-attributes.js +++ b/test/test-markdown-element-attributes.js @@ -19,7 +19,7 @@ Reveal.addEventListener( 'ready', function() { }); test( 'Attributes on element list items in vertical slides', function() { - strictEqual( document.querySelectorAll( '.reveal .slides section>section li.fragment.roll-in' ).length, 3, 'found a vertical slide with three list items with class fragment.roll-in' ); + strictEqual( document.querySelectorAll( '.reveal .slides section>section li.fragment.grow' ).length, 3, 'found a vertical slide with three list items with class fragment.grow' ); }); test( 'Attributes on element paragraphs in horizontal slides', function() { diff --git a/test/test.html b/test/test.html index 29d02a9..34cf832 100644 --- a/test/test.html +++ b/test/test.html @@ -22,6 +22,8 @@ <section data-background-image="examples/assets/image1.png"> <h1>1</h1> <img data-src="fake-url.png"> + <video data-src="fake-url.mp4"></video> + <audio data-src="fake-url.mp3"></audio> </section> <section> @@ -52,6 +54,7 @@ <li class="fragment" data-fragment-index="0">4.1</li> <li class="fragment" data-fragment-index="0">4.2</li> </ul> + <iframe data-src="http://example.com"></iframe> </section> <section> diff --git a/test/test.js b/test/test.js index 3f93d3c..79ff81e 100644 --- a/test/test.js +++ b/test/test.js @@ -495,6 +495,23 @@ Reveal.addEventListener( 'ready', function() { strictEqual( document.querySelectorAll( '.reveal section img[src]' ).length, 1, 'Image source has been set' ); }); + test( 'video with data-src', function() { + strictEqual( document.querySelectorAll( '.reveal section video[src]' ).length, 1, 'Video source has been set' ); + }); + + test( 'audio with data-src', function() { + strictEqual( document.querySelectorAll( '.reveal section audio[src]' ).length, 1, 'Audio source has been set' ); + }); + + test( 'iframe with data-src', function() { + Reveal.slide( 0, 0 ); + strictEqual( document.querySelectorAll( '.reveal section iframe[src]' ).length, 0, 'Iframe source is not set' ); + Reveal.slide( 2, 1 ); + strictEqual( document.querySelectorAll( '.reveal section iframe[src]' ).length, 1, 'Iframe source is set' ); + Reveal.slide( 2, 2 ); + strictEqual( document.querySelectorAll( '.reveal section iframe[src]' ).length, 0, 'Iframe source is not set' ); + }); + test( 'background images', function() { var imageSource1 = Reveal.getSlide( 0 ).getAttribute( 'data-background-image' ); var imageSource2 = Reveal.getSlide( 1, 0 ).getAttribute( 'data-background' ); |