diff --git a/openlp/core/display/html/reveal.css b/openlp/core/display/html/reveal.css index 5f501b12c..eda311e8d 100644 --- a/openlp/core/display/html/reveal.css +++ b/openlp/core/display/html/reveal.css @@ -1,9 +1,9 @@ /*! * reveal.js - * http://lab.hakim.se/reveal-js + * http://revealjs.com * MIT licensed * - * Copyright (C) 2017 Hakim El Hattab, http://hakim.se + * Copyright (C) 2018 Hakim El Hattab, http://hakim.se */ /********************************************* * RESET STYLES @@ -53,8 +53,7 @@ body { .reveal .slides section .fragment { opacity: 0; visibility: hidden; - -webkit-transition: all .2s ease; - transition: all .2s ease; } + transition: all .2s ease; } .reveal .slides section .fragment.visible { opacity: 1; visibility: inherit; } @@ -128,13 +127,25 @@ body { -webkit-transform: translate(0, 0); transform: translate(0, 0); } +.reveal .slides section .fragment.fade-in-then-out, .reveal .slides section .fragment.current-visible { opacity: 0; visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-out.current-fragment, .reveal .slides section .fragment.current-visible.current-fragment { opacity: 1; visibility: inherit; } +.reveal .slides section .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; } + .reveal .slides section .fragment.fade-in-then-semi-out.visible { + opacity: 0.5; + visibility: inherit; } + .reveal .slides section .fragment.fade-in-then-semi-out.current-fragment { + opacity: 1; + visibility: inherit; } + .reveal .slides section .fragment.highlight-red, .reveal .slides section .fragment.highlight-current-red, .reveal .slides section .fragment.highlight-green, @@ -189,106 +200,267 @@ body { /********************************************* * CONTROLS *********************************************/ +@-webkit-keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateX(0); + transform: translateX(0); } + 20% { + -webkit-transform: translateX(10px); + transform: translateX(10px); } + 30% { + -webkit-transform: translateX(-5px); + transform: translateX(-5px); } } + +@-webkit-keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% { + -webkit-transform: translateY(0); + transform: translateY(0); } + 20% { + -webkit-transform: translateY(10px); + transform: translateY(10px); } + 30% { + -webkit-transform: translateY(-5px); + transform: translateY(-5px); } } + .reveal .controls { display: none; - position: fixed; - width: 110px; - height: 110px; - z-index: 30; - right: 10px; - bottom: 10px; - -webkit-user-select: none; } - -.reveal .controls button { - padding: 0; position: absolute; - opacity: 0.05; - width: 0; - height: 0; - background-color: transparent; - border: 12px solid transparent; - -webkit-transform: scale(0.9999); - transform: scale(0.9999); - -webkit-transition: all 0.2s ease; - transition: all 0.2s ease; - -webkit-appearance: none; - -webkit-tap-highlight-color: transparent; } + top: auto; + bottom: 12px; + right: 12px; + left: auto; + z-index: 1; + color: #000; + pointer-events: none; + font-size: 10px; } + .reveal .controls button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + -webkit-transform: scale(0.9999); + transform: scale(0.9999); + transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease; + transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease; + z-index: 2; + pointer-events: auto; + font-size: inherit; + visibility: hidden; + opacity: 0; + -webkit-appearance: none; + -webkit-tap-highlight-color: transparent; } + .reveal .controls .controls-arrow:before, + .reveal .controls .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 2.6em; + height: 0.5em; + border-radius: 0.25em; + background-color: currentColor; + transition: all 0.15s ease, background-color 0.8s ease; + -webkit-transform-origin: 0.2em 50%; + transform-origin: 0.2em 50%; + will-change: transform; } + .reveal .controls .controls-arrow { + position: relative; + width: 3.6em; + height: 3.6em; } + .reveal .controls .controls-arrow:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } + .reveal .controls .controls-arrow:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } + .reveal .controls .controls-arrow:hover:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(40deg); } + .reveal .controls .controls-arrow:hover:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); } + .reveal .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(36deg); } + .reveal .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); } + .reveal .controls .navigate-left { + right: 6.4em; + bottom: 3.2em; + -webkit-transform: translateX(-10px); + transform: translateX(-10px); } + .reveal .controls .navigate-right { + right: 0; + bottom: 3.2em; + -webkit-transform: translateX(10px); + transform: translateX(10px); } + .reveal .controls .navigate-right .controls-arrow { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + .reveal .controls .navigate-right.highlight { + -webkit-animation: bounce-right 2s 50 both ease-out; + animation: bounce-right 2s 50 both ease-out; } + .reveal .controls .navigate-up { + right: 3.2em; + bottom: 6.4em; + -webkit-transform: translateY(-10px); + transform: translateY(-10px); } + .reveal .controls .navigate-up .controls-arrow { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + .reveal .controls .navigate-down { + right: 3.2em; + bottom: 0; + -webkit-transform: translateY(10px); + transform: translateY(10px); } + .reveal .controls .navigate-down .controls-arrow { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); } + .reveal .controls .navigate-down.highlight { + -webkit-animation: bounce-down 2s 50 both ease-out; + animation: bounce-down 2s 50 both ease-out; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; } + .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover, + .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover { + opacity: 1; } + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled, + .reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; } + .reveal .controls .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + -webkit-transform: none; + transform: none; } + .reveal .controls .enabled.fragmented { + opacity: 0.5; } + .reveal .controls .enabled:hover, + .reveal .controls .enabled.fragmented:hover { + opacity: 1; } -.reveal .controls .enabled { - opacity: 0.7; - cursor: pointer; } +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: 1.4em; + right: 5.5em; } -.reveal .controls .enabled:active { - margin-top: 1px; } +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: 1.4em; + right: 0.5em; } -.reveal .controls .navigate-left { - top: 42px; - border-right-width: 22px; - border-right-color: #000; } +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: 1.4em; + bottom: 5em; } -.reveal .controls .navigate-left.fragmented { - opacity: 0.3; } +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: 1.4em; + bottom: 0.5em; } -.reveal .controls .navigate-right { - left: 74px; - top: 42px; - border-left-width: 22px; - border-left-color: #000; } +.reveal.has-dark-background .controls { + color: #fff; } -.reveal .controls .navigate-right.fragmented { - opacity: 0.3; } +.reveal.has-light-background .controls { + color: #000; } -.reveal .controls .navigate-up { - left: 42px; - border-bottom-width: 22px; - border-bottom-color: #000; } +.reveal.no-hover .controls .controls-arrow:hover:before, +.reveal.no-hover .controls .controls-arrow:active:before { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } -.reveal .controls .navigate-up.fragmented { - opacity: 0.3; } +.reveal.no-hover .controls .controls-arrow:hover:after, +.reveal.no-hover .controls .controls-arrow:active:after { + -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); + transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } -.reveal .controls .navigate-down { - left: 42px; - top: 74px; - border-top-width: 22px; - border-top-color: #000; } - -.reveal .controls .navigate-down.fragmented { - opacity: 0.3; } +@media screen and (min-width: 500px) { + .reveal .controls[data-controls-layout="edges"] { + top: 0; + right: 0; + bottom: 0; + left: 0; } + .reveal .controls[data-controls-layout="edges"] .navigate-left, + .reveal .controls[data-controls-layout="edges"] .navigate-right, + .reveal .controls[data-controls-layout="edges"] .navigate-up, + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: auto; + right: auto; } + .reveal .controls[data-controls-layout="edges"] .navigate-left { + top: 50%; + left: 8px; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-right { + top: 50%; + right: 8px; + margin-top: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-up { + top: 8px; + left: 50%; + margin-left: -1.8em; } + .reveal .controls[data-controls-layout="edges"] .navigate-down { + bottom: 8px; + left: 50%; + margin-left: -1.8em; } } /********************************************* * PROGRESS BAR *********************************************/ .reveal .progress { - position: fixed; + position: absolute; display: none; height: 3px; width: 100%; bottom: 0; left: 0; z-index: 10; - background-color: rgba(0, 0, 0, 0.2); } + background-color: rgba(0, 0, 0, 0.2); + color: #fff; } .reveal .progress:after { content: ''; display: block; position: absolute; - height: 20px; + height: 10px; width: 100%; - top: -20px; } + top: -10px; } .reveal .progress span { display: block; height: 100%; width: 0px; - background-color: #000; - -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); - transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + background-color: currentColor; + transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /********************************************* * SLIDE NUMBER *********************************************/ .reveal .slide-number { - position: fixed; + position: absolute; display: block; right: 8px; bottom: 8px; @@ -300,6 +472,9 @@ body { background-color: rgba(0, 0, 0, 0.4); padding: 5px; } +.reveal .slide-number a { + color: currentColor; } + .reveal .slide-number-delimiter { margin: 0 3px; } @@ -314,6 +489,10 @@ body { -ms-touch-action: none; touch-action: none; } +@media only screen and (orientation: landscape) { + .reveal.ua-iphone { + position: fixed; } } + .reveal .slides { position: absolute; width: 100%; @@ -345,30 +524,27 @@ body { z-index: 10; -webkit-transform-style: flat; transform-style: flat; - -webkit-transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); - transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); + transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } /* Global transition speed settings */ .reveal[data-transition-speed="fast"] .slides section { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal[data-transition-speed="slow"] .slides section { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } /* Slide-specific transition speed overrides */ .reveal .slides section[data-transition-speed="fast"] { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal .slides section[data-transition-speed="slow"] { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } .reveal .slides > section.stack { padding-top: 0; - padding-bottom: 0; } + padding-bottom: 0; + pointer-events: none; } .reveal .slides > section.present, .reveal .slides > section > section.present { @@ -566,8 +742,7 @@ body { *********************************************/ .reveal .slides section[data-transition=zoom], .reveal.zoom .slides section:not([data-transition]) { - -webkit-transition-timing-function: ease; - transition-timing-function: ease; } + transition-timing-function: ease; } .reveal .slides > section[data-transition=zoom].past, .reveal .slides > section[data-transition~=zoom-out].past, @@ -759,13 +934,11 @@ body { .reveal.fade .slides > section > section:not([data-transition]) { -webkit-transform: none; transform: none; - -webkit-transition: opacity 0.5s; - transition: opacity 0.5s; } + transition: opacity 0.5s; } .reveal.fade.overview .slides section, .reveal.fade.overview .slides > section > section { - -webkit-transition: none; - transition: none; } + transition: none; } /********************************************* * NO TRANSITION @@ -774,8 +947,7 @@ body { .reveal.none .slides section:not([data-transition]) { -webkit-transform: none; transform: none; - -webkit-transition: none; - transition: none; } + transition: none; } /********************************************* * PAUSED MODE @@ -790,8 +962,22 @@ body { visibility: hidden; opacity: 0; z-index: 100; - -webkit-transition: all 1s ease; - transition: all 1s ease; } + transition: all 1s ease; } + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; } + .reveal .pause-overlay .resume-button:hover { + color: #fff; + border-color: #fff; } .reveal.paused .pause-overlay { visibility: visible; @@ -833,8 +1019,7 @@ body { .reveal .no-transition, .reveal .no-transition * { - -webkit-transition: none !important; - transition: none !important; } + transition: none !important; } /********************************************* * PER-SLIDE BACKGROUNDS @@ -857,11 +1042,15 @@ body { visibility: hidden; overflow: hidden; background-color: transparent; + transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + +.reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; background-position: 50% 50%; background-repeat: no-repeat; - background-size: cover; - -webkit-transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); - transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } + background-size: cover; } .reveal .slide-background.stack { display: block; } @@ -894,8 +1083,7 @@ body { /* Immediate transition style */ .reveal[data-background-transition=none] > .backgrounds .slide-background, .reveal > .backgrounds .slide-background[data-background-transition=none] { - -webkit-transition: none; - transition: none; } + transition: none; } /* Slide */ .reveal[data-background-transition=slide] > .backgrounds .slide-background, @@ -977,8 +1165,7 @@ body { /* Zoom */ .reveal[data-background-transition=zoom] > .backgrounds .slide-background, .reveal > .backgrounds .slide-background[data-background-transition=zoom] { - -webkit-transition-timing-function: ease; - transition-timing-function: ease; } + transition-timing-function: ease; } .reveal[data-background-transition=zoom] > .backgrounds .slide-background.past, .reveal > .backgrounds .slide-background.past[data-background-transition=zoom] { @@ -1010,12 +1197,10 @@ body { /* Global transition speed settings */ .reveal[data-transition-speed="fast"] > .backgrounds .slide-background { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal[data-transition-speed="slow"] > .backgrounds .slide-background { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } /********************************************* * OVERVIEW @@ -1041,8 +1226,7 @@ body { outline-offset: 10px; } .reveal.overview .slides section .fragment { opacity: 1; - -webkit-transition: none; - transition: none; } + transition: none; } .reveal.overview .slides section:after, .reveal.overview .slides section:before { display: none !important; } @@ -1066,13 +1250,11 @@ body { .reveal.overview .slides section, .reveal.overview-deactivating .slides section { - -webkit-transition: none; - transition: none; } + transition: none; } .reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background { - -webkit-transition: none; - transition: none; } + transition: none; } /********************************************* * RTL SUPPORT @@ -1102,17 +1284,14 @@ body { * PARALLAX BACKGROUND *********************************************/ .reveal.has-parallax-background .backgrounds { - -webkit-transition: all 0.8s ease; - transition: all 0.8s ease; } + transition: all 0.8s ease; } /* Global transition speed settings */ .reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { - -webkit-transition-duration: 400ms; - transition-duration: 400ms; } + transition-duration: 400ms; } .reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { - -webkit-transition-duration: 1200ms; - transition-duration: 1200ms; } + transition-duration: 1200ms; } /********************************************* * LINK PREVIEW OVERLAY @@ -1127,8 +1306,7 @@ body { background: rgba(0, 0, 0, 0.9); opacity: 0; visibility: hidden; - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; } + transition: all 0.3s ease; } .reveal .overlay.visible { opacity: 1; @@ -1146,8 +1324,7 @@ body { background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); visibility: visible; opacity: 0.6; - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; } + transition: all 0.3s ease; } .reveal .overlay header { position: absolute; @@ -1188,7 +1365,6 @@ body { .reveal .overlay .viewport { position: absolute; display: -webkit-box; - display: -webkit-flex; display: -ms-flexbox; display: flex; top: 40px; @@ -1204,8 +1380,7 @@ body { border: 0; opacity: 0; visibility: hidden; - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; } + transition: all 0.3s ease; } .reveal .overlay.overlay-preview.loaded .viewport iframe { opacity: 1; @@ -1222,8 +1397,7 @@ body { .reveal .overlay.overlay-preview .x-frame-error { opacity: 0; - -webkit-transition: opacity 0.3s ease 0.3s; - transition: opacity 0.3s ease 0.3s; } + transition: opacity 0.3s ease 0.3s; } .reveal .overlay.overlay-preview.loaded .x-frame-error { opacity: 1; } @@ -1268,13 +1442,13 @@ body { * PLAYBACK COMPONENT *********************************************/ .reveal .playback { - position: fixed; + position: absolute; left: 15px; bottom: 20px; z-index: 30; cursor: pointer; - -webkit-transition: all 400ms ease; - transition: all 400ms ease; } + transition: all 400ms ease; + -webkit-tap-highlight-color: transparent; } .reveal.overview .playback { opacity: 0; @@ -1302,8 +1476,7 @@ body { position: relative; padding: 0 2px; pointer-events: none; - -webkit-transition: all 400ms ease; - transition: all 400ms ease; + transition: all 400ms ease; -webkit-transform-origin: 50% 0%; transform-origin: 50% 0%; -webkit-transform-style: preserve-3d; @@ -1339,33 +1512,64 @@ body { .reveal .speaker-notes { display: none; position: absolute; - width: 70%; - max-height: 15%; - left: 15%; - bottom: 26px; - padding: 10px; + width: 25vw; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; z-index: 1; font-size: 18px; line-height: 1.4; - color: #fff; - background-color: rgba(0, 0, 0, 0.5); + border: 1px solid rgba(0, 0, 0, 0.05); + color: #222; + background-color: #f5f5f5; overflow: auto; box-sizing: border-box; text-align: left; font-family: Helvetica, sans-serif; -webkit-overflow-scrolling: touch; } + .reveal .speaker-notes .notes-placeholder { + color: #ccc; + font-style: italic; } + .reveal .speaker-notes:focus { + outline: none; } + .reveal .speaker-notes:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; } -.reveal .speaker-notes.visible:not(:empty) { +.reveal.show-notes { + max-width: 75vw; + overflow: visible; } + +.reveal.show-notes .speaker-notes { display: block; } -@media screen and (max-width: 1024px) { +@media screen and (min-width: 1600px) { .reveal .speaker-notes { - font-size: 14px; } } + font-size: 20px; } } + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + overflow: visible; } + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: 42.8571428571%; } } @media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; } + .reveal.show-notes .speaker-notes { + top: 100%; + height: 66.6666666667%; } .reveal .speaker-notes { - width: 90%; - left: 5%; } } + font-size: 14px; } } /********************************************* * ZOOM PLUGIN diff --git a/openlp/core/display/html/reveal.js b/openlp/core/display/html/reveal.js index 099505e2c..400b86f4b 100644 --- a/openlp/core/display/html/reveal.js +++ b/openlp/core/display/html/reveal.js @@ -1,9 +1,9 @@ /*! * reveal.js - * http://lab.hakim.se/reveal-js + * http://revealjs.com * MIT licensed * - * Copyright (C) 2017 Hakim El Hattab, http://hakim.se + * Copyright (C) 2018 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.5.0'; + var VERSION = '3.7.0'; var SLIDES_SELECTOR = '.slides section', HORIZONTAL_SLIDES_SELECTOR = '.slides>section', @@ -49,15 +49,30 @@ minScale: 0.2, maxScale: 2.0, - // Display controls in the bottom right corner + // Display presentation control arrows controls: true, + // Help the user learn the controls by providing hints, for example by + // bouncing the down arrow when they first encounter a vertical slide + controlsTutorial: true, + + // Determines where controls appear, "edges" or "bottom-right" + controlsLayout: 'bottom-right', + + // Visibility rule for backwards navigation arrows; "faded", "hidden" + // or "visible" + controlsBackArrows: 'faded', + // Display a presentation progress bar progress: true, // Display the page number of the current slide slideNumber: false, + // Use 1 based indexing for # links to match slide number (default is zero + // based) + hashOneBasedIndex: false, + // Determine which displays to show the slide number on showSlideNumber: 'all', @@ -73,6 +88,10 @@ // Enable the slide overview mode overview: true, + // Disables the default reveal.js slide layout so that you can use + // custom CSS layout + disableLayout: false, + // Vertical centering of slides center: true, @@ -91,6 +110,10 @@ // Turns fragments on and off globally fragments: true, + // Flags whether to include the current fragment in the URL, + // so that reloading brings you to the same fragment position + fragmentInURL: false, + // Flags if the presentation is running in an embedded mode, // i.e. contained within a limited portion of the screen embedded: false, @@ -106,14 +129,16 @@ showNotes: false, // Global override for autolaying embedded media (video/audio/iframe) - // - null: Media will only autoplay if data-autoplay is present - // - true: All media will autoplay, regardless of individual setting - // - false: No media will autoplay, regardless of individual setting + // - null: Media will only autoplay if data-autoplay is present + // - true: All media will autoplay, regardless of individual setting + // - false: No media will autoplay, regardless of individual setting autoPlayMedia: null, - // Number of milliseconds between automatically proceeding to the - // next slide, disabled when set to 0, this value can be overwritten - // by using a data-autoslide attribute on your slides + // Controls automatic progression to the next slide + // - 0: Auto-sliding only happens if the data-autoslide HTML attribute + // is present on the current slide or fragment + // - 1+: All slides will progress automatically at the given interval + // - false: No auto-sliding, even if data-autoslide is present autoSlide: 0, // Stop auto-sliding after user input @@ -122,6 +147,11 @@ // Use this method for navigation when auto-sliding (defaults to navigateNext) autoSlideMethod: null, + // Specify the average time in seconds that you think you will spend + // presenting each slide. This is used to show a pacing timer in the + // speaker view + defaultTiming: null, + // Enable slide navigation via mouse wheel mouseWheel: false, @@ -132,6 +162,8 @@ hideAddressBar: true, // Opens links in an iframe preview overlay + // Add `data-preview-link` and `data-preview-link="false"` to customise each link + // individually previewLinks: false, // Exposes the reveal.js API through window.postMessage @@ -158,6 +190,12 @@ // Parallax background size parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px" + // Parallax background repeat + parallaxBackgroundRepeat: '', // repeat/repeat-x/repeat-y/no-repeat/initial/inherit + + // Parallax background position + parallaxBackgroundPosition: '', // CSS syntax, e.g. "top left" + // Amount of pixels to move the parallax background per slide step parallaxBackgroundHorizontal: null, parallaxBackgroundVertical: null, @@ -166,6 +204,9 @@ // to PDF, unlimited by default pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, + // Prints each fragment on a separate slide + pdfSeparateFragments: true, + // Offset used to reduce the height of content within exported PDF pages. // This exists to account for environment differences based on how you // print to PDF. CLI printing options, like phantomjs and wkpdf, can end @@ -207,6 +248,10 @@ previousBackground, + // Remember which directions that the user has navigated towards + hasNavigatedRight = false, + hasNavigatedDown = false, + // Slides may hold a data-state attribute which we pick up and apply // as a class to the body. This list contains the combined state of // all current slides. @@ -272,7 +317,10 @@ 'B , .': 'Pause', 'F': 'Fullscreen', 'ESC, O': 'Slide overview' - }; + }, + + // Holds custom key code mappings + registeredKeyBindings = {}; /** * Starts up the presentation if the client is capable. @@ -382,13 +430,13 @@ } - /** - * Loads the dependencies of reveal.js. Dependencies are - * defined via the configuration option 'dependencies' - * and will be loaded prior to starting/binding reveal.js. - * Some dependencies may have an 'async' flag, if so they - * will load after reveal.js has been started up. - */ + /** + * Loads the dependencies of reveal.js. Dependencies are + * defined via the configuration option 'dependencies' + * and will be loaded prior to starting/binding reveal.js. + * Some dependencies may have an 'async' flag, if so they + * will load after reveal.js has been started up. + */ function load() { var scripts = [], @@ -406,7 +454,7 @@ } function loadScript( s ) { - head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], function() { + head.ready( s.src.match( /([\w\d_\-]*)\.?js(\?[\w\d.=&]*)?$|[^\\\/]*$/i )[0], function() { // Extension may contain callback functions if( typeof s.callback === 'function' ) { s.callback.apply( this ); @@ -452,6 +500,8 @@ */ function start() { + loaded = true; + // Make sure we've got all the DOM elements we need setupDOM(); @@ -479,8 +529,6 @@ // Enable transitions now that we're loaded dom.slides.classList.remove( 'no-transition' ); - loaded = true; - dom.wrapper.classList.add( 'ready' ); dispatchEvent( 'ready', { @@ -516,6 +564,20 @@ // Prevent transitions while we're loading dom.slides.classList.add( 'no-transition' ); + if( isMobileDevice ) { + dom.wrapper.classList.add( 'no-hover' ); + } + else { + dom.wrapper.classList.remove( 'no-hover' ); + } + + if( /iphone/gi.test( UA ) ) { + dom.wrapper.classList.add( 'ua-iphone' ); + } + else { + dom.wrapper.classList.remove( 'ua-iphone' ); + } + // Background element dom.background = createSingletonNode( dom.wrapper, 'div', 'backgrounds', null ); @@ -524,11 +586,11 @@ dom.progressbar = dom.progress.querySelector( 'span' ); // Arrow controls - createSingletonNode( dom.wrapper, 'aside', 'controls', - '' + - '' + - '' + - '' ); + dom.controls = createSingletonNode( dom.wrapper, 'aside', 'controls', + '' + + '' + + '' + + '' ); // Slide number dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' ); @@ -539,10 +601,8 @@ dom.speakerNotes.setAttribute( 'tabindex', '0' ); // Overlay graphic which is displayed during the paused mode - createSingletonNode( dom.wrapper, 'div', 'pause-overlay', null ); - - // Cache references to elements - dom.controls = document.querySelector( '.reveal .controls' ); + dom.pauseOverlay = createSingletonNode( dom.wrapper, 'div', 'pause-overlay', '' ); + dom.resumeButton = dom.pauseOverlay.querySelector( '.resume-button' ); dom.wrapper.setAttribute( 'role', 'application' ); @@ -554,6 +614,10 @@ dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) ); dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) ); + // The right and down arrows in the standard reveal.js controls + dom.controlsRightArrow = dom.controls.querySelector( '.navigate-right' ); + dom.controlsDownArrow = dom.controls.querySelector( '.navigate-down' ); + dom.statusDiv = createStatusDiv(); } @@ -735,15 +799,60 @@ numberElement.innerHTML = formatSlideNumber( slideNumberH, '.', slideNumberV ); page.appendChild( numberElement ); } + + // Copy page and show fragments one after another + if( config.pdfSeparateFragments ) { + + // Each fragment 'group' is an array containing one or more + // fragments. Multiple fragments that appear at the same time + // are part of the same group. + var fragmentGroups = sortFragments( page.querySelectorAll( '.fragment' ), true ); + + var previousFragmentStep; + var previousPage; + + fragmentGroups.forEach( function( fragments ) { + + // Remove 'current-fragment' from the previous group + if( previousFragmentStep ) { + previousFragmentStep.forEach( function( fragment ) { + fragment.classList.remove( 'current-fragment' ); + } ); + } + + // Show the fragments for the current index + fragments.forEach( function( fragment ) { + fragment.classList.add( 'visible', 'current-fragment' ); + } ); + + // Create a separate page for the current fragment state + var clonedPage = page.cloneNode( true ); + page.parentNode.insertBefore( clonedPage, ( previousPage || page ).nextSibling ); + + previousFragmentStep = fragments; + previousPage = clonedPage; + + } ); + + // Reset the first/original page so that all fragments are hidden + fragmentGroups.forEach( function( fragments ) { + fragments.forEach( function( fragment ) { + fragment.classList.remove( 'visible', 'current-fragment' ); + } ); + } ); + + } + // Show all fragments + else { + toArray( page.querySelectorAll( '.fragment:not(.fade-out)' ) ).forEach( function( fragment ) { + fragment.classList.add( 'visible' ); + } ); + } + } } ); - // Show all fragments - toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ' .fragment' ) ).forEach( function( fragment ) { - fragment.classList.add( 'visible' ); - } ); - // Notify subscribers that the PDF layout is good to go dispatchEvent( 'pdf-ready' ); @@ -797,7 +906,7 @@ // If no node was found, create it now var node = document.createElement( tagname ); - node.classList.add( classname ); + node.className = classname; if( typeof innerHTML === 'string' ) { node.innerHTML = innerHTML; } @@ -841,6 +950,8 @@ dom.background.style.backgroundImage = 'url("' + config.parallaxBackgroundImage + '")'; dom.background.style.backgroundSize = config.parallaxBackgroundSize; + dom.background.style.backgroundRepeat = config.parallaxBackgroundRepeat; + dom.background.style.backgroundPosition = config.parallaxBackgroundPosition; // Make sure the below properties are set on the element - these properties are // needed for proper transitions to be set on the element via CSS. To remove @@ -870,6 +981,57 @@ */ function createBackground( slide, container ) { + + // Main slide background element + var element = document.createElement( 'div' ); + element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' ); + + // Inner background element that wraps images/videos/iframes + var contentElement = document.createElement( 'div' ); + contentElement.className = 'slide-background-content'; + + element.appendChild( contentElement ); + container.appendChild( element ); + + slide.slideBackgroundElement = element; + slide.slideBackgroundContentElement = contentElement; + + // Syncs the background to reflect all current background settings + syncBackground( slide ); + + return element; + + } + + /** + * Renders all of the visual properties of a slide background + * based on the various background attributes. + * + * @param {HTMLElement} slide + */ + function syncBackground( slide ) { + + var element = slide.slideBackgroundElement, + contentElement = slide.slideBackgroundContentElement; + + // Reset the prior background state in case this is not the + // initial sync + slide.classList.remove( 'has-dark-background' ); + slide.classList.remove( 'has-light-background' ); + + element.removeAttribute( 'data-loaded' ); + element.removeAttribute( 'data-background-hash' ); + element.removeAttribute( 'data-background-size' ); + element.removeAttribute( 'data-background-transition' ); + element.style.backgroundColor = ''; + + contentElement.style.backgroundSize = ''; + contentElement.style.backgroundRepeat = ''; + contentElement.style.backgroundPosition = ''; + contentElement.style.backgroundImage = ''; + contentElement.style.opacity = ''; + contentElement.innerHTML = ''; + var data = { background: slide.getAttribute( 'data-background' ), backgroundSize: slide.getAttribute( 'data-background-size' ), @@ -879,17 +1041,13 @@ backgroundColor: slide.getAttribute( 'data-background-color' ), backgroundRepeat: slide.getAttribute( 'data-background-repeat' ), backgroundPosition: slide.getAttribute( 'data-background-position' ), - backgroundTransition: slide.getAttribute( 'data-background-transition' ) + backgroundTransition: slide.getAttribute( 'data-background-transition' ), + backgroundOpacity: slide.getAttribute( 'data-background-opacity' ) }; - var element = document.createElement( 'div' ); - - // Carry over custom classes from the slide to the background - element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' ); - if( data.background ) { // Auto-wrap image urls in url(...) - if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#]|$)/gi.test( data.background ) ) { + if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#\s]|$)/gi.test( data.background ) ) { slide.setAttribute( 'data-background-image', data.background ); } else { @@ -909,24 +1067,20 @@ data.backgroundColor + data.backgroundRepeat + data.backgroundPosition + - data.backgroundTransition ); + data.backgroundTransition + + data.backgroundOpacity ); } // 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; if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition ); - container.appendChild( element ); - - // If backgrounds are being recreated, clear old classes - slide.classList.remove( 'has-dark-background' ); - slide.classList.remove( 'has-light-background' ); - - slide.slideBackgroundElement = element; + // Background image options are set on the content wrapper + if( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize; + if( data.backgroundRepeat ) contentElement.style.backgroundRepeat = data.backgroundRepeat; + if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition; + if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity; // If this slide has a background color, add a class that // signals if it is light or dark. If the slide has no background @@ -948,8 +1102,6 @@ } } - return element; - } /** @@ -990,14 +1142,22 @@ */ function configure( options ) { - var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length; - - dom.wrapper.classList.remove( config.transition ); + var oldTransition = config.transition; // New config options may be passed when this method // is invoked through the API after initialization if( typeof options === 'object' ) extend( config, options ); + // Abort if reveal.js hasn't finished loading, config + // changes will be applied automatically once loading + // finishes + if( loaded === false ) return; + + var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length; + + // Remove the previously configured transition class + dom.wrapper.classList.remove( oldTransition ); + // Force linear transition based on browser capabilities if( features.transforms3d === false ) config.transition = 'linear'; @@ -1009,6 +1169,9 @@ dom.controls.style.display = config.controls ? 'block' : 'none'; dom.progress.style.display = config.progress ? 'block' : 'none'; + dom.controls.setAttribute( 'data-controls-layout', config.controlsLayout ); + dom.controls.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows ); + if( config.shuffle ) { shuffle(); } @@ -1033,12 +1196,8 @@ } 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' ); - } if( config.mouseWheel ) { document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF @@ -1119,13 +1278,8 @@ window.addEventListener( 'resize', onWindowResize, false ); if( config.touch ) { - dom.wrapper.addEventListener( 'touchstart', onTouchStart, false ); - dom.wrapper.addEventListener( 'touchmove', onTouchMove, false ); - dom.wrapper.addEventListener( 'touchend', onTouchEnd, false ); - - // Support pointer-style touch interaction as well - if( window.navigator.pointerEnabled ) { - // IE 11 uses un-prefixed version of pointer events + if( 'onpointerdown' in window ) { + // Use W3C pointer events dom.wrapper.addEventListener( 'pointerdown', onPointerDown, false ); dom.wrapper.addEventListener( 'pointermove', onPointerMove, false ); dom.wrapper.addEventListener( 'pointerup', onPointerUp, false ); @@ -1136,6 +1290,12 @@ dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false ); dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false ); } + else { + // Fall back to touch events + dom.wrapper.addEventListener( 'touchstart', onTouchStart, false ); + dom.wrapper.addEventListener( 'touchmove', onTouchMove, false ); + dom.wrapper.addEventListener( 'touchend', onTouchEnd, false ); + } } if( config.keyboard ) { @@ -1147,6 +1307,8 @@ dom.progress.addEventListener( 'click', onProgressClicked, false ); } + dom.resumeButton.addEventListener( 'click', resume, false ); + if( config.focusBodyOnPageVisibilityChange ) { var visibilityChange; @@ -1198,22 +1360,19 @@ window.removeEventListener( 'hashchange', onWindowHashChange, false ); window.removeEventListener( 'resize', onWindowResize, false ); + dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false ); + dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false ); + dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false ); + + dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false ); + dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false ); + dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false ); + dom.wrapper.removeEventListener( 'touchstart', onTouchStart, false ); dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false ); dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false ); - // IE11 - if( window.navigator.pointerEnabled ) { - dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false ); - dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false ); - dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false ); - } - // IE10 - else if( window.navigator.msPointerEnabled ) { - dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false ); - dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false ); - dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false ); - } + dom.resumeButton.removeEventListener( 'click', resume, false ); if ( config.progress && dom.progress ) { dom.progress.removeEventListener( 'click', onProgressClicked, false ); @@ -1230,6 +1389,38 @@ } + /** + * Add a custom key binding with optional description to + * be added to the help screen. + */ + function addKeyBinding( binding, callback ) { + + if( typeof binding === 'object' && binding.keyCode ) { + registeredKeyBindings[binding.keyCode] = { + callback: callback, + key: binding.key, + description: binding.description + }; + } + else { + registeredKeyBindings[binding] = { + callback: callback, + key: null, + description: null + }; + } + + } + + /** + * Removes the specified custom key binding. + */ + function removeKeyBinding( keyCode ) { + + delete registeredKeyBindings[keyCode]; + + } + /** * Extend object a with the properties of object b. * If there's a conflict, object b takes precedence. @@ -1243,6 +1434,8 @@ a[ i ] = b[ i ]; } + return a; + } /** @@ -1269,7 +1462,7 @@ if( value === 'null' ) return null; else if( value === 'true' ) return true; else if( value === 'false' ) return false; - else if( value.match( /^[\d\.]+$/ ) ) return parseFloat( value ); + else if( value.match( /^-?[\d\.]+$/ ) ) return parseFloat( value ); } return value; @@ -1505,6 +1698,15 @@ } + /** + * Check if this instance is being used to print a PDF with fragments. + */ + function isPrintingPDFFragments() { + + return ( /print-pdf-fragments/gi ).test( window.location.search ); + + } + /** * Hides the address bar if we're on a mobile device. */ @@ -1715,6 +1917,13 @@ html += '