aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gruntfile.js2
-rw-r--r--LICENSE2
-rw-r--r--README.md7
-rw-r--r--bower.json2
-rw-r--r--css/reveal.css56
-rw-r--r--css/reveal.scss51
-rw-r--r--js/reveal.js144
-rw-r--r--package.json2
8 files changed, 186 insertions, 80 deletions
diff --git a/Gruntfile.js b/Gruntfile.js
index 96a4f52..059bb05 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -15,7 +15,7 @@ module.exports = function(grunt) {
' * http://lab.hakim.se/reveal-js\n' +
' * MIT licensed\n' +
' *\n' +
- ' * Copyright (C) 2016 Hakim El Hattab, http://hakim.se\n' +
+ ' * Copyright (C) 2017 Hakim El Hattab, http://hakim.se\n' +
' */'
},
diff --git a/LICENSE b/LICENSE
index 924cd89..c3e6e5f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (C) 2016 Hakim El Hattab, http://hakim.se, and reveal.js contributors
+Copyright (C) 2017 Hakim El Hattab, http://hakim.se, and reveal.js contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 1c55623..22014c5 100644
--- a/README.md
+++ b/README.md
@@ -160,7 +160,7 @@ Special syntax (in html comment) is available for adding attributes to the slide
</section>
```
-#### Configuring `marked`
+#### Configuring *marked*
We use [marked](https://github.com/chjj/marked) to parse Markdown. To customise marked's rendering, you can pass in options when [configuring Reveal](#configuration):
@@ -172,6 +172,7 @@ Reveal.initialize({
smartypants: true
}
});
+```
### Configuration
@@ -363,6 +364,7 @@ You can add your own extensions using the same syntax. The following properties
- **callback**: [optional] Function to execute when the script has loaded
- **condition**: [optional] Function which must return true for the script to be loaded
+To load these dependencies, reveal.js requires [head.js](http://headjs.com/) *(a script loading library)* to be loaded before reveal.js.
### Ready Event
@@ -576,6 +578,7 @@ Automatically plays a full size video behind the slide.
| data-background-video | | A single video source, or a comma separated list of video sources. |
| data-background-video-loop | false | Flags if the video should play repeatedly. |
| data-background-video-muted | false | Flags if the audio should be muted. |
+| data-background-size | cover | Use `cover` for full screen and some cropping or `contain` for letterboxing. |
```html
<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 data-background-video-muted>
@@ -1165,4 +1168,4 @@ Some reveal.js features, like external Markdown and speaker notes, require that
MIT licensed
-Copyright (C) 2016 Hakim El Hattab, http://hakim.se
+Copyright (C) 2017 Hakim El Hattab, http://hakim.se
diff --git a/bower.json b/bower.json
index a42ca8d..b3bc42d 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "reveal.js",
- "version": "3.3.0",
+ "version": "3.4.0",
"main": [
"js/reveal.js",
"css/reveal.css"
diff --git a/css/reveal.css b/css/reveal.css
index dbabfcb..296c8e9 100644
--- a/css/reveal.css
+++ b/css/reveal.css
@@ -3,7 +3,7 @@
* http://lab.hakim.se/reveal-js
* MIT licensed
*
- * Copyright (C) 2016 Hakim El Hattab, http://hakim.se
+ * Copyright (C) 2017 Hakim El Hattab, http://hakim.se
*/
/*********************************************
* RESET STYLES
@@ -57,18 +57,18 @@ body {
transition: all .2s ease; }
.reveal .slides section .fragment.visible {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.grow {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.grow.visible {
-webkit-transform: scale(1.3);
transform: scale(1.3); }
.reveal .slides section .fragment.shrink {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.shrink.visible {
-webkit-transform: scale(0.7);
transform: scale(0.7); }
@@ -82,21 +82,21 @@ body {
.reveal .slides section .fragment.fade-out {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.fade-out.visible {
opacity: 0;
visibility: hidden; }
.reveal .slides section .fragment.semi-fade-out {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.semi-fade-out.visible {
opacity: 0.5;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.strike {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.strike.visible {
text-decoration: line-through; }
@@ -133,7 +133,7 @@ body {
visibility: hidden; }
.reveal .slides section .fragment.current-visible.current-fragment {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.highlight-red,
.reveal .slides section .fragment.highlight-current-red,
@@ -142,7 +142,7 @@ body {
.reveal .slides section .fragment.highlight-blue,
.reveal .slides section .fragment.highlight-current-blue {
opacity: 1;
- visibility: visible; }
+ visibility: inherit; }
.reveal .slides section .fragment.highlight-red.visible {
color: #ff2c2d; }
@@ -323,6 +323,7 @@ body {
bottom: 0;
left: 0;
margin: auto;
+ pointer-events: none;
overflow: visible;
z-index: 1;
text-align: center;
@@ -340,6 +341,7 @@ body {
position: absolute;
width: 100%;
padding: 20px 0px;
+ pointer-events: auto;
z-index: 10;
-webkit-transform-style: flat;
transform-style: flat;
@@ -374,6 +376,10 @@ body {
z-index: 11;
opacity: 1; }
+.reveal .slides > section:empty,
+.reveal .slides > section > section:empty {
+ pointer-events: none; }
+
.reveal.center,
.reveal.center .slides,
.reveal.center .slides section {
@@ -839,6 +845,7 @@ body {
height: 100%;
opacity: 0;
visibility: hidden;
+ overflow: hidden;
background-color: transparent;
background-position: 50% 50%;
background-repeat: no-repeat;
@@ -851,7 +858,8 @@ body {
.reveal .slide-background.present {
opacity: 1;
- visibility: visible; }
+ visibility: visible;
+ z-index: 2; }
.print-pdf .reveal .slide-background {
opacity: 1 !important;
@@ -865,7 +873,13 @@ body {
max-width: none;
max-height: none;
top: 0;
- left: 0; }
+ left: 0;
+ -o-object-fit: cover;
+ object-fit: cover; }
+
+.reveal .slide-background[data-background-size="contain"] video {
+ -o-object-fit: contain;
+ object-fit: contain; }
/* Immediate transition style */
.reveal[data-background-transition=none] > .backgrounds .slide-background,
@@ -1140,6 +1154,7 @@ body {
display: inline-block;
width: 40px;
height: 40px;
+ line-height: 36px;
padding: 0 10px;
float: right;
opacity: 0.6;
@@ -1188,6 +1203,23 @@ body {
opacity: 1;
visibility: visible; }
+.reveal .overlay.overlay-preview.loaded .viewport-inner {
+ position: absolute;
+ z-index: -1;
+ left: 0;
+ top: 45%;
+ width: 100%;
+ text-align: center;
+ letter-spacing: normal; }
+
+.reveal .overlay.overlay-preview .x-frame-error {
+ opacity: 0;
+ -webkit-transition: opacity 0.3s ease 0.3s;
+ transition: opacity 0.3s ease 0.3s; }
+
+.reveal .overlay.overlay-preview.loaded .x-frame-error {
+ opacity: 1; }
+
.reveal .overlay.overlay-preview.loaded .spinner {
opacity: 0;
visibility: hidden;
diff --git a/css/reveal.scss b/css/reveal.scss
index f6a37ad..ee3c440 100644
--- a/css/reveal.scss
+++ b/css/reveal.scss
@@ -3,7 +3,7 @@
* http://lab.hakim.se/reveal-js
* MIT licensed
*
- * Copyright (C) 2016 Hakim El Hattab, http://hakim.se
+ * Copyright (C) 2017 Hakim El Hattab, http://hakim.se
*/
@@ -69,13 +69,13 @@ body {
&.visible {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
}
}
.reveal .slides section .fragment.grow {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
&.visible {
transform: scale( 1.3 );
@@ -84,7 +84,7 @@ body {
.reveal .slides section .fragment.shrink {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
&.visible {
transform: scale( 0.7 );
@@ -101,7 +101,7 @@ body {
.reveal .slides section .fragment.fade-out {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
&.visible {
opacity: 0;
@@ -111,17 +111,17 @@ body {
.reveal .slides section .fragment.semi-fade-out {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
&.visible {
opacity: 0.5;
- visibility: visible;
+ visibility: inherit;
}
}
.reveal .slides section .fragment.strike {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
&.visible {
text-decoration: line-through;
@@ -166,7 +166,7 @@ body {
&.current-fragment {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
}
}
@@ -177,7 +177,7 @@ body {
.reveal .slides section .fragment.highlight-blue,
.reveal .slides section .fragment.highlight-current-blue {
opacity: 1;
- visibility: visible;
+ visibility: inherit;
}
.reveal .slides section .fragment.highlight-red.visible {
color: #ff2c2d
@@ -388,6 +388,7 @@ body {
bottom: 0;
left: 0;
margin: auto;
+ pointer-events: none;
overflow: visible;
z-index: 1;
@@ -406,6 +407,7 @@ body {
position: absolute;
width: 100%;
padding: 20px 0px;
+ pointer-events: auto;
z-index: 10;
transform-style: flat;
@@ -443,6 +445,11 @@ body {
opacity: 1;
}
+.reveal .slides>section:empty,
+.reveal .slides>section>section:empty {
+ pointer-events: none;
+}
+
.reveal.center,
.reveal.center .slides,
.reveal.center .slides section {
@@ -866,6 +873,7 @@ body {
height: 100%;
opacity: 0;
visibility: hidden;
+ overflow: hidden;
background-color: rgba( 0, 0, 0, 0 );
background-position: 50% 50%;
@@ -882,6 +890,7 @@ body {
.reveal .slide-background.present {
opacity: 1;
visibility: visible;
+ z-index: 2;
}
.print-pdf .reveal .slide-background {
@@ -898,7 +907,11 @@ body {
max-height: none;
top: 0;
left: 0;
+ object-fit: cover;
}
+ .reveal .slide-background[data-background-size="contain"] video {
+ object-fit: contain;
+ }
/* Immediate transition style */
.reveal[data-background-transition=none]>.backgrounds .slide-background,
@@ -1195,6 +1208,7 @@ body {
display: inline-block;
width: 40px;
height: 40px;
+ line-height: 36px;
padding: 0 10px;
float: right;
opacity: 0.6;
@@ -1246,6 +1260,23 @@ body {
visibility: visible;
}
+ .reveal .overlay.overlay-preview.loaded .viewport-inner {
+ position: absolute;
+ z-index: -1;
+ left: 0;
+ top: 45%;
+ width: 100%;
+ text-align: center;
+ letter-spacing: normal;
+ }
+ .reveal .overlay.overlay-preview .x-frame-error {
+ opacity: 0;
+ transition: opacity 0.3s ease 0.3s;
+ }
+ .reveal .overlay.overlay-preview.loaded .x-frame-error {
+ opacity: 1;
+ }
+
.reveal .overlay.overlay-preview.loaded .spinner {
opacity: 0;
visibility: hidden;
diff --git a/js/reveal.js b/js/reveal.js
index 695b26b..6a31424 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -3,7 +3,7 @@
* http://lab.hakim.se/reveal-js
* MIT licensed
*
- * Copyright (C) 2016 Hakim El Hattab, http://hakim.se
+ * Copyright (C) 2017 Hakim El Hattab, http://hakim.se
*/
(function( root, factory ) {
if( typeof define === 'function' && define.amd ) {
@@ -26,7 +26,7 @@
var Reveal;
// The reveal.js version
- var VERSION = '3.3.0';
+ var VERSION = '3.4.0';
var SLIDES_SELECTOR = '.slides section',
HORIZONTAL_SLIDES_SELECTOR = '.slides>section',
@@ -884,6 +884,7 @@
// Additional and optional background properties
if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
+ if( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize );
if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat;
if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition;
@@ -1603,6 +1604,9 @@
'<div class="spinner"></div>',
'<div class="viewport">',
'<iframe src="'+ url +'"></iframe>',
+ '<small class="viewport-inner">',
+ '<span class="x-frame-error">Unable to load iframe. This is likely due to the site\'s policy (x-frame-options).</span>',
+ '</small>',
'</div>'
].join('');
@@ -2392,9 +2396,9 @@
updateControls();
updateProgress();
- updateBackground( true );
updateSlideNumber();
updateSlidesVisibility();
+ updateBackground( true );
updateNotes();
formatEmbeddedContent();
@@ -2870,34 +2874,17 @@
} );
- // Stop any currently playing video background
+ // Stop content inside of previous backgrounds
if( previousBackground ) {
- var previousVideo = previousBackground.querySelector( 'video' );
- if( previousVideo ) previousVideo.pause();
+ stopEmbeddedContent( previousBackground );
}
+ // Start content in the current background
if( currentBackground ) {
- // Start video playback
- var currentVideo = currentBackground.querySelector( 'video' );
- if( currentVideo ) {
-
- var startVideo = function() {
- currentVideo.currentTime = 0;
- currentVideo.play();
- currentVideo.removeEventListener( 'loadeddata', startVideo );
- };
-
- if( currentVideo.readyState > 1 ) {
- startVideo();
- }
- else {
- currentVideo.addEventListener( 'loadeddata', startVideo );
- }
-
- }
+ startEmbeddedContent( currentBackground );
var backgroundImageURL = currentBackground.style.backgroundImage || '';
@@ -3074,11 +3061,20 @@
// Iframes
else if( backgroundIframe ) {
var iframe = document.createElement( 'iframe' );
+
+ // Only load autoplaying content when the slide is shown to
+ // avoid having it play in the background
+ if( /autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) {
+ iframe.setAttribute( 'data-src', backgroundIframe );
+ }
+ else {
iframe.setAttribute( 'src', backgroundIframe );
- iframe.style.width = '100%';
- iframe.style.height = '100%';
- iframe.style.maxHeight = '100%';
- iframe.style.maxWidth = '100%';
+ }
+
+ iframe.style.width = '100%';
+ iframe.style.height = '100%';
+ iframe.style.maxHeight = '100%';
+ iframe.style.maxWidth = '100%';
background.appendChild( iframe );
}
@@ -3186,11 +3182,12 @@
* Start playback of any embedded content inside of
* the given element.
*
- * @param {HTMLElement} slide
+ * @param {HTMLElement} element
*/
function startEmbeddedContent( element ) {
if( element && !isSpeakerNotes() ) {
+
// Restart GIFs
toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) {
// Setting the same unchanged source like this was confirmed
@@ -3204,8 +3201,19 @@
return;
}
- if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) {
- el.play();
+ // Autoplay is always on for slide backgrounds
+ var autoplay = el.hasAttribute( 'data-autoplay' ) || !!closestParent( el, '.slide-background' );
+
+ if( autoplay && typeof el.play === 'function' ) {
+
+ if( el.readyState > 1 ) {
+ startEmbeddedMedia( { target: el } );
+ }
+ else {
+ el.removeEventListener( 'loadeddata', startEmbeddedMedia ); // remove first to avoid dupes
+ el.addEventListener( 'loadeddata', startEmbeddedMedia );
+ }
+
}
} );
@@ -3230,15 +3238,36 @@
el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
}
} );
+
}
}
/**
+ * Starts playing an embedded video/audio element after
+ * it has finished loading.
+ *
+ * @param {object} event
+ */
+ function startEmbeddedMedia( event ) {
+
+ var isAttachedToDOM = !!closestParent( event.target, 'html' ),
+ isVisible = !!closestParent( event.target, '.present' );
+
+ if( isAttachedToDOM && isVisible ) {
+ event.target.currentTime = 0;
+ event.target.play();
+ }
+
+ event.target.removeEventListener( 'loadeddata', startEmbeddedMedia );
+
+ }
+
+ /**
* "Starts" the content of an embedded iframe using the
* postMessage API.
*
- * @param {object} event - postMessage API event
+ * @param {object} event
*/
function startEmbeddedIframe( event ) {
@@ -3246,17 +3275,26 @@
if( iframe && iframe.contentWindow ) {
- // 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', '*' );
+ var isAttachedToDOM = !!closestParent( event.target, 'html' ),
+ isVisible = !!closestParent( event.target, '.present' );
+
+ if( isAttachedToDOM && isVisible ) {
+
+ var autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' );
+
+ // YouTube postMessage API
+ if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {
+ iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
+ }
+ // Vimeo postMessage API
+ else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {
+ iframe.contentWindow.postMessage( '{"method":"play"}', '*' );
+ }
+ // Generic postMessage API
+ else {
+ iframe.contentWindow.postMessage( 'slide:start', '*' );
+ }
+
}
}
@@ -3267,40 +3305,42 @@
* Stop playback of any embedded content inside of
* the targeted slide.
*
- * @param {HTMLElement} slide
+ * @param {HTMLElement} element
+ * @param {boolean} autoplay Optionally override the
+ * autoplay setting of media elements
*/
- function stopEmbeddedContent( slide ) {
+ function stopEmbeddedContent( element, autoplay ) {
- if( slide && slide.parentNode ) {
+ if( element && element.parentNode ) {
// HTML5 media elements
- toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
+ toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
el.pause();
}
} );
// Generic postMessage API for non-lazy loaded iframes
- toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
+ toArray( element.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
el.contentWindow.postMessage( 'slide:stop', '*' );
el.removeEventListener( 'load', startEmbeddedIframe );
});
// YouTube postMessage API
- toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
+ toArray( element.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 postMessage API
- toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
+ toArray( element.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 ) {
+ toArray( element.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' );
@@ -3897,7 +3937,7 @@
// If there are media elements with data-autoplay,
// automatically set the autoSlide duration to the
// length of that media. Not applicable if the slide
- // is divided up into fragments.
+ // is divided up into fragments.
// playbackRate is accounted for in the duration.
if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
diff --git a/package.json b/package.json
index 7a9f185..1899fd9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "reveal.js",
- "version": "3.3.0",
+ "version": "3.4.0",
"description": "The HTML Presentation Framework",
"homepage": "http://lab.hakim.se/reveal-js",
"subdomain": "revealjs",