diff options
-rw-r--r-- | README.md | 83 | ||||
-rw-r--r-- | css/print/pdf.css | 34 | ||||
-rw-r--r-- | css/theme/beige.css | 5 | ||||
-rw-r--r-- | css/theme/black.css | 5 | ||||
-rw-r--r-- | css/theme/blood.css | 5 | ||||
-rw-r--r-- | css/theme/league.css | 5 | ||||
-rw-r--r-- | css/theme/moon.css | 5 | ||||
-rw-r--r-- | css/theme/night.css | 5 | ||||
-rw-r--r-- | css/theme/serif.css | 5 | ||||
-rw-r--r-- | css/theme/simple.css | 8 | ||||
-rw-r--r-- | css/theme/sky.css | 5 | ||||
-rw-r--r-- | css/theme/solarized.css | 5 | ||||
-rw-r--r-- | css/theme/source/simple.scss | 5 | ||||
-rw-r--r-- | css/theme/template/theme.scss | 6 | ||||
-rw-r--r-- | css/theme/white.css | 5 | ||||
-rw-r--r-- | js/reveal.js | 153 | ||||
-rw-r--r-- | plugin/zoom-js/zoom.js | 12 |
17 files changed, 228 insertions, 123 deletions
@@ -1,8 +1,8 @@ -# reveal.js [](https://travis-ci.org/hakimel/reveal.js) +# reveal.js [](https://travis-ci.org/hakimel/reveal.js) <a href="https://slides.com?ref=github"><img src="https://s3.amazonaws.com/static.slid.es/images/slides-github-banner-320x40.png?1" alt="Slides" width="160" height="20"></a> A framework for easily creating beautiful presentations using HTML. [Check out the live demo](http://lab.hakim.se/reveal-js/). -reveal.js comes with a broad range of features including [nested slides](https://github.com/hakimel/reveal.js#markup), [Markdown contents](https://github.com/hakimel/reveal.js#markdown), [PDF export](https://github.com/hakimel/reveal.js#pdf-export), [speaker notes](https://github.com/hakimel/reveal.js#speaker-notes) and a [JavaScript API](https://github.com/hakimel/reveal.js#api). There's also a fully featured visual editor and platform for sharing reveal.js presentations at [slides.com](https://slides.com). +reveal.js comes with a broad range of features including [nested slides](https://github.com/hakimel/reveal.js#markup), [Markdown contents](https://github.com/hakimel/reveal.js#markdown), [PDF export](https://github.com/hakimel/reveal.js#pdf-export), [speaker notes](https://github.com/hakimel/reveal.js#speaker-notes) and a [JavaScript API](https://github.com/hakimel/reveal.js#api). There's also a fully featured visual editor and platform for sharing reveal.js presentations at [slides.com](https://slides.com?ref=github). ## Table of contents - [Online Editor](#online-editor) @@ -60,7 +60,7 @@ reveal.js comes with a broad range of features including [nested slides](https:/ ## Online Editor -Presentations are written using HTML or Markdown but there's also an online editor for those of you who prefer a graphical interface. Give it a try at [http://slides.com](http://slides.com?ref=github). +Presentations are written using HTML or Markdown but there's also an online editor for those of you who prefer a graphical interface. Give it a try at [https://slides.com](https://slides.com?ref=github). ## Instructions @@ -434,6 +434,9 @@ Reveal.nextFragment(); // Randomize the order of slides Reveal.shuffle(); +// Shows a help overlay with keyboard shortcuts +Reveal.showHelp(); + // Toggle presentation states, optionally pass true/false to force on/off Reveal.toggleOverview(); Reveal.togglePause(); @@ -510,26 +513,58 @@ Reveal.addEventListener( 'somestate', function() { ### Slide Backgrounds -Slides are contained within a limited portion of the screen by default to allow them to fit any display and scale uniformly. You can apply full page backgrounds outside of the slide area by adding a ```data-background``` attribute to your ```<section>``` elements. Four different types of backgrounds are supported: color, image, video and iframe. Below are a few examples. +Slides are contained within a limited portion of the screen by default to allow them to fit any display and scale uniformly. You can apply full page backgrounds outside of the slide area by adding a ```data-background``` attribute to your ```<section>``` elements. Four different types of backgrounds are supported: color, image, video and iframe. +##### Color Backgrounds +All CSS color formats are supported, like rgba() or hsl(). ```html -<section data-background="#ff0000"> - <h2>All CSS color formats are supported, like rgba() or hsl().</h2> +<section data-background-color="#ff0000"> + <h2>Color</h2> </section> -<section data-background="http://example.com/image.png"> - <h2>This slide will have a full-size background image.</h2> +``` + +##### Image Backgrounds +By default, background images are resized to cover the full page. Available options: + +| Attribute | Default | Description | +| :--------------------------- | :--------- | :---------- | +| data-background-image | | URL of the image to show. GIFs restart when the slide opens. | +| data-background-size | cover | See [background-size](https://developer.mozilla.org/docs/Web/CSS/background-size) on MDN. | +| data-background-position | center | See [background-position](https://developer.mozilla.org/docs/Web/CSS/background-position) on MDN. | +| data-background-repeat | no-repeat | See [background-repeat](https://developer.mozilla.org/docs/Web/CSS/background-repeat) on MDN. | +```html +<section data-background-image="http://example.com/image.png"> + <h2>Image</h2> </section> -<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 data-background-image="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> +``` + +##### Video Backgrounds +Automatically plays a full size video behind the slide. + +| Attribute | Default | Description | +| :--------------------------- | :------ | :---------- | +| 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. | + +```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> - <h2>Video. Multiple sources can be defined using a comma separated list. Video will loop when the data-background-video-loop attribute is provided and can be muted with the data-background-video-muted attribute.</h2> + <h2>Video</h2> </section> +``` + +##### Iframe Backgrounds +Embeds a web page as a background. Note that since the iframe is in the background layer, behind your slides, it is not possible to interact with the embedded page. +```html <section data-background-iframe="https://slides.com"> - <h2>Embeds a web page as a background. Note that the page won't be interactive.</h2> + <h2>Iframe</h2> </section> ``` +##### Background Transitions Backgrounds transition using a fade animation by default. This can be changed to a linear sliding transition by passing ```backgroundTransition: 'slide'``` to the ```Reveal.initialize()``` call. Alternatively you can set ```data-background-transition``` on any section with a background to override that specific transition. @@ -780,10 +815,12 @@ Reveal.initialize({ ## PDF Export -Presentations can be exported to PDF via a special print stylesheet. This feature requires that you use [Google Chrome](http://google.com/chrome) or [Chromium](https://www.chromium.org/Home). +Presentations can be exported to PDF via a special print stylesheet. This feature requires that you use [Google Chrome](http://google.com/chrome) or [Chromium](https://www.chromium.org/Home) and to be serving the presention from a webserver. Here's an example of an exported presentation that's been uploaded to SlideShare: http://www.slideshare.net/hakimel/revealjs-300. -1. Open your presentation with `print-pdf` included anywhere in the query string. This triggers the default index HTML to load the PDF print stylesheet ([css/print/pdf.css](https://github.com/hakimel/reveal.js/blob/master/css/print/pdf.css)). You can test this with [lab.hakim.se/reveal-js?print-pdf](http://lab.hakim.se/reveal-js?print-pdf). +Export dimensions are inferred from the configured [presentation size](#presentation-size). Slides that are too tall to fit within a single page will expand onto multiple pages. You can limit how many pages a slide may expand onto using the `pdfMaxPagesPerSlide` config option, for example `Reveal.configure({ pdfMaxPagesPerSlide: 1 })` ensures that no slide ever grows to more than one printed page. + +1. Open your presentation with `print-pdf` included in the query string i.e. http://localhost:8000/?print-pdf#/. This triggers the default index HTML to load the PDF print stylesheet ([css/print/pdf.css](https://github.com/hakimel/reveal.js/blob/master/css/print/pdf.css)). You can test this with [lab.hakim.se/reveal-js?print-pdf](http://lab.hakim.se/reveal-js?print-pdf). 2. Open the in-browser print dialog (CTRL/CMD+P). 3. Change the **Destination** setting to **Save as PDF**. 4. Change the **Layout** to **Landscape**. @@ -858,7 +895,7 @@ This will only display in the notes window. Notes are only visible to the speaker inside of the speaker view. If you wish to share your notes with others you can initialize reveal.js with the `showNotes` config value set to `true`. Notes will appear along the bottom of the presentations. -When `showNotes` is enabled notes are also included when you [export to PDF](https://github.com/hakimel/reveal.js#pdf-export). +When `showNotes` is enabled notes are also included when you [export to PDF](https://github.com/hakimel/reveal.js#pdf-export). By default, notes are printed in a semi-transparent box on top of slide. If you'd rather print them on a separate page after the slide, set `showNotes: "separate-page"`. ## Server Side Speaker Notes @@ -1065,31 +1102,29 @@ Some reveal.js features, like external Markdown and speaker notes, require that 1. Install [Node.js](http://nodejs.org/) (1.0.0 or later) -2. Install [Grunt](http://gruntjs.com/getting-started#installing-the-cli) - -4. Clone the reveal.js repository +1. Clone the reveal.js repository ```sh $ git clone https://github.com/hakimel/reveal.js.git ``` -5. Navigate to the reveal.js folder +1. Navigate to the reveal.js folder ```sh $ cd reveal.js ``` -6. Install dependencies +1. Install dependencies ```sh $ npm install ``` -7. Serve the presentation and monitor source files for changes +1. Serve the presentation and monitor source files for changes ```sh - $ grunt serve + $ npm start ``` -8. Open <http://localhost:8000> to view your presentation +1. Open <http://localhost:8000> to view your presentation - You can change the port by using `grunt serve --port 8001`. + You can change the port by using `npm start -- --port 8001`. ### Folder Structure diff --git a/css/print/pdf.css b/css/print/pdf.css index 9ed90d6..4bfcddc 100644 --- a/css/print/pdf.css +++ b/css/print/pdf.css @@ -60,8 +60,9 @@ ul, ol, div, p { } .reveal .slides { position: static; - width: 100%; - height: auto; + width: 100% !important; + height: auto !important; + zoom: 1 !important; left: auto; top: auto; @@ -82,11 +83,16 @@ ul, ol, div, p { perspective-origin: 50% 50%; } +.reveal .slides .pdf-page { + position: relative; + overflow: hidden; + z-index: 1; +} + .reveal .slides section { page-break-after: always !important; visibility: visible !important; - position: relative !important; display: block !important; position: relative !important; @@ -132,13 +138,7 @@ ul, ol, div, p { top: 0; left: 0; width: 100%; - z-index: -1; -} - -/* All elements should be above the slide-background */ -.reveal section>* { - position: relative; - z-index: 1; + height: 100%; } /* Display slide speaker notes when 'showNotes' is enabled */ @@ -146,15 +146,25 @@ ul, ol, div, p { display: block; width: 100%; max-height: none; - left: auto; top: auto; + right: auto; + bottom: auto; + left: auto; z-index: 100; } +/* Layout option which makes notes appear on a separate page */ +.reveal .speaker-notes-pdf[data-layout="separate-page"] { + position: relative; + color: inherit; + background-color: transparent; + padding: 20px; + page-break-after: always; +} + /* Display slide numbers when 'slideNumber' is enabled */ .reveal .slide-number-pdf { display: block; position: absolute; font-size: 14px; } - diff --git a/css/theme/beige.css b/css/theme/beige.css index 5bbda4b..7f71dd9 100644 --- a/css/theme/beige.css +++ b/css/theme/beige.css @@ -29,6 +29,11 @@ body { background: rgba(79, 64, 28, 0.99); text-shadow: none; } +::-moz-selection { + color: #fff; + background: rgba(79, 64, 28, 0.99); + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/black.css b/css/theme/black.css index 511fa79..9228c46 100644 --- a/css/theme/black.css +++ b/css/theme/black.css @@ -25,6 +25,11 @@ body { background: #bee4fd; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #bee4fd; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/blood.css b/css/theme/blood.css index 6fe3d67..2da8d68 100644 --- a/css/theme/blood.css +++ b/css/theme/blood.css @@ -28,6 +28,11 @@ body { background: #a23; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #a23; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/league.css b/css/theme/league.css index 03c44ce..aa5bee5 100644 --- a/css/theme/league.css +++ b/css/theme/league.css @@ -31,6 +31,11 @@ body { background: #FF5E99; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #FF5E99; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/moon.css b/css/theme/moon.css index 5e5d6e4..5cb1176 100644 --- a/css/theme/moon.css +++ b/css/theme/moon.css @@ -29,6 +29,11 @@ body { background: #d33682; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/night.css b/css/theme/night.css index a439cdc..cf2c7a7 100644 --- a/css/theme/night.css +++ b/css/theme/night.css @@ -23,6 +23,11 @@ body { background: #e7ad52; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #e7ad52; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/serif.css b/css/theme/serif.css index 40ccb39..bbb9f7e 100644 --- a/css/theme/serif.css +++ b/css/theme/serif.css @@ -25,6 +25,11 @@ body { background: #26351C; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #26351C; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/simple.css b/css/theme/simple.css index b17fa5c..cb840d9 100644 --- a/css/theme/simple.css +++ b/css/theme/simple.css @@ -7,6 +7,9 @@ */ @import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); +section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 { + color: #fff; } + /********************************************* * GLOBAL STYLES *********************************************/ @@ -25,6 +28,11 @@ body { background: rgba(0, 0, 0, 0.99); text-shadow: none; } +::-moz-selection { + color: #fff; + background: rgba(0, 0, 0, 0.99); + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/sky.css b/css/theme/sky.css index 99f1cfd..202ade8 100644 --- a/css/theme/sky.css +++ b/css/theme/sky.css @@ -32,6 +32,11 @@ body { background: #134674; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #134674; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/solarized.css b/css/theme/solarized.css index b4d4d4b..44771dc 100644 --- a/css/theme/solarized.css +++ b/css/theme/solarized.css @@ -29,6 +29,11 @@ body { background: #d33682; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #d33682; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/css/theme/source/simple.scss b/css/theme/source/simple.scss index 84c7d9b..394c9cd 100644 --- a/css/theme/source/simple.scss +++ b/css/theme/source/simple.scss @@ -31,6 +31,11 @@ $linkColor: #00008B; $linkColorHover: lighten( $linkColor, 20% ); $selectionBackgroundColor: rgba(0, 0, 0, 0.99); +section.has-dark-background { + &, h1, h2, h3, h4, h5, h6 { + color: #fff; + } +} // Theme template ------------------------------ diff --git a/css/theme/template/theme.scss b/css/theme/template/theme.scss index 101a567..bcbaf0c 100644 --- a/css/theme/template/theme.scss +++ b/css/theme/template/theme.scss @@ -22,6 +22,12 @@ body { text-shadow: none; } +::-moz-selection { + color: $selectionColor; + background: $selectionBackgroundColor; + text-shadow: none; +} + .reveal .slides>section, .reveal .slides>section>section { line-height: 1.3; diff --git a/css/theme/white.css b/css/theme/white.css index b10dd0e..16a1d23 100644 --- a/css/theme/white.css +++ b/css/theme/white.css @@ -25,6 +25,11 @@ body { background: #98bdef; text-shadow: none; } +::-moz-selection { + color: #fff; + background: #98bdef; + text-shadow: none; } + .reveal .slides > section, .reveal .slides > section > section { line-height: 1.3; diff --git a/js/reveal.js b/js/reveal.js index 10c609e..ed4d769 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -153,6 +153,10 @@ parallaxBackgroundHorizontal: null, parallaxBackgroundVertical: null, + // The maximum number of pages a single slide can expand onto when printing + // to PDF, unlimited by default + pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, + // Number of slides away from the current that are visible viewDistance: 3, @@ -495,6 +499,7 @@ // Element containing notes that are visible to the audience dom.speakerNotes = createSingletonNode( dom.wrapper, 'div', 'speaker-notes', null ); dom.speakerNotes.setAttribute( 'data-prevent-swipe', '' ); + dom.speakerNotes.setAttribute( 'tabindex', '0' ); // Overlay graphic which is displayed during the paused mode createSingletonNode( dom.wrapper, 'div', 'pause-overlay', null ); @@ -589,43 +594,61 @@ var left = ( pageWidth - slideWidth ) / 2, top = ( pageHeight - slideHeight ) / 2; - var contentHeight = getAbsoluteHeight( slide ); + var contentHeight = slide.scrollHeight; var numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 ); + // Adhere to configured pages per slide limit + numberOfPages = Math.min( numberOfPages, config.pdfMaxPagesPerSlide ); + // Center slides vertically if( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) { top = Math.max( ( pageHeight - contentHeight ) / 2, 0 ); } + // Wrap the slide in a page element and hide its overflow + // so that no page ever flows onto another + var page = document.createElement( 'div' ); + page.className = 'pdf-page'; + page.style.height = ( pageHeight * numberOfPages ) + 'px'; + slide.parentNode.insertBefore( page, slide ); + page.appendChild( slide ); + // Position the slide inside of the page slide.style.left = left + 'px'; slide.style.top = top + 'px'; slide.style.width = slideWidth + 'px'; - // TODO Backgrounds need to be multiplied when the slide - // stretches over multiple pages - var background = slide.querySelector( '.slide-background' ); - if( background ) { - background.style.width = pageWidth + 'px'; - background.style.height = ( pageHeight * numberOfPages ) + 'px'; - background.style.top = -top + 'px'; - background.style.left = -left + 'px'; + if( slide.slideBackgroundElement ) { + page.insertBefore( slide.slideBackgroundElement, slide ); } // Inject notes if `showNotes` is enabled if( config.showNotes ) { + + // Are there notes for this slide? var notes = getSlideNotes( slide ); if( notes ) { + var notesSpacing = 8; + var notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline'; var notesElement = document.createElement( 'div' ); notesElement.classList.add( 'speaker-notes' ); notesElement.classList.add( 'speaker-notes-pdf' ); + notesElement.setAttribute( 'data-layout', notesLayout ); notesElement.innerHTML = notes; - notesElement.style.left = ( notesSpacing - left ) + 'px'; - notesElement.style.bottom = ( notesSpacing - top ) + 'px'; - notesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px'; - slide.appendChild( notesElement ); + + if( notesLayout === 'separate-page' ) { + page.parentNode.insertBefore( notesElement, page.nextSibling ); + } + else { + notesElement.style.left = ( notesSpacing - left ) + 'px'; + notesElement.style.bottom = ( notesSpacing - top ) + 'px'; + notesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px'; + slide.appendChild( notesElement ); + } + } + } // Inject slide numbers if `slideNumbers` are enabled @@ -637,7 +660,7 @@ numberElement.classList.add( 'slide-number' ); numberElement.classList.add( 'slide-number-pdf' ); numberElement.innerHTML = formatSlideNumber( slideNumberH, '.', slideNumberV ); - background.appendChild( numberElement ); + page.appendChild( numberElement ); } } @@ -717,24 +740,12 @@ // Iterate over all horizontal slides toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( slideh ) { - var backgroundStack; - - if( printMode ) { - backgroundStack = createBackground( slideh, slideh ); - } - else { - backgroundStack = createBackground( slideh, dom.background ); - } + var backgroundStack = createBackground( slideh, dom.background ); // Iterate over all vertical slides toArray( slideh.querySelectorAll( 'section' ) ).forEach( function( slidev ) { - if( printMode ) { - createBackground( slidev, slidev ); - } - else { - createBackground( slidev, backgroundStack ); - } + createBackground( slidev, backgroundStack ); backgroundStack.classList.add( 'stack' ); @@ -830,6 +841,8 @@ slide.classList.remove( 'has-dark-background' ); slide.classList.remove( 'has-light-background' ); + slide.slideBackgroundElement = element; + // If this slide has a background color, add a class that // signals if it is light or dark. If the slide has no background // color, no class will be set @@ -935,6 +948,7 @@ if( config.showNotes ) { dom.speakerNotes.classList.add( 'visible' ); + dom.speakerNotes.setAttribute( 'data-layout', typeof config.showNotes === 'string' ? config.showNotes : 'inline' ); } else { dom.speakerNotes.classList.remove( 'visible' ); @@ -1291,41 +1305,6 @@ } /** - * Retrieves the height of the given element by looking - * at the position and height of its immediate children. - */ - function getAbsoluteHeight( element ) { - - var height = 0; - - if( element ) { - var absoluteChildren = 0; - - toArray( element.childNodes ).forEach( function( child ) { - - if( typeof child.offsetTop === 'number' && child.style ) { - // Count # of abs children - if( window.getComputedStyle( child ).position === 'absolute' ) { - absoluteChildren += 1; - } - - height = Math.max( height, child.offsetTop + child.offsetHeight ); - } - - } ); - - // If there are no absolute children, use offsetHeight - if( absoluteChildren === 0 ) { - height = element.offsetHeight; - } - - } - - return height; - - } - - /** * Returns the remaining height within the parent of the * target element. * @@ -1589,10 +1568,8 @@ var size = getComputedSlideSize(); - var slidePadding = 20; // TODO Dig this out of DOM - // Layout the contents of the slides - layoutSlideContents( config.width, config.height, slidePadding ); + layoutSlideContents( config.width, config.height ); dom.slides.style.width = size.width + 'px'; dom.slides.style.height = size.height + 'px'; @@ -1654,7 +1631,7 @@ slide.style.top = 0; } else { - slide.style.top = Math.max( ( ( size.height - getAbsoluteHeight( slide ) ) / 2 ) - slidePadding, 0 ) + 'px'; + slide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px'; } } else { @@ -1674,7 +1651,7 @@ * Applies layout logic to the contents of all slides in * the presentation. */ - function layoutSlideContents( width, height, padding ) { + function layoutSlideContents( width, height ) { // Handle sizing of elements with the 'stretch' class toArray( dom.slides.querySelectorAll( 'section > .stretch' ) ).forEach( function( element ) { @@ -2652,34 +2629,37 @@ .concat( dom.controlsNext ).forEach( function( node ) { node.classList.remove( 'enabled' ); node.classList.remove( 'fragmented' ); + + // Set 'disabled' attribute on all directions + node.setAttribute( 'disabled', 'disabled' ); } ); - // Add the 'enabled' class to the available routes - if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); } ); + // Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons + if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); // Prev/next buttons - if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); } ); - if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); } ); + if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } ); // Highlight fragment directions if( currentSlide ) { // Always apply fragment decorator to prev/next buttons - if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); - if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); + if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); // Apply fragment decorators to directional buttons based on // what slide axis they are in if( isVerticalSlide( currentSlide ) ) { - if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); - if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); + if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); } else { - if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); - if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } ); + if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); + if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } ); } } @@ -3427,10 +3407,7 @@ if( isPrintingPDF() ) { var slide = getSlide( x, y ); if( slide ) { - var background = slide.querySelector( '.slide-background' ); - if( background && background.parentNode === slide ) { - return background; - } + return slide.slideBackgroundElement; } return undefined; @@ -3963,10 +3940,11 @@ // the keyboard var activeElementIsCE = document.activeElement && document.activeElement.contentEditable !== 'inherit'; var activeElementIsInput = document.activeElement && document.activeElement.tagName && /input|textarea/i.test( document.activeElement.tagName ); + var activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className); // Disregard the event if there's a focused element or a // keyboard modifier key is present - if( activeElementIsCE || activeElementIsInput || (event.shiftKey && event.keyCode !== 32) || event.altKey || event.ctrlKey || event.metaKey ) return; + if( activeElementIsCE || activeElementIsInput || activeElementIsNotes || (event.shiftKey && event.keyCode !== 32) || event.altKey || event.ctrlKey || event.metaKey ) return; // While paused only allow resume keyboard events; 'b', '.'' var resumeKeyCodes = [66,190,191]; @@ -4602,6 +4580,9 @@ navigatePrev: navigatePrev, navigateNext: navigateNext, + // Shows a help overlay with keyboard shortcuts + showHelp: showHelp, + // Forces an update in slide layout layout: layout, diff --git a/plugin/zoom-js/zoom.js b/plugin/zoom-js/zoom.js index 95093e0..8738083 100644 --- a/plugin/zoom-js/zoom.js +++ b/plugin/zoom-js/zoom.js @@ -11,7 +11,17 @@ if( event[ modifier ] && isEnabled ) { event.preventDefault(); - var bounds = event.target.getBoundingClientRect(); + var bounds; + var originalDisplay = event.target.style.display; + + // Get the bounding rect of the contents, not the containing box + if( window.getComputedStyle( event.target ).display === 'block' ) { + event.target.style.display = 'inline-block'; + bounds = event.target.getBoundingClientRect(); + event.target.style.display = originalDisplay; + } else { + bounds = event.target.getBoundingClientRect(); + } zoom.to({ x: ( bounds.left * revealScale ) - zoomPadding, |