add slidenumber & location controllers
This commit is contained in:
1 parent
ac15678dea
commit
3683ad255d
6 files changed
+240
-184
No files matched your search
Vendored
+1
-1
@@ -5,4 +5,4 @@
|
|||||||
*
|
*
|
||||||
* Copyright (C) 2020 Hakim El Hattab, https://hakim.se
|
* Copyright (C) 2020 Hakim El Hattab, https://hakim.se
|
||||||
*/
|
*/
|
||||||
!function(e){var t={};function a(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,a),n.l=!0,n.exports}a.m=e,a.c=t,a.d=function(e,t,i){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(a.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)a.d(i,n,function(t){return e[t]}.bind(null,n));return i},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="",a(a.s=0)}([function(e,t,a){"use strict";a.r(t);const i=/registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener/,n=(e,t)=>{for(let a in t)e[a]=t[a];return e},r=e=>Array.prototype.slice.call(e),s=e=>{if("string"==typeof e){if("null"===e)return null;if("true"===e)return!0;if("false"===e)return!1;if(e.match(/^-?[\d\.]+$/))return parseFloat(e)}return e},o=(e,t)=>{e.style.transform=t},l=(e,t)=>{let a=e.parentNode;for(;a;){let e=a.matches||a.matchesSelector||a.msMatchesSelector;if(e&&e.call(a,t))return a;a=a.parentNode}return null},d=e=>{let t=document.createElement("style");return t.type="text/css",e&&e.length>0&&(t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document.createTextNode(e))),document.head.appendChild(t),t},c=()=>{let e={};location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi,t=>{e[t.split("=").shift()]=t.split("=").pop()});for(let t in e){let a=e[t];e[t]=s(unescape(a))}return void 0!==e.dependencies&&delete e.dependencies,e},u=navigator.userAgent,h=document.createElement("div"),p=/(iphone|ipod|ipad|android)/gi.test(u)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1,g=/chrome/i.test(u)&&!/edge/i.test(u),f=/android/gi.test(u),v="zoom"in h.style&&!p&&(g||/Version\/[\d\.]+.*Safari/.test(u));class m{constructor(e){this.Reveal=e}shouldPreload(e){let t=this.Reveal.getConfig().preloadIframes;return"boolean"!=typeof t&&(t=e.hasAttribute("data-preload")),t}load(e,t={}){e.style.display=this.Reveal.getConfig().display,r(e.querySelectorAll("img[data-src], video[data-src], audio[data-src], iframe[data-src]")).forEach(e=>{("IFRAME"!==e.tagName||this.shouldPreload(e))&&(e.setAttribute("src",e.getAttribute("data-src")),e.setAttribute("data-lazy-loaded",""),e.removeAttribute("data-src"))}),r(e.querySelectorAll("video, audio")).forEach(e=>{let t=0;r(e.querySelectorAll("source[data-src]")).forEach(e=>{e.setAttribute("src",e.getAttribute("data-src")),e.removeAttribute("data-src"),e.setAttribute("data-lazy-loaded",""),t+=1}),t>0&&e.load()});let a=e.slideBackgroundElement;if(a){a.style.display="block";let i=e.slideBackgroundContentElement,n=e.getAttribute("data-background-iframe");if(!1===a.hasAttribute("data-loaded")){a.setAttribute("data-loaded","true");let r=e.getAttribute("data-background-image"),s=e.getAttribute("data-background-video"),o=e.hasAttribute("data-background-video-loop"),l=e.hasAttribute("data-background-video-muted");if(r)i.style.backgroundImage="url("+encodeURI(r)+")";else if(s&&!this.Reveal.isSpeakerNotes()){let e=document.createElement("video");o&&e.setAttribute("loop",""),l&&(e.muted=!0),p&&(e.muted=!0,e.autoplay=!0,e.setAttribute("playsinline","")),s.split(",").forEach(t=>{e.innerHTML+='<source src="'+t+'">'}),i.appendChild(e)}else if(n&&!0!==t.excludeIframes){let e=document.createElement("iframe");e.setAttribute("allowfullscreen",""),e.setAttribute("mozallowfullscreen",""),e.setAttribute("webkitallowfullscreen",""),e.setAttribute("allow","autoplay"),e.setAttribute("data-src",n),e.style.width="100%",e.style.height="100%",e.style.maxHeight="100%",e.style.maxWidth="100%",i.appendChild(e)}}let r=i.querySelector("iframe[data-src]");r&&this.shouldPreload(a)&&!/autoplay=(1|true|yes)/gi.test(n)&&r.getAttribute("src")!==n&&r.setAttribute("src",n)}}unload(e){e.style.display="none";let t=this.Reveal.getSlideBackground(e);t&&(t.style.display="none",r(t.querySelectorAll("iframe[src]")).forEach(e=>{e.removeAttribute("src")})),r(e.querySelectorAll("video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")}),r(e.querySelectorAll("video[data-lazy-loaded] source[src], audio source[src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")})}formatEmbeddedContent(){let e=(e,t,a)=>{r(this.Reveal.getSlidesElement().querySelectorAll("iframe["+e+'*="'+t+'"]')).forEach(t=>{let i=t.getAttribute(e);i&&-1===i.indexOf(a)&&t.setAttribute(e,i+(/\?/.test(i)?"&":"?")+a)})};e("src","youtube.com/embed/","enablejsapi=1"),e("data-src","youtube.com/embed/","enablejsapiLine truncated
|
!function(e){var t={};function a(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,a),n.l=!0,n.exports}a.m=e,a.c=t,a.d=function(e,t,i){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(a.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)a.d(i,n,function(t){return e[t]}.bind(null,n));return i},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="",a(a.s=0)}([function(e,t,a){"use strict";a.r(t);const i=/registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener/,n=(e,t)=>{for(let a in t)e[a]=t[a];return e},r=e=>Array.prototype.slice.call(e),s=e=>{if("string"==typeof e){if("null"===e)return null;if("true"===e)return!0;if("false"===e)return!1;if(e.match(/^-?[\d\.]+$/))return parseFloat(e)}return e},o=(e,t)=>{e.style.transform=t},l=(e,t)=>{let a=e.parentNode;for(;a;){let e=a.matches||a.matchesSelector||a.msMatchesSelector;if(e&&e.call(a,t))return a;a=a.parentNode}return null},d=(e,t,a,i="")=>{let n=e.querySelectorAll("."+a);for(let t=0;t<n.length;t++){let a=n[t];if(a.parentNode===e)return a}let r=document.createElement(t);return r.className=a,r.innerHTML=i,e.appendChild(r),r},c=e=>{let t=document.createElement("style");return t.type="text/css",e&&e.length>0&&(t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document.createTextNode(e))),document.head.appendChild(t),t},u=()=>{let e={};location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi,t=>{e[t.split("=").shift()]=t.split("=").pop()});for(let t in e){let a=e[t];e[t]=s(unescape(a))}return void 0!==e.dependencies&&delete e.dependencies,e},h=navigator.userAgent,g=document.createElement("div"),p=/(iphone|ipod|ipad|android)/gi.test(h)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1,f=/chrome/i.test(h)&&!/edge/i.test(h),v=/android/gi.test(h),m="zoom"in g.style&&!p&&(f||/Version\/[\d\.]+.*Safari/.test(h));class b{constructor(e){this.Reveal=e}shouldPreload(e){let t=this.Reveal.getConfig().preloadIframes;return"boolean"!=typeof t&&(t=e.hasAttribute("data-preload")),t}load(e,t={}){e.style.display=this.Reveal.getConfig().display,r(e.querySelectorAll("img[data-src], video[data-src], audio[data-src], iframe[data-src]")).forEach(e=>{("IFRAME"!==e.tagName||this.shouldPreload(e))&&(e.setAttribute("src",e.getAttribute("data-src")),e.setAttribute("data-lazy-loaded",""),e.removeAttribute("data-src"))}),r(e.querySelectorAll("video, audio")).forEach(e=>{let t=0;r(e.querySelectorAll("source[data-src]")).forEach(e=>{e.setAttribute("src",e.getAttribute("data-src")),e.removeAttribute("data-src"),e.setAttribute("data-lazy-loaded",""),t+=1}),t>0&&e.load()});let a=e.slideBackgroundElement;if(a){a.style.display="block";let i=e.slideBackgroundContentElement,n=e.getAttribute("data-background-iframe");if(!1===a.hasAttribute("data-loaded")){a.setAttribute("data-loaded","true");let r=e.getAttribute("data-background-image"),s=e.getAttribute("data-background-video"),o=e.hasAttribute("data-background-video-loop"),l=e.hasAttribute("data-background-video-muted");if(r)i.style.backgroundImage="url("+encodeURI(r)+")";else if(s&&!this.Reveal.isSpeakerNotes()){let e=document.createElement("video");o&&e.setAttribute("loop",""),l&&(e.muted=!0),p&&(e.muted=!0,e.autoplay=!0,e.setAttribute("playsinline","")),s.split(",").forEach(t=>{e.innerHTML+='<source src="'+t+'">'}),i.appendChild(e)}else if(n&&!0!==t.excludeIframes){let e=document.createElement("iframe");e.setAttribute("allowfullscreen",""),e.setAttribute("mozallowfullscreen",""),e.setAttribute("webkitallowfullscreen",""),e.setAttribute("allow","autoplay"),e.setAttribute("data-src",n),e.style.width="100%",e.style.height="100%",e.style.maxHeight="100%",e.style.maxWidth="100%",i.appendChild(e)}}let r=i.querySelector("iframe[data-src]");r&&this.shouldPreload(a)&&!/autoplay=(1|true|yes)/gi.test(n)&&r.getAttribute("src")!==n&&r.setAttribute("src",n)}}unload(e){e.style.display="none";let t=this.Reveal.getSlideBackground(e);t&&(t.style.display="none",r(t.querySelectorAll("iframe[src]")).forEach(e=>{e.removeAttribute("src")})),r(e.querySelectorAll("video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")}),r(e.querySelectorAll("video[data-lazy-loaded] source[src], audio source[src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")})}formatEmbeddedContent(){let e=(e,t,a)=>{r(this.Reveal.getSlidesElement().querySelectorAll("iframe["+e+'*="'+t+'Line truncated
|
||||||
@@ -263,7 +263,7 @@ export default class Keyboard {
|
|||||||
}
|
}
|
||||||
// N, PAGE DOWN
|
// N, PAGE DOWN
|
||||||
else if( keyCode === 78 || keyCode === 34 ) {
|
else if( keyCode === 78 || keyCode === 34 ) {
|
||||||
this.Review.next();
|
this.Reveal.next();
|
||||||
}
|
}
|
||||||
// H, LEFT
|
// H, LEFT
|
||||||
else if( keyCode === 72 || keyCode === 37 ) {
|
else if( keyCode === 72 || keyCode === 37 ) {
|
||||||
@@ -283,7 +283,7 @@ export default class Keyboard {
|
|||||||
this.Reveal.slide( Number.MAX_VALUE );
|
this.Reveal.slide( Number.MAX_VALUE );
|
||||||
}
|
}
|
||||||
else if( !this.Reveal.overview.isActive() && useLinearMode ) {
|
else if( !this.Reveal.overview.isActive() && useLinearMode ) {
|
||||||
this.Review.next();
|
this.Reveal.next();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.Reveal.right();
|
this.Reveal.right();
|
||||||
@@ -301,7 +301,7 @@ export default class Keyboard {
|
|||||||
// J, DOWN
|
// J, DOWN
|
||||||
else if( keyCode === 74 || keyCode === 40 ) {
|
else if( keyCode === 74 || keyCode === 40 ) {
|
||||||
if( !this.Reveal.overview.isActive() && useLinearMode ) {
|
if( !this.Reveal.overview.isActive() && useLinearMode ) {
|
||||||
this.Review.next();
|
this.Reveal.next();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.Reveal.down();
|
this.Reveal.down();
|
||||||
@@ -324,7 +324,7 @@ export default class Keyboard {
|
|||||||
this.Reveal.prev();
|
this.Reveal.prev();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.Review.next();
|
this.Reveal.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON
|
// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { enterFullscreen } from '../utils/util.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles all reveal.js keyboard interactions.
|
||||||
|
*/
|
||||||
|
export default class Location {
|
||||||
|
|
||||||
|
constructor( Reveal ) {
|
||||||
|
|
||||||
|
this.Reveal = Reveal;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a hash URL that will resolve to the given slide location.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} [slide=currentSlide] The slide to link to
|
||||||
|
*/
|
||||||
|
getHash( slide = this.Reveal.getCurrentSlide() ) {
|
||||||
|
|
||||||
|
let url = '/';
|
||||||
|
|
||||||
|
// Attempt to create a named link based on the slide's ID
|
||||||
|
let id = slide ? slide.getAttribute( 'id' ) : null;
|
||||||
|
if( id ) {
|
||||||
|
id = encodeURIComponent( id );
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = this.Reveal.getIndices( slide );
|
||||||
|
if( !this.Reveal.getConfig().fragmentInURL ) {
|
||||||
|
index.f = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the current slide has an ID, use that as a named link,
|
||||||
|
// but we don't support named links with a fragment index
|
||||||
|
if( typeof id === 'string' && id.length && index.f === undefined ) {
|
||||||
|
url = '/' + id;
|
||||||
|
}
|
||||||
|
// Otherwise use the /h/v index
|
||||||
|
else {
|
||||||
|
let hashIndexBase = this.Reveal.getConfig().hashOneBasedIndex ? 1 : 0;
|
||||||
|
if( index.h > 0 || index.v > 0 || index.f !== undefined ) url += index.h + hashIndexBase;
|
||||||
|
if( index.v > 0 || index.f !== undefined ) url += '/' + (index.v + hashIndexBase );
|
||||||
|
if( index.f !== undefined ) url += '/' + index.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import { enterFullscreen } from '../utils/util.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles all reveal.js keyboard interactions.
|
||||||
|
*/
|
||||||
|
export default class SlideNumber {
|
||||||
|
|
||||||
|
constructor( Reveal ) {
|
||||||
|
|
||||||
|
this.Reveal = Reveal;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
createElement() {
|
||||||
|
|
||||||
|
this.element = document.createElement( 'div' );
|
||||||
|
this.element.className = 'slide-number';
|
||||||
|
this.Reveal.getRevealElement().appendChild( this.element );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows or hides the slide number depending on the
|
||||||
|
* current config and state.
|
||||||
|
*/
|
||||||
|
refreshVisibility() {
|
||||||
|
|
||||||
|
let config = this.Reveal.getConfig();
|
||||||
|
|
||||||
|
let slideNumberDisplay = 'none';
|
||||||
|
if( config.slideNumber && !this.Reveal.isPrintingPDF() ) {
|
||||||
|
if( config.showSlideNumber === 'all' ) {
|
||||||
|
slideNumberDisplay = 'block';
|
||||||
|
}
|
||||||
|
else if( config.showSlideNumber === 'speaker' && this.Reveal.isSpeakerNotes() ) {
|
||||||
|
slideNumberDisplay = 'block';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.style.display = slideNumberDisplay;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the slide number to match the current slide.
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
|
||||||
|
// Update slide number if enabled
|
||||||
|
if( this.Reveal.getConfig().slideNumber && this.element ) {
|
||||||
|
this.element.innerHTML = this.getSlideNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTML string corresponding to the current slide
|
||||||
|
* number, including formatting.
|
||||||
|
*/
|
||||||
|
getSlideNumber( slide = this.Reveal.getCurrentSlide() ) {
|
||||||
|
|
||||||
|
let config = this.Reveal.getConfig();
|
||||||
|
let value;
|
||||||
|
let format = 'h.v';
|
||||||
|
|
||||||
|
if ( typeof config.slideNumber === 'function' ) {
|
||||||
|
value = config.slideNumber( slide );
|
||||||
|
} else {
|
||||||
|
// Check if a custom number format is available
|
||||||
|
if( typeof config.slideNumber === 'string' ) {
|
||||||
|
format = config.slideNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are ONLY vertical slides in this deck, always use
|
||||||
|
// a flattened slide number
|
||||||
|
if( !/c/.test( format ) && this.Reveal.getHorizontalSlides().length === 1 ) {
|
||||||
|
format = 'c';
|
||||||
|
}
|
||||||
|
|
||||||
|
value = [];
|
||||||
|
switch( format ) {
|
||||||
|
case 'c':
|
||||||
|
value.push( this.Reveal.getSlidePastCount( slide ) + 1 );
|
||||||
|
break;
|
||||||
|
case 'c/t':
|
||||||
|
value.push( this.Reveal.getSlidePastCount( slide ) + 1, '/', this.Reveal.getTotalSlides() );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
let indices = this.Reveal.getIndices( slide );
|
||||||
|
value.push( indices.h + 1 );
|
||||||
|
let sep = format === 'h/v' ? '/' : '.';
|
||||||
|
if( this.Reveal.isVerticalSlide( slide ) ) value.push( sep, indices.v + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = '#' + this.Reveal.location.getHash( slide );
|
||||||
|
return this.formatNumber( value[0], value[1], value[2], url );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies HTML formatting to a slide number before it's
|
||||||
|
* written to the DOM.
|
||||||
|
*
|
||||||
|
* @param {number} a Current slide
|
||||||
|
* @param {string} delimiter Character to separate slide numbers
|
||||||
|
* @param {(number|*)} b Total slides
|
||||||
|
* @param {HTMLElement} [url='#'+locationHash()] The url to link to
|
||||||
|
* @return {string} HTML string fragment
|
||||||
|
*/
|
||||||
|
formatNumber( a, delimiter, b, url = '#' + this.Reveal.location.getHash() ) {
|
||||||
|
|
||||||
|
if( typeof b === 'number' && !isNaN( b ) ) {
|
||||||
|
return `<a href="${url}">
|
||||||
|
<span class="slide-number-a">${a}</span>
|
||||||
|
<span class="slide-number-delimiter">${delimiter}</span>
|
||||||
|
<span class="slide-number-b">${b}</span>
|
||||||
|
</a>`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return `<a href="${url}">
|
||||||
|
<span class="slide-number-a">${a}</span>
|
||||||
|
</a>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+20
-179
@@ -1,8 +1,10 @@
|
|||||||
import SlideContent from './controllers/slidecontent.js'
|
import SlideContent from './controllers/slidecontent.js'
|
||||||
|
import SlideNumber from './controllers/slidenumber.js'
|
||||||
import AutoAnimate from './controllers/autoanimate.js'
|
import AutoAnimate from './controllers/autoanimate.js'
|
||||||
import Fragments from './controllers/fragments.js'
|
import Fragments from './controllers/fragments.js'
|
||||||
import Overview from './controllers/overview.js'
|
import Overview from './controllers/overview.js'
|
||||||
import Keyboard from './controllers/keyboard.js'
|
import Keyboard from './controllers/keyboard.js'
|
||||||
|
import Location from './controllers/location.js'
|
||||||
import Plugins from './controllers/plugins.js'
|
import Plugins from './controllers/plugins.js'
|
||||||
import Playback from './components/playback.js'
|
import Playback from './components/playback.js'
|
||||||
import defaultConfig from './config.js'
|
import defaultConfig from './config.js'
|
||||||
@@ -18,6 +20,7 @@ import {
|
|||||||
distanceBetween,
|
distanceBetween,
|
||||||
deserialize,
|
deserialize,
|
||||||
transformElement,
|
transformElement,
|
||||||
|
createSingletonNode,
|
||||||
createStyleSheet,
|
createStyleSheet,
|
||||||
closestParent,
|
closestParent,
|
||||||
enterFullscreen,
|
enterFullscreen,
|
||||||
@@ -81,6 +84,9 @@ export default function( revealElement, options ) {
|
|||||||
// Controls loading and playback of slide content
|
// Controls loading and playback of slide content
|
||||||
slideContent = new SlideContent( Reveal ),
|
slideContent = new SlideContent( Reveal ),
|
||||||
|
|
||||||
|
// Controls the optional slide number display
|
||||||
|
slideNumber = new SlideNumber( Reveal ),
|
||||||
|
|
||||||
// Controls auto-animations between slides
|
// Controls auto-animations between slides
|
||||||
autoAnimate = new AutoAnimate( Reveal ),
|
autoAnimate = new AutoAnimate( Reveal ),
|
||||||
|
|
||||||
@@ -93,6 +99,9 @@ export default function( revealElement, options ) {
|
|||||||
// Controls all keyboard interactions
|
// Controls all keyboard interactions
|
||||||
keyboard = new Keyboard( Reveal ),
|
keyboard = new Keyboard( Reveal ),
|
||||||
|
|
||||||
|
// Controls the current location/URL
|
||||||
|
location = new Location( Reveal ),
|
||||||
|
|
||||||
// List of asynchronously loaded reveal.js dependencies
|
// List of asynchronously loaded reveal.js dependencies
|
||||||
asyncDependencies = [],
|
asyncDependencies = [],
|
||||||
|
|
||||||
@@ -248,7 +257,7 @@ export default function( revealElement, options ) {
|
|||||||
<button class="navigate-down" aria-label="below slide"><div class="controls-arrow"></div></button>` );
|
<button class="navigate-down" aria-label="below slide"><div class="controls-arrow"></div></button>` );
|
||||||
|
|
||||||
// Slide number
|
// Slide number
|
||||||
dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' );
|
slideNumber.createElement();
|
||||||
|
|
||||||
// Element containing notes that are visible to the audience
|
// Element containing notes that are visible to the audience
|
||||||
dom.speakerNotes = createSingletonNode( dom.wrapper, 'div', 'speaker-notes', null );
|
dom.speakerNotes = createSingletonNode( dom.wrapper, 'div', 'speaker-notes', null );
|
||||||
@@ -377,7 +386,7 @@ export default function( revealElement, options ) {
|
|||||||
// Compute slide numbers now, before we start duplicating slides
|
// Compute slide numbers now, before we start duplicating slides
|
||||||
let doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber );
|
let doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber );
|
||||||
toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
|
toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
|
||||||
slide.setAttribute( 'data-slide-number', getSlideNumber( slide ) );
|
slide.setAttribute( 'data-slide-number', slideNumber.getSlideNumber( slide ) );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// Slide and slide background layout
|
// Slide and slide background layout
|
||||||
@@ -534,42 +543,6 @@ export default function( revealElement, options ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an HTML element and returns a reference to it.
|
|
||||||
* If the element already exists the existing instance will
|
|
||||||
* be returned.
|
|
||||||
*
|
|
||||||
* @param {HTMLElement} container
|
|
||||||
* @param {string} tagname
|
|
||||||
* @param {string} classname
|
|
||||||
* @param {string} innerHTML
|
|
||||||
*
|
|
||||||
* @return {HTMLElement}
|
|
||||||
*/
|
|
||||||
function createSingletonNode( container, tagname, classname, innerHTML='' ) {
|
|
||||||
|
|
||||||
// Find all nodes matching the description
|
|
||||||
let nodes = container.querySelectorAll( '.' + classname );
|
|
||||||
|
|
||||||
// Check all matches to find one which is a direct child of
|
|
||||||
// the specified container
|
|
||||||
for( let i = 0; i < nodes.length; i++ ) {
|
|
||||||
let testNode = nodes[i];
|
|
||||||
if( testNode.parentNode === container ) {
|
|
||||||
return testNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no node was found, create it now
|
|
||||||
let node = document.createElement( tagname );
|
|
||||||
node.className = classname;
|
|
||||||
node.innerHTML = innerHTML;
|
|
||||||
container.appendChild( node );
|
|
||||||
|
|
||||||
return node;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the slide background elements and appends them
|
* Creates the slide background elements and appends them
|
||||||
* to the background container. One element is created per
|
* to the background container. One element is created per
|
||||||
@@ -831,9 +804,8 @@ export default function( revealElement, options ) {
|
|||||||
|
|
||||||
const numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length;
|
const numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length;
|
||||||
|
|
||||||
// Remove the previously configured transition class
|
// The transition is added as a class on the .reveal element
|
||||||
dom.wrapper.classList.remove( oldTransition );
|
dom.wrapper.classList.remove( oldTransition );
|
||||||
|
|
||||||
dom.wrapper.classList.add( config.transition );
|
dom.wrapper.classList.add( config.transition );
|
||||||
|
|
||||||
dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
|
dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
|
||||||
@@ -927,19 +899,6 @@ export default function( revealElement, options ) {
|
|||||||
fragments.showAll();
|
fragments.showAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slide numbers
|
|
||||||
let slideNumberDisplay = 'none';
|
|
||||||
if( config.slideNumber && !isPrintingPDF() ) {
|
|
||||||
if( config.showSlideNumber === 'all' ) {
|
|
||||||
slideNumberDisplay = 'block';
|
|
||||||
}
|
|
||||||
else if( config.showSlideNumber === 'speaker' && isSpeakerNotes() ) {
|
|
||||||
slideNumberDisplay = 'block';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dom.slideNumber.style.display = slideNumberDisplay;
|
|
||||||
|
|
||||||
// Add the navigation mode to the DOM so we can adjust styling
|
// Add the navigation mode to the DOM so we can adjust styling
|
||||||
if( config.navigationMode !== 'default' ) {
|
if( config.navigationMode !== 'default' ) {
|
||||||
dom.wrapper.setAttribute( 'data-navigation-mode', config.navigationMode );
|
dom.wrapper.setAttribute( 'data-navigation-mode', config.navigationMode );
|
||||||
@@ -948,6 +907,7 @@ export default function( revealElement, options ) {
|
|||||||
dom.wrapper.removeAttribute( 'data-navigation-mode' );
|
dom.wrapper.removeAttribute( 'data-navigation-mode' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slideNumber.refreshVisibility();
|
||||||
keyboard.refreshSortcuts();
|
keyboard.refreshSortcuts();
|
||||||
|
|
||||||
sync();
|
sync();
|
||||||
@@ -1551,44 +1511,6 @@ export default function( revealElement, options ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a hash URL that will resolve to the given slide location.
|
|
||||||
*
|
|
||||||
* @param {HTMLElement} [slide=currentSlide] The slide to link to
|
|
||||||
*/
|
|
||||||
function locationHash( slide ) {
|
|
||||||
|
|
||||||
let url = '/';
|
|
||||||
|
|
||||||
// Attempt to create a named link based on the slide's ID
|
|
||||||
let s = slide || currentSlide;
|
|
||||||
let id = s ? s.getAttribute( 'id' ) : null;
|
|
||||||
if( id ) {
|
|
||||||
id = encodeURIComponent( id );
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = getIndices( slide );
|
|
||||||
if( !config.fragmentInURL ) {
|
|
||||||
index.f = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the current slide has an ID, use that as a named link,
|
|
||||||
// but we don't support named links with a fragment index
|
|
||||||
if( typeof id === 'string' && id.length && index.f === undefined ) {
|
|
||||||
url = '/' + id;
|
|
||||||
}
|
|
||||||
// Otherwise use the /h/v index
|
|
||||||
else {
|
|
||||||
let hashIndexBase = config.hashOneBasedIndex ? 1 : 0;
|
|
||||||
if( index.h > 0 || index.v > 0 || index.f !== undefined ) url += index.h + hashIndexBase;
|
|
||||||
if( index.v > 0 || index.f !== undefined ) url += '/' + (index.v + hashIndexBase );
|
|
||||||
if( index.f !== undefined ) url += '/' + index.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the current or specified slide is vertical
|
* Checks if the current or specified slide is vertical
|
||||||
* (nested within another slide).
|
* (nested within another slide).
|
||||||
@@ -1908,9 +1830,9 @@ export default function( revealElement, options ) {
|
|||||||
updateProgress();
|
updateProgress();
|
||||||
updateBackground();
|
updateBackground();
|
||||||
updateParallax();
|
updateParallax();
|
||||||
updateSlideNumber();
|
|
||||||
updateNotes();
|
updateNotes();
|
||||||
|
|
||||||
|
slideNumber.update();
|
||||||
fragments.update();
|
fragments.update();
|
||||||
|
|
||||||
// Update the URL hash
|
// Update the URL hash
|
||||||
@@ -1970,12 +1892,12 @@ export default function( revealElement, options ) {
|
|||||||
|
|
||||||
updateControls();
|
updateControls();
|
||||||
updateProgress();
|
updateProgress();
|
||||||
updateSlideNumber();
|
|
||||||
updateSlidesVisibility();
|
updateSlidesVisibility();
|
||||||
updateBackground( true );
|
updateBackground( true );
|
||||||
updateNotesVisibility();
|
updateNotesVisibility();
|
||||||
updateNotes();
|
updateNotes();
|
||||||
|
|
||||||
|
slideNumber.update();
|
||||||
slideContent.formatEmbeddedContent();
|
slideContent.formatEmbeddedContent();
|
||||||
|
|
||||||
// Start or stop embedded content depending on global config
|
// Start or stop embedded content depending on global config
|
||||||
@@ -2322,90 +2244,6 @@ export default function( revealElement, options ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the slide number to match the current slide.
|
|
||||||
*/
|
|
||||||
function updateSlideNumber() {
|
|
||||||
|
|
||||||
// Update slide number if enabled
|
|
||||||
if( config.slideNumber && dom.slideNumber ) {
|
|
||||||
dom.slideNumber.innerHTML = getSlideNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the HTML string corresponding to the current slide number,
|
|
||||||
* including formatting.
|
|
||||||
*/
|
|
||||||
function getSlideNumber( slide = currentSlide ) {
|
|
||||||
|
|
||||||
let value;
|
|
||||||
let format = 'h.v';
|
|
||||||
|
|
||||||
if ( typeof config.slideNumber === 'function' ) {
|
|
||||||
value = config.slideNumber( slide );
|
|
||||||
} else {
|
|
||||||
// Check if a custom number format is available
|
|
||||||
if( typeof config.slideNumber === 'string' ) {
|
|
||||||
format = config.slideNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are ONLY vertical slides in this deck, always use
|
|
||||||
// a flattened slide number
|
|
||||||
if( !/c/.test( format ) && dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ).length === 1 ) {
|
|
||||||
format = 'c';
|
|
||||||
}
|
|
||||||
|
|
||||||
value = [];
|
|
||||||
switch( format ) {
|
|
||||||
case 'c':
|
|
||||||
value.push( getSlidePastCount( slide ) + 1 );
|
|
||||||
break;
|
|
||||||
case 'c/t':
|
|
||||||
value.push( getSlidePastCount( slide ) + 1, '/', getTotalSlides() );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
let indices = getIndices( slide );
|
|
||||||
value.push( indices.h + 1 );
|
|
||||||
let sep = format === 'h/v' ? '/' : '.';
|
|
||||||
if( isVerticalSlide( slide ) ) value.push( sep, indices.v + 1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = '#' + locationHash( slide );
|
|
||||||
return formatSlideNumber( value[0], value[1], value[2], url );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies HTML formatting to a slide number before it's
|
|
||||||
* written to the DOM.
|
|
||||||
*
|
|
||||||
* @param {number} a Current slide
|
|
||||||
* @param {string} delimiter Character to separate slide numbers
|
|
||||||
* @param {(number|*)} b Total slides
|
|
||||||
* @param {HTMLElement} [url='#'+locationHash()] The url to link to
|
|
||||||
* @return {string} HTML string fragment
|
|
||||||
*/
|
|
||||||
function formatSlideNumber( a, delimiter, b, url = '#' + locationHash() ) {
|
|
||||||
|
|
||||||
if( typeof b === 'number' && !isNaN( b ) ) {
|
|
||||||
return `<a href="${url}">
|
|
||||||
<span class="slide-number-a">${a}</span>
|
|
||||||
<span class="slide-number-delimiter">${delimiter}</span>
|
|
||||||
<span class="slide-number-b">${b}</span>
|
|
||||||
</a>`;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return `<a href="${url}">
|
|
||||||
<span class="slide-number-a">${a}</span>
|
|
||||||
</a>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the state of all control/navigation arrows.
|
* Updates the state of all control/navigation arrows.
|
||||||
*/
|
*/
|
||||||
@@ -2881,12 +2719,12 @@ export default function( revealElement, options ) {
|
|||||||
// If we're configured to push to history OR the history
|
// If we're configured to push to history OR the history
|
||||||
// API is not avaialble.
|
// API is not avaialble.
|
||||||
if( config.history || !window.history ) {
|
if( config.history || !window.history ) {
|
||||||
window.location.hash = locationHash();
|
window.location.hash = location.getHash();
|
||||||
}
|
}
|
||||||
// If we're configured to reflect the current slide in the
|
// If we're configured to reflect the current slide in the
|
||||||
// URL without pushing to history.
|
// URL without pushing to history.
|
||||||
else if( config.hash ) {
|
else if( config.hash ) {
|
||||||
window.history.replaceState( null, null, '#' + locationHash() );
|
window.history.replaceState( null, null, '#' + location.getHash() );
|
||||||
}
|
}
|
||||||
// If history and hash are both disabled, a hash may still
|
// If history and hash are both disabled, a hash may still
|
||||||
// be added to the URL by clicking on a href with a hash
|
// be added to the URL by clicking on a href with a hash
|
||||||
@@ -3810,12 +3648,14 @@ export default function( revealElement, options ) {
|
|||||||
isFirstSlide,
|
isFirstSlide,
|
||||||
isLastSlide,
|
isLastSlide,
|
||||||
isLastVerticalSlide,
|
isLastVerticalSlide,
|
||||||
|
isVerticalSlide,
|
||||||
|
|
||||||
// State checks
|
// State checks
|
||||||
isOverview: overview.isActive.bind( overview ),
|
isOverview: overview.isActive.bind( overview ),
|
||||||
isPaused,
|
isPaused,
|
||||||
isAutoSliding,
|
isAutoSliding,
|
||||||
isSpeakerNotes,
|
isSpeakerNotes,
|
||||||
|
isPrintingPDF,
|
||||||
|
|
||||||
// Slide preloading
|
// Slide preloading
|
||||||
loadSlide: slideContent.load.bind( slideContent ),
|
loadSlide: slideContent.load.bind( slideContent ),
|
||||||
@@ -3916,6 +3756,7 @@ export default function( revealElement, options ) {
|
|||||||
announceStatus,
|
announceStatus,
|
||||||
getStatusText,
|
getStatusText,
|
||||||
|
|
||||||
|
location,
|
||||||
overview,
|
overview,
|
||||||
slideContent,
|
slideContent,
|
||||||
onUserInput,
|
onUserInput,
|
||||||
|
|||||||
@@ -135,6 +135,42 @@ export const enterFullscreen = () => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an HTML element and returns a reference to it.
|
||||||
|
* If the element already exists the existing instance will
|
||||||
|
* be returned.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} container
|
||||||
|
* @param {string} tagname
|
||||||
|
* @param {string} classname
|
||||||
|
* @param {string} innerHTML
|
||||||
|
*
|
||||||
|
* @return {HTMLElement}
|
||||||
|
*/
|
||||||
|
export const createSingletonNode = ( container, tagname, classname, innerHTML='' ) => {
|
||||||
|
|
||||||
|
// Find all nodes matching the description
|
||||||
|
let nodes = container.querySelectorAll( '.' + classname );
|
||||||
|
|
||||||
|
// Check all matches to find one which is a direct child of
|
||||||
|
// the specified container
|
||||||
|
for( let i = 0; i < nodes.length; i++ ) {
|
||||||
|
let testNode = nodes[i];
|
||||||
|
if( testNode.parentNode === container ) {
|
||||||
|
return testNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no node was found, create it now
|
||||||
|
let node = document.createElement( tagname );
|
||||||
|
node.className = classname;
|
||||||
|
node.innerHTML = innerHTML;
|
||||||
|
container.appendChild( node );
|
||||||
|
|
||||||
|
return node;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injects the given CSS styles into the DOM.
|
* Injects the given CSS styles into the DOM.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in new issue
Block a user