add slidenumber & location controllers
This commit is contained in:
parent
ac15678dea
commit
3683ad255d
6 changed files with 240 additions and 184 deletions
2
dist/reveal.min.js
vendored
2
dist/reveal.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -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
|
||||||
|
|
51
js/controllers/location.js
Normal file
51
js/controllers/location.js
Normal file
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
128
js/controllers/slidenumber.js
Normal file
128
js/controllers/slidenumber.js
Normal file
|
@ -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>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
199
js/reveal.js
199
js/reveal.js
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue