mirror of
https://github.com/hakimel/reveal.js.git
synced 2025-01-29 19:08:02 +01:00
1 line
377 KiB
Plaintext
1 line
377 KiB
Plaintext
{"version":3,"file":"reveal.js","sources":["../js/utils/util.js","../js/utils/device.js","../node_modules/fitty/dist/fitty.module.js","../js/controllers/slidecontent.js","../js/controllers/slidenumber.js","../js/controllers/jumptoslide.js","../js/utils/color.js","../js/controllers/backgrounds.js","../js/utils/constants.js","../js/controllers/autoanimate.js","../js/controllers/fragments.js","../js/controllers/overview.js","../js/controllers/keyboard.js","../js/controllers/location.js","../js/controllers/controls.js","../js/controllers/progress.js","../js/controllers/pointer.js","../js/utils/loader.js","../js/controllers/plugins.js","../js/controllers/reader.js","../js/controllers/print.js","../js/controllers/touch.js","../js/controllers/focus.js","../js/controllers/notes.js","../js/components/playback.js","../js/config.js","../js/reveal.js","../js/index.js"],"sourcesContent":["/**\n * Extend object a with the properties of object b.\n * If there's a conflict, object b takes precedence.\n *\n * @param {object} a\n * @param {object} b\n */\nexport const extend = ( a, b ) => {\n\n\tfor( let i in b ) {\n\t\ta[ i ] = b[ i ];\n\t}\n\n\treturn a;\n\n}\n\n/**\n * querySelectorAll but returns an Array.\n */\nexport const queryAll = ( el, selector ) => {\n\n\treturn Array.from( el.querySelectorAll( selector ) );\n\n}\n\n/**\n * classList.toggle() with cross browser support\n */\nexport const toggleClass = ( el, className, value ) => {\n\tif( value ) {\n\t\tel.classList.add( className );\n\t}\n\telse {\n\t\tel.classList.remove( className );\n\t}\n}\n\n/**\n * Utility for deserializing a value.\n *\n * @param {*} value\n * @return {*}\n */\nexport const deserialize = ( value ) => {\n\n\tif( typeof value === 'string' ) {\n\t\tif( value === 'null' ) return null;\n\t\telse if( value === 'true' ) return true;\n\t\telse if( value === 'false' ) return false;\n\t\telse if( value.match( /^-?[\\d\\.]+$/ ) ) return parseFloat( value );\n\t}\n\n\treturn value;\n\n}\n\n/**\n * Measures the distance in pixels between point a\n * and point b.\n *\n * @param {object} a point with x/y properties\n * @param {object} b point with x/y properties\n *\n * @return {number}\n */\nexport const distanceBetween = ( a, b ) => {\n\n\tlet dx = a.x - b.x,\n\t\tdy = a.y - b.y;\n\n\treturn Math.sqrt( dx*dx + dy*dy );\n\n}\n\n/**\n * Applies a CSS transform to the target element.\n *\n * @param {HTMLElement} element\n * @param {string} transform\n */\nexport const transformElement = ( element, transform ) => {\n\n\telement.style.transform = transform;\n\n}\n\n/**\n * Element.matches with IE support.\n *\n * @param {HTMLElement} target The element to match\n * @param {String} selector The CSS selector to match\n * the element against\n *\n * @return {Boolean}\n */\nexport const matches = ( target, selector ) => {\n\n\tlet matchesMethod = target.matches || target.matchesSelector || target.msMatchesSelector;\n\n\treturn !!( matchesMethod && matchesMethod.call( target, selector ) );\n\n}\n\n/**\n * Find the closest parent that matches the given\n * selector.\n *\n * @param {HTMLElement} target The child element\n * @param {String} selector The CSS selector to match\n * the parents against\n *\n * @return {HTMLElement} The matched parent or null\n * if no matching parent was found\n */\nexport const closest = ( target, selector ) => {\n\n\t// Native Element.closest\n\tif( typeof target.closest === 'function' ) {\n\t\treturn target.closest( selector );\n\t}\n\n\t// Polyfill\n\twhile( target ) {\n\t\tif( matches( target, selector ) ) {\n\t\t\treturn target;\n\t\t}\n\n\t\t// Keep searching\n\t\ttarget = target.parentNode;\n\t}\n\n\treturn null;\n\n}\n\n/**\n * Handling the fullscreen functionality via the fullscreen API\n *\n * @see http://fullscreen.spec.whatwg.org/\n * @see https://developer.mozilla.org/en-US/docs/DOM/Using_fullscreen_mode\n */\nexport const enterFullscreen = element => {\n\n\telement = element || document.documentElement;\n\n\t// Check which implementation is available\n\tlet requestMethod = element.requestFullscreen ||\n\t\t\t\t\t\telement.webkitRequestFullscreen ||\n\t\t\t\t\t\telement.webkitRequestFullScreen ||\n\t\t\t\t\t\telement.mozRequestFullScreen ||\n\t\t\t\t\t\telement.msRequestFullscreen;\n\n\tif( requestMethod ) {\n\t\trequestMethod.apply( element );\n\t}\n\n}\n\n/**\n * Creates an HTML element and returns a reference to it.\n * If the element already exists the existing instance will\n * be returned.\n *\n * @param {HTMLElement} container\n * @param {string} tagname\n * @param {string} classname\n * @param {string} innerHTML\n *\n * @return {HTMLElement}\n */\nexport const createSingletonNode = ( container, tagname, classname, innerHTML='' ) => {\n\n\t// Find all nodes matching the description\n\tlet nodes = container.querySelectorAll( '.' + classname );\n\n\t// Check all matches to find one which is a direct child of\n\t// the specified container\n\tfor( let i = 0; i < nodes.length; i++ ) {\n\t\tlet testNode = nodes[i];\n\t\tif( testNode.parentNode === container ) {\n\t\t\treturn testNode;\n\t\t}\n\t}\n\n\t// If no node was found, create it now\n\tlet node = document.createElement( tagname );\n\tnode.className = classname;\n\tnode.innerHTML = innerHTML;\n\tcontainer.appendChild( node );\n\n\treturn node;\n\n}\n\n/**\n * Injects the given CSS styles into the DOM.\n *\n * @param {string} value\n */\nexport const createStyleSheet = ( value ) => {\n\n\tlet tag = document.createElement( 'style' );\n\ttag.type = 'text/css';\n\n\tif( value && value.length > 0 ) {\n\t\tif( tag.styleSheet ) {\n\t\t\ttag.styleSheet.cssText = value;\n\t\t}\n\t\telse {\n\t\t\ttag.appendChild( document.createTextNode( value ) );\n\t\t}\n\t}\n\n\tdocument.head.appendChild( tag );\n\n\treturn tag;\n\n}\n\n/**\n * Returns a key:value hash of all query params.\n */\nexport const getQueryHash = () => {\n\n\tlet query = {};\n\n\tlocation.search.replace( /[A-Z0-9]+?=([\\w\\.%-]*)/gi, a => {\n\t\tquery[ a.split( '=' ).shift() ] = a.split( '=' ).pop();\n\t} );\n\n\t// Basic deserialization\n\tfor( let i in query ) {\n\t\tlet value = query[ i ];\n\n\t\tquery[ i ] = deserialize( unescape( value ) );\n\t}\n\n\t// Do not accept new dependencies via query config to avoid\n\t// the potential of malicious script injection\n\tif( typeof query['dependencies'] !== 'undefined' ) delete query['dependencies'];\n\n\treturn query;\n\n}\n\n/**\n * Returns the remaining height within the parent of the\n * target element.\n *\n * remaining height = [ configured parent height ] - [ current parent height ]\n *\n * @param {HTMLElement} element\n * @param {number} [height]\n */\nexport const getRemainingHeight = ( element, height = 0 ) => {\n\n\tif( element ) {\n\t\tlet newHeight, oldHeight = element.style.height;\n\n\t\t// Change the .stretch element height to 0 in order find the height of all\n\t\t// the other elements\n\t\telement.style.height = '0px';\n\n\t\t// In Overview mode, the parent (.slide) height is set of 700px.\n\t\t// Restore it temporarily to its natural height.\n\t\telement.parentNode.style.height = 'auto';\n\n\t\tnewHeight = height - element.parentNode.offsetHeight;\n\n\t\t// Restore the old height, just in case\n\t\telement.style.height = oldHeight + 'px';\n\n\t\t// Clear the parent (.slide) height. .removeProperty works in IE9+\n\t\telement.parentNode.style.removeProperty('height');\n\n\t\treturn newHeight;\n\t}\n\n\treturn height;\n\n}\n\nconst fileExtensionToMimeMap = {\n\t'mp4': 'video/mp4',\n\t'm4a': 'video/mp4',\n\t'ogv': 'video/ogg',\n\t'mpeg': 'video/mpeg',\n\t'webm': 'video/webm'\n}\n\n/**\n * Guess the MIME type for common file formats.\n */\nexport const getMimeTypeFromFile = ( filename='' ) => {\n\treturn fileExtensionToMimeMap[filename.split('.').pop()]\n}\n\n/**\n * Encodes a string for RFC3986-compliant URL format.\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#encoding_for_rfc3986\n *\n * @param {string} url\n */\nexport const encodeRFC3986URI = ( url='' ) => {\n\treturn encodeURI(url)\n\t .replace(/%5B/g, \"[\")\n\t .replace(/%5D/g, \"]\")\n\t .replace(\n\t\t/[!'()*]/g,\n\t\t(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`\n\t );\n}","const UA = navigator.userAgent;\n\nexport const isMobile = /(iphone|ipod|ipad|android)/gi.test( UA ) ||\n\t\t\t\t\t\t( navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 ); // iPadOS\n\nexport const isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA );\n\nexport const isAndroid = /android/gi.test( UA );","/*\n * fitty v2.3.3 - Snugly resizes text to fit its parent container\n * Copyright (c) 2020 Rik Schennink <rik@pqina.nl> (https://pqina.nl/)\n */\n'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nexports.default = function (w) {\n\n // no window, early exit\n if (!w) return;\n\n // node list to array helper method\n var toArray = function toArray(nl) {\n return [].slice.call(nl);\n };\n\n // states\n var DrawState = {\n IDLE: 0,\n DIRTY_CONTENT: 1,\n DIRTY_LAYOUT: 2,\n DIRTY: 3\n };\n\n // all active fitty elements\n var fitties = [];\n\n // group all redraw calls till next frame, we cancel each frame request when a new one comes in. If no support for request animation frame, this is an empty function and supports for fitty stops.\n var redrawFrame = null;\n var requestRedraw = 'requestAnimationFrame' in w ? function () {\n w.cancelAnimationFrame(redrawFrame);\n redrawFrame = w.requestAnimationFrame(function () {\n return redraw(fitties.filter(function (f) {\n return f.dirty && f.active;\n }));\n });\n } : function () {};\n\n // sets all fitties to dirty so they are redrawn on the next redraw loop, then calls redraw\n var redrawAll = function redrawAll(type) {\n return function () {\n fitties.forEach(function (f) {\n return f.dirty = type;\n });\n requestRedraw();\n };\n };\n\n // redraws fitties so they nicely fit their parent container\n var redraw = function redraw(fitties) {\n\n // getting info from the DOM at this point should not trigger a reflow, let's gather as much intel as possible before triggering a reflow\n\n // check if styles of all fitties have been computed\n fitties.filter(function (f) {\n return !f.styleComputed;\n }).forEach(function (f) {\n f.styleComputed = computeStyle(f);\n });\n\n // restyle elements that require pre-styling, this triggers a reflow, please try to prevent by adding CSS rules (see docs)\n fitties.filter(shouldPreStyle).forEach(applyStyle);\n\n // we now determine which fitties should be redrawn\n var fittiesToRedraw = fitties.filter(shouldRedraw);\n\n // we calculate final styles for these fitties\n fittiesToRedraw.forEach(calculateStyles);\n\n // now we apply the calculated styles from our previous loop\n fittiesToRedraw.forEach(function (f) {\n applyStyle(f);\n markAsClean(f);\n });\n\n // now we dispatch events for all restyled fitties\n fittiesToRedraw.forEach(dispatchFitEvent);\n };\n\n var markAsClean = function markAsClean(f) {\n return f.dirty = DrawState.IDLE;\n };\n\n var calculateStyles = function calculateStyles(f) {\n\n // get available width from parent node\n f.availableWidth = f.element.parentNode.clientWidth;\n\n // the space our target element uses\n f.currentWidth = f.element.scrollWidth;\n\n // remember current font size\n f.previousFontSize = f.currentFontSize;\n\n // let's calculate the new font size\n f.currentFontSize = Math.min(Math.max(f.minSize, f.availableWidth / f.currentWidth * f.previousFontSize), f.maxSize);\n\n // if allows wrapping, only wrap when at minimum font size (otherwise would break container)\n f.whiteSpace = f.multiLine && f.currentFontSize === f.minSize ? 'normal' : 'nowrap';\n };\n\n // should always redraw if is not dirty layout, if is dirty layout, only redraw if size has changed\n var shouldRedraw = function shouldRedraw(f) {\n return f.dirty !== DrawState.DIRTY_LAYOUT || f.dirty === DrawState.DIRTY_LAYOUT && f.element.parentNode.clientWidth !== f.availableWidth;\n };\n\n // every fitty element is tested for invalid styles\n var computeStyle = function computeStyle(f) {\n\n // get style properties\n var style = w.getComputedStyle(f.element, null);\n\n // get current font size in pixels (if we already calculated it, use the calculated version)\n f.currentFontSize = parseFloat(style.getPropertyValue('font-size'));\n\n // get display type and wrap mode\n f.display = style.getPropertyValue('display');\n f.whiteSpace = style.getPropertyValue('white-space');\n };\n\n // determines if this fitty requires initial styling, can be prevented by applying correct styles through CSS\n var shouldPreStyle = function shouldPreStyle(f) {\n\n var preStyle = false;\n\n // if we already tested for prestyling we don't have to do it again\n if (f.preStyleTestCompleted) return false;\n\n // should have an inline style, if not, apply\n if (!/inline-/.test(f.display)) {\n preStyle = true;\n f.display = 'inline-block';\n }\n\n // to correctly calculate dimensions the element should have whiteSpace set to nowrap\n if (f.whiteSpace !== 'nowrap') {\n preStyle = true;\n f.whiteSpace = 'nowrap';\n }\n\n // we don't have to do this twice\n f.preStyleTestCompleted = true;\n\n return preStyle;\n };\n\n // apply styles to single fitty\n var applyStyle = function applyStyle(f) {\n f.element.style.whiteSpace = f.whiteSpace;\n f.element.style.display = f.display;\n f.element.style.fontSize = f.currentFontSize + 'px';\n };\n\n // dispatch a fit event on a fitty\n var dispatchFitEvent = function dispatchFitEvent(f) {\n f.element.dispatchEvent(new CustomEvent('fit', {\n detail: {\n oldValue: f.previousFontSize,\n newValue: f.currentFontSize,\n scaleFactor: f.currentFontSize / f.previousFontSize\n }\n }));\n };\n\n // fit method, marks the fitty as dirty and requests a redraw (this will also redraw any other fitty marked as dirty)\n var fit = function fit(f, type) {\n return function () {\n f.dirty = type;\n if (!f.active) return;\n requestRedraw();\n };\n };\n\n var init = function init(f) {\n\n // save some of the original CSS properties before we change them\n f.originalStyle = {\n whiteSpace: f.element.style.whiteSpace,\n display: f.element.style.display,\n fontSize: f.element.style.fontSize\n };\n\n // should we observe DOM mutations\n observeMutations(f);\n\n // this is a new fitty so we need to validate if it's styles are in order\n f.newbie = true;\n\n // because it's a new fitty it should also be dirty, we want it to redraw on the first loop\n f.dirty = true;\n\n // we want to be able to update this fitty\n fitties.push(f);\n };\n\n var destroy = function destroy(f) {\n return function () {\n\n // remove from fitties array\n fitties = fitties.filter(function (_) {\n return _.element !== f.element;\n });\n\n // stop observing DOM\n if (f.observeMutations) f.observer.disconnect();\n\n // reset the CSS properties we changes\n f.element.style.whiteSpace = f.originalStyle.whiteSpace;\n f.element.style.display = f.originalStyle.display;\n f.element.style.fontSize = f.originalStyle.fontSize;\n };\n };\n\n // add a new fitty, does not redraw said fitty\n var subscribe = function subscribe(f) {\n return function () {\n if (f.active) return;\n f.active = true;\n requestRedraw();\n };\n };\n\n // remove an existing fitty\n var unsubscribe = function unsubscribe(f) {\n return function () {\n return f.active = false;\n };\n };\n\n var observeMutations = function observeMutations(f) {\n\n // no observing?\n if (!f.observeMutations) return;\n\n // start observing mutations\n f.observer = new MutationObserver(fit(f, DrawState.DIRTY_CONTENT));\n\n // start observing\n f.observer.observe(f.element, f.observeMutations);\n };\n\n // default mutation observer settings\n var mutationObserverDefaultSetting = {\n subtree: true,\n childList: true,\n characterData: true\n };\n\n // default fitty options\n var defaultOptions = {\n minSize: 16,\n maxSize: 512,\n multiLine: true,\n observeMutations: 'MutationObserver' in w ? mutationObserverDefaultSetting : false\n };\n\n // array of elements in, fitty instances out\n function fittyCreate(elements, options) {\n\n // set options object\n var fittyOptions = _extends({}, defaultOptions, options);\n\n // create fitties\n var publicFitties = elements.map(function (element) {\n\n // create fitty instance\n var f = _extends({}, fittyOptions, {\n\n // internal options for this fitty\n element: element,\n active: true\n });\n\n // initialise this fitty\n init(f);\n\n // expose API\n return {\n element: element,\n fit: fit(f, DrawState.DIRTY),\n unfreeze: subscribe(f),\n freeze: unsubscribe(f),\n unsubscribe: destroy(f)\n };\n });\n\n // call redraw on newly initiated fitties\n requestRedraw();\n\n // expose fitties\n return publicFitties;\n }\n\n // fitty creation function\n function fitty(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n\n // if target is a string\n return typeof target === 'string' ?\n\n // treat it as a querySelector\n fittyCreate(toArray(document.querySelectorAll(target)), options) :\n\n // create single fitty\n fittyCreate([target], options)[0];\n }\n\n // handles viewport changes, redraws all fitties, but only does so after a timeout\n var resizeDebounce = null;\n var onWindowResized = function onWindowResized() {\n w.clearTimeout(resizeDebounce);\n resizeDebounce = w.setTimeout(redrawAll(DrawState.DIRTY_LAYOUT), fitty.observeWindowDelay);\n };\n\n // define observe window property, so when we set it to true or false events are automatically added and removed\n var events = ['resize', 'orientationchange'];\n Object.defineProperty(fitty, 'observeWindow', {\n set: function set(enabled) {\n var method = (enabled ? 'add' : 'remove') + 'EventListener';\n events.forEach(function (e) {\n w[method](e, onWindowResized);\n });\n }\n });\n\n // fitty global properties (by setting observeWindow to true the events above get added)\n fitty.observeWindow = true;\n fitty.observeWindowDelay = 100;\n\n // public fit all method, will force redraw no matter what\n fitty.fitAll = redrawAll(DrawState.DIRTY);\n\n // export our fitty function, we don't want to keep it to our selves\n return fitty;\n}(typeof window === 'undefined' ? null : window);","import { extend, queryAll, closest, getMimeTypeFromFile, encodeRFC3986URI } from '../utils/util.js'\nimport { isMobile } from '../utils/device.js'\n\nimport fitty from 'fitty';\n\n/**\n * Handles loading, unloading and playback of slide\n * content such as images, videos and iframes.\n */\nexport default class SlideContent {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\tthis.startEmbeddedIframe = this.startEmbeddedIframe.bind( this );\n\n\t}\n\n\t/**\n\t * Should the given element be preloaded?\n\t * Decides based on local element attributes and global config.\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tshouldPreload( element ) {\n\n\t\tif( this.Reveal.isReaderMode() ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Prefer an explicit global preload setting\n\t\tlet preload = this.Reveal.getConfig().preloadIframes;\n\n\t\t// If no global setting is available, fall back on the element's\n\t\t// own preload setting\n\t\tif( typeof preload !== 'boolean' ) {\n\t\t\tpreload = element.hasAttribute( 'data-preload' );\n\t\t}\n\n\t\treturn preload;\n\t}\n\n\t/**\n\t * Called when the given slide is within the configured view\n\t * distance. Shows the slide element and loads any content\n\t * that is set to load lazily (data-src).\n\t *\n\t * @param {HTMLElement} slide Slide to show\n\t */\n\tload( slide, options = {} ) {\n\n\t\t// Show the slide element\n\t\tslide.style.display = this.Reveal.getConfig().display;\n\n\t\t// Media elements with data-src attributes\n\t\tqueryAll( slide, 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ).forEach( element => {\n\t\t\tif( element.tagName !== 'IFRAME' || this.shouldPreload( element ) ) {\n\t\t\t\telement.setAttribute( 'src', element.getAttribute( 'data-src' ) );\n\t\t\t\telement.setAttribute( 'data-lazy-loaded', '' );\n\t\t\t\telement.removeAttribute( 'data-src' );\n\t\t\t}\n\t\t} );\n\n\t\t// Media elements with <source> children\n\t\tqueryAll( slide, 'video, audio' ).forEach( media => {\n\t\t\tlet sources = 0;\n\n\t\t\tqueryAll( media, 'source[data-src]' ).forEach( source => {\n\t\t\t\tsource.setAttribute( 'src', source.getAttribute( 'data-src' ) );\n\t\t\t\tsource.removeAttribute( 'data-src' );\n\t\t\t\tsource.setAttribute( 'data-lazy-loaded', '' );\n\t\t\t\tsources += 1;\n\t\t\t} );\n\n\t\t\t// Enable inline video playback in mobile Safari\n\t\t\tif( isMobile && media.tagName === 'VIDEO' ) {\n\t\t\t\tmedia.setAttribute( 'playsinline', '' );\n\t\t\t}\n\n\t\t\t// If we rewrote sources for this video/audio element, we need\n\t\t\t// to manually tell it to load from its new origin\n\t\t\tif( sources > 0 ) {\n\t\t\t\tmedia.load();\n\t\t\t}\n\t\t} );\n\n\n\t\t// Show the corresponding background element\n\t\tlet background = slide.slideBackgroundElement;\n\t\tif( background ) {\n\t\t\tbackground.style.display = 'block';\n\n\t\t\tlet backgroundContent = slide.slideBackgroundContentElement;\n\t\t\tlet backgroundIframe = slide.getAttribute( 'data-background-iframe' );\n\n\t\t\t// If the background contains media, load it\n\t\t\tif( background.hasAttribute( 'data-loaded' ) === false ) {\n\t\t\t\tbackground.setAttribute( 'data-loaded', 'true' );\n\n\t\t\t\tlet backgroundImage = slide.getAttribute( 'data-background-image' ),\n\t\t\t\t\tbackgroundVideo = slide.getAttribute( 'data-background-video' ),\n\t\t\t\t\tbackgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ),\n\t\t\t\t\tbackgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' );\n\n\t\t\t\t// Images\n\t\t\t\tif( backgroundImage ) {\n\t\t\t\t\t// base64\n\t\t\t\t\tif( /^data:/.test( backgroundImage.trim() ) ) {\n\t\t\t\t\t\tbackgroundContent.style.backgroundImage = `url(${backgroundImage.trim()})`;\n\t\t\t\t\t}\n\t\t\t\t\t// URL(s)\n\t\t\t\t\telse {\n\t\t\t\t\t\tbackgroundContent.style.backgroundImage = backgroundImage.split( ',' ).map( background => {\n\t\t\t\t\t\t\t// Decode URL(s) that are already encoded first\n\t\t\t\t\t\t\tlet decoded = decodeURI(background.trim());\n\t\t\t\t\t\t\treturn `url(${encodeRFC3986URI(decoded)})`;\n\t\t\t\t\t\t}).join( ',' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Videos\n\t\t\t\telse if ( backgroundVideo && !this.Reveal.isSpeakerNotes() ) {\n\t\t\t\t\tlet video = document.createElement( 'video' );\n\n\t\t\t\t\tif( backgroundVideoLoop ) {\n\t\t\t\t\t\tvideo.setAttribute( 'loop', '' );\n\t\t\t\t\t}\n\n\t\t\t\t\tif( backgroundVideoMuted ) {\n\t\t\t\t\t\tvideo.muted = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Enable inline playback in mobile Safari\n\t\t\t\t\t//\n\t\t\t\t\t// Mute is required for video to play when using\n\t\t\t\t\t// swipe gestures to navigate since they don't\n\t\t\t\t\t// count as direct user actions :'(\n\t\t\t\t\tif( isMobile ) {\n\t\t\t\t\t\tvideo.muted = true;\n\t\t\t\t\t\tvideo.setAttribute( 'playsinline', '' );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support comma separated lists of video sources\n\t\t\t\t\tbackgroundVideo.split( ',' ).forEach( source => {\n\t\t\t\t\t\tlet type = getMimeTypeFromFile( source );\n\t\t\t\t\t\tif( type ) {\n\t\t\t\t\t\t\tvideo.innerHTML += `<source src=\"${source}\" type=\"${type}\">`;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tvideo.innerHTML += `<source src=\"${source}\">`;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\tbackgroundContent.appendChild( video );\n\t\t\t\t}\n\t\t\t\t// Iframes\n\t\t\t\telse if( backgroundIframe && options.excludeIframes !== true ) {\n\t\t\t\t\tlet iframe = document.createElement( 'iframe' );\n\t\t\t\t\tiframe.setAttribute( 'allowfullscreen', '' );\n\t\t\t\t\tiframe.setAttribute( 'mozallowfullscreen', '' );\n\t\t\t\t\tiframe.setAttribute( 'webkitallowfullscreen', '' );\n\t\t\t\t\tiframe.setAttribute( 'allow', 'autoplay' );\n\n\t\t\t\t\tiframe.setAttribute( 'data-src', backgroundIframe );\n\n\t\t\t\t\tiframe.style.width = '100%';\n\t\t\t\t\tiframe.style.height = '100%';\n\t\t\t\t\tiframe.style.maxHeight = '100%';\n\t\t\t\t\tiframe.style.maxWidth = '100%';\n\n\t\t\t\t\tbackgroundContent.appendChild( iframe );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start loading preloadable iframes\n\t\t\tlet backgroundIframeElement = backgroundContent.querySelector( 'iframe[data-src]' );\n\t\t\tif( backgroundIframeElement ) {\n\n\t\t\t\t// Check if this iframe is eligible to be preloaded\n\t\t\t\tif( this.shouldPreload( background ) && !/autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) {\n\t\t\t\t\tif( backgroundIframeElement.getAttribute( 'src' ) !== backgroundIframe ) {\n\t\t\t\t\t\tbackgroundIframeElement.setAttribute( 'src', backgroundIframe );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.layout( slide );\n\n\t}\n\n\t/**\n\t * Applies JS-dependent layout helpers for the scope.\n\t */\n\tlayout( scopeElement ) {\n\n\t\t// Autosize text with the r-fit-text class based on the\n\t\t// size of its container. This needs to happen after the\n\t\t// slide is visible in order to measure the text.\n\t\tArray.from( scopeElement.querySelectorAll( '.r-fit-text' ) ).forEach( element => {\n\t\t\tfitty( element, {\n\t\t\t\tminSize: 24,\n\t\t\t\tmaxSize: this.Reveal.getConfig().height * 0.8,\n\t\t\t\tobserveMutations: false,\n\t\t\t\tobserveWindow: false\n\t\t\t} );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Unloads and hides the given slide. This is called when the\n\t * slide is moved outside of the configured view distance.\n\t *\n\t * @param {HTMLElement} slide\n\t */\n\tunload( slide ) {\n\n\t\t// Hide the slide element\n\t\tslide.style.display = 'none';\n\n\t\t// Hide the corresponding background element\n\t\tlet background = this.Reveal.getSlideBackground( slide );\n\t\tif( background ) {\n\t\t\tbackground.style.display = 'none';\n\n\t\t\t// Unload any background iframes\n\t\t\tqueryAll( background, 'iframe[src]' ).forEach( element => {\n\t\t\t\telement.removeAttribute( 'src' );\n\t\t\t} );\n\t\t}\n\n\t\t// Reset lazy-loaded media elements with src attributes\n\t\tqueryAll( slide, 'video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]' ).forEach( element => {\n\t\t\telement.setAttribute( 'data-src', element.getAttribute( 'src' ) );\n\t\t\telement.removeAttribute( 'src' );\n\t\t} );\n\n\t\t// Reset lazy-loaded media elements with <source> children\n\t\tqueryAll( slide, 'video[data-lazy-loaded] source[src], audio source[src]' ).forEach( source => {\n\t\t\tsource.setAttribute( 'data-src', source.getAttribute( 'src' ) );\n\t\t\tsource.removeAttribute( 'src' );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Enforces origin-specific format rules for embedded media.\n\t */\n\tformatEmbeddedContent() {\n\n\t\tlet _appendParamToIframeSource = ( sourceAttribute, sourceURL, param ) => {\n\t\t\tqueryAll( this.Reveal.getSlidesElement(), 'iframe['+ sourceAttribute +'*=\"'+ sourceURL +'\"]' ).forEach( el => {\n\t\t\t\tlet src = el.getAttribute( sourceAttribute );\n\t\t\t\tif( src && src.indexOf( param ) === -1 ) {\n\t\t\t\t\tel.setAttribute( sourceAttribute, src + ( !/\\?/.test( src ) ? '?' : '&' ) + param );\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t// YouTube frames must include \"?enablejsapi=1\"\n\t\t_appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' );\n\t\t_appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' );\n\n\t\t// Vimeo frames must include \"?api=1\"\n\t\t_appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' );\n\t\t_appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' );\n\n\t}\n\n\t/**\n\t * Start playback of any embedded content inside of\n\t * the given element.\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tstartEmbeddedContent( element ) {\n\n\t\tif( element && !this.Reveal.isSpeakerNotes() ) {\n\n\t\t\t// Restart GIFs\n\t\t\tqueryAll( element, 'img[src$=\".gif\"]' ).forEach( el => {\n\t\t\t\t// Setting the same unchanged source like this was confirmed\n\t\t\t\t// to work in Chrome, FF & Safari\n\t\t\t\tel.setAttribute( 'src', el.getAttribute( 'src' ) );\n\t\t\t} );\n\n\t\t\t// HTML5 media elements\n\t\t\tqueryAll( element, 'video, audio' ).forEach( el => {\n\t\t\t\tif( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Prefer an explicit global autoplay setting\n\t\t\t\tlet autoplay = this.Reveal.getConfig().autoPlayMedia;\n\n\t\t\t\t// If no global setting is available, fall back on the element's\n\t\t\t\t// own autoplay setting\n\t\t\t\tif( typeof autoplay !== 'boolean' ) {\n\t\t\t\t\tautoplay = el.hasAttribute( 'data-autoplay' ) || !!closest( el, '.slide-background' );\n\t\t\t\t}\n\n\t\t\t\tif( autoplay && typeof el.play === 'function' ) {\n\n\t\t\t\t\t// If the media is ready, start playback\n\t\t\t\t\tif( el.readyState > 1 ) {\n\t\t\t\t\t\tthis.startEmbeddedMedia( { target: el } );\n\t\t\t\t\t}\n\t\t\t\t\t// Mobile devices never fire a loaded event so instead\n\t\t\t\t\t// of waiting, we initiate playback\n\t\t\t\t\telse if( isMobile ) {\n\t\t\t\t\t\tlet promise = el.play();\n\n\t\t\t\t\t\t// If autoplay does not work, ensure that the controls are visible so\n\t\t\t\t\t\t// that the viewer can start the media on their own\n\t\t\t\t\t\tif( promise && typeof promise.catch === 'function' && el.controls === false ) {\n\t\t\t\t\t\t\tpromise.catch( () => {\n\t\t\t\t\t\t\t\tel.controls = true;\n\n\t\t\t\t\t\t\t\t// Once the video does start playing, hide the controls again\n\t\t\t\t\t\t\t\tel.addEventListener( 'play', () => {\n\t\t\t\t\t\t\t\t\tel.controls = false;\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// If the media isn't loaded, wait before playing\n\t\t\t\t\telse {\n\t\t\t\t\t\tel.removeEventListener( 'loadeddata', this.startEmbeddedMedia ); // remove first to avoid dupes\n\t\t\t\t\t\tel.addEventListener( 'loadeddata', this.startEmbeddedMedia );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Normal iframes\n\t\t\tqueryAll( element, 'iframe[src]' ).forEach( el => {\n\t\t\t\tif( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.startEmbeddedIframe( { target: el } );\n\t\t\t} );\n\n\t\t\t// Lazy loading iframes\n\t\t\tqueryAll( element, 'iframe[data-src]' ).forEach( el => {\n\t\t\t\tif( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) {\n\t\t\t\t\tel.removeEventListener( 'load', this.startEmbeddedIframe ); // remove first to avoid dupes\n\t\t\t\t\tel.addEventListener( 'load', this.startEmbeddedIframe );\n\t\t\t\t\tel.setAttribute( 'src', el.getAttribute( 'data-src' ) );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Starts playing an embedded video/audio element after\n\t * it has finished loading.\n\t *\n\t * @param {object} event\n\t */\n\tstartEmbeddedMedia( event ) {\n\n\t\tlet isAttachedToDOM = !!closest( event.target, 'html' ),\n\t\t\tisVisible \t\t= !!closest( event.target, '.present' );\n\n\t\tif( isAttachedToDOM && isVisible ) {\n\t\t\tevent.target.currentTime = 0;\n\t\t\tevent.target.play();\n\t\t}\n\n\t\tevent.target.removeEventListener( 'loadeddata', this.startEmbeddedMedia );\n\n\t}\n\n\t/**\n\t * \"Starts\" the content of an embedded iframe using the\n\t * postMessage API.\n\t *\n\t * @param {object} event\n\t */\n\tstartEmbeddedIframe( event ) {\n\n\t\tlet iframe = event.target;\n\n\t\tif( iframe && iframe.contentWindow ) {\n\n\t\t\tlet isAttachedToDOM = !!closest( event.target, 'html' ),\n\t\t\t\tisVisible \t\t= !!closest( event.target, '.present' );\n\n\t\t\tif( isAttachedToDOM && isVisible ) {\n\n\t\t\t\t// Prefer an explicit global autoplay setting\n\t\t\t\tlet autoplay = this.Reveal.getConfig().autoPlayMedia;\n\n\t\t\t\t// If no global setting is available, fall back on the element's\n\t\t\t\t// own autoplay setting\n\t\t\t\tif( typeof autoplay !== 'boolean' ) {\n\t\t\t\t\tautoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closest( iframe, '.slide-background' );\n\t\t\t\t}\n\n\t\t\t\t// YouTube postMessage API\n\t\t\t\tif( /youtube\\.com\\/embed\\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {\n\t\t\t\t\tiframe.contentWindow.postMessage( '{\"event\":\"command\",\"func\":\"playVideo\",\"args\":\"\"}', '*' );\n\t\t\t\t}\n\t\t\t\t// Vimeo postMessage API\n\t\t\t\telse if( /player\\.vimeo\\.com\\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {\n\t\t\t\t\tiframe.contentWindow.postMessage( '{\"method\":\"play\"}', '*' );\n\t\t\t\t}\n\t\t\t\t// Generic postMessage API\n\t\t\t\telse {\n\t\t\t\t\tiframe.contentWindow.postMessage( 'slide:start', '*' );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Stop playback of any embedded content inside of\n\t * the targeted slide.\n\t *\n\t * @param {HTMLElement} element\n\t */\n\tstopEmbeddedContent( element, options = {} ) {\n\n\t\toptions = extend( {\n\t\t\t// Defaults\n\t\t\tunloadIframes: true\n\t\t}, options );\n\n\t\tif( element && element.parentNode ) {\n\t\t\t// HTML5 media elements\n\t\t\tqueryAll( element, 'video, audio' ).forEach( el => {\n\t\t\t\tif( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {\n\t\t\t\t\tel.setAttribute('data-paused-by-reveal', '');\n\t\t\t\t\tel.pause();\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Generic postMessage API for non-lazy loaded iframes\n\t\t\tqueryAll( element, 'iframe' ).forEach( el => {\n\t\t\t\tif( el.contentWindow ) el.contentWindow.postMessage( 'slide:stop', '*' );\n\t\t\t\tel.removeEventListener( 'load', this.startEmbeddedIframe );\n\t\t\t});\n\n\t\t\t// YouTube postMessage API\n\t\t\tqueryAll( element, 'iframe[src*=\"youtube.com/embed/\"]' ).forEach( el => {\n\t\t\t\tif( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) {\n\t\t\t\t\tel.contentWindow.postMessage( '{\"event\":\"command\",\"func\":\"pauseVideo\",\"args\":\"\"}', '*' );\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Vimeo postMessage API\n\t\t\tqueryAll( element, 'iframe[src*=\"player.vimeo.com/\"]' ).forEach( el => {\n\t\t\t\tif( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) {\n\t\t\t\t\tel.contentWindow.postMessage( '{\"method\":\"pause\"}', '*' );\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif( options.unloadIframes === true ) {\n\t\t\t\t// Unload lazy-loaded iframes\n\t\t\t\tqueryAll( element, 'iframe[data-src]' ).forEach( el => {\n\t\t\t\t\t// Only removing the src doesn't actually unload the frame\n\t\t\t\t\t// in all browsers (Firefox) so we set it to blank first\n\t\t\t\t\tel.setAttribute( 'src', 'about:blank' );\n\t\t\t\t\tel.removeAttribute( 'src' );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t}\n\n}\n","/**\n * Handles the display of reveal.js' optional slide number.\n */\nexport default class SlideNumber {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t}\n\n\trender() {\n\n\t\tthis.element = document.createElement( 'div' );\n\t\tthis.element.className = 'slide-number';\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tlet slideNumberDisplay = 'none';\n\t\tif( config.slideNumber && !this.Reveal.isPrinting() ) {\n\t\t\tif( config.showSlideNumber === 'all' ) {\n\t\t\t\tslideNumberDisplay = 'block';\n\t\t\t}\n\t\t\telse if( config.showSlideNumber === 'speaker' && this.Reveal.isSpeakerNotes() ) {\n\t\t\t\tslideNumberDisplay = 'block';\n\t\t\t}\n\t\t}\n\n\t\tthis.element.style.display = slideNumberDisplay;\n\n\t}\n\n\t/**\n\t * Updates the slide number to match the current slide.\n\t */\n\tupdate() {\n\n\t\t// Update slide number if enabled\n\t\tif( this.Reveal.getConfig().slideNumber && this.element ) {\n\t\t\tthis.element.innerHTML = this.getSlideNumber();\n\t\t}\n\n\t}\n\n\t/**\n\t * Returns the HTML string corresponding to the current slide\n\t * number, including formatting.\n\t */\n\tgetSlideNumber( slide = this.Reveal.getCurrentSlide() ) {\n\n\t\tlet config = this.Reveal.getConfig();\n\t\tlet value;\n\t\tlet format = 'h.v';\n\n\t\tif ( typeof config.slideNumber === 'function' ) {\n\t\t\tvalue = config.slideNumber( slide );\n\t\t} else {\n\t\t\t// Check if a custom number format is available\n\t\t\tif( typeof config.slideNumber === 'string' ) {\n\t\t\t\tformat = config.slideNumber;\n\t\t\t}\n\n\t\t\t// If there are ONLY vertical slides in this deck, always use\n\t\t\t// a flattened slide number\n\t\t\tif( !/c/.test( format ) && this.Reveal.getHorizontalSlides().length === 1 ) {\n\t\t\t\tformat = 'c';\n\t\t\t}\n\n\t\t\t// Offset the current slide number by 1 to make it 1-indexed\n\t\t\tlet horizontalOffset = slide && slide.dataset.visibility === 'uncounted' ? 0 : 1;\n\n\t\t\tvalue = [];\n\t\t\tswitch( format ) {\n\t\t\t\tcase 'c':\n\t\t\t\t\tvalue.push( this.Reveal.getSlidePastCount( slide ) + horizontalOffset );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'c/t':\n\t\t\t\t\tvalue.push( this.Reveal.getSlidePastCount( slide ) + horizontalOffset, '/', this.Reveal.getTotalSlides() );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tlet indices = this.Reveal.getIndices( slide );\n\t\t\t\t\tvalue.push( indices.h + horizontalOffset );\n\t\t\t\t\tlet sep = format === 'h/v' ? '/' : '.';\n\t\t\t\t\tif( this.Reveal.isVerticalSlide( slide ) ) value.push( sep, indices.v + 1 );\n\t\t\t}\n\t\t}\n\n\t\tlet url = '#' + this.Reveal.location.getHash( slide );\n\t\treturn this.formatNumber( value[0], value[1], value[2], url );\n\n\t}\n\n\t/**\n\t * Applies HTML formatting to a slide number before it's\n\t * written to the DOM.\n\t *\n\t * @param {number} a Current slide\n\t * @param {string} delimiter Character to separate slide numbers\n\t * @param {(number|*)} b Total slides\n\t * @param {HTMLElement} [url='#'+locationHash()] The url to link to\n\t * @return {string} HTML string fragment\n\t */\n\tformatNumber( a, delimiter, b, url = '#' + this.Reveal.location.getHash() ) {\n\n\t\tif( typeof b === 'number' && !isNaN( b ) ) {\n\t\t\treturn `<a href=\"${url}\">\n\t\t\t\t\t<span class=\"slide-number-a\">${a}</span>\n\t\t\t\t\t<span class=\"slide-number-delimiter\">${delimiter}</span>\n\t\t\t\t\t<span class=\"slide-number-b\">${b}</span>\n\t\t\t\t\t</a>`;\n\t\t}\n\t\telse {\n\t\t\treturn `<a href=\"${url}\">\n\t\t\t\t\t<span class=\"slide-number-a\">${a}</span>\n\t\t\t\t\t</a>`;\n\t\t}\n\n\t}\n\n\tdestroy() {\n\n\t\tthis.element.remove();\n\n\t}\n\n}","/**\n * Makes it possible to jump to a slide by entering its\n * slide number or id.\n */\nexport default class JumpToSlide {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\tthis.onInput = this.onInput.bind( this );\n\t\tthis.onBlur = this.onBlur.bind( this );\n\t\tthis.onKeyDown = this.onKeyDown.bind( this );\n\n\t}\n\n\trender() {\n\n\t\tthis.element = document.createElement( 'div' );\n\t\tthis.element.className = 'jump-to-slide';\n\n this.jumpInput = document.createElement( 'input' );\n this.jumpInput.type = 'text';\n this.jumpInput.className = 'jump-to-slide-input';\n this.jumpInput.placeholder = 'Jump to slide';\n\t\tthis.jumpInput.addEventListener( 'input', this.onInput );\n\t\tthis.jumpInput.addEventListener( 'keydown', this.onKeyDown );\n\t\tthis.jumpInput.addEventListener( 'blur', this.onBlur );\n\n this.element.appendChild( this.jumpInput );\n\n\t}\n\n\tshow() {\n\n\t\tthis.indicesOnShow = this.Reveal.getIndices();\n\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\n\t\tthis.jumpInput.focus();\n\n\t}\n\n\thide() {\n\n\t\tif( this.isVisible() ) {\n\t\t\tthis.element.remove();\n\t\t\tthis.jumpInput.value = '';\n\n\t\t\tclearTimeout( this.jumpTimeout );\n\t\t\tdelete this.jumpTimeout;\n\t\t}\n\n\t}\n\n\tisVisible() {\n\n\t\treturn !!this.element.parentNode;\n\n\t}\n\n\t/**\n\t * Parses the current input and jumps to the given slide.\n\t */\n\tjump() {\n\n\t\tclearTimeout( this.jumpTimeout );\n\t\tdelete this.jumpTimeout;\n\n\t\tconst query = this.jumpInput.value.trim( '' );\n\t\tlet indices = this.Reveal.location.getIndicesFromHash( query, { oneBasedIndex: true } );\n\n\t\t// If no valid index was found and the input query is a\n\t\t// string, fall back on a simple search\n\t\tif( !indices && /\\S+/i.test( query ) && query.length > 1 ) {\n\t\t\tindices = this.search( query );\n\t\t}\n\n\t\tif( indices && query !== '' ) {\n\t\t\tthis.Reveal.slide( indices.h, indices.v, indices.f );\n\t\t\treturn true;\n\t\t}\n\t\telse {\n\t\t\tthis.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );\n\t\t\treturn false;\n\t\t}\n\n\t}\n\n\tjumpAfter( delay ) {\n\n\t\tclearTimeout( this.jumpTimeout );\n\t\tthis.jumpTimeout = setTimeout( () => this.jump(), delay );\n\n\t}\n\n\t/**\n\t * A lofi search that looks for the given query in all\n\t * of our slides and returns the first match.\n\t */\n\tsearch( query ) {\n\n\t\tconst regex = new RegExp( '\\\\b' + query.trim() + '\\\\b', 'i' );\n\n\t\tconst slide = this.Reveal.getSlides().find( ( slide ) => {\n\t\t\treturn regex.test( slide.innerText );\n\t\t} );\n\n\t\tif( slide ) {\n\t\t\treturn this.Reveal.getIndices( slide );\n\t\t}\n\t\telse {\n\t\t\treturn null;\n\t\t}\n\n\t}\n\n\t/**\n\t * Reverts back to the slide we were on when jump to slide was\n\t * invoked.\n\t */\n\tcancel() {\n\n\t\tthis.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );\n\t\tthis.hide();\n\n\t}\n\n\tconfirm() {\n\n\t\tthis.jump();\n\t\tthis.hide();\n\n\t}\n\n\tdestroy() {\n\n\t\tthis.jumpInput.removeEventListener( 'input', this.onInput );\n\t\tthis.jumpInput.removeEventListener( 'keydown', this.onKeyDown );\n\t\tthis.jumpInput.removeEventListener( 'blur', this.onBlur );\n\n\t\tthis.element.remove();\n\n\t}\n\n\tonKeyDown( event ) {\n\n\t\tif( event.keyCode === 13 ) {\n\t\t\tthis.confirm();\n\t\t}\n\t\telse if( event.keyCode === 27 ) {\n\t\t\tthis.cancel();\n\n\t\t\tevent.stopImmediatePropagation();\n\t\t}\n\n\t}\n\n\tonInput( event ) {\n\n\t\tthis.jumpAfter( 200 );\n\n\t}\n\n\tonBlur() {\n\n\t\tsetTimeout( () => this.hide(), 1 );\n\n\t}\n\n}","/**\n * Converts various color input formats to an {r:0,g:0,b:0} object.\n *\n * @param {string} color The string representation of a color\n * @example\n * colorToRgb('#000');\n * @example\n * colorToRgb('#000000');\n * @example\n * colorToRgb('rgb(0,0,0)');\n * @example\n * colorToRgb('rgba(0,0,0)');\n *\n * @return {{r: number, g: number, b: number, [a]: number}|null}\n */\nexport const colorToRgb = ( color ) => {\n\n\tlet hex3 = color.match( /^#([0-9a-f]{3})$/i );\n\tif( hex3 && hex3[1] ) {\n\t\thex3 = hex3[1];\n\t\treturn {\n\t\t\tr: parseInt( hex3.charAt( 0 ), 16 ) * 0x11,\n\t\t\tg: parseInt( hex3.charAt( 1 ), 16 ) * 0x11,\n\t\t\tb: parseInt( hex3.charAt( 2 ), 16 ) * 0x11\n\t\t};\n\t}\n\n\tlet hex6 = color.match( /^#([0-9a-f]{6})$/i );\n\tif( hex6 && hex6[1] ) {\n\t\thex6 = hex6[1];\n\t\treturn {\n\t\t\tr: parseInt( hex6.slice( 0, 2 ), 16 ),\n\t\t\tg: parseInt( hex6.slice( 2, 4 ), 16 ),\n\t\t\tb: parseInt( hex6.slice( 4, 6 ), 16 )\n\t\t};\n\t}\n\n\tlet rgb = color.match( /^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/i );\n\tif( rgb ) {\n\t\treturn {\n\t\t\tr: parseInt( rgb[1], 10 ),\n\t\t\tg: parseInt( rgb[2], 10 ),\n\t\t\tb: parseInt( rgb[3], 10 )\n\t\t};\n\t}\n\n\tlet rgba = color.match( /^rgba\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\,\\s*([\\d]+|[\\d]*.[\\d]+)\\s*\\)$/i );\n\tif( rgba ) {\n\t\treturn {\n\t\t\tr: parseInt( rgba[1], 10 ),\n\t\t\tg: parseInt( rgba[2], 10 ),\n\t\t\tb: parseInt( rgba[3], 10 ),\n\t\t\ta: parseFloat( rgba[4] )\n\t\t};\n\t}\n\n\treturn null;\n\n}\n\n/**\n * Calculates brightness on a scale of 0-255.\n *\n * @param {string} color See colorToRgb for supported formats.\n * @see {@link colorToRgb}\n */\nexport const colorBrightness = ( color ) => {\n\n\tif( typeof color === 'string' ) color = colorToRgb( color );\n\n\tif( color ) {\n\t\treturn ( color.r * 299 + color.g * 587 + color.b * 114 ) / 1000;\n\t}\n\n\treturn null;\n\n}","import { queryAll } from '../utils/util.js'\nimport { colorToRgb, colorBrightness } from '../utils/color.js'\n\n/**\n * Creates and updates slide backgrounds.\n */\nexport default class Backgrounds {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t}\n\n\trender() {\n\n\t\tthis.element = document.createElement( 'div' );\n\t\tthis.element.className = 'backgrounds';\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\n\n\t}\n\n\t/**\n\t * Creates the slide background elements and appends them\n\t * to the background container. One element is created per\n\t * slide no matter if the given slide has visible background.\n\t */\n\tcreate() {\n\n\t\t// Clear prior backgrounds\n\t\tthis.element.innerHTML = '';\n\t\tthis.element.classList.add( 'no-transition' );\n\n\t\t// Iterate over all horizontal slides\n\t\tthis.Reveal.getHorizontalSlides().forEach( slideh => {\n\n\t\t\tlet backgroundStack = this.createBackground( slideh, this.element );\n\n\t\t\t// Iterate over all vertical slides\n\t\t\tqueryAll( slideh, 'section' ).forEach( slidev => {\n\n\t\t\t\tthis.createBackground( slidev, backgroundStack );\n\n\t\t\t\tbackgroundStack.classList.add( 'stack' );\n\n\t\t\t} );\n\n\t\t} );\n\n\t\t// Add parallax background if specified\n\t\tif( this.Reveal.getConfig().parallaxBackgroundImage ) {\n\n\t\t\tthis.element.style.backgroundImage = 'url(\"' + this.Reveal.getConfig().parallaxBackgroundImage + '\")';\n\t\t\tthis.element.style.backgroundSize = this.Reveal.getConfig().parallaxBackgroundSize;\n\t\t\tthis.element.style.backgroundRepeat = this.Reveal.getConfig().parallaxBackgroundRepeat;\n\t\t\tthis.element.style.backgroundPosition = this.Reveal.getConfig().parallaxBackgroundPosition;\n\n\t\t\t// Make sure the below properties are set on the element - these properties are\n\t\t\t// needed for proper transitions to be set on the element via CSS. To remove\n\t\t\t// annoying background slide-in effect when the presentation starts, apply\n\t\t\t// these properties after short time delay\n\t\t\tsetTimeout( () => {\n\t\t\t\tthis.Reveal.getRevealElement().classList.add( 'has-parallax-background' );\n\t\t\t}, 1 );\n\n\t\t}\n\t\telse {\n\n\t\t\tthis.element.style.backgroundImage = '';\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'has-parallax-background' );\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Creates a background for the given slide.\n\t *\n\t * @param {HTMLElement} slide\n\t * @param {HTMLElement} container The element that the background\n\t * should be appended to\n\t * @return {HTMLElement} New background div\n\t */\n\tcreateBackground( slide, container ) {\n\n\t\t// Main slide background element\n\t\tlet element = document.createElement( 'div' );\n\t\telement.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' );\n\n\t\t// Inner background element that wraps images/videos/iframes\n\t\tlet contentElement = document.createElement( 'div' );\n\t\tcontentElement.className = 'slide-background-content';\n\n\t\telement.appendChild( contentElement );\n\t\tcontainer.appendChild( element );\n\n\t\tslide.slideBackgroundElement = element;\n\t\tslide.slideBackgroundContentElement = contentElement;\n\n\t\t// Syncs the background to reflect all current background settings\n\t\tthis.sync( slide );\n\n\t\treturn element;\n\n\t}\n\n\t/**\n\t * Renders all of the visual properties of a slide background\n\t * based on the various background attributes.\n\t *\n\t * @param {HTMLElement} slide\n\t */\n\tsync( slide ) {\n\n\t\tconst element = slide.slideBackgroundElement,\n\t\t\tcontentElement = slide.slideBackgroundContentElement;\n\n\t\tconst data = {\n\t\t\tbackground: slide.getAttribute( 'data-background' ),\n\t\t\tbackgroundSize: slide.getAttribute( 'data-background-size' ),\n\t\t\tbackgroundImage: slide.getAttribute( 'data-background-image' ),\n\t\t\tbackgroundVideo: slide.getAttribute( 'data-background-video' ),\n\t\t\tbackgroundIframe: slide.getAttribute( 'data-background-iframe' ),\n\t\t\tbackgroundColor: slide.getAttribute( 'data-background-color' ),\n\t\t\tbackgroundGradient: slide.getAttribute( 'data-background-gradient' ),\n\t\t\tbackgroundRepeat: slide.getAttribute( 'data-background-repeat' ),\n\t\t\tbackgroundPosition: slide.getAttribute( 'data-background-position' ),\n\t\t\tbackgroundTransition: slide.getAttribute( 'data-background-transition' ),\n\t\t\tbackgroundOpacity: slide.getAttribute( 'data-background-opacity' ),\n\t\t};\n\n\t\tconst dataPreload = slide.hasAttribute( 'data-preload' );\n\n\t\t// Reset the prior background state in case this is not the\n\t\t// initial sync\n\t\tslide.classList.remove( 'has-dark-background' );\n\t\tslide.classList.remove( 'has-light-background' );\n\n\t\telement.removeAttribute( 'data-loaded' );\n\t\telement.removeAttribute( 'data-background-hash' );\n\t\telement.removeAttribute( 'data-background-size' );\n\t\telement.removeAttribute( 'data-background-transition' );\n\t\telement.style.backgroundColor = '';\n\n\t\tcontentElement.style.backgroundSize = '';\n\t\tcontentElement.style.backgroundRepeat = '';\n\t\tcontentElement.style.backgroundPosition = '';\n\t\tcontentElement.style.backgroundImage = '';\n\t\tcontentElement.style.opacity = '';\n\t\tcontentElement.innerHTML = '';\n\n\t\tif( data.background ) {\n\t\t\t// Auto-wrap image urls in url(...)\n\t\t\tif( /^(http|file|\\/\\/)/gi.test( data.background ) || /\\.(svg|png|jpg|jpeg|gif|bmp|webp)([?#\\s]|$)/gi.test( data.background ) ) {\n\t\t\t\tslide.setAttribute( 'data-background-image', data.background );\n\t\t\t}\n\t\t\telse {\n\t\t\t\telement.style.background = data.background;\n\t\t\t}\n\t\t}\n\n\t\t// Create a hash for this combination of background settings.\n\t\t// This is used to determine when two slide backgrounds are\n\t\t// the same.\n\t\tif( data.background || data.backgroundColor || data.backgroundGradient || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) {\n\t\t\telement.setAttribute( 'data-background-hash', data.background +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundSize +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundImage +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundVideo +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundIframe +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundColor +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundGradient +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundRepeat +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundPosition +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundTransition +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundOpacity );\n\t\t}\n\n\t\t// Additional and optional background properties\n\t\tif( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize );\n\t\tif( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;\n\t\tif( data.backgroundGradient ) element.style.backgroundImage = data.backgroundGradient;\n\t\tif( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );\n\n\t\tif( dataPreload ) element.setAttribute( 'data-preload', '' );\n\n\t\t// Background image options are set on the content wrapper\n\t\tif( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize;\n\t\tif( data.backgroundRepeat ) contentElement.style.backgroundRepeat = data.backgroundRepeat;\n\t\tif( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition;\n\t\tif( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity;\n\n\t\t// If this slide has a background color, we add a class that\n\t\t// signals if it is light or dark. If the slide has no background\n\t\t// color, no class will be added\n\t\tlet contrastColor = data.backgroundColor;\n\n\t\t// If no bg color was found, or it cannot be converted by colorToRgb, check the computed background\n\t\tif( !contrastColor || !colorToRgb( contrastColor ) ) {\n\t\t\tlet computedBackgroundStyle = window.getComputedStyle( element );\n\t\t\tif( computedBackgroundStyle && computedBackgroundStyle.backgroundColor ) {\n\t\t\t\tcontrastColor = computedBackgroundStyle.backgroundColor;\n\t\t\t}\n\t\t}\n\n\t\tif( contrastColor ) {\n\t\t\tconst rgb = colorToRgb( contrastColor );\n\n\t\t\t// Ignore fully transparent backgrounds. Some browsers return\n\t\t\t// rgba(0,0,0,0) when reading the computed background color of\n\t\t\t// an element with no background\n\t\t\tif( rgb && rgb.a !== 0 ) {\n\t\t\t\tif( colorBrightness( contrastColor ) < 128 ) {\n\t\t\t\t\tslide.classList.add( 'has-dark-background' );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tslide.classList.add( 'has-light-background' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates the background elements to reflect the current\n\t * slide.\n\t *\n\t * @param {boolean} includeAll If true, the backgrounds of\n\t * all vertical slides (not just the present) will be updated.\n\t */\n\tupdate( includeAll = false ) {\n\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\n\t\tlet indices = this.Reveal.getIndices();\n\n\t\tlet currentBackground = null;\n\n\t\t// Reverse past/future classes when in RTL mode\n\t\tlet horizontalPast = this.Reveal.getConfig().rtl ? 'future' : 'past',\n\t\t\thorizontalFuture = this.Reveal.getConfig().rtl ? 'past' : 'future';\n\n\t\t// Update the classes of all backgrounds to match the\n\t\t// states of their slides (past/present/future)\n\t\tArray.from( this.element.childNodes ).forEach( ( backgroundh, h ) => {\n\n\t\t\tbackgroundh.classList.remove( 'past', 'present', 'future' );\n\n\t\t\tif( h < indices.h ) {\n\t\t\t\tbackgroundh.classList.add( horizontalPast );\n\t\t\t}\n\t\t\telse if ( h > indices.h ) {\n\t\t\t\tbackgroundh.classList.add( horizontalFuture );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbackgroundh.classList.add( 'present' );\n\n\t\t\t\t// Store a reference to the current background element\n\t\t\t\tcurrentBackground = backgroundh;\n\t\t\t}\n\n\t\t\tif( includeAll || h === indices.h ) {\n\t\t\t\tqueryAll( backgroundh, '.slide-background' ).forEach( ( backgroundv, v ) => {\n\n\t\t\t\t\tbackgroundv.classList.remove( 'past', 'present', 'future' );\n\n\t\t\t\t\tif( v < indices.v ) {\n\t\t\t\t\t\tbackgroundv.classList.add( 'past' );\n\t\t\t\t\t}\n\t\t\t\t\telse if ( v > indices.v ) {\n\t\t\t\t\t\tbackgroundv.classList.add( 'future' );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tbackgroundv.classList.add( 'present' );\n\n\t\t\t\t\t\t// Only if this is the present horizontal and vertical slide\n\t\t\t\t\t\tif( h === indices.h ) currentBackground = backgroundv;\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\t\t\t}\n\n\t\t} );\n\n\t\t// Stop content inside of previous backgrounds\n\t\tif( this.previousBackground ) {\n\n\t\t\tthis.Reveal.slideContent.stopEmbeddedContent( this.previousBackground, { unloadIframes: !this.Reveal.slideContent.shouldPreload( this.previousBackground ) } );\n\n\t\t}\n\n\t\t// Start content in the current background\n\t\tif( currentBackground ) {\n\n\t\t\tthis.Reveal.slideContent.startEmbeddedContent( currentBackground );\n\n\t\t\tlet currentBackgroundContent = currentBackground.querySelector( '.slide-background-content' );\n\t\t\tif( currentBackgroundContent ) {\n\n\t\t\t\tlet backgroundImageURL = currentBackgroundContent.style.backgroundImage || '';\n\n\t\t\t\t// Restart GIFs (doesn't work in Firefox)\n\t\t\t\tif( /\\.gif/i.test( backgroundImageURL ) ) {\n\t\t\t\t\tcurrentBackgroundContent.style.backgroundImage = '';\n\t\t\t\t\twindow.getComputedStyle( currentBackgroundContent ).opacity;\n\t\t\t\t\tcurrentBackgroundContent.style.backgroundImage = backgroundImageURL;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Don't transition between identical backgrounds. This\n\t\t\t// prevents unwanted flicker.\n\t\t\tlet previousBackgroundHash = this.previousBackground ? this.previousBackground.getAttribute( 'data-background-hash' ) : null;\n\t\t\tlet currentBackgroundHash = currentBackground.getAttribute( 'data-background-hash' );\n\t\t\tif( currentBackgroundHash && currentBackgroundHash === previousBackgroundHash && currentBackground !== this.previousBackground ) {\n\t\t\t\tthis.element.classList.add( 'no-transition' );\n\t\t\t}\n\n\t\t\tthis.previousBackground = currentBackground;\n\n\t\t}\n\n\t\t// If there's a background brightness flag for this slide,\n\t\t// bubble it to the .reveal container\n\t\tif( currentSlide ) {\n\t\t\t[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => {\n\t\t\t\tif( currentSlide.classList.contains( classToBubble ) ) {\n\t\t\t\t\tthis.Reveal.getRevealElement().classList.add( classToBubble );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.Reveal.getRevealElement().classList.remove( classToBubble );\n\t\t\t\t}\n\t\t\t}, this );\n\t\t}\n\n\t\t// Allow the first background to apply without transition\n\t\tsetTimeout( () => {\n\t\t\tthis.element.classList.remove( 'no-transition' );\n\t\t}, 1 );\n\n\t}\n\n\t/**\n\t * Updates the position of the parallax background based\n\t * on the current slide index.\n\t */\n\tupdateParallax() {\n\n\t\tlet indices = this.Reveal.getIndices();\n\n\t\tif( this.Reveal.getConfig().parallaxBackgroundImage ) {\n\n\t\t\tlet horizontalSlides = this.Reveal.getHorizontalSlides(),\n\t\t\t\tverticalSlides = this.Reveal.getVerticalSlides();\n\n\t\t\tlet backgroundSize = this.element.style.backgroundSize.split( ' ' ),\n\t\t\t\tbackgroundWidth, backgroundHeight;\n\n\t\t\tif( backgroundSize.length === 1 ) {\n\t\t\t\tbackgroundWidth = backgroundHeight = parseInt( backgroundSize[0], 10 );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbackgroundWidth = parseInt( backgroundSize[0], 10 );\n\t\t\t\tbackgroundHeight = parseInt( backgroundSize[1], 10 );\n\t\t\t}\n\n\t\t\tlet slideWidth = this.element.offsetWidth,\n\t\t\t\thorizontalSlideCount = horizontalSlides.length,\n\t\t\t\thorizontalOffsetMultiplier,\n\t\t\t\thorizontalOffset;\n\n\t\t\tif( typeof this.Reveal.getConfig().parallaxBackgroundHorizontal === 'number' ) {\n\t\t\t\thorizontalOffsetMultiplier = this.Reveal.getConfig().parallaxBackgroundHorizontal;\n\t\t\t}\n\t\t\telse {\n\t\t\t\thorizontalOffsetMultiplier = horizontalSlideCount > 1 ? ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ) : 0;\n\t\t\t}\n\n\t\t\thorizontalOffset = horizontalOffsetMultiplier * indices.h * -1;\n\n\t\t\tlet slideHeight = this.element.offsetHeight,\n\t\t\t\tverticalSlideCount = verticalSlides.length,\n\t\t\t\tverticalOffsetMultiplier,\n\t\t\t\tverticalOffset;\n\n\t\t\tif( typeof this.Reveal.getConfig().parallaxBackgroundVertical === 'number' ) {\n\t\t\t\tverticalOffsetMultiplier = this.Reveal.getConfig().parallaxBackgroundVertical;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tverticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 );\n\t\t\t}\n\n\t\t\tverticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indices.v : 0;\n\n\t\t\tthis.element.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px';\n\n\t\t}\n\n\t}\n\n\tdestroy() {\n\n\t\tthis.element.remove();\n\n\t}\n\n}\n","\nexport const SLIDES_SELECTOR = '.slides section';\nexport const HORIZONTAL_SLIDES_SELECTOR = '.slides>section';\nexport const VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section';\n\n// Methods that may not be invoked via the postMessage API\nexport const POST_MESSAGE_METHOD_BLACKLIST = /registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener|showPreview/;\n\n// Regex for retrieving the fragment style from a class attribute\nexport const FRAGMENT_STYLE_REGEX = /fade-(down|up|right|left|out|in-then-out|in-then-semi-out)|semi-fade-out|current-visible|shrink|grow/;","import { queryAll, extend, createStyleSheet, matches, closest } from '../utils/util.js'\nimport { FRAGMENT_STYLE_REGEX } from '../utils/constants.js'\n\n// Counter used to generate unique IDs for auto-animated elements\nlet autoAnimateCounter = 0;\n\n/**\n * Automatically animates matching elements across\n * slides with the [data-auto-animate] attribute.\n */\nexport default class AutoAnimate {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t}\n\n\t/**\n\t * Runs an auto-animation between the given slides.\n\t *\n\t * @param {HTMLElement} fromSlide\n\t * @param {HTMLElement} toSlide\n\t */\n\trun( fromSlide, toSlide ) {\n\n\t\t// Clean up after prior animations\n\t\tthis.reset();\n\n\t\tlet allSlides = this.Reveal.getSlides();\n\t\tlet toSlideIndex = allSlides.indexOf( toSlide );\n\t\tlet fromSlideIndex = allSlides.indexOf( fromSlide );\n\n\t\t// Ensure that both slides are auto-animate targets with the same data-auto-animate-id value\n\t\t// (including null if absent on both) and that data-auto-animate-restart isn't set on the\n\t\t// physically latter slide (independent of slide direction)\n\t\tif( fromSlide.hasAttribute( 'data-auto-animate' ) && toSlide.hasAttribute( 'data-auto-animate' )\n\t\t\t\t&& fromSlide.getAttribute( 'data-auto-animate-id' ) === toSlide.getAttribute( 'data-auto-animate-id' ) \n\t\t\t\t&& !( toSlideIndex > fromSlideIndex ? toSlide : fromSlide ).hasAttribute( 'data-auto-animate-restart' ) ) {\n\n\t\t\t// Create a new auto-animate sheet\n\t\t\tthis.autoAnimateStyleSheet = this.autoAnimateStyleSheet || createStyleSheet();\n\n\t\t\tlet animationOptions = this.getAutoAnimateOptions( toSlide );\n\n\t\t\t// Set our starting state\n\t\t\tfromSlide.dataset.autoAnimate = 'pending';\n\t\t\ttoSlide.dataset.autoAnimate = 'pending';\n\n\t\t\t// Flag the navigation direction, needed for fragment buildup\n\t\t\tanimationOptions.slideDirection = toSlideIndex > fromSlideIndex ? 'forward' : 'backward';\n\n\t\t\t// If the from-slide is hidden because it has moved outside\n\t\t\t// the view distance, we need to temporarily show it while\n\t\t\t// measuring\n\t\t\tlet fromSlideIsHidden = fromSlide.style.display === 'none';\n\t\t\tif( fromSlideIsHidden ) fromSlide.style.display = this.Reveal.getConfig().display;\n\n\t\t\t// Inject our auto-animate styles for this transition\n\t\t\tlet css = this.getAutoAnimatableElements( fromSlide, toSlide ).map( elements => {\n\t\t\t\treturn this.autoAnimateElements( elements.from, elements.to, elements.options || {}, animationOptions, autoAnimateCounter++ );\n\t\t\t} );\n\n\t\t\tif( fromSlideIsHidden ) fromSlide.style.display = 'none';\n\n\t\t\t// Animate unmatched elements, if enabled\n\t\t\tif( toSlide.dataset.autoAnimateUnmatched !== 'false' && this.Reveal.getConfig().autoAnimateUnmatched === true ) {\n\n\t\t\t\t// Our default timings for unmatched elements\n\t\t\t\tlet defaultUnmatchedDuration = animationOptions.duration * 0.8,\n\t\t\t\t\tdefaultUnmatchedDelay = animationOptions.duration * 0.2;\n\n\t\t\t\tthis.getUnmatchedAutoAnimateElements( toSlide ).forEach( unmatchedElement => {\n\n\t\t\t\t\tlet unmatchedOptions = this.getAutoAnimateOptions( unmatchedElement, animationOptions );\n\t\t\t\t\tlet id = 'unmatched';\n\n\t\t\t\t\t// If there is a duration or delay set specifically for this\n\t\t\t\t\t// element our unmatched elements should adhere to those\n\t\t\t\t\tif( unmatchedOptions.duration !== animationOptions.duration || unmatchedOptions.delay !== animationOptions.delay ) {\n\t\t\t\t\t\tid = 'unmatched-' + autoAnimateCounter++;\n\t\t\t\t\t\tcss.push( `[data-auto-animate=\"running\"] [data-auto-animate-target=\"${id}\"] { transition: opacity ${unmatchedOptions.duration}s ease ${unmatchedOptions.delay}s; }` );\n\t\t\t\t\t}\n\n\t\t\t\t\tunmatchedElement.dataset.autoAnimateTarget = id;\n\n\t\t\t\t}, this );\n\n\t\t\t\t// Our default transition for unmatched elements\n\t\t\t\tcss.push( `[data-auto-animate=\"running\"] [data-auto-animate-target=\"unmatched\"] { transition: opacity ${defaultUnmatchedDuration}s ease ${defaultUnmatchedDelay}s; }` );\n\n\t\t\t}\n\n\t\t\t// Setting the whole chunk of CSS at once is the most\n\t\t\t// efficient way to do this. Using sheet.insertRule\n\t\t\t// is multiple factors slower.\n\t\t\tthis.autoAnimateStyleSheet.innerHTML = css.join( '' );\n\n\t\t\t// Start the animation next cycle\n\t\t\trequestAnimationFrame( () => {\n\t\t\t\tif( this.autoAnimateStyleSheet ) {\n\t\t\t\t\t// This forces our newly injected styles to be applied in Firefox\n\t\t\t\t\tgetComputedStyle( this.autoAnimateStyleSheet ).fontWeight;\n\n\t\t\t\t\ttoSlide.dataset.autoAnimate = 'running';\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tthis.Reveal.dispatchEvent({\n\t\t\t\ttype: 'autoanimate',\n\t\t\t\tdata: {\n\t\t\t\t\tfromSlide,\n\t\t\t\t\ttoSlide,\n\t\t\t\t\tsheet: this.autoAnimateStyleSheet\n\t\t\t\t}\n\t\t\t});\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Rolls back all changes that we've made to the DOM so\n\t * that as part of animating.\n\t */\n\treset() {\n\n\t\t// Reset slides\n\t\tqueryAll( this.Reveal.getRevealElement(), '[data-auto-animate]:not([data-auto-animate=\"\"])' ).forEach( element => {\n\t\t\telement.dataset.autoAnimate = '';\n\t\t} );\n\n\t\t// Reset elements\n\t\tqueryAll( this.Reveal.getRevealElement(), '[data-auto-animate-target]' ).forEach( element => {\n\t\t\tdelete element.dataset.autoAnimateTarget;\n\t\t} );\n\n\t\t// Remove the animation sheet\n\t\tif( this.autoAnimateStyleSheet && this.autoAnimateStyleSheet.parentNode ) {\n\t\t\tthis.autoAnimateStyleSheet.parentNode.removeChild( this.autoAnimateStyleSheet );\n\t\t\tthis.autoAnimateStyleSheet = null;\n\t\t}\n\n\t}\n\n\t/**\n\t * Creates a FLIP animation where the `to` element starts out\n\t * in the `from` element position and animates to its original\n\t * state.\n\t *\n\t * @param {HTMLElement} from\n\t * @param {HTMLElement} to\n\t * @param {Object} elementOptions Options for this element pair\n\t * @param {Object} animationOptions Options set at the slide level\n\t * @param {String} id Unique ID that we can use to identify this\n\t * auto-animate element in the DOM\n\t */\n\tautoAnimateElements( from, to, elementOptions, animationOptions, id ) {\n\n\t\t// 'from' elements are given a data-auto-animate-target with no value,\n\t\t// 'to' elements are are given a data-auto-animate-target with an ID\n\t\tfrom.dataset.autoAnimateTarget = '';\n\t\tto.dataset.autoAnimateTarget = id;\n\n\t\t// Each element may override any of the auto-animate options\n\t\t// like transition easing, duration and delay via data-attributes\n\t\tlet options = this.getAutoAnimateOptions( to, animationOptions );\n\n\t\t// If we're using a custom element matcher the element options\n\t\t// may contain additional transition overrides\n\t\tif( typeof elementOptions.delay !== 'undefined' ) options.delay = elementOptions.delay;\n\t\tif( typeof elementOptions.duration !== 'undefined' ) options.duration = elementOptions.duration;\n\t\tif( typeof elementOptions.easing !== 'undefined' ) options.easing = elementOptions.easing;\n\n\t\tlet fromProps = this.getAutoAnimatableProperties( 'from', from, elementOptions ),\n\t\t\ttoProps = this.getAutoAnimatableProperties( 'to', to, elementOptions );\n\n\t\t// Maintain fragment visibility for matching elements when\n\t\t// we're navigating forwards, this way the viewer won't need\n\t\t// to step through the same fragments twice\n\t\tif( to.classList.contains( 'fragment' ) ) {\n\n\t\t\t// Don't auto-animate the opacity of fragments to avoid\n\t\t\t// conflicts with fragment animations\n\t\t\tdelete toProps.styles['opacity'];\n\n\t\t\tif( from.classList.contains( 'fragment' ) ) {\n\n\t\t\t\tlet fromFragmentStyle = ( from.className.match( FRAGMENT_STYLE_REGEX ) || [''] )[0];\n\t\t\t\tlet toFragmentStyle = ( to.className.match( FRAGMENT_STYLE_REGEX ) || [''] )[0];\n\n\t\t\t\t// Only skip the fragment if the fragment animation style\n\t\t\t\t// remains unchanged\n\t\t\t\tif( fromFragmentStyle === toFragmentStyle && animationOptions.slideDirection === 'forward' ) {\n\t\t\t\t\tto.classList.add( 'visible', 'disabled' );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// If translation and/or scaling are enabled, css transform\n\t\t// the 'to' element so that it matches the position and size\n\t\t// of the 'from' element\n\t\tif( elementOptions.translate !== false || elementOptions.scale !== false ) {\n\n\t\t\tlet presentationScale = this.Reveal.getScale();\n\n\t\t\tlet delta = {\n\t\t\t\tx: ( fromProps.x - toProps.x ) / presentationScale,\n\t\t\t\ty: ( fromProps.y - toProps.y ) / presentationScale,\n\t\t\t\tscaleX: fromProps.width / toProps.width,\n\t\t\t\tscaleY: fromProps.height / toProps.height\n\t\t\t};\n\n\t\t\t// Limit decimal points to avoid 0.0001px blur and stutter\n\t\t\tdelta.x = Math.round( delta.x * 1000 ) / 1000;\n\t\t\tdelta.y = Math.round( delta.y * 1000 ) / 1000;\n\t\t\tdelta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000;\n\t\t\tdelta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000;\n\n\t\t\tlet translate = elementOptions.translate !== false && ( delta.x !== 0 || delta.y !== 0 ),\n\t\t\t\tscale = elementOptions.scale !== false && ( delta.scaleX !== 0 || delta.scaleY !== 0 );\n\n\t\t\t// No need to transform if nothing's changed\n\t\t\tif( translate || scale ) {\n\n\t\t\t\tlet transform = [];\n\n\t\t\t\tif( translate ) transform.push( `translate(${delta.x}px, ${delta.y}px)` );\n\t\t\t\tif( scale ) transform.push( `scale(${delta.scaleX}, ${delta.scaleY})` );\n\n\t\t\t\tfromProps.styles['transform'] = transform.join( ' ' );\n\t\t\t\tfromProps.styles['transform-origin'] = 'top left';\n\n\t\t\t\ttoProps.styles['transform'] = 'none';\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Delete all unchanged 'to' styles\n\t\tfor( let propertyName in toProps.styles ) {\n\t\t\tconst toValue = toProps.styles[propertyName];\n\t\t\tconst fromValue = fromProps.styles[propertyName];\n\n\t\t\tif( toValue === fromValue ) {\n\t\t\t\tdelete toProps.styles[propertyName];\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// If these property values were set via a custom matcher providing\n\t\t\t\t// an explicit 'from' and/or 'to' value, we always inject those values.\n\t\t\t\tif( toValue.explicitValue === true ) {\n\t\t\t\t\ttoProps.styles[propertyName] = toValue.value;\n\t\t\t\t}\n\n\t\t\t\tif( fromValue.explicitValue === true ) {\n\t\t\t\t\tfromProps.styles[propertyName] = fromValue.value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet css = '';\n\n\t\tlet toStyleProperties = Object.keys( toProps.styles );\n\n\t\t// Only create animate this element IF at least one style\n\t\t// property has changed\n\t\tif( toStyleProperties.length > 0 ) {\n\n\t\t\t// Instantly move to the 'from' state\n\t\t\tfromProps.styles['transition'] = 'none';\n\n\t\t\t// Animate towards the 'to' state\n\t\t\ttoProps.styles['transition'] = `all ${options.duration}s ${options.easing} ${options.delay}s`;\n\t\t\ttoProps.styles['transition-property'] = toStyleProperties.join( ', ' );\n\t\t\ttoProps.styles['will-change'] = toStyleProperties.join( ', ' );\n\n\t\t\t// Build up our custom CSS. We need to override inline styles\n\t\t\t// so we need to make our styles vErY IMPORTANT!1!!\n\t\t\tlet fromCSS = Object.keys( fromProps.styles ).map( propertyName => {\n\t\t\t\treturn propertyName + ': ' + fromProps.styles[propertyName] + ' !important;';\n\t\t\t} ).join( '' );\n\n\t\t\tlet toCSS = Object.keys( toProps.styles ).map( propertyName => {\n\t\t\t\treturn propertyName + ': ' + toProps.styles[propertyName] + ' !important;';\n\t\t\t} ).join( '' );\n\n\t\t\tcss = \t'[data-auto-animate-target=\"'+ id +'\"] {'+ fromCSS +'}' +\n\t\t\t\t\t'[data-auto-animate=\"running\"] [data-auto-animate-target=\"'+ id +'\"] {'+ toCSS +'}';\n\n\t\t}\n\n\t\treturn css;\n\n\t}\n\n\t/**\n\t * Returns the auto-animate options for the given element.\n\t *\n\t * @param {HTMLElement} element Element to pick up options\n\t * from, either a slide or an animation target\n\t * @param {Object} [inheritedOptions] Optional set of existing\n\t * options\n\t */\n\tgetAutoAnimateOptions( element, inheritedOptions ) {\n\n\t\tlet options = {\n\t\t\teasing: this.Reveal.getConfig().autoAnimateEasing,\n\t\t\tduration: this.Reveal.getConfig().autoAnimateDuration,\n\t\t\tdelay: 0\n\t\t};\n\n\t\toptions = extend( options, inheritedOptions );\n\n\t\t// Inherit options from parent elements\n\t\tif( element.parentNode ) {\n\t\t\tlet autoAnimatedParent = closest( element.parentNode, '[data-auto-animate-target]' );\n\t\t\tif( autoAnimatedParent ) {\n\t\t\t\toptions = this.getAutoAnimateOptions( autoAnimatedParent, options );\n\t\t\t}\n\t\t}\n\n\t\tif( element.dataset.autoAnimateEasing ) {\n\t\t\toptions.easing = element.dataset.autoAnimateEasing;\n\t\t}\n\n\t\tif( element.dataset.autoAnimateDuration ) {\n\t\t\toptions.duration = parseFloat( element.dataset.autoAnimateDuration );\n\t\t}\n\n\t\tif( element.dataset.autoAnimateDelay ) {\n\t\t\toptions.delay = parseFloat( element.dataset.autoAnimateDelay );\n\t\t}\n\n\t\treturn options;\n\n\t}\n\n\t/**\n\t * Returns an object containing all of the properties\n\t * that can be auto-animated for the given element and\n\t * their current computed values.\n\t *\n\t * @param {String} direction 'from' or 'to'\n\t */\n\tgetAutoAnimatableProperties( direction, element, elementOptions ) {\n\n\t\tlet config = this.Reveal.getConfig();\n\n\t\tlet properties = { styles: [] };\n\n\t\t// Position and size\n\t\tif( elementOptions.translate !== false || elementOptions.scale !== false ) {\n\t\t\tlet bounds;\n\n\t\t\t// Custom auto-animate may optionally return a custom tailored\n\t\t\t// measurement function\n\t\t\tif( typeof elementOptions.measure === 'function' ) {\n\t\t\t\tbounds = elementOptions.measure( element );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif( config.center ) {\n\t\t\t\t\t// More precise, but breaks when used in combination\n\t\t\t\t\t// with zoom for scaling the deck ¯\\_(ツ)_/¯\n\t\t\t\t\tbounds = element.getBoundingClientRect();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tlet scale = this.Reveal.getScale();\n\t\t\t\t\tbounds = {\n\t\t\t\t\t\tx: element.offsetLeft * scale,\n\t\t\t\t\t\ty: element.offsetTop * scale,\n\t\t\t\t\t\twidth: element.offsetWidth * scale,\n\t\t\t\t\t\theight: element.offsetHeight * scale\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tproperties.x = bounds.x;\n\t\t\tproperties.y = bounds.y;\n\t\t\tproperties.width = bounds.width;\n\t\t\tproperties.height = bounds.height;\n\t\t}\n\n\t\tconst computedStyles = getComputedStyle( element );\n\n\t\t// CSS styles\n\t\t( elementOptions.styles || config.autoAnimateStyles ).forEach( style => {\n\t\t\tlet value;\n\n\t\t\t// `style` is either the property name directly, or an object\n\t\t\t// definition of a style property\n\t\t\tif( typeof style === 'string' ) style = { property: style };\n\n\t\t\tif( typeof style.from !== 'undefined' && direction === 'from' ) {\n\t\t\t\tvalue = { value: style.from, explicitValue: true };\n\t\t\t}\n\t\t\telse if( typeof style.to !== 'undefined' && direction === 'to' ) {\n\t\t\t\tvalue = { value: style.to, explicitValue: true };\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Use a unitless value for line-height so that it inherits properly\n\t\t\t\tif( style.property === 'line-height' ) {\n\t\t\t\t\tvalue = parseFloat( computedStyles['line-height'] ) / parseFloat( computedStyles['font-size'] );\n\t\t\t\t}\n\n\t\t\t\tif( isNaN(value) ) {\n\t\t\t\t\tvalue = computedStyles[style.property];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif( value !== '' ) {\n\t\t\t\tproperties.styles[style.property] = value;\n\t\t\t}\n\t\t} );\n\n\t\treturn properties;\n\n\t}\n\n\t/**\n\t * Get a list of all element pairs that we can animate\n\t * between the given slides.\n\t *\n\t * @param {HTMLElement} fromSlide\n\t * @param {HTMLElement} toSlide\n\t *\n\t * @return {Array} Each value is an array where [0] is\n\t * the element we're animating from and [1] is the\n\t * element we're animating to\n\t */\n\tgetAutoAnimatableElements( fromSlide, toSlide ) {\n\n\t\tlet matcher = typeof this.Reveal.getConfig().autoAnimateMatcher === 'function' ? this.Reveal.getConfig().autoAnimateMatcher : this.getAutoAnimatePairs;\n\n\t\tlet pairs = matcher.call( this, fromSlide, toSlide );\n\n\t\tlet reserved = [];\n\n\t\t// Remove duplicate pairs\n\t\treturn pairs.filter( ( pair, index ) => {\n\t\t\tif( reserved.indexOf( pair.to ) === -1 ) {\n\t\t\t\treserved.push( pair.to );\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} );\n\n\t}\n\n\t/**\n\t * Identifies matching elements between slides.\n\t *\n\t * You can specify a custom matcher function by using\n\t * the `autoAnimateMatcher` config option.\n\t */\n\tgetAutoAnimatePairs( fromSlide, toSlide ) {\n\n\t\tlet pairs = [];\n\n\t\tconst codeNodes = 'pre';\n\t\tconst textNodes = 'h1, h2, h3, h4, h5, h6, p, li';\n\t\tconst mediaNodes = 'img, video, iframe';\n\n\t\t// Explicit matches via data-id\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, '[data-id]', node => {\n\t\t\treturn node.nodeName + ':::' + node.getAttribute( 'data-id' );\n\t\t} );\n\n\t\t// Text\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, textNodes, node => {\n\t\t\treturn node.nodeName + ':::' + node.innerText;\n\t\t} );\n\n\t\t// Media\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, mediaNodes, node => {\n\t\t\treturn node.nodeName + ':::' + ( node.getAttribute( 'src' ) || node.getAttribute( 'data-src' ) );\n\t\t} );\n\n\t\t// Code\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, codeNodes, node => {\n\t\t\treturn node.nodeName + ':::' + node.innerText;\n\t\t} );\n\n\t\tpairs.forEach( pair => {\n\t\t\t// Disable scale transformations on text nodes, we transition\n\t\t\t// each individual text property instead\n\t\t\tif( matches( pair.from, textNodes ) ) {\n\t\t\t\tpair.options = { scale: false };\n\t\t\t}\n\t\t\t// Animate individual lines of code\n\t\t\telse if( matches( pair.from, codeNodes ) ) {\n\n\t\t\t\t// Transition the code block's width and height instead of scaling\n\t\t\t\t// to prevent its content from being squished\n\t\t\t\tpair.options = { scale: false, styles: [ 'width', 'height' ] };\n\n\t\t\t\t// Lines of code\n\t\t\t\tthis.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-code', node => {\n\t\t\t\t\treturn node.textContent;\n\t\t\t\t}, {\n\t\t\t\t\tscale: false,\n\t\t\t\t\tstyles: [],\n\t\t\t\t\tmeasure: this.getLocalBoundingBox.bind( this )\n\t\t\t\t} );\n\n\t\t\t\t// Line numbers\n\t\t\t\tthis.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-numbers[data-line-number]', node => {\n\t\t\t\t\treturn node.getAttribute( 'data-line-number' );\n\t\t\t\t}, {\n\t\t\t\t\tscale: false,\n\t\t\t\t\tstyles: [ 'width' ],\n\t\t\t\t\tmeasure: this.getLocalBoundingBox.bind( this )\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t}, this );\n\n\t\treturn pairs;\n\n\t}\n\n\t/**\n\t * Helper method which returns a bounding box based on\n\t * the given elements offset coordinates.\n\t *\n\t * @param {HTMLElement} element\n\t * @return {Object} x, y, width, height\n\t */\n\tgetLocalBoundingBox( element ) {\n\n\t\tconst presentationScale = this.Reveal.getScale();\n\n\t\treturn {\n\t\t\tx: Math.round( ( element.offsetLeft * presentationScale ) * 100 ) / 100,\n\t\t\ty: Math.round( ( element.offsetTop * presentationScale ) * 100 ) / 100,\n\t\t\twidth: Math.round( ( element.offsetWidth * presentationScale ) * 100 ) / 100,\n\t\t\theight: Math.round( ( element.offsetHeight * presentationScale ) * 100 ) / 100\n\t\t};\n\n\t}\n\n\t/**\n\t * Finds matching elements between two slides.\n\t *\n\t * @param {Array} pairs \tList of pairs to push matches to\n\t * @param {HTMLElement} fromScope Scope within the from element exists\n\t * @param {HTMLElement} toScope Scope within the to element exists\n\t * @param {String} selector CSS selector of the element to match\n\t * @param {Function} serializer A function that accepts an element and returns\n\t * a stringified ID based on its contents\n\t * @param {Object} animationOptions Optional config options for this pair\n\t */\n\tfindAutoAnimateMatches( pairs, fromScope, toScope, selector, serializer, animationOptions ) {\n\n\t\tlet fromMatches = {};\n\t\tlet toMatches = {};\n\n\t\t[].slice.call( fromScope.querySelectorAll( selector ) ).forEach( ( element, i ) => {\n\t\t\tconst key = serializer( element );\n\t\t\tif( typeof key === 'string' && key.length ) {\n\t\t\t\tfromMatches[key] = fromMatches[key] || [];\n\t\t\t\tfromMatches[key].push( element );\n\t\t\t}\n\t\t} );\n\n\t\t[].slice.call( toScope.querySelectorAll( selector ) ).forEach( ( element, i ) => {\n\t\t\tconst key = serializer( element );\n\t\t\ttoMatches[key] = toMatches[key] || [];\n\t\t\ttoMatches[key].push( element );\n\n\t\t\tlet fromElement;\n\n\t\t\t// Retrieve the 'from' element\n\t\t\tif( fromMatches[key] ) {\n\t\t\t\tconst primaryIndex = toMatches[key].length - 1;\n\t\t\t\tconst secondaryIndex = fromMatches[key].length - 1;\n\n\t\t\t\t// If there are multiple identical from elements, retrieve\n\t\t\t\t// the one at the same index as our to-element.\n\t\t\t\tif( fromMatches[key][ primaryIndex ] ) {\n\t\t\t\t\tfromElement = fromMatches[key][ primaryIndex ];\n\t\t\t\t\tfromMatches[key][ primaryIndex ] = null;\n\t\t\t\t}\n\t\t\t\t// If there are no matching from-elements at the same index,\n\t\t\t\t// use the last one.\n\t\t\t\telse if( fromMatches[key][ secondaryIndex ] ) {\n\t\t\t\t\tfromElement = fromMatches[key][ secondaryIndex ];\n\t\t\t\t\tfromMatches[key][ secondaryIndex ] = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we've got a matching pair, push it to the list of pairs\n\t\t\tif( fromElement ) {\n\t\t\t\tpairs.push({\n\t\t\t\t\tfrom: fromElement,\n\t\t\t\t\tto: element,\n\t\t\t\t\toptions: animationOptions\n\t\t\t\t});\n\t\t\t}\n\t\t} );\n\n\t}\n\n\t/**\n\t * Returns a all elements within the given scope that should\n\t * be considered unmatched in an auto-animate transition. If\n\t * fading of unmatched elements is turned on, these elements\n\t * will fade when going between auto-animate slides.\n\t *\n\t * Note that parents of auto-animate targets are NOT considered\n\t * unmatched since fading them would break the auto-animation.\n\t *\n\t * @param {HTMLElement} rootElement\n\t * @return {Array}\n\t */\n\tgetUnmatchedAutoAnimateElements( rootElement ) {\n\n\t\treturn [].slice.call( rootElement.children ).reduce( ( result, element ) => {\n\n\t\t\tconst containsAnimatedElements = element.querySelector( '[data-auto-animate-target]' );\n\n\t\t\t// The element is unmatched if\n\t\t\t// - It is not an auto-animate target\n\t\t\t// - It does not contain any auto-animate targets\n\t\t\tif( !element.hasAttribute( 'data-auto-animate-target' ) && !containsAnimatedElements ) {\n\t\t\t\tresult.push( element );\n\t\t\t}\n\n\t\t\tif( element.querySelector( '[data-auto-animate-target]' ) ) {\n\t\t\t\tresult = result.concat( this.getUnmatchedAutoAnimateElements( element ) );\n\t\t\t}\n\n\t\t\treturn result;\n\n\t\t}, [] );\n\n\t}\n\n}\n","import { extend, queryAll } from '../utils/util.js'\n\n/**\n * Handles sorting and navigation of slide fragments.\n * Fragments are elements within a slide that are\n * revealed/animated incrementally.\n */\nexport default class Fragments {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tif( config.fragments === false ) {\n\t\t\tthis.disable();\n\t\t}\n\t\telse if( oldConfig.fragments === false ) {\n\t\t\tthis.enable();\n\t\t}\n\n\t}\n\n\t/**\n\t * If fragments are disabled in the deck, they should all be\n\t * visible rather than stepped through.\n\t */\n\tdisable() {\n\n\t\tqueryAll( this.Reveal.getSlidesElement(), '.fragment' ).forEach( element => {\n\t\t\telement.classList.add( 'visible' );\n\t\t\telement.classList.remove( 'current-fragment' );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Reverse of #disable(). Only called if fragments have\n\t * previously been disabled.\n\t */\n\tenable() {\n\n\t\tqueryAll( this.Reveal.getSlidesElement(), '.fragment' ).forEach( element => {\n\t\t\telement.classList.remove( 'visible' );\n\t\t\telement.classList.remove( 'current-fragment' );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Returns an object describing the available fragment\n\t * directions.\n\t *\n\t * @return {{prev: boolean, next: boolean}}\n\t */\n\tavailableRoutes() {\n\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\n\t\tif( currentSlide && this.Reveal.getConfig().fragments ) {\n\t\t\tlet fragments = currentSlide.querySelectorAll( '.fragment:not(.disabled)' );\n\t\t\tlet hiddenFragments = currentSlide.querySelectorAll( '.fragment:not(.disabled):not(.visible)' );\n\n\t\t\treturn {\n\t\t\t\tprev: fragments.length - hiddenFragments.length > 0,\n\t\t\t\tnext: !!hiddenFragments.length\n\t\t\t};\n\t\t}\n\t\telse {\n\t\t\treturn { prev: false, next: false };\n\t\t}\n\n\t}\n\n\t/**\n\t * Return a sorted fragments list, ordered by an increasing\n\t * \"data-fragment-index\" attribute.\n\t *\n\t * Fragments will be revealed in the order that they are returned by\n\t * this function, so you can use the index attributes to control the\n\t * order of fragment appearance.\n\t *\n\t * To maintain a sensible default fragment order, fragments are presumed\n\t * to be passed in document order. This function adds a \"fragment-index\"\n\t * attribute to each node if such an attribute is not already present,\n\t * and sets that attribute to an integer value which is the position of\n\t * the fragment within the fragments list.\n\t *\n\t * @param {object[]|*} fragments\n\t * @param {boolean} grouped If true the returned array will contain\n\t * nested arrays for all fragments with the same index\n\t * @return {object[]} sorted Sorted array of fragments\n\t */\n\tsort( fragments, grouped = false ) {\n\n\t\tfragments = Array.from( fragments );\n\n\t\tlet ordered = [],\n\t\t\tunordered = [],\n\t\t\tsorted = [];\n\n\t\t// Group ordered and unordered elements\n\t\tfragments.forEach( fragment => {\n\t\t\tif( fragment.hasAttribute( 'data-fragment-index' ) ) {\n\t\t\t\tlet index = parseInt( fragment.getAttribute( 'data-fragment-index' ), 10 );\n\n\t\t\t\tif( !ordered[index] ) {\n\t\t\t\t\tordered[index] = [];\n\t\t\t\t}\n\n\t\t\t\tordered[index].push( fragment );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tunordered.push( [ fragment ] );\n\t\t\t}\n\t\t} );\n\n\t\t// Append fragments without explicit indices in their\n\t\t// DOM order\n\t\tordered = ordered.concat( unordered );\n\n\t\t// Manually count the index up per group to ensure there\n\t\t// are no gaps\n\t\tlet index = 0;\n\n\t\t// Push all fragments in their sorted order to an array,\n\t\t// this flattens the groups\n\t\tordered.forEach( group => {\n\t\t\tgroup.forEach( fragment => {\n\t\t\t\tsorted.push( fragment );\n\t\t\t\tfragment.setAttribute( 'data-fragment-index', index );\n\t\t\t} );\n\n\t\t\tindex ++;\n\t\t} );\n\n\t\treturn grouped === true ? ordered : sorted;\n\n\t}\n\n\t/**\n\t * Sorts and formats all of fragments in the\n\t * presentation.\n\t */\n\tsortAll() {\n\n\t\tthis.Reveal.getHorizontalSlides().forEach( horizontalSlide => {\n\n\t\t\tlet verticalSlides = queryAll( horizontalSlide, 'section' );\n\t\t\tverticalSlides.forEach( ( verticalSlide, y ) => {\n\n\t\t\t\tthis.sort( verticalSlide.querySelectorAll( '.fragment' ) );\n\n\t\t\t}, this );\n\n\t\t\tif( verticalSlides.length === 0 ) this.sort( horizontalSlide.querySelectorAll( '.fragment' ) );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Refreshes the fragments on the current slide so that they\n\t * have the appropriate classes (.visible + .current-fragment).\n\t *\n\t * @param {number} [index] The index of the current fragment\n\t * @param {array} [fragments] Array containing all fragments\n\t * in the current slide\n\t *\n\t * @return {{shown: array, hidden: array}}\n\t */\n\tupdate( index, fragments, slide = this.Reveal.getCurrentSlide() ) {\n\n\t\tlet changedFragments = {\n\t\t\tshown: [],\n\t\t\thidden: []\n\t\t};\n\n\t\tif( slide && this.Reveal.getConfig().fragments ) {\n\n\t\t\tfragments = fragments || this.sort( slide.querySelectorAll( '.fragment' ) );\n\n\t\t\tif( fragments.length ) {\n\n\t\t\t\tlet maxIndex = 0;\n\n\t\t\t\tif( typeof index !== 'number' ) {\n\t\t\t\t\tlet currentFragment = this.sort( slide.querySelectorAll( '.fragment.visible' ) ).pop();\n\t\t\t\t\tif( currentFragment ) {\n\t\t\t\t\t\tindex = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tArray.from( fragments ).forEach( ( el, i ) => {\n\n\t\t\t\t\tif( el.hasAttribute( 'data-fragment-index' ) ) {\n\t\t\t\t\t\ti = parseInt( el.getAttribute( 'data-fragment-index' ), 10 );\n\t\t\t\t\t}\n\n\t\t\t\t\tmaxIndex = Math.max( maxIndex, i );\n\n\t\t\t\t\t// Visible fragments\n\t\t\t\t\tif( i <= index ) {\n\t\t\t\t\t\tlet wasVisible = el.classList.contains( 'visible' )\n\t\t\t\t\t\tel.classList.add( 'visible' );\n\t\t\t\t\t\tel.classList.remove( 'current-fragment' );\n\n\t\t\t\t\t\tif( i === index ) {\n\t\t\t\t\t\t\t// Announce the fragments one by one to the Screen Reader\n\t\t\t\t\t\t\tthis.Reveal.announceStatus( this.Reveal.getStatusText( el ) );\n\n\t\t\t\t\t\t\tel.classList.add( 'current-fragment' );\n\t\t\t\t\t\t\tthis.Reveal.slideContent.startEmbeddedContent( el );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif( !wasVisible ) {\n\t\t\t\t\t\t\tchangedFragments.shown.push( el )\n\t\t\t\t\t\t\tthis.Reveal.dispatchEvent({\n\t\t\t\t\t\t\t\ttarget: el,\n\t\t\t\t\t\t\t\ttype: 'visible',\n\t\t\t\t\t\t\t\tbubbles: false\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Hidden fragments\n\t\t\t\t\telse {\n\t\t\t\t\t\tlet wasVisible = el.classList.contains( 'visible' )\n\t\t\t\t\t\tel.classList.remove( 'visible' );\n\t\t\t\t\t\tel.classList.remove( 'current-fragment' );\n\n\t\t\t\t\t\tif( wasVisible ) {\n\t\t\t\t\t\t\tthis.Reveal.slideContent.stopEmbeddedContent( el );\n\t\t\t\t\t\t\tchangedFragments.hidden.push( el );\n\t\t\t\t\t\t\tthis.Reveal.dispatchEvent({\n\t\t\t\t\t\t\t\ttarget: el,\n\t\t\t\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\t\t\t\tbubbles: false\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\t// Write the current fragment index to the slide <section>.\n\t\t\t\t// This can be used by end users to apply styles based on\n\t\t\t\t// the current fragment index.\n\t\t\t\tindex = typeof index === 'number' ? index : -1;\n\t\t\t\tindex = Math.max( Math.min( index, maxIndex ), -1 );\n\t\t\t\tslide.setAttribute( 'data-fragment', index );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn changedFragments;\n\n\t}\n\n\t/**\n\t * Formats the fragments on the given slide so that they have\n\t * valid indices. Call this if fragments are changed in the DOM\n\t * after reveal.js has already initialized.\n\t *\n\t * @param {HTMLElement} slide\n\t * @return {Array} a list of the HTML fragments that were synced\n\t */\n\tsync( slide = this.Reveal.getCurrentSlide() ) {\n\n\t\treturn this.sort( slide.querySelectorAll( '.fragment' ) );\n\n\t}\n\n\t/**\n\t * Navigate to the specified slide fragment.\n\t *\n\t * @param {?number} index The index of the fragment that\n\t * should be shown, -1 means all are invisible\n\t * @param {number} offset Integer offset to apply to the\n\t * fragment index\n\t *\n\t * @return {boolean} true if a change was made in any\n\t * fragments visibility as part of this call\n\t */\n\tgoto( index, offset = 0 ) {\n\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\n\t\tif( currentSlide && this.Reveal.getConfig().fragments ) {\n\n\t\t\tlet fragments = this.sort( currentSlide.querySelectorAll( '.fragment:not(.disabled)' ) );\n\t\t\tif( fragments.length ) {\n\n\t\t\t\t// If no index is specified, find the current\n\t\t\t\tif( typeof index !== 'number' ) {\n\t\t\t\t\tlet lastVisibleFragment = this.sort( currentSlide.querySelectorAll( '.fragment:not(.disabled).visible' ) ).pop();\n\n\t\t\t\t\tif( lastVisibleFragment ) {\n\t\t\t\t\t\tindex = parseInt( lastVisibleFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tindex = -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply the offset if there is one\n\t\t\t\tindex += offset;\n\n\t\t\t\tlet changedFragments = this.update( index, fragments );\n\n\t\t\t\tif( changedFragments.hidden.length ) {\n\t\t\t\t\tthis.Reveal.dispatchEvent({\n\t\t\t\t\t\ttype: 'fragmenthidden',\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tfragment: changedFragments.hidden[0],\n\t\t\t\t\t\t\tfragments: changedFragments.hidden\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif( changedFragments.shown.length ) {\n\t\t\t\t\tthis.Reveal.dispatchEvent({\n\t\t\t\t\t\ttype: 'fragmentshown',\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tfragment: changedFragments.shown[0],\n\t\t\t\t\t\t\tfragments: changedFragments.shown\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.Reveal.controls.update();\n\t\t\t\tthis.Reveal.progress.update();\n\n\t\t\t\tif( this.Reveal.getConfig().fragmentInURL ) {\n\t\t\t\t\tthis.Reveal.location.writeURL();\n\t\t\t\t}\n\n\t\t\t\treturn !!( changedFragments.shown.length || changedFragments.hidden.length );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t/**\n\t * Navigate to the next slide fragment.\n\t *\n\t * @return {boolean} true if there was a next fragment,\n\t * false otherwise\n\t */\n\tnext() {\n\n\t\treturn this.goto( null, 1 );\n\n\t}\n\n\t/**\n\t * Navigate to the previous slide fragment.\n\t *\n\t * @return {boolean} true if there was a previous fragment,\n\t * false otherwise\n\t */\n\tprev() {\n\n\t\treturn this.goto( null, -1 );\n\n\t}\n\n}","import { SLIDES_SELECTOR } from '../utils/constants.js'\nimport { extend, queryAll, transformElement } from '../utils/util.js'\n\n/**\n * Handles all logic related to the overview mode\n * (birds-eye view of all slides).\n */\nexport default class Overview {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\tthis.active = false;\n\n\t\tthis.onSlideClicked = this.onSlideClicked.bind( this );\n\n\t}\n\n\t/**\n\t * Displays the overview of slides (quick nav) by scaling\n\t * down and arranging all slide elements.\n\t */\n\tactivate() {\n\n\t\t// Only proceed if enabled in config\n\t\tif( this.Reveal.getConfig().overview && !this.isActive() ) {\n\n\t\t\tthis.active = true;\n\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'overview' );\n\n\t\t\t// Don't auto-slide while in overview mode\n\t\t\tthis.Reveal.cancelAutoSlide();\n\n\t\t\t// Move the backgrounds element into the slide container to\n\t\t\t// that the same scaling is applied\n\t\t\tthis.Reveal.getSlidesElement().appendChild( this.Reveal.getBackgroundsElement() );\n\n\t\t\t// Clicking on an overview slide navigates to it\n\t\t\tqueryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( slide => {\n\t\t\t\tif( !slide.classList.contains( 'stack' ) ) {\n\t\t\t\t\tslide.addEventListener( 'click', this.onSlideClicked, true );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Calculate slide sizes\n\t\t\tconst margin = 70;\n\t\t\tconst slideSize = this.Reveal.getComputedSlideSize();\n\t\t\tthis.overviewSlideWidth = slideSize.width + margin;\n\t\t\tthis.overviewSlideHeight = slideSize.height + margin;\n\n\t\t\t// Reverse in RTL mode\n\t\t\tif( this.Reveal.getConfig().rtl ) {\n\t\t\t\tthis.overviewSlideWidth = -this.overviewSlideWidth;\n\t\t\t}\n\n\t\t\tthis.Reveal.updateSlidesVisibility();\n\n\t\t\tthis.layout();\n\t\t\tthis.update();\n\n\t\t\tthis.Reveal.layout();\n\n\t\t\tconst indices = this.Reveal.getIndices();\n\n\t\t\t// Notify observers of the overview showing\n\t\t\tthis.Reveal.dispatchEvent({\n\t\t\t\ttype: 'overviewshown',\n\t\t\t\tdata: {\n\t\t\t\t\t'indexh': indices.h,\n\t\t\t\t\t'indexv': indices.v,\n\t\t\t\t\t'currentSlide': this.Reveal.getCurrentSlide()\n\t\t\t\t}\n\t\t\t});\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Uses CSS transforms to position all slides in a grid for\n\t * display inside of the overview mode.\n\t */\n\tlayout() {\n\n\t\t// Layout slides\n\t\tthis.Reveal.getHorizontalSlides().forEach( ( hslide, h ) => {\n\t\t\thslide.setAttribute( 'data-index-h', h );\n\t\t\ttransformElement( hslide, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' );\n\n\t\t\tif( hslide.classList.contains( 'stack' ) ) {\n\n\t\t\t\tqueryAll( hslide, 'section' ).forEach( ( vslide, v ) => {\n\t\t\t\t\tvslide.setAttribute( 'data-index-h', h );\n\t\t\t\t\tvslide.setAttribute( 'data-index-v', v );\n\n\t\t\t\t\ttransformElement( vslide, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' );\n\t\t\t\t} );\n\n\t\t\t}\n\t\t} );\n\n\t\t// Layout slide backgrounds\n\t\tArray.from( this.Reveal.getBackgroundsElement().childNodes ).forEach( ( hbackground, h ) => {\n\t\t\ttransformElement( hbackground, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' );\n\n\t\t\tqueryAll( hbackground, '.slide-background' ).forEach( ( vbackground, v ) => {\n\t\t\t\ttransformElement( vbackground, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' );\n\t\t\t} );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Moves the overview viewport to the current slides.\n\t * Called each time the current slide changes.\n\t */\n\tupdate() {\n\n\t\tconst vmin = Math.min( window.innerWidth, window.innerHeight );\n\t\tconst scale = Math.max( vmin / 5, 150 ) / vmin;\n\t\tconst indices = this.Reveal.getIndices();\n\n\t\tthis.Reveal.transformSlides( {\n\t\t\toverview: [\n\t\t\t\t'scale('+ scale +')',\n\t\t\t\t'translateX('+ ( -indices.h * this.overviewSlideWidth ) +'px)',\n\t\t\t\t'translateY('+ ( -indices.v * this.overviewSlideHeight ) +'px)'\n\t\t\t].join( ' ' )\n\t\t} );\n\n\t}\n\n\t/**\n\t * Exits the slide overview and enters the currently\n\t * active slide.\n\t */\n\tdeactivate() {\n\n\t\t// Only proceed if enabled in config\n\t\tif( this.Reveal.getConfig().overview ) {\n\n\t\t\tthis.active = false;\n\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'overview' );\n\n\t\t\t// Temporarily add a class so that transitions can do different things\n\t\t\t// depending on whether they are exiting/entering overview, or just\n\t\t\t// moving from slide to slide\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'overview-deactivating' );\n\n\t\t\tsetTimeout( () => {\n\t\t\t\tthis.Reveal.getRevealElement().classList.remove( 'overview-deactivating' );\n\t\t\t}, 1 );\n\n\t\t\t// Move the background element back out\n\t\t\tthis.Reveal.getRevealElement().appendChild( this.Reveal.getBackgroundsElement() );\n\n\t\t\t// Clean up changes made to slides\n\t\t\tqueryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( slide => {\n\t\t\t\ttransformElement( slide, '' );\n\n\t\t\t\tslide.removeEventListener( 'click', this.onSlideClicked, true );\n\t\t\t} );\n\n\t\t\t// Clean up changes made to backgrounds\n\t\t\tqueryAll( this.Reveal.getBackgroundsElement(), '.slide-background' ).forEach( background => {\n\t\t\t\ttransformElement( background, '' );\n\t\t\t} );\n\n\t\t\tthis.Reveal.transformSlides( { overview: '' } );\n\n\t\t\tconst indices = this.Reveal.getIndices();\n\n\t\t\tthis.Reveal.slide( indices.h, indices.v );\n\t\t\tthis.Reveal.layout();\n\t\t\tthis.Reveal.cueAutoSlide();\n\n\t\t\t// Notify observers of the overview hiding\n\t\t\tthis.Reveal.dispatchEvent({\n\t\t\t\ttype: 'overviewhidden',\n\t\t\t\tdata: {\n\t\t\t\t\t'indexh': indices.h,\n\t\t\t\t\t'indexv': indices.v,\n\t\t\t\t\t'currentSlide': this.Reveal.getCurrentSlide()\n\t\t\t\t}\n\t\t\t});\n\n\t\t}\n\t}\n\n\t/**\n\t * Toggles the slide overview mode on and off.\n\t *\n\t * @param {Boolean} [override] Flag which overrides the\n\t * toggle logic and forcibly sets the desired state. True means\n\t * overview is open, false means it's closed.\n\t */\n\ttoggle( override ) {\n\n\t\tif( typeof override === 'boolean' ) {\n\t\t\toverride ? this.activate() : this.deactivate();\n\t\t}\n\t\telse {\n\t\t\tthis.isActive() ? this.deactivate() : this.activate();\n\t\t}\n\n\t}\n\n\t/**\n\t * Checks if the overview is currently active.\n\t *\n\t * @return {Boolean} true if the overview is active,\n\t * false otherwise\n\t */\n\tisActive() {\n\n\t\treturn this.active;\n\n\t}\n\n\t/**\n\t * Invoked when a slide is and we're in the overview.\n\t *\n\t * @param {object} event\n\t */\n\tonSlideClicked( event ) {\n\n\t\tif( this.isActive() ) {\n\t\t\tevent.preventDefault();\n\n\t\t\tlet element = event.target;\n\n\t\t\twhile( element && !element.nodeName.match( /section/gi ) ) {\n\t\t\t\telement = element.parentNode;\n\t\t\t}\n\n\t\t\tif( element && !element.classList.contains( 'disabled' ) ) {\n\n\t\t\t\tthis.deactivate();\n\n\t\t\t\tif( element.nodeName.match( /section/gi ) ) {\n\t\t\t\t\tlet h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),\n\t\t\t\t\t\tv = parseInt( element.getAttribute( 'data-index-v' ), 10 );\n\n\t\t\t\t\tthis.Reveal.slide( h, v );\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t}\n\n}","import { enterFullscreen } from '../utils/util.js'\n\n/**\n * Handles all reveal.js keyboard interactions.\n */\nexport default class Keyboard {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\t// A key:value map of keyboard keys and descriptions of\n\t\t// the actions they trigger\n\t\tthis.shortcuts = {};\n\n\t\t// Holds custom key code mappings\n\t\tthis.bindings = {};\n\n\t\tthis.onDocumentKeyDown = this.onDocumentKeyDown.bind( this );\n\t\tthis.onDocumentKeyPress = this.onDocumentKeyPress.bind( this );\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tif( config.navigationMode === 'linear' ) {\n\t\t\tthis.shortcuts['→ , ↓ , SPACE , N , L , J'] = 'Next slide';\n\t\t\tthis.shortcuts['← , ↑ , P , H , K'] = 'Previous slide';\n\t\t}\n\t\telse {\n\t\t\tthis.shortcuts['N , SPACE'] = 'Next slide';\n\t\t\tthis.shortcuts['P , Shift SPACE'] = 'Previous slide';\n\t\t\tthis.shortcuts['← , H'] = 'Navigate left';\n\t\t\tthis.shortcuts['→ , L'] = 'Navigate right';\n\t\t\tthis.shortcuts['↑ , K'] = 'Navigate up';\n\t\t\tthis.shortcuts['↓ , J'] = 'Navigate down';\n\t\t}\n\n\t\tthis.shortcuts['Alt + ←/↑/→/↓'] = 'Navigate without fragments';\n\t\tthis.shortcuts['Shift + ←/↑/→/↓'] = 'Jump to first/last slide';\n\t\tthis.shortcuts['B , .'] = 'Pause';\n\t\tthis.shortcuts['F'] = 'Fullscreen';\n\t\tthis.shortcuts['G'] = 'Jump to slide';\n\t\tthis.shortcuts['ESC, O'] = 'Slide overview';\n\n\t}\n\n\t/**\n\t * Starts listening for keyboard events.\n\t */\n\tbind() {\n\n\t\tdocument.addEventListener( 'keydown', this.onDocumentKeyDown, false );\n\t\tdocument.addEventListener( 'keypress', this.onDocumentKeyPress, false );\n\n\t}\n\n\t/**\n\t * Stops listening for keyboard events.\n\t */\n\tunbind() {\n\n\t\tdocument.removeEventListener( 'keydown', this.onDocumentKeyDown, false );\n\t\tdocument.removeEventListener( 'keypress', this.onDocumentKeyPress, false );\n\n\t}\n\n\t/**\n\t * Add a custom key binding with optional description to\n\t * be added to the help screen.\n\t */\n\taddKeyBinding( binding, callback ) {\n\n\t\tif( typeof binding === 'object' && binding.keyCode ) {\n\t\t\tthis.bindings[binding.keyCode] = {\n\t\t\t\tcallback: callback,\n\t\t\t\tkey: binding.key,\n\t\t\t\tdescription: binding.description\n\t\t\t};\n\t\t}\n\t\telse {\n\t\t\tthis.bindings[binding] = {\n\t\t\t\tcallback: callback,\n\t\t\t\tkey: null,\n\t\t\t\tdescription: null\n\t\t\t};\n\t\t}\n\n\t}\n\n\t/**\n\t * Removes the specified custom key binding.\n\t */\n\tremoveKeyBinding( keyCode ) {\n\n\t\tdelete this.bindings[keyCode];\n\n\t}\n\n\t/**\n\t * Programmatically triggers a keyboard event\n\t *\n\t * @param {int} keyCode\n\t */\n\ttriggerKey( keyCode ) {\n\n\t\tthis.onDocumentKeyDown( { keyCode } );\n\n\t}\n\n\t/**\n\t * Registers a new shortcut to include in the help overlay\n\t *\n\t * @param {String} key\n\t * @param {String} value\n\t */\n\tregisterKeyboardShortcut( key, value ) {\n\n\t\tthis.shortcuts[key] = value;\n\n\t}\n\n\tgetShortcuts() {\n\n\t\treturn this.shortcuts;\n\n\t}\n\n\tgetBindings() {\n\n\t\treturn this.bindings;\n\n\t}\n\n\t/**\n\t * Handler for the document level 'keypress' event.\n\t *\n\t * @param {object} event\n\t */\n\tonDocumentKeyPress( event ) {\n\n\t\t// Check if the pressed key is question mark\n\t\tif( event.shiftKey && event.charCode === 63 ) {\n\t\t\tthis.Reveal.toggleHelp();\n\t\t}\n\n\t}\n\n\t/**\n\t * Handler for the document level 'keydown' event.\n\t *\n\t * @param {object} event\n\t */\n\tonDocumentKeyDown( event ) {\n\n\t\tlet config = this.Reveal.getConfig();\n\n\t\t// If there's a condition specified and it returns false,\n\t\t// ignore this event\n\t\tif( typeof config.keyboardCondition === 'function' && config.keyboardCondition(event) === false ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// If keyboardCondition is set, only capture keyboard events\n\t\t// for embedded decks when they are focused\n\t\tif( config.keyboardCondition === 'focused' && !this.Reveal.isFocused() ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Shorthand\n\t\tlet keyCode = event.keyCode;\n\n\t\t// Remember if auto-sliding was paused so we can toggle it\n\t\tlet autoSlideWasPaused = !this.Reveal.isAutoSliding();\n\n\t\tthis.Reveal.onUserInput( event );\n\n\t\t// Is there a focused element that could be using the keyboard?\n\t\tlet activeElementIsCE = document.activeElement && document.activeElement.isContentEditable === true;\n\t\tlet activeElementIsInput = document.activeElement && document.activeElement.tagName && /input|textarea/i.test( document.activeElement.tagName );\n\t\tlet activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className);\n\n\t\t// Whitelist certain modifiers for slide navigation shortcuts\n\t\tlet isNavigationKey = [32, 37, 38, 39, 40, 78, 80].indexOf( event.keyCode ) !== -1;\n\n\t\t// Prevent all other events when a modifier is pressed\n\t\tlet unusedModifier = \t!( isNavigationKey && event.shiftKey || event.altKey ) &&\n\t\t\t\t\t\t\t\t( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey );\n\n\t\t// Disregard the event if there's a focused element or a\n\t\t// keyboard modifier key is present\n\t\tif( activeElementIsCE || activeElementIsInput || activeElementIsNotes || unusedModifier ) return;\n\n\t\t// While paused only allow resume keyboard events; 'b', 'v', '.'\n\t\tlet resumeKeyCodes = [66,86,190,191];\n\t\tlet key;\n\n\t\t// Custom key bindings for togglePause should be able to resume\n\t\tif( typeof config.keyboard === 'object' ) {\n\t\t\tfor( key in config.keyboard ) {\n\t\t\t\tif( config.keyboard[key] === 'togglePause' ) {\n\t\t\t\t\tresumeKeyCodes.push( parseInt( key, 10 ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif( this.Reveal.isPaused() && resumeKeyCodes.indexOf( keyCode ) === -1 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Use linear navigation if we're configured to OR if\n\t\t// the presentation is one-dimensional\n\t\tlet useLinearMode = config.navigationMode === 'linear' || !this.Reveal.hasHorizontalSlides() || !this.Reveal.hasVerticalSlides();\n\n\t\tlet triggered = false;\n\n\t\t// 1. User defined key bindings\n\t\tif( typeof config.keyboard === 'object' ) {\n\n\t\t\tfor( key in config.keyboard ) {\n\n\t\t\t\t// Check if this binding matches the pressed key\n\t\t\t\tif( parseInt( key, 10 ) === keyCode ) {\n\n\t\t\t\t\tlet value = config.keyboard[ key ];\n\n\t\t\t\t\t// Callback function\n\t\t\t\t\tif( typeof value === 'function' ) {\n\t\t\t\t\t\tvalue.apply( null, [ event ] );\n\t\t\t\t\t}\n\t\t\t\t\t// String shortcuts to reveal.js API\n\t\t\t\t\telse if( typeof value === 'string' && typeof this.Reveal[ value ] === 'function' ) {\n\t\t\t\t\t\tthis.Reveal[ value ].call();\n\t\t\t\t\t}\n\n\t\t\t\t\ttriggered = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// 2. Registered custom key bindings\n\t\tif( triggered === false ) {\n\n\t\t\tfor( key in this.bindings ) {\n\n\t\t\t\t// Check if this binding matches the pressed key\n\t\t\t\tif( parseInt( key, 10 ) === keyCode ) {\n\n\t\t\t\t\tlet action = this.bindings[ key ].callback;\n\n\t\t\t\t\t// Callback function\n\t\t\t\t\tif( typeof action === 'function' ) {\n\t\t\t\t\t\taction.apply( null, [ event ] );\n\t\t\t\t\t}\n\t\t\t\t\t// String shortcuts to reveal.js API\n\t\t\t\t\telse if( typeof action === 'string' && typeof this.Reveal[ action ] === 'function' ) {\n\t\t\t\t\t\tthis.Reveal[ action ].call();\n\t\t\t\t\t}\n\n\t\t\t\t\ttriggered = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 3. System defined key bindings\n\t\tif( triggered === false ) {\n\n\t\t\t// Assume true and try to prove false\n\t\t\ttriggered = true;\n\n\t\t\t// P, PAGE UP\n\t\t\tif( keyCode === 80 || keyCode === 33 ) {\n\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\n\t\t\t}\n\t\t\t// N, PAGE DOWN\n\t\t\telse if( keyCode === 78 || keyCode === 34 ) {\n\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\n\t\t\t}\n\t\t\t// H, LEFT\n\t\t\telse if( keyCode === 72 || keyCode === 37 ) {\n\t\t\t\tif( event.shiftKey ) {\n\t\t\t\t\tthis.Reveal.slide( 0 );\n\t\t\t\t}\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\n\t\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.Reveal.left({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// L, RIGHT\n\t\t\telse if( keyCode === 76 || keyCode === 39 ) {\n\t\t\t\tif( event.shiftKey ) {\n\t\t\t\t\tthis.Reveal.slide( this.Reveal.getHorizontalSlides().length - 1 );\n\t\t\t\t}\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\n\t\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.Reveal.right({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// K, UP\n\t\t\telse if( keyCode === 75 || keyCode === 38 ) {\n\t\t\t\tif( event.shiftKey ) {\n\t\t\t\t\tthis.Reveal.slide( undefined, 0 );\n\t\t\t\t}\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\n\t\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.Reveal.up({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// J, DOWN\n\t\t\telse if( keyCode === 74 || keyCode === 40 ) {\n\t\t\t\tif( event.shiftKey ) {\n\t\t\t\t\tthis.Reveal.slide( undefined, Number.MAX_VALUE );\n\t\t\t\t}\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\n\t\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.Reveal.down({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// HOME\n\t\t\telse if( keyCode === 36 ) {\n\t\t\t\tthis.Reveal.slide( 0 );\n\t\t\t}\n\t\t\t// END\n\t\t\telse if( keyCode === 35 ) {\n\t\t\t\tthis.Reveal.slide( this.Reveal.getHorizontalSlides().length - 1 );\n\t\t\t}\n\t\t\t// SPACE\n\t\t\telse if( keyCode === 32 ) {\n\t\t\t\tif( this.Reveal.overview.isActive() ) {\n\t\t\t\t\tthis.Reveal.overview.deactivate();\n\t\t\t\t}\n\t\t\t\tif( event.shiftKey ) {\n\t\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS \"BLACK SCREEN\" BUTTON\n\t\t\telse if( keyCode === 58 || keyCode === 59 || keyCode === 66 || keyCode === 86 || keyCode === 190 || keyCode === 191 ) {\n\t\t\t\tthis.Reveal.togglePause();\n\t\t\t}\n\t\t\t// F\n\t\t\telse if( keyCode === 70 ) {\n\t\t\t\tenterFullscreen( config.embedded ? this.Reveal.getViewportElement() : document.documentElement );\n\t\t\t}\n\t\t\t// A\n\t\t\telse if( keyCode === 65 ) {\n\t\t\t\tif( config.autoSlideStoppable ) {\n\t\t\t\t\tthis.Reveal.toggleAutoSlide( autoSlideWasPaused );\n\t\t\t\t}\n\t\t\t}\n\t\t\t// G\n\t\t\telse if( keyCode === 71 ) {\n\t\t\t\tif( config.jumpToSlide ) {\n\t\t\t\t\tthis.Reveal.toggleJumpToSlide();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttriggered = false;\n\t\t\t}\n\n\t\t}\n\n\t\t// If the input resulted in a triggered action we should prevent\n\t\t// the browsers default behavior\n\t\tif( triggered ) {\n\t\t\tevent.preventDefault && event.preventDefault();\n\t\t}\n\t\t// ESC or O key\n\t\telse if( keyCode === 27 || keyCode === 79 ) {\n\t\t\tif( this.Reveal.closeOverlay() === false ) {\n\t\t\t\tthis.Reveal.overview.toggle();\n\t\t\t}\n\n\t\t\tevent.preventDefault && event.preventDefault();\n\t\t}\n\n\t\t// If auto-sliding is enabled we need to cue up\n\t\t// another timeout\n\t\tthis.Reveal.cueAutoSlide();\n\n\t}\n\n}","/**\n * Reads and writes the URL based on reveal.js' current state.\n */\nexport default class Location {\n\n\t// The minimum number of milliseconds that must pass between\n\t// calls to history.replaceState\n\tMAX_REPLACE_STATE_FREQUENCY = 1000\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\t// Delays updates to the URL due to a Chrome thumbnailer bug\n\t\tthis.writeURLTimeout = 0;\n\n\t\tthis.replaceStateTimestamp = 0;\n\n\t\tthis.onWindowHashChange = this.onWindowHashChange.bind( this );\n\n\t}\n\n\tbind() {\n\n\t\twindow.addEventListener( 'hashchange', this.onWindowHashChange, false );\n\n\t}\n\n\tunbind() {\n\n\t\twindow.removeEventListener( 'hashchange', this.onWindowHashChange, false );\n\n\t}\n\n\t/**\n\t * Returns the slide indices for the given hash link.\n\t *\n\t * @param {string} [hash] the hash string that we want to\n\t * find the indices for\n\t *\n\t * @returns slide indices or null\n\t */\n\tgetIndicesFromHash( hash=window.location.hash, options={} ) {\n\n\t\t// Attempt to parse the hash as either an index or name\n\t\tlet name = hash.replace( /^#\\/?/, '' );\n\t\tlet bits = name.split( '/' );\n\n\t\t// If the first bit is not fully numeric and there is a name we\n\t\t// can assume that this is a named link\n\t\tif( !/^[0-9]*$/.test( bits[0] ) && name.length ) {\n\t\t\tlet slide;\n\n\t\t\tlet f;\n\n\t\t\t// Parse named links with fragments (#/named-link/2)\n\t\t\tif( /\\/[-\\d]+$/g.test( name ) ) {\n\t\t\t\tf = parseInt( name.split( '/' ).pop(), 10 );\n\t\t\t\tf = isNaN(f) ? undefined : f;\n\t\t\t\tname = name.split( '/' ).shift();\n\t\t\t}\n\n\t\t\t// Ensure the named link is a valid HTML ID attribute\n\t\t\ttry {\n\t\t\t\tslide = document\n\t\t\t\t\t.getElementById( decodeURIComponent( name ) )\n\t\t\t\t\t.closest('.slides>section, .slides>section>section');\n\t\t\t}\n\t\t\tcatch ( error ) { }\n\n\t\t\tif( slide ) {\n\t\t\t\treturn { ...this.Reveal.getIndices( slide ), f };\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tconst config = this.Reveal.getConfig();\n\t\t\tlet hashIndexBase = config.hashOneBasedIndex || options.oneBasedIndex ? 1 : 0;\n\n\t\t\t// Read the index components of the hash\n\t\t\tlet h = ( parseInt( bits[0], 10 ) - hashIndexBase ) || 0,\n\t\t\t\tv = ( parseInt( bits[1], 10 ) - hashIndexBase ) || 0,\n\t\t\t\tf;\n\n\t\t\tif( config.fragmentInURL ) {\n\t\t\t\tf = parseInt( bits[2], 10 );\n\t\t\t\tif( isNaN( f ) ) {\n\t\t\t\t\tf = undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { h, v, f };\n\t\t}\n\n\t\t// The hash couldn't be parsed or no matching named link was found\n\t\treturn null\n\n\t}\n\n\t/**\n\t * Reads the current URL (hash) and navigates accordingly.\n\t */\n\treadURL() {\n\n\t\tconst currentIndices = this.Reveal.getIndices();\n\t\tconst newIndices = this.getIndicesFromHash();\n\n\t\tif( newIndices ) {\n\t\t\tif( ( newIndices.h !== currentIndices.h || newIndices.v !== currentIndices.v || newIndices.f !== undefined ) ) {\n\t\t\t\t\tthis.Reveal.slide( newIndices.h, newIndices.v, newIndices.f );\n\t\t\t}\n\t\t}\n\t\t// If no new indices are available, we're trying to navigate to\n\t\t// a slide hash that does not exist\n\t\telse {\n\t\t\tthis.Reveal.slide( currentIndices.h || 0, currentIndices.v || 0 );\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates the page URL (hash) to reflect the current\n\t * state.\n\t *\n\t * @param {number} delay The time in ms to wait before\n\t * writing the hash\n\t */\n\twriteURL( delay ) {\n\n\t\tlet config = this.Reveal.getConfig();\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\n\n\t\t// Make sure there's never more than one timeout running\n\t\tclearTimeout( this.writeURLTimeout );\n\n\t\t// If a delay is specified, timeout this call\n\t\tif( typeof delay === 'number' ) {\n\t\t\tthis.writeURLTimeout = setTimeout( this.writeURL, delay );\n\t\t}\n\t\telse if( currentSlide ) {\n\n\t\t\tlet hash = this.getHash();\n\n\t\t\t// If we're configured to push to history OR the history\n\t\t\t// API is not available.\n\t\t\tif( config.history ) {\n\t\t\t\twindow.location.hash = hash;\n\t\t\t}\n\t\t\t// If we're configured to reflect the current slide in the\n\t\t\t// URL without pushing to history.\n\t\t\telse if( config.hash ) {\n\t\t\t\t// If the hash is empty, don't add it to the URL\n\t\t\t\tif( hash === '/' ) {\n\t\t\t\t\tthis.debouncedReplaceState( window.location.pathname + window.location.search );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.debouncedReplaceState( '#' + hash );\n\t\t\t\t}\n\t\t\t}\n\t\t\t// UPDATE: The below nuking of all hash changes breaks\n\t\t\t// anchors on pages where reveal.js is running. Removed\n\t\t\t// in 4.0. Why was it here in the first place? ¯\\_(ツ)_/¯\n\t\t\t//\n\t\t\t// If history and hash are both disabled, a hash may still\n\t\t\t// be added to the URL by clicking on a href with a hash\n\t\t\t// target. Counter this by always removing the hash.\n\t\t\t// else {\n\t\t\t// \twindow.history.replaceState( null, null, window.location.pathname + window.location.search );\n\t\t\t// }\n\n\t\t}\n\n\t}\n\n\treplaceState( url ) {\n\n\t\twindow.history.replaceState( null, null, url );\n\t\tthis.replaceStateTimestamp = Date.now();\n\n\t}\n\n\tdebouncedReplaceState( url ) {\n\n\t\tclearTimeout( this.replaceStateTimeout );\n\n\t\tif( Date.now() - this.replaceStateTimestamp > this.MAX_REPLACE_STATE_FREQUENCY ) {\n\t\t\tthis.replaceState( url );\n\t\t}\n\t\telse {\n\t\t\tthis.replaceStateTimeout = setTimeout( () => this.replaceState( url ), this.MAX_REPLACE_STATE_FREQUENCY );\n\t\t}\n\n\t}\n\n\t/**\n\t * Return a hash URL that will resolve to the given slide location.\n\t *\n\t * @param {HTMLElement} [slide=currentSlide] The slide to link to\n\t */\n\tgetHash( slide ) {\n\n\t\tlet url = '/';\n\n\t\t// Attempt to create a named link based on the slide's ID\n\t\tlet s = slide || this.Reveal.getCurrentSlide();\n\t\tlet id = s ? s.getAttribute( 'id' ) : null;\n\t\tif( id ) {\n\t\t\tid = encodeURIComponent( id );\n\t\t}\n\n\t\tlet index = this.Reveal.getIndices( slide );\n\t\tif( !this.Reveal.getConfig().fragmentInURL ) {\n\t\t\tindex.f = undefined;\n\t\t}\n\n\t\t// If the current slide has an ID, use that as a named link,\n\t\t// but we don't support named links with a fragment index\n\t\tif( typeof id === 'string' && id.length ) {\n\t\t\turl = '/' + id;\n\n\t\t\t// If there is also a fragment, append that at the end\n\t\t\t// of the named link, like: #/named-link/2\n\t\t\tif( index.f >= 0 ) url += '/' + index.f;\n\t\t}\n\t\t// Otherwise use the /h/v index\n\t\telse {\n\t\t\tlet hashIndexBase = this.Reveal.getConfig().hashOneBasedIndex ? 1 : 0;\n\t\t\tif( index.h > 0 || index.v > 0 || index.f >= 0 ) url += index.h + hashIndexBase;\n\t\t\tif( index.v > 0 || index.f >= 0 ) url += '/' + (index.v + hashIndexBase );\n\t\t\tif( index.f >= 0 ) url += '/' + index.f;\n\t\t}\n\n\t\treturn url;\n\n\t}\n\n\t/**\n\t * Handler for the window level 'hashchange' event.\n\t *\n\t * @param {object} [event]\n\t */\n\tonWindowHashChange( event ) {\n\n\t\tthis.readURL();\n\n\t}\n\n}","import { queryAll } from '../utils/util.js'\nimport { isAndroid } from '../utils/device.js'\n\n/**\n * Manages our presentation controls. This includes both\n * the built-in control arrows as well as event monitoring\n * of any elements within the presentation with either of the\n * following helper classes:\n * - .navigate-up\n * - .navigate-right\n * - .navigate-down\n * - .navigate-left\n * - .navigate-next\n * - .navigate-prev\n */\nexport default class Controls {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\tthis.onNavigateLeftClicked = this.onNavigateLeftClicked.bind( this );\n\t\tthis.onNavigateRightClicked = this.onNavigateRightClicked.bind( this );\n\t\tthis.onNavigateUpClicked = this.onNavigateUpClicked.bind( this );\n\t\tthis.onNavigateDownClicked = this.onNavigateDownClicked.bind( this );\n\t\tthis.onNavigatePrevClicked = this.onNavigatePrevClicked.bind( this );\n\t\tthis.onNavigateNextClicked = this.onNavigateNextClicked.bind( this );\n\n\t}\n\n\trender() {\n\n\t\tconst rtl = this.Reveal.getConfig().rtl;\n\t\tconst revealElement = this.Reveal.getRevealElement();\n\n\t\tthis.element = document.createElement( 'aside' );\n\t\tthis.element.className = 'controls';\n\t\tthis.element.innerHTML =\n\t\t\t`<button class=\"navigate-left\" aria-label=\"${ rtl ? 'next slide' : 'previous slide' }\"><div class=\"controls-arrow\"></div></button>\n\t\t\t<button class=\"navigate-right\" aria-label=\"${ rtl ? 'previous slide' : 'next slide' }\"><div class=\"controls-arrow\"></div></button>\n\t\t\t<button class=\"navigate-up\" aria-label=\"above slide\"><div class=\"controls-arrow\"></div></button>\n\t\t\t<button class=\"navigate-down\" aria-label=\"below slide\"><div class=\"controls-arrow\"></div></button>`;\n\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\n\n\t\t// There can be multiple instances of controls throughout the page\n\t\tthis.controlsLeft = queryAll( revealElement, '.navigate-left' );\n\t\tthis.controlsRight = queryAll( revealElement, '.navigate-right' );\n\t\tthis.controlsUp = queryAll( revealElement, '.navigate-up' );\n\t\tthis.controlsDown = queryAll( revealElement, '.navigate-down' );\n\t\tthis.controlsPrev = queryAll( revealElement, '.navigate-prev' );\n\t\tthis.controlsNext = queryAll( revealElement, '.navigate-next' );\n\n\t\t// The left, right and down arrows in the standard reveal.js controls\n\t\tthis.controlsRightArrow = this.element.querySelector( '.navigate-right' );\n\t\tthis.controlsLeftArrow = this.element.querySelector( '.navigate-left' );\n\t\tthis.controlsDownArrow = this.element.querySelector( '.navigate-down' );\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tthis.element.style.display = config.controls ? 'block' : 'none';\n\n\t\tthis.element.setAttribute( 'data-controls-layout', config.controlsLayout );\n\t\tthis.element.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows );\n\n\t}\n\n\tbind() {\n\n\t\t// Listen to both touch and click events, in case the device\n\t\t// supports both\n\t\tlet pointerEvents = [ 'touchstart', 'click' ];\n\n\t\t// Only support touch for Android, fixes double navigations in\n\t\t// stock browser\n\t\tif( isAndroid ) {\n\t\t\tpointerEvents = [ 'touchstart' ];\n\t\t}\n\n\t\tpointerEvents.forEach( eventName => {\n\t\t\tthis.controlsLeft.forEach( el => el.addEventListener( eventName, this.onNavigateLeftClicked, false ) );\n\t\t\tthis.controlsRight.forEach( el => el.addEventListener( eventName, this.onNavigateRightClicked, false ) );\n\t\t\tthis.controlsUp.forEach( el => el.addEventListener( eventName, this.onNavigateUpClicked, false ) );\n\t\t\tthis.controlsDown.forEach( el => el.addEventListener( eventName, this.onNavigateDownClicked, false ) );\n\t\t\tthis.controlsPrev.forEach( el => el.addEventListener( eventName, this.onNavigatePrevClicked, false ) );\n\t\t\tthis.controlsNext.forEach( el => el.addEventListener( eventName, this.onNavigateNextClicked, false ) );\n\t\t} );\n\n\t}\n\n\tunbind() {\n\n\t\t[ 'touchstart', 'click' ].forEach( eventName => {\n\t\t\tthis.controlsLeft.forEach( el => el.removeEventListener( eventName, this.onNavigateLeftClicked, false ) );\n\t\t\tthis.controlsRight.forEach( el => el.removeEventListener( eventName, this.onNavigateRightClicked, false ) );\n\t\t\tthis.controlsUp.forEach( el => el.removeEventListener( eventName, this.onNavigateUpClicked, false ) );\n\t\t\tthis.controlsDown.forEach( el => el.removeEventListener( eventName, this.onNavigateDownClicked, false ) );\n\t\t\tthis.controlsPrev.forEach( el => el.removeEventListener( eventName, this.onNavigatePrevClicked, false ) );\n\t\t\tthis.controlsNext.forEach( el => el.removeEventListener( eventName, this.onNavigateNextClicked, false ) );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Updates the state of all control/navigation arrows.\n\t */\n\tupdate() {\n\n\t\tlet routes = this.Reveal.availableRoutes();\n\n\t\t// Remove the 'enabled' class from all directions\n\t\t[...this.controlsLeft, ...this.controlsRight, ...this.controlsUp, ...this.controlsDown, ...this.controlsPrev, ...this.controlsNext].forEach( node => {\n\t\t\tnode.classList.remove( 'enabled', 'fragmented' );\n\n\t\t\t// Set 'disabled' attribute on all directions\n\t\t\tnode.setAttribute( 'disabled', 'disabled' );\n\t\t} );\n\n\t\t// Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons\n\t\tif( routes.left ) this.controlsLeft.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\tif( routes.right ) this.controlsRight.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\tif( routes.up ) this.controlsUp.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\tif( routes.down ) this.controlsDown.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\n\t\t// Prev/next buttons\n\t\tif( routes.left || routes.up ) this.controlsPrev.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\tif( routes.right || routes.down ) this.controlsNext.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\n\t\t// Highlight fragment directions\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\n\t\tif( currentSlide ) {\n\n\t\t\tlet fragmentsRoutes = this.Reveal.fragments.availableRoutes();\n\n\t\t\t// Always apply fragment decorator to prev/next buttons\n\t\t\tif( fragmentsRoutes.prev ) this.controlsPrev.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\t\tif( fragmentsRoutes.next ) this.controlsNext.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\n\t\t\t// Apply fragment decorators to directional buttons based on\n\t\t\t// what slide axis they are in\n\t\t\tif( this.Reveal.isVerticalSlide( currentSlide ) ) {\n\t\t\t\tif( fragmentsRoutes.prev ) this.controlsUp.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\t\t\tif( fragmentsRoutes.next ) this.controlsDown.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif( fragmentsRoutes.prev ) this.controlsLeft.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\t\t\tif( fragmentsRoutes.next ) this.controlsRight.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\n\t\t\t}\n\n\t\t}\n\n\t\tif( this.Reveal.getConfig().controlsTutorial ) {\n\n\t\t\tlet indices = this.Reveal.getIndices();\n\n\t\t\t// Highlight control arrows with an animation to ensure\n\t\t\t// that the viewer knows how to navigate\n\t\t\tif( !this.Reveal.hasNavigatedVertically() && routes.down ) {\n\t\t\t\tthis.controlsDownArrow.classList.add( 'highlight' );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.controlsDownArrow.classList.remove( 'highlight' );\n\n\t\t\t\tif( this.Reveal.getConfig().rtl ) {\n\n\t\t\t\t\tif( !this.Reveal.hasNavigatedHorizontally() && routes.left && indices.v === 0 ) {\n\t\t\t\t\t\tthis.controlsLeftArrow.classList.add( 'highlight' );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.controlsLeftArrow.classList.remove( 'highlight' );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif( !this.Reveal.hasNavigatedHorizontally() && routes.right && indices.v === 0 ) {\n\t\t\t\t\t\tthis.controlsRightArrow.classList.add( 'highlight' );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.controlsRightArrow.classList.remove( 'highlight' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tdestroy() {\n\n\t\tthis.unbind();\n\t\tthis.element.remove();\n\n\t}\n\n\t/**\n\t * Event handlers for navigation control buttons.\n\t */\n\tonNavigateLeftClicked( event ) {\n\n\t\tevent.preventDefault();\n\t\tthis.Reveal.onUserInput();\n\n\t\tif( this.Reveal.getConfig().navigationMode === 'linear' ) {\n\t\t\tthis.Reveal.prev();\n\t\t}\n\t\telse {\n\t\t\tthis.Reveal.left();\n\t\t}\n\n\t}\n\n\tonNavigateRightClicked( event ) {\n\n\t\tevent.preventDefault();\n\t\tthis.Reveal.onUserInput();\n\n\t\tif( this.Reveal.getConfig().navigationMode === 'linear' ) {\n\t\t\tthis.Reveal.next();\n\t\t}\n\t\telse {\n\t\t\tthis.Reveal.right();\n\t\t}\n\n\t}\n\n\tonNavigateUpClicked( event ) {\n\n\t\tevent.preventDefault();\n\t\tthis.Reveal.onUserInput();\n\n\t\tthis.Reveal.up();\n\n\t}\n\n\tonNavigateDownClicked( event ) {\n\n\t\tevent.preventDefault();\n\t\tthis.Reveal.onUserInput();\n\n\t\tthis.Reveal.down();\n\n\t}\n\n\tonNavigatePrevClicked( event ) {\n\n\t\tevent.preventDefault();\n\t\tthis.Reveal.onUserInput();\n\n\t\tthis.Reveal.prev();\n\n\t}\n\n\tonNavigateNextClicked( event ) {\n\n\t\tevent.preventDefault();\n\t\tthis.Reveal.onUserInput();\n\n\t\tthis.Reveal.next();\n\n\t}\n\n\n}","/**\n * Creates a visual progress bar for the presentation.\n */\nexport default class Progress {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\tthis.onProgressClicked = this.onProgressClicked.bind( this );\n\n\t}\n\n\trender() {\n\n\t\tthis.element = document.createElement( 'div' );\n\t\tthis.element.className = 'progress';\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\n\n\t\tthis.bar = document.createElement( 'span' );\n\t\tthis.element.appendChild( this.bar );\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tthis.element.style.display = config.progress ? 'block' : 'none';\n\n\t}\n\n\tbind() {\n\n\t\tif( this.Reveal.getConfig().progress && this.element ) {\n\t\t\tthis.element.addEventListener( 'click', this.onProgressClicked, false );\n\t\t}\n\n\t}\n\n\tunbind() {\n\n\t\tif ( this.Reveal.getConfig().progress && this.element ) {\n\t\t\tthis.element.removeEventListener( 'click', this.onProgressClicked, false );\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates the progress bar to reflect the current slide.\n\t */\n\tupdate() {\n\n\t\t// Update progress if enabled\n\t\tif( this.Reveal.getConfig().progress && this.bar ) {\n\n\t\t\tlet scale = this.Reveal.getProgress();\n\n\t\t\t// Don't fill the progress bar if there's only one slide\n\t\t\tif( this.Reveal.getTotalSlides() < 2 ) {\n\t\t\t\tscale = 0;\n\t\t\t}\n\n\t\t\tthis.bar.style.transform = 'scaleX('+ scale +')';\n\n\t\t}\n\n\t}\n\n\tgetMaxWidth() {\n\n\t\treturn this.Reveal.getRevealElement().offsetWidth;\n\n\t}\n\n\t/**\n\t * Clicking on the progress bar results in a navigation to the\n\t * closest approximate horizontal slide using this equation:\n\t *\n\t * ( clickX / presentationWidth ) * numberOfSlides\n\t *\n\t * @param {object} event\n\t */\n\tonProgressClicked( event ) {\n\n\t\tthis.Reveal.onUserInput( event );\n\n\t\tevent.preventDefault();\n\n\t\tlet slides = this.Reveal.getSlides();\n\t\tlet slidesTotal = slides.length;\n\t\tlet slideIndex = Math.floor( ( event.clientX / this.getMaxWidth() ) * slidesTotal );\n\n\t\tif( this.Reveal.getConfig().rtl ) {\n\t\t\tslideIndex = slidesTotal - slideIndex;\n\t\t}\n\n\t\tlet targetIndices = this.Reveal.getIndices(slides[slideIndex]);\n\t\tthis.Reveal.slide( targetIndices.h, targetIndices.v );\n\n\t}\n\n\tdestroy() {\n\n\t\tthis.element.remove();\n\n\t}\n\n}","/**\n * Handles hiding of the pointer/cursor when inactive.\n */\nexport default class Pointer {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\t// Throttles mouse wheel navigation\n\t\tthis.lastMouseWheelStep = 0;\n\n\t\t// Is the mouse pointer currently hidden from view\n\t\tthis.cursorHidden = false;\n\n\t\t// Timeout used to determine when the cursor is inactive\n\t\tthis.cursorInactiveTimeout = 0;\n\n\t\tthis.onDocumentCursorActive = this.onDocumentCursorActive.bind( this );\n\t\tthis.onDocumentMouseScroll = this.onDocumentMouseScroll.bind( this );\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tif( config.mouseWheel ) {\n\t\t\tdocument.addEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false ); // FF\n\t\t\tdocument.addEventListener( 'mousewheel', this.onDocumentMouseScroll, false );\n\t\t}\n\t\telse {\n\t\t\tdocument.removeEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false ); // FF\n\t\t\tdocument.removeEventListener( 'mousewheel', this.onDocumentMouseScroll, false );\n\t\t}\n\n\t\t// Auto-hide the mouse pointer when its inactive\n\t\tif( config.hideInactiveCursor ) {\n\t\t\tdocument.addEventListener( 'mousemove', this.onDocumentCursorActive, false );\n\t\t\tdocument.addEventListener( 'mousedown', this.onDocumentCursorActive, false );\n\t\t}\n\t\telse {\n\t\t\tthis.showCursor();\n\n\t\t\tdocument.removeEventListener( 'mousemove', this.onDocumentCursorActive, false );\n\t\t\tdocument.removeEventListener( 'mousedown', this.onDocumentCursorActive, false );\n\t\t}\n\n\t}\n\n\t/**\n\t * Shows the mouse pointer after it has been hidden with\n\t * #hideCursor.\n\t */\n\tshowCursor() {\n\n\t\tif( this.cursorHidden ) {\n\t\t\tthis.cursorHidden = false;\n\t\t\tthis.Reveal.getRevealElement().style.cursor = '';\n\t\t}\n\n\t}\n\n\t/**\n\t * Hides the mouse pointer when it's on top of the .reveal\n\t * container.\n\t */\n\thideCursor() {\n\n\t\tif( this.cursorHidden === false ) {\n\t\t\tthis.cursorHidden = true;\n\t\t\tthis.Reveal.getRevealElement().style.cursor = 'none';\n\t\t}\n\n\t}\n\n\tdestroy() {\n\n\t\tthis.showCursor();\n\n\t\tdocument.removeEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false );\n\t\tdocument.removeEventListener( 'mousewheel', this.onDocumentMouseScroll, false );\n\t\tdocument.removeEventListener( 'mousemove', this.onDocumentCursorActive, false );\n\t\tdocument.removeEventListener( 'mousedown', this.onDocumentCursorActive, false );\n\n\t}\n\n\t/**\n\t * Called whenever there is mouse input at the document level\n\t * to determine if the cursor is active or not.\n\t *\n\t * @param {object} event\n\t */\n\tonDocumentCursorActive( event ) {\n\n\t\tthis.showCursor();\n\n\t\tclearTimeout( this.cursorInactiveTimeout );\n\n\t\tthis.cursorInactiveTimeout = setTimeout( this.hideCursor.bind( this ), this.Reveal.getConfig().hideCursorTime );\n\n\t}\n\n\t/**\n\t * Handles mouse wheel scrolling, throttled to avoid skipping\n\t * multiple slides.\n\t *\n\t * @param {object} event\n\t */\n\tonDocumentMouseScroll( event ) {\n\n\t\tif( Date.now() - this.lastMouseWheelStep > 1000 ) {\n\n\t\t\tthis.lastMouseWheelStep = Date.now();\n\n\t\t\tlet delta = event.detail || -event.wheelDelta;\n\t\t\tif( delta > 0 ) {\n\t\t\t\tthis.Reveal.next();\n\t\t\t}\n\t\t\telse if( delta < 0 ) {\n\t\t\t\tthis.Reveal.prev();\n\t\t\t}\n\n\t\t}\n\n\t}\n\n}","/**\n * Loads a JavaScript file from the given URL and executes it.\n *\n * @param {string} url Address of the .js file to load\n * @param {function} callback Method to invoke when the script\n * has loaded and executed\n */\nexport const loadScript = ( url, callback ) => {\n\n\tconst script = document.createElement( 'script' );\n\tscript.type = 'text/javascript';\n\tscript.async = false;\n\tscript.defer = false;\n\tscript.src = url;\n\n\tif( typeof callback === 'function' ) {\n\n\t\t// Success callback\n\t\tscript.onload = script.onreadystatechange = event => {\n\t\t\tif( event.type === 'load' || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t// Kill event listeners\n\t\t\t\tscript.onload = script.onreadystatechange = script.onerror = null;\n\n\t\t\t\tcallback();\n\n\t\t\t}\n\t\t};\n\n\t\t// Error callback\n\t\tscript.onerror = err => {\n\n\t\t\t// Kill event listeners\n\t\t\tscript.onload = script.onreadystatechange = script.onerror = null;\n\n\t\t\tcallback( new Error( 'Failed loading script: ' + script.src + '\\n' + err ) );\n\n\t\t};\n\n\t}\n\n\t// Append the script at the end of <head>\n\tconst head = document.querySelector( 'head' );\n\thead.insertBefore( script, head.lastChild );\n\n}","import { loadScript } from '../utils/loader.js'\n\n/**\n * Manages loading and registering of reveal.js plugins.\n */\nexport default class Plugins {\n\n\tconstructor( reveal ) {\n\n\t\tthis.Reveal = reveal;\n\n\t\t// Flags our current state (idle -> loading -> loaded)\n\t\tthis.state = 'idle';\n\n\t\t// An id:instance map of currently registered plugins\n\t\tthis.registeredPlugins = {};\n\n\t\tthis.asyncDependencies = [];\n\n\t}\n\n\t/**\n\t * Loads reveal.js dependencies, registers and\n\t * initializes plugins.\n\t *\n\t * Plugins are direct references to a reveal.js plugin\n\t * object that we register and initialize after any\n\t * synchronous dependencies have loaded.\n\t *\n\t * Dependencies are defined via the 'dependencies' config\n\t * option and will be loaded prior to starting reveal.js.\n\t * Some dependencies may have an 'async' flag, if so they\n\t * will load after reveal.js has been started up.\n\t */\n\tload( plugins, dependencies ) {\n\n\t\tthis.state = 'loading';\n\n\t\tplugins.forEach( this.registerPlugin.bind( this ) );\n\n\t\treturn new Promise( resolve => {\n\n\t\t\tlet scripts = [],\n\t\t\t\tscriptsToLoad = 0;\n\n\t\t\tdependencies.forEach( s => {\n\t\t\t\t// Load if there's no condition or the condition is truthy\n\t\t\t\tif( !s.condition || s.condition() ) {\n\t\t\t\t\tif( s.async ) {\n\t\t\t\t\t\tthis.asyncDependencies.push( s );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tscripts.push( s );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif( scripts.length ) {\n\t\t\t\tscriptsToLoad = scripts.length;\n\n\t\t\t\tconst scriptLoadedCallback = (s) => {\n\t\t\t\t\tif( s && typeof s.callback === 'function' ) s.callback();\n\n\t\t\t\t\tif( --scriptsToLoad === 0 ) {\n\t\t\t\t\t\tthis.initPlugins().then( resolve );\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Load synchronous scripts\n\t\t\t\tscripts.forEach( s => {\n\t\t\t\t\tif( typeof s.id === 'string' ) {\n\t\t\t\t\t\tthis.registerPlugin( s );\n\t\t\t\t\t\tscriptLoadedCallback( s );\n\t\t\t\t\t}\n\t\t\t\t\telse if( typeof s.src === 'string' ) {\n\t\t\t\t\t\tloadScript( s.src, () => scriptLoadedCallback(s) );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tconsole.warn( 'Unrecognized plugin format', s );\n\t\t\t\t\t\tscriptLoadedCallback();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.initPlugins().then( resolve );\n\t\t\t}\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Initializes our plugins and waits for them to be ready\n\t * before proceeding.\n\t */\n\tinitPlugins() {\n\n\t\treturn new Promise( resolve => {\n\n\t\t\tlet pluginValues = Object.values( this.registeredPlugins );\n\t\t\tlet pluginsToInitialize = pluginValues.length;\n\n\t\t\t// If there are no plugins, skip this step\n\t\t\tif( pluginsToInitialize === 0 ) {\n\t\t\t\tthis.loadAsync().then( resolve );\n\t\t\t}\n\t\t\t// ... otherwise initialize plugins\n\t\t\telse {\n\n\t\t\t\tlet initNextPlugin;\n\n\t\t\t\tlet afterPlugInitialized = () => {\n\t\t\t\t\tif( --pluginsToInitialize === 0 ) {\n\t\t\t\t\t\tthis.loadAsync().then( resolve );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tinitNextPlugin();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tlet i = 0;\n\n\t\t\t\t// Initialize plugins serially\n\t\t\t\tinitNextPlugin = () => {\n\n\t\t\t\t\tlet plugin = pluginValues[i++];\n\n\t\t\t\t\t// If the plugin has an 'init' method, invoke it\n\t\t\t\t\tif( typeof plugin.init === 'function' ) {\n\t\t\t\t\t\tlet promise = plugin.init( this.Reveal );\n\n\t\t\t\t\t\t// If the plugin returned a Promise, wait for it\n\t\t\t\t\t\tif( promise && typeof promise.then === 'function' ) {\n\t\t\t\t\t\t\tpromise.then( afterPlugInitialized );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tafterPlugInitialized();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tafterPlugInitialized();\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tinitNextPlugin();\n\n\t\t\t}\n\n\t\t} )\n\n\t}\n\n\t/**\n\t * Loads all async reveal.js dependencies.\n\t */\n\tloadAsync() {\n\n\t\tthis.state = 'loaded';\n\n\t\tif( this.asyncDependencies.length ) {\n\t\t\tthis.asyncDependencies.forEach( s => {\n\t\t\t\tloadScript( s.src, s.callback );\n\t\t\t} );\n\t\t}\n\n\t\treturn Promise.resolve();\n\n\t}\n\n\t/**\n\t * Registers a new plugin with this reveal.js instance.\n\t *\n\t * reveal.js waits for all registered plugins to initialize\n\t * before considering itself ready, as long as the plugin\n\t * is registered before calling `Reveal.initialize()`.\n\t */\n\tregisterPlugin( plugin ) {\n\n\t\t// Backwards compatibility to make reveal.js ~3.9.0\n\t\t// plugins work with reveal.js 4.0.0\n\t\tif( arguments.length === 2 && typeof arguments[0] === 'string' ) {\n\t\t\tplugin = arguments[1];\n\t\t\tplugin.id = arguments[0];\n\t\t}\n\t\t// Plugin can optionally be a function which we call\n\t\t// to create an instance of the plugin\n\t\telse if( typeof plugin === 'function' ) {\n\t\t\tplugin = plugin();\n\t\t}\n\n\t\tlet id = plugin.id;\n\n\t\tif( typeof id !== 'string' ) {\n\t\t\tconsole.warn( 'Unrecognized plugin format; can\\'t find plugin.id', plugin );\n\t\t}\n\t\telse if( this.registeredPlugins[id] === undefined ) {\n\t\t\tthis.registeredPlugins[id] = plugin;\n\n\t\t\t// If a plugin is registered after reveal.js is loaded,\n\t\t\t// initialize it right away\n\t\t\tif( this.state === 'loaded' && typeof plugin.init === 'function' ) {\n\t\t\t\tplugin.init( this.Reveal );\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tconsole.warn( 'reveal.js: \"'+ id +'\" plugin has already been registered' );\n\t\t}\n\n\t}\n\n\t/**\n\t * Checks if a specific plugin has been registered.\n\t *\n\t * @param {String} id Unique plugin identifier\n\t */\n\thasPlugin( id ) {\n\n\t\treturn !!this.registeredPlugins[id];\n\n\t}\n\n\t/**\n\t * Returns the specific plugin instance, if a plugin\n\t * with the given ID has been registered.\n\t *\n\t * @param {String} id Unique plugin identifier\n\t */\n\tgetPlugin( id ) {\n\n\t\treturn this.registeredPlugins[id];\n\n\t}\n\n\tgetRegisteredPlugins() {\n\n\t\treturn this.registeredPlugins;\n\n\t}\n\n\tdestroy() {\n\n\t\tObject.values( this.registeredPlugins ).forEach( plugin => {\n\t\t\tif( typeof plugin.destroy === 'function' ) {\n\t\t\t\tplugin.destroy();\n\t\t\t}\n\t\t} );\n\n\t\tthis.registeredPlugins = {};\n\t\tthis.asyncDependencies = [];\n\n\t}\n\n}\n","import { SLIDES_SELECTOR } from '../utils/constants.js'\nimport { queryAll, createStyleSheet } from '../utils/util.js'\n\n/**\n * The reader mode lets you read a reveal.js presentation\n * as a linear scrollable page.\n */\nexport default class Reader {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\tthis.active = false;\n\t\tthis.activatedCallbacks = [];\n\n\t\tthis.onScroll = this.onScroll.bind( this );\n\n\t}\n\n\t/**\n\t * Activates the reader mode. This rearranges the presentation DOM\n\t * by—among other things—wrapping each slide in a page element.\n\t */\n\tactivate() {\n\n\t\tif( this.active ) return;\n\n\t\tthis.active = true;\n\n\t\tthis.slideHTMLBeforeActivation = this.Reveal.getSlidesElement().innerHTML;\n\n\t\tconst viewportElement = this.Reveal.getViewportElement();\n\t\tconst slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR );\n\n\t\tviewportElement.classList.add( 'loading-scroll-mode', 'reveal-reader' );\n\t\tviewportElement.addEventListener( 'scroll', this.onScroll );\n\n\t\tlet presentationBackground;\n\t\tif( viewportElement ) {\n\t\t\tconst viewportStyles = window.getComputedStyle( viewportElement );\n\t\t\tif( viewportStyles && viewportStyles.background ) {\n\t\t\t\tpresentationBackground = viewportStyles.background;\n\t\t\t}\n\t\t}\n\n\t\tconst pageElements = [];\n\t\tconst pageContainer = slides[0].parentNode;\n\n\t\t// Slide and slide background layout\n\t\tslides.forEach( function( slide ) {\n\n\t\t\t// Vertical stacks are not centred since their section\n\t\t\t// children will be\n\t\t\tif( slide.classList.contains( 'stack' ) === false ) {\n\t\t\t\t// Wrap the slide in a page element and hide its overflow\n\t\t\t\t// so that no page ever flows onto another\n\t\t\t\tconst page = document.createElement( 'div' );\n\t\t\t\tpage.className = 'reader-page';\n\t\t\t\tpageElements.push( page );\n\n\t\t\t\t// Copy the presentation-wide background to each individual\n\t\t\t\t// page when printing\n\t\t\t\tif( presentationBackground ) {\n\t\t\t\t\tpage.style.background = presentationBackground;\n\t\t\t\t}\n\n\t\t\t\tconst stickyContainer = document.createElement( 'div' );\n\t\t\t\tstickyContainer.className = 'reader-page-sticky';\n\t\t\t\tpage.appendChild( stickyContainer );\n\n\t\t\t\tconst contentContainer = document.createElement( 'div' );\n\t\t\t\tcontentContainer.className = 'reader-page-content';\n\t\t\t\tstickyContainer.appendChild( contentContainer );\n\n\t\t\t\tcontentContainer.appendChild( slide );\n\n\t\t\t\tslide.classList.remove( 'past', 'future' );\n\n\t\t\t\tif( slide.slideBackgroundElement ) {\n\t\t\t\t\tslide.slideBackgroundElement.remove( 'past', 'future' );\n\t\t\t\t\tcontentContainer.insertBefore( slide.slideBackgroundElement, slide );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}, this );\n\n\t\t// Remove leftover stacks\n\t\tqueryAll( this.Reveal.getRevealElement(), '.stack' ).forEach( stack => stack.remove() );\n\n\t\tpageElements.forEach( page => pageContainer.appendChild( page ) );\n\n\t\t// Re-run JS-based content layout after the slide is added to page DOM\n\t\tthis.Reveal.slideContent.layout( this.Reveal.getSlidesElement() );\n\n\t\tthis.Reveal.layout();\n\n\t\tviewportElement.classList.remove( 'loading-scroll-mode' );\n\n\t\tthis.activatedCallbacks.forEach( callback => callback() );\n\t\tthis.activatedCallbacks = [];\n\n\t}\n\n\t/**\n\t * Deactivates the reader mode and restores the standard slide-based\n\t * presentation.\n\t */\n\tdeactivate() {\n\n\t\tif( !this.active ) return;\n\n\t\tthis.active = false;\n\n\t\tconst viewportElement = this.Reveal.getViewportElement();\n\n\t\tviewportElement.removeEventListener( 'scroll', this.onScroll );\n\t\tviewportElement.classList.remove( 'reveal-reader' );\n\n\t\tthis.Reveal.getSlidesElement().innerHTML = this.slideHTMLBeforeActivation;\n\t\tthis.Reveal.sync();\n\n\t\t// TODO Navigate to the slide that is currently scrolled into view\n\t\tthis.Reveal.slide( 0 );\n\n\t}\n\n\ttoggle( override ) {\n\n\t\tif( typeof override === 'boolean' ) {\n\t\t\toverride ? this.activate() : this.deactivate();\n\t\t}\n\t\telse {\n\t\t\tthis.isActive() ? this.deactivate() : this.activate();\n\t\t}\n\n\t}\n\n\t/**\n\t * Checks if the reader mode is currently active.\n\t */\n\tisActive() {\n\n\t\treturn this.active;\n\n\t}\n\n\t/**\n\t * Updates our reader pages to match the latest configuration and\n\t * presentation size.\n\t */\n\tsync() {\n\n\t\tconst config = this.Reveal.getConfig();\n\n\t\tconst slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );\n\t\tconst scale = this.Reveal.getScale();\n\t\tconst readerLayout = config.readerLayout;\n\n\t\tconst viewportElement = this.Reveal.getViewportElement();\n\t\tconst viewportHeight = viewportElement.offsetHeight;\n\t\tconst compactHeight = slideSize.height * scale;\n\t\tconst pageHeight = readerLayout === 'full' ? viewportHeight : compactHeight;\n\n\t\t// The height that needs to be scrolled between scroll triggers\n\t\tconst scrollTriggerHeight = viewportHeight / 2;\n\n\t\tviewportElement.style.setProperty( '--page-height', pageHeight + 'px' );\n\t\tviewportElement.style.scrollSnapType = typeof config.readerScrollSnap === 'string' ?\n\t\t\t\t\t\t\t\t\t\t\t\t`y ${config.readerScrollSnap}` : '';\n\n\t\tconst pageElements = Array.from( this.Reveal.getRevealElement().querySelectorAll( '.reader-page' ) );\n\n\t\tthis.pages = pageElements.map( pageElement => {\n\t\t\tconst page = {\n\t\t\t\tpageElement: pageElement,\n\t\t\t\tstickyElement: pageElement.querySelector( '.reader-page-sticky' ),\n\t\t\t\tslideElement: pageElement.querySelector( 'section' ),\n\t\t\t\tbackgroundElement: pageElement.querySelector( '.slide-background' ),\n\t\t\t\ttop: pageElement.offsetTop,\n\t\t\t\tscrollTriggers: []\n\t\t\t};\n\n\t\t\tpage.slideElement.style.width = slideSize.width + 'px';\n\t\t\tpage.slideElement.style.height = config.center === true ? '' : slideSize.height + 'px';\n\n\t\t\t// Each fragment 'group' is an array containing one or more\n\t\t\t// fragments. Multiple fragments that appear at the same time\n\t\t\t// are part of the same group.\n\t\t\tpage.fragments = this.Reveal.fragments.sort( pageElement.querySelectorAll( '.fragment:not(.disabled)' ) );\n\t\t\tpage.fragmentGroups = this.Reveal.fragments.sort( pageElement.querySelectorAll( '.fragment' ), true );\n\n\t\t\t// Create scroll triggers that show/hide fragments\n\t\t\tif( page.fragmentGroups.length ) {\n\t\t\t\tconst segmentSize = 1 / ( page.fragmentGroups.length + 1 );\n\t\t\t\tpage.scrollTriggers.push(\n\t\t\t\t\t// Trigger for the initial state with no fragments visible\n\t\t\t\t\t{ range: [ 0, segmentSize ], fragmentIndex: -1 },\n\n\t\t\t\t\t// Triggers for each fragment group\n\t\t\t\t\t...page.fragmentGroups.map( ( fragments, i ) => ({\n\t\t\t\t\t\trange: [ segmentSize * ( i + 1 ), segmentSize * ( i + 2 ) ],\n\t\t\t\t\t\tfragmentIndex: i\n\t\t\t\t\t}))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Add scroll padding based on how many scroll triggers we have\n\t\t\tpage.scrollPadding = scrollTriggerHeight * page.scrollTriggers.length;\n\n\t\t\t// In the compact layout, only slides with scroll triggers cover the\n\t\t\t// full viewport height. This helps avoid empty gaps before or after\n\t\t\t// a sticky slide.\n\t\t\tif( readerLayout === 'compact' && page.scrollTriggers.length > 0 ) {\n\t\t\t\tpage.pageHeight = viewportHeight;\n\t\t\t\tpage.pageElement.style.setProperty( '--page-height', viewportHeight + 'px' );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpage.pageHeight = pageHeight;\n\t\t\t\tpage.pageElement.style.removeProperty( '--page-height' );\n\t\t\t}\n\n\t\t\tpage.pageElement.style.scrollSnapAlign = page.pageHeight < viewportHeight ? 'center' : 'start';\n\n\t\t\t// This variable is used to pad the height of our page in CSS\n\t\t\tpage.pageElement.style.setProperty( '--page-scroll-padding', page.scrollPadding + 'px' );\n\n\t\t\t// The total height including scrollable space\n\t\t\tpage.totalHeight = page.pageHeight + page.scrollPadding;\n\n\t\t\tpage.bottom = page.top + page.totalHeight;\n\n\t\t\t// If this is a sticky page, stick it to the vertical center\n\t\t\tif( page.scrollTriggers.length > 0 ) {\n\t\t\t\tpage.stickyElement.style.position = 'sticky';\n\t\t\t\tpage.stickyElement.style.top = Math.max( ( viewportHeight - page.pageHeight ) / 2, 0 ) + 'px';\n\n\t\t\t\t// Make this page freeze at the vertical center of the viewport\n\t\t\t\tpage.top -= ( viewportHeight - page.pageHeight ) / 2;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpage.stickyElement.style.position = 'relative';\n\t\t\t}\n\n\t\t\treturn page;\n\t\t} );\n\n\t}\n\n\tlayout() {\n\n\t\tthis.sync();\n\t\tthis.onScroll();\n\n\t}\n\n\tscrollToSlide( slideElement ) {\n\n\t\tif( !this.active ) {\n\t\t\tthis.activatedCallbacks.push( () => this.scrollToSlide( slideElement ) );\n\t\t}\n\t\telse {\n\t\t\tslideElement.parentNode.scrollIntoView();\n\t\t}\n\n\t}\n\n\tonScroll() {\n\n\t\tconst viewportElement = this.Reveal.getViewportElement();\n\t\tconst viewportHeight = viewportElement.offsetHeight;\n\n\t\tconst scrollTop = viewportElement.scrollTop;\n\n\t\t// Find the page closest to the center of the viewport, this\n\t\t// is the page we want to focus and activate\n\t\tconst activePage = this.pages.reduce( ( closestPage, page ) => {\n\t\t\tconst distance = Math.abs( ( page.top + page.pageHeight / 2 ) - scrollTop - viewportHeight / 2 );\n\t\t\treturn distance < closestPage.distance ? { page, distance } : closestPage;\n\t\t}, { page: this.pages[0], distance: Infinity } ).page;\n\n\t\tthis.pages.forEach( ( page, pageIndex ) => {\n\t\t\tconst isWithinPreloadRange = scrollTop + viewportHeight >= page.top - viewportHeight && scrollTop < page.top + page.bottom + viewportHeight;\n\t\t\tconst isPartiallyVisible = scrollTop + viewportHeight >= page.top && scrollTop < page.top + page.bottom;\n\n\t\t\t// Preload content when it appears within range\n\t\t\tif( isWithinPreloadRange ) {\n\t\t\t\tif( !page.preloaded ) {\n\t\t\t\t\tpage.preloaded = true;\n\t\t\t\t\tthis.Reveal.slideContent.load( page.slideElement );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if( page.preloaded ) {\n\t\t\t\tpage.preloaded = false;\n\t\t\t\tthis.Reveal.slideContent.unload( page.slideElement );\n\t\t\t}\n\n\t\t\t// Activate the current page — there can only be one active page at\n\t\t\t// a time.\n\t\t\tif( page === activePage ) {\n\t\t\t\tif( !page.active ) {\n\t\t\t\t\tpage.active = true;\n\t\t\t\t\tpage.pageElement.classList.add( 'present' );\n\t\t\t\t\tpage.slideElement.classList.add( 'present' );\n\n\t\t\t\t\tthis.Reveal.setCurrentReaderPage( pageIndex, page.pageElement );\n\t\t\t\t\tthis.Reveal.slideContent.startEmbeddedContent( page.slideElement );\n\n\t\t\t\t\tif( page.backgroundElement ) {\n\t\t\t\t\t\tthis.Reveal.slideContent.startEmbeddedContent( page.backgroundElement );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Deactivate previously active pages\n\t\t\telse if( page.active ) {\n\t\t\t\tpage.active = false;\n\t\t\t\tpage.pageElement.classList.remove( 'present' );\n\t\t\t\tpage.slideElement.classList.remove( 'present' );\n\t\t\t\tthis.Reveal.slideContent.stopEmbeddedContent( page.slideElement );\n\n\t\t\t\tif( page.backgroundElement ) {\n\t\t\t\t\tthis.Reveal.slideContent.stopEmbeddedContent( page.backgroundElement );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle scroll freezing and triggers for slides in view\n\t\t\tif( isPartiallyVisible && page.totalHeight > page.pageHeight ) {\n\t\t\t\tlet scrollProgress = ( scrollTop - page.top ) / page.scrollPadding;\n\t\t\t\tscrollProgress = Math.max( Math.min( scrollProgress, 1 ), 0 );\n\n\t\t\t\tpage.scrollTriggers.forEach( trigger => {\n\t\t\t\t\tif( scrollProgress >= trigger.range[0] && scrollProgress < trigger.range[1] ) {\n\t\t\t\t\t\tif( !trigger.active ) {\n\t\t\t\t\t\t\ttrigger.active = true;\n\t\t\t\t\t\t\tthis.Reveal.fragments.update( trigger.fragmentIndex, page.fragments, page.slideElement );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\ttrigger.active = false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t}\n\n}\n","import { SLIDES_SELECTOR } from '../utils/constants.js'\nimport { queryAll, createStyleSheet } from '../utils/util.js'\n\n/**\n * Setups up our presentation for printing/exporting to PDF.\n */\nexport default class Print {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t}\n\n\t/**\n\t * Configures the presentation for printing to a static\n\t * PDF.\n\t */\n\tasync activate() {\n\n\t\tconst config = this.Reveal.getConfig();\n\t\tconst slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR )\n\n\t\t// Compute slide numbers now, before we start duplicating slides\n\t\tconst injectPageNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber );\n\n\t\tconst slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );\n\n\t\t// Dimensions of the PDF pages\n\t\tconst pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ),\n\t\t\tpageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) );\n\n\t\t// Dimensions of slides within the pages\n\t\tconst slideWidth = slideSize.width,\n\t\t\tslideHeight = slideSize.height;\n\n\t\tawait new Promise( requestAnimationFrame );\n\n\t\t// Let the browser know what page size we want to print\n\t\tcreateStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0px;}' );\n\n\t\t// Limit the size of certain elements to the dimensions of the slide\n\t\tcreateStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );\n\n\t\tdocument.documentElement.classList.add( 'reveal-print', 'print-pdf' );\n\t\tdocument.body.style.width = pageWidth + 'px';\n\t\tdocument.body.style.height = pageHeight + 'px';\n\n\t\tconst viewportElement = this.Reveal.getViewportElement();\n\t\tlet presentationBackground;\n\t\tif( viewportElement ) {\n\t\t\tconst viewportStyles = window.getComputedStyle( viewportElement );\n\t\t\tif( viewportStyles && viewportStyles.background ) {\n\t\t\t\tpresentationBackground = viewportStyles.background;\n\t\t\t}\n\t\t}\n\n\t\t// Make sure stretch elements fit on slide\n\t\tawait new Promise( requestAnimationFrame );\n\t\tthis.Reveal.layoutSlideContents( slideWidth, slideHeight );\n\n\t\t// Batch scrollHeight access to prevent layout thrashing\n\t\tawait new Promise( requestAnimationFrame );\n\n\t\tconst slideScrollHeights = slides.map( slide => slide.scrollHeight );\n\n\t\tconst pages = [];\n\t\tconst pageContainer = slides[0].parentNode;\n\t\tlet slideNumber = 1;\n\n\t\t// Slide and slide background layout\n\t\tslides.forEach( function( slide, index ) {\n\n\t\t\t// Vertical stacks are not centred since their section\n\t\t\t// children will be\n\t\t\tif( slide.classList.contains( 'stack' ) === false ) {\n\t\t\t\t// Center the slide inside of the page, giving the slide some margin\n\t\t\t\tlet left = ( pageWidth - slideWidth ) / 2;\n\t\t\t\tlet top = ( pageHeight - slideHeight ) / 2;\n\n\t\t\t\tconst contentHeight = slideScrollHeights[ index ];\n\t\t\t\tlet numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 );\n\n\t\t\t\t// Adhere to configured pages per slide limit\n\t\t\t\tnumberOfPages = Math.min( numberOfPages, config.pdfMaxPagesPerSlide );\n\n\t\t\t\t// Center slides vertically\n\t\t\t\tif( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) {\n\t\t\t\t\ttop = Math.max( ( pageHeight - contentHeight ) / 2, 0 );\n\t\t\t\t}\n\n\t\t\t\t// Wrap the slide in a page element and hide its overflow\n\t\t\t\t// so that no page ever flows onto another\n\t\t\t\tconst page = document.createElement( 'div' );\n\t\t\t\tpages.push( page );\n\n\t\t\t\tpage.className = 'pdf-page';\n\t\t\t\tpage.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px';\n\n\t\t\t\t// Copy the presentation-wide background to each individual\n\t\t\t\t// page when printing\n\t\t\t\tif( presentationBackground ) {\n\t\t\t\t\tpage.style.background = presentationBackground;\n\t\t\t\t}\n\n\t\t\t\tpage.appendChild( slide );\n\n\t\t\t\t// Position the slide inside of the page\n\t\t\t\tslide.style.left = left + 'px';\n\t\t\t\tslide.style.top = top + 'px';\n\t\t\t\tslide.style.width = slideWidth + 'px';\n\n\t\t\t\tthis.Reveal.slideContent.layout( slide );\n\n\t\t\t\tif( slide.slideBackgroundElement ) {\n\t\t\t\t\tpage.insertBefore( slide.slideBackgroundElement, slide );\n\t\t\t\t}\n\n\t\t\t\t// Inject notes if `showNotes` is enabled\n\t\t\t\tif( config.showNotes ) {\n\n\t\t\t\t\t// Are there notes for this slide?\n\t\t\t\t\tconst notes = this.Reveal.getSlideNotes( slide );\n\t\t\t\t\tif( notes ) {\n\n\t\t\t\t\t\tconst notesSpacing = 8;\n\t\t\t\t\t\tconst notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline';\n\t\t\t\t\t\tconst notesElement = document.createElement( 'div' );\n\t\t\t\t\t\tnotesElement.classList.add( 'speaker-notes' );\n\t\t\t\t\t\tnotesElement.classList.add( 'speaker-notes-pdf' );\n\t\t\t\t\t\tnotesElement.setAttribute( 'data-layout', notesLayout );\n\t\t\t\t\t\tnotesElement.innerHTML = notes;\n\n\t\t\t\t\t\tif( notesLayout === 'separate-page' ) {\n\t\t\t\t\t\t\tpages.push( notesElement );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnotesElement.style.left = notesSpacing + 'px';\n\t\t\t\t\t\t\tnotesElement.style.bottom = notesSpacing + 'px';\n\t\t\t\t\t\t\tnotesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px';\n\t\t\t\t\t\t\tpage.appendChild( notesElement );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\t// Inject page numbers if `slideNumbers` are enabled\n\t\t\t\tif( injectPageNumbers ) {\n\t\t\t\t\tconst numberElement = document.createElement( 'div' );\n\t\t\t\t\tnumberElement.classList.add( 'slide-number' );\n\t\t\t\t\tnumberElement.classList.add( 'slide-number-pdf' );\n\t\t\t\t\tnumberElement.innerHTML = slideNumber++;\n\t\t\t\t\tpage.appendChild( numberElement );\n\t\t\t\t}\n\n\t\t\t\t// Copy page and show fragments one after another\n\t\t\t\tif( config.pdfSeparateFragments ) {\n\n\t\t\t\t\t// Each fragment 'group' is an array containing one or more\n\t\t\t\t\t// fragments. Multiple fragments that appear at the same time\n\t\t\t\t\t// are part of the same group.\n\t\t\t\t\tconst fragmentGroups = this.Reveal.fragments.sort( page.querySelectorAll( '.fragment' ), true );\n\n\t\t\t\t\tlet previousFragmentStep;\n\n\t\t\t\t\tfragmentGroups.forEach( function( fragments, index ) {\n\n\t\t\t\t\t\t// Remove 'current-fragment' from the previous group\n\t\t\t\t\t\tif( previousFragmentStep ) {\n\t\t\t\t\t\t\tpreviousFragmentStep.forEach( function( fragment ) {\n\t\t\t\t\t\t\t\tfragment.classList.remove( 'current-fragment' );\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Show the fragments for the current index\n\t\t\t\t\t\tfragments.forEach( function( fragment ) {\n\t\t\t\t\t\t\tfragment.classList.add( 'visible', 'current-fragment' );\n\t\t\t\t\t\t}, this );\n\n\t\t\t\t\t\t// Create a separate page for the current fragment state\n\t\t\t\t\t\tconst clonedPage = page.cloneNode( true );\n\n\t\t\t\t\t\t// Inject unique page numbers for fragments\n\t\t\t\t\t\tif( injectPageNumbers ) {\n\t\t\t\t\t\t\tconst numberElement = clonedPage.querySelector( '.slide-number-pdf' );\n\t\t\t\t\t\t\tconst fragmentNumber = index + 1;\n\t\t\t\t\t\t\tnumberElement.innerHTML += '.' + fragmentNumber;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpages.push( clonedPage );\n\n\t\t\t\t\t\tpreviousFragmentStep = fragments;\n\n\t\t\t\t\t}, this );\n\n\t\t\t\t\t// Reset the first/original page so that all fragments are hidden\n\t\t\t\t\tfragmentGroups.forEach( function( fragments ) {\n\t\t\t\t\t\tfragments.forEach( function( fragment ) {\n\t\t\t\t\t\t\tfragment.classList.remove( 'visible', 'current-fragment' );\n\t\t\t\t\t\t} );\n\t\t\t\t\t} );\n\n\t\t\t\t}\n\t\t\t\t// Show all fragments\n\t\t\t\telse {\n\t\t\t\t\tqueryAll( page, '.fragment:not(.fade-out)' ).forEach( function( fragment ) {\n\t\t\t\t\t\tfragment.classList.add( 'visible' );\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}, this );\n\n\t\tawait new Promise( requestAnimationFrame );\n\n\t\tpages.forEach( page => pageContainer.appendChild( page ) );\n\n\t\t// Re-run JS-based content layout after the slide is added to page DOM\n\t\tthis.Reveal.slideContent.layout( this.Reveal.getSlidesElement() );\n\n\t\t// Notify subscribers that the PDF layout is good to go\n\t\tthis.Reveal.dispatchEvent({ type: 'pdf-ready' });\n\n\t}\n\n\t/**\n\t * Checks if the print mode is/should be activated.\n\t */\n\tisActive() {\n\n\t\treturn this.Reveal.getConfig().view === 'print';\n\n\t}\n\n}","import { isAndroid } from '../utils/device.js'\nimport { matches } from '../utils/util.js'\n\nconst SWIPE_THRESHOLD = 40;\n\n/**\n * Controls all touch interactions and navigations for\n * a presentation.\n */\nexport default class Touch {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\t// Holds information about the currently ongoing touch interaction\n\t\tthis.touchStartX = 0;\n\t\tthis.touchStartY = 0;\n\t\tthis.touchStartCount = 0;\n\t\tthis.touchCaptured = false;\n\n\t\tthis.onPointerDown = this.onPointerDown.bind( this );\n\t\tthis.onPointerMove = this.onPointerMove.bind( this );\n\t\tthis.onPointerUp = this.onPointerUp.bind( this );\n\t\tthis.onTouchStart = this.onTouchStart.bind( this );\n\t\tthis.onTouchMove = this.onTouchMove.bind( this );\n\t\tthis.onTouchEnd = this.onTouchEnd.bind( this );\n\n\t}\n\n\t/**\n\t *\n\t */\n\tbind() {\n\n\t\tlet revealElement = this.Reveal.getRevealElement();\n\n\t\tif( 'onpointerdown' in window ) {\n\t\t\t// Use W3C pointer events\n\t\t\trevealElement.addEventListener( 'pointerdown', this.onPointerDown, false );\n\t\t\trevealElement.addEventListener( 'pointermove', this.onPointerMove, false );\n\t\t\trevealElement.addEventListener( 'pointerup', this.onPointerUp, false );\n\t\t}\n\t\telse if( window.navigator.msPointerEnabled ) {\n\t\t\t// IE 10 uses prefixed version of pointer events\n\t\t\trevealElement.addEventListener( 'MSPointerDown', this.onPointerDown, false );\n\t\t\trevealElement.addEventListener( 'MSPointerMove', this.onPointerMove, false );\n\t\t\trevealElement.addEventListener( 'MSPointerUp', this.onPointerUp, false );\n\t\t}\n\t\telse {\n\t\t\t// Fall back to touch events\n\t\t\trevealElement.addEventListener( 'touchstart', this.onTouchStart, false );\n\t\t\trevealElement.addEventListener( 'touchmove', this.onTouchMove, false );\n\t\t\trevealElement.addEventListener( 'touchend', this.onTouchEnd, false );\n\t\t}\n\n\t}\n\n\t/**\n\t *\n\t */\n\tunbind() {\n\n\t\tlet revealElement = this.Reveal.getRevealElement();\n\n\t\trevealElement.removeEventListener( 'pointerdown', this.onPointerDown, false );\n\t\trevealElement.removeEventListener( 'pointermove', this.onPointerMove, false );\n\t\trevealElement.removeEventListener( 'pointerup', this.onPointerUp, false );\n\n\t\trevealElement.removeEventListener( 'MSPointerDown', this.onPointerDown, false );\n\t\trevealElement.removeEventListener( 'MSPointerMove', this.onPointerMove, false );\n\t\trevealElement.removeEventListener( 'MSPointerUp', this.onPointerUp, false );\n\n\t\trevealElement.removeEventListener( 'touchstart', this.onTouchStart, false );\n\t\trevealElement.removeEventListener( 'touchmove', this.onTouchMove, false );\n\t\trevealElement.removeEventListener( 'touchend', this.onTouchEnd, false );\n\n\t}\n\n\t/**\n\t * Checks if the target element prevents the triggering of\n\t * swipe navigation.\n\t */\n\tisSwipePrevented( target ) {\n\n\t\t// Prevent accidental swipes when scrubbing timelines\n\t\tif( matches( target, 'video, audio' ) ) return true;\n\n\t\twhile( target && typeof target.hasAttribute === 'function' ) {\n\t\t\tif( target.hasAttribute( 'data-prevent-swipe' ) ) return true;\n\t\t\ttarget = target.parentNode;\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t/**\n\t * Handler for the 'touchstart' event, enables support for\n\t * swipe and pinch gestures.\n\t *\n\t * @param {object} event\n\t */\n\tonTouchStart( event ) {\n\n\t\tif( this.isSwipePrevented( event.target ) ) return true;\n\n\t\tthis.touchStartX = event.touches[0].clientX;\n\t\tthis.touchStartY = event.touches[0].clientY;\n\t\tthis.touchStartCount = event.touches.length;\n\n\t}\n\n\t/**\n\t * Handler for the 'touchmove' event.\n\t *\n\t * @param {object} event\n\t */\n\tonTouchMove( event ) {\n\n\t\tif( this.isSwipePrevented( event.target ) ) return true;\n\n\t\tlet config = this.Reveal.getConfig();\n\n\t\t// Each touch should only trigger one action\n\t\tif( !this.touchCaptured ) {\n\t\t\tthis.Reveal.onUserInput( event );\n\n\t\t\tlet currentX = event.touches[0].clientX;\n\t\t\tlet currentY = event.touches[0].clientY;\n\n\t\t\t// There was only one touch point, look for a swipe\n\t\t\tif( event.touches.length === 1 && this.touchStartCount !== 2 ) {\n\n\t\t\t\tlet availableRoutes = this.Reveal.availableRoutes({ includeFragments: true });\n\n\t\t\t\tlet deltaX = currentX - this.touchStartX,\n\t\t\t\t\tdeltaY = currentY - this.touchStartY;\n\n\t\t\t\tif( deltaX > SWIPE_THRESHOLD && Math.abs( deltaX ) > Math.abs( deltaY ) ) {\n\t\t\t\t\tthis.touchCaptured = true;\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\n\t\t\t\t\t\tif( config.rtl ) {\n\t\t\t\t\t\t\tthis.Reveal.next();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis.Reveal.prev();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.Reveal.left();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( deltaX < -SWIPE_THRESHOLD && Math.abs( deltaX ) > Math.abs( deltaY ) ) {\n\t\t\t\t\tthis.touchCaptured = true;\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\n\t\t\t\t\t\tif( config.rtl ) {\n\t\t\t\t\t\t\tthis.Reveal.prev();\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tthis.Reveal.next();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.Reveal.right();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( deltaY > SWIPE_THRESHOLD && availableRoutes.up ) {\n\t\t\t\t\tthis.touchCaptured = true;\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\n\t\t\t\t\t\tthis.Reveal.prev();\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.Reveal.up();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( deltaY < -SWIPE_THRESHOLD && availableRoutes.down ) {\n\t\t\t\t\tthis.touchCaptured = true;\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\n\t\t\t\t\t\tthis.Reveal.next();\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.Reveal.down();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If we're embedded, only block touch events if they have\n\t\t\t\t// triggered an action\n\t\t\t\tif( config.embedded ) {\n\t\t\t\t\tif( this.touchCaptured || this.Reveal.isVerticalSlide() ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Not embedded? Block them all to avoid needless tossing\n\t\t\t\t// around of the viewport in iOS\n\t\t\t\telse {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t\t// There's a bug with swiping on some Android devices unless\n\t\t// the default action is always prevented\n\t\telse if( isAndroid ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\n\t}\n\n\t/**\n\t * Handler for the 'touchend' event.\n\t *\n\t * @param {object} event\n\t */\n\tonTouchEnd( event ) {\n\n\t\tthis.touchCaptured = false;\n\n\t}\n\n\t/**\n\t * Convert pointer down to touch start.\n\t *\n\t * @param {object} event\n\t */\n\tonPointerDown( event ) {\n\n\t\tif( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === \"touch\" ) {\n\t\t\tevent.touches = [{ clientX: event.clientX, clientY: event.clientY }];\n\t\t\tthis.onTouchStart( event );\n\t\t}\n\n\t}\n\n\t/**\n\t * Convert pointer move to touch move.\n\t *\n\t * @param {object} event\n\t */\n\tonPointerMove( event ) {\n\n\t\tif( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === \"touch\" ) {\n\t\t\tevent.touches = [{ clientX: event.clientX, clientY: event.clientY }];\n\t\t\tthis.onTouchMove( event );\n\t\t}\n\n\t}\n\n\t/**\n\t * Convert pointer up to touch end.\n\t *\n\t * @param {object} event\n\t */\n\tonPointerUp( event ) {\n\n\t\tif( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === \"touch\" ) {\n\t\t\tevent.touches = [{ clientX: event.clientX, clientY: event.clientY }];\n\t\t\tthis.onTouchEnd( event );\n\t\t}\n\n\t}\n\n}","import { closest } from '../utils/util.js'\n\n/**\n * Manages focus when a presentation is embedded. This\n * helps us only capture keyboard from the presentation\n * a user is currently interacting with in a page where\n * multiple presentations are embedded.\n */\n\nconst STATE_FOCUS = 'focus';\nconst STATE_BLUR = 'blur';\n\nexport default class Focus {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t\tthis.onRevealPointerDown = this.onRevealPointerDown.bind( this );\n\t\tthis.onDocumentPointerDown = this.onDocumentPointerDown.bind( this );\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tif( config.embedded ) {\n\t\t\tthis.blur();\n\t\t}\n\t\telse {\n\t\t\tthis.focus();\n\t\t\tthis.unbind();\n\t\t}\n\n\t}\n\n\tbind() {\n\n\t\tif( this.Reveal.getConfig().embedded ) {\n\t\t\tthis.Reveal.getRevealElement().addEventListener( 'pointerdown', this.onRevealPointerDown, false );\n\t\t}\n\n\t}\n\n\tunbind() {\n\n\t\tthis.Reveal.getRevealElement().removeEventListener( 'pointerdown', this.onRevealPointerDown, false );\n\t\tdocument.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );\n\n\t}\n\n\tfocus() {\n\n\t\tif( this.state !== STATE_FOCUS ) {\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'focused' );\n\t\t\tdocument.addEventListener( 'pointerdown', this.onDocumentPointerDown, false );\n\t\t}\n\n\t\tthis.state = STATE_FOCUS;\n\n\t}\n\n\tblur() {\n\n\t\tif( this.state !== STATE_BLUR ) {\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'focused' );\n\t\t\tdocument.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );\n\t\t}\n\n\t\tthis.state = STATE_BLUR;\n\n\t}\n\n\tisFocused() {\n\n\t\treturn this.state === STATE_FOCUS;\n\n\t}\n\n\tdestroy() {\n\n\t\tthis.Reveal.getRevealElement().classList.remove( 'focused' );\n\n\t}\n\n\tonRevealPointerDown( event ) {\n\n\t\tthis.focus();\n\n\t}\n\n\tonDocumentPointerDown( event ) {\n\n\t\tlet revealElement = closest( event.target, '.reveal' );\n\t\tif( !revealElement || revealElement !== this.Reveal.getRevealElement() ) {\n\t\t\tthis.blur();\n\t\t}\n\n\t}\n\n}","/**\n * Handles the showing of speaker notes\n */\nexport default class Notes {\n\n\tconstructor( Reveal ) {\n\n\t\tthis.Reveal = Reveal;\n\n\t}\n\n\trender() {\n\n\t\tthis.element = document.createElement( 'div' );\n\t\tthis.element.className = 'speaker-notes';\n\t\tthis.element.setAttribute( 'data-prevent-swipe', '' );\n\t\tthis.element.setAttribute( 'tabindex', '0' );\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\n\n\t}\n\n\t/**\n\t * Called when the reveal.js config is updated.\n\t */\n\tconfigure( config, oldConfig ) {\n\n\t\tif( config.showNotes ) {\n\t\t\tthis.element.setAttribute( 'data-layout', typeof config.showNotes === 'string' ? config.showNotes : 'inline' );\n\t\t}\n\n\t}\n\n\t/**\n\t * Pick up notes from the current slide and display them\n\t * to the viewer.\n\t *\n\t * @see {@link config.showNotes}\n\t */\n\tupdate() {\n\n\t\tif( this.Reveal.getConfig().showNotes &&\n\t\t\tthis.element && this.Reveal.getCurrentSlide() &&\n\t\t\t!this.Reveal.isReaderMode() &&\n\t\t\t!this.Reveal.isPrinting()\n\t\t) {\n\t\t\tthis.element.innerHTML = this.getSlideNotes() || '<span class=\"notes-placeholder\">No notes on this slide.</span>';\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates the visibility of the speaker notes sidebar that\n\t * is used to share annotated slides. The notes sidebar is\n\t * only visible if showNotes is true and there are notes on\n\t * one or more slides in the deck.\n\t */\n\tupdateVisibility() {\n\n\t\tif( this.Reveal.getConfig().showNotes &&\n\t\t\tthis.hasNotes() &&\n\t\t\t!this.Reveal.isReaderMode() &&\n\t\t\t!this.Reveal.isPrinting()\n\t\t) {\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'show-notes' );\n\t\t}\n\t\telse {\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'show-notes' );\n\t\t}\n\n\t}\n\n\t/**\n\t * Checks if there are speaker notes for ANY slide in the\n\t * presentation.\n\t */\n\thasNotes() {\n\n\t\treturn this.Reveal.getSlidesElement().querySelectorAll( '[data-notes], aside.notes' ).length > 0;\n\n\t}\n\n\t/**\n\t * Checks if this presentation is running inside of the\n\t * speaker notes window.\n\t *\n\t * @return {boolean}\n\t */\n\tisSpeakerNotesWindow() {\n\n\t\treturn !!window.location.search.match( /receiver/gi );\n\n\t}\n\n\t/**\n\t * Retrieves the speaker notes from a slide. Notes can be\n\t * defined in two ways:\n\t * 1. As a data-notes attribute on the slide <section>\n\t * 2. With <aside class=\"notes\"> elements inside the slide\n\t *\n\t * @param {HTMLElement} [slide=currentSlide]\n\t * @return {(string|null)}\n\t */\n\tgetSlideNotes( slide = this.Reveal.getCurrentSlide() ) {\n\n\t\t// Notes can be specified via the data-notes attribute...\n\t\tif( slide.hasAttribute( 'data-notes' ) ) {\n\t\t\treturn slide.getAttribute( 'data-notes' );\n\t\t}\n\n\t\t// ... or using <aside class=\"notes\"> elements\n\t\tlet notesElements = slide.querySelectorAll( 'aside.notes' );\n\t\tif( notesElements ) {\n\t\t\treturn Array.from(notesElements).map( notesElement => notesElement.innerHTML ).join( '\\n' );\n\t\t}\n\n\t\treturn null;\n\n\t}\n\n\tdestroy() {\n\n\t\tthis.element.remove();\n\n\t}\n\n}","/**\n * UI component that lets the use control auto-slide\n * playback via play/pause.\n */\nexport default class Playback {\n\n\t/**\n\t * @param {HTMLElement} container The component will append\n\t * itself to this\n\t * @param {function} progressCheck A method which will be\n\t * called frequently to get the current playback progress on\n\t * a range of 0-1\n\t */\n\tconstructor( container, progressCheck ) {\n\n\t\t// Cosmetics\n\t\tthis.diameter = 100;\n\t\tthis.diameter2 = this.diameter/2;\n\t\tthis.thickness = 6;\n\n\t\t// Flags if we are currently playing\n\t\tthis.playing = false;\n\n\t\t// Current progress on a 0-1 range\n\t\tthis.progress = 0;\n\n\t\t// Used to loop the animation smoothly\n\t\tthis.progressOffset = 1;\n\n\t\tthis.container = container;\n\t\tthis.progressCheck = progressCheck;\n\n\t\tthis.canvas = document.createElement( 'canvas' );\n\t\tthis.canvas.className = 'playback';\n\t\tthis.canvas.width = this.diameter;\n\t\tthis.canvas.height = this.diameter;\n\t\tthis.canvas.style.width = this.diameter2 + 'px';\n\t\tthis.canvas.style.height = this.diameter2 + 'px';\n\t\tthis.context = this.canvas.getContext( '2d' );\n\n\t\tthis.container.appendChild( this.canvas );\n\n\t\tthis.render();\n\n\t}\n\n\tsetPlaying( value ) {\n\n\t\tconst wasPlaying = this.playing;\n\n\t\tthis.playing = value;\n\n\t\t// Start repainting if we weren't already\n\t\tif( !wasPlaying && this.playing ) {\n\t\t\tthis.animate();\n\t\t}\n\t\telse {\n\t\t\tthis.render();\n\t\t}\n\n\t}\n\n\tanimate() {\n\n\t\tconst progressBefore = this.progress;\n\n\t\tthis.progress = this.progressCheck();\n\n\t\t// When we loop, offset the progress so that it eases\n\t\t// smoothly rather than immediately resetting\n\t\tif( progressBefore > 0.8 && this.progress < 0.2 ) {\n\t\t\tthis.progressOffset = this.progress;\n\t\t}\n\n\t\tthis.render();\n\n\t\tif( this.playing ) {\n\t\t\trequestAnimationFrame( this.animate.bind( this ) );\n\t\t}\n\n\t}\n\n\t/**\n\t * Renders the current progress and playback state.\n\t */\n\trender() {\n\n\t\tlet progress = this.playing ? this.progress : 0,\n\t\t\tradius = ( this.diameter2 ) - this.thickness,\n\t\t\tx = this.diameter2,\n\t\t\ty = this.diameter2,\n\t\t\ticonSize = 28;\n\n\t\t// Ease towards 1\n\t\tthis.progressOffset += ( 1 - this.progressOffset ) * 0.1;\n\n\t\tconst endAngle = ( - Math.PI / 2 ) + ( progress * ( Math.PI * 2 ) );\n\t\tconst startAngle = ( - Math.PI / 2 ) + ( this.progressOffset * ( Math.PI * 2 ) );\n\n\t\tthis.context.save();\n\t\tthis.context.clearRect( 0, 0, this.diameter, this.diameter );\n\n\t\t// Solid background color\n\t\tthis.context.beginPath();\n\t\tthis.context.arc( x, y, radius + 4, 0, Math.PI * 2, false );\n\t\tthis.context.fillStyle = 'rgba( 0, 0, 0, 0.4 )';\n\t\tthis.context.fill();\n\n\t\t// Draw progress track\n\t\tthis.context.beginPath();\n\t\tthis.context.arc( x, y, radius, 0, Math.PI * 2, false );\n\t\tthis.context.lineWidth = this.thickness;\n\t\tthis.context.strokeStyle = 'rgba( 255, 255, 255, 0.2 )';\n\t\tthis.context.stroke();\n\n\t\tif( this.playing ) {\n\t\t\t// Draw progress on top of track\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.arc( x, y, radius, startAngle, endAngle, false );\n\t\t\tthis.context.lineWidth = this.thickness;\n\t\t\tthis.context.strokeStyle = '#fff';\n\t\t\tthis.context.stroke();\n\t\t}\n\n\t\tthis.context.translate( x - ( iconSize / 2 ), y - ( iconSize / 2 ) );\n\n\t\t// Draw play/pause icons\n\t\tif( this.playing ) {\n\t\t\tthis.context.fillStyle = '#fff';\n\t\t\tthis.context.fillRect( 0, 0, iconSize / 2 - 4, iconSize );\n\t\t\tthis.context.fillRect( iconSize / 2 + 4, 0, iconSize / 2 - 4, iconSize );\n\t\t}\n\t\telse {\n\t\t\tthis.context.beginPath();\n\t\t\tthis.context.translate( 4, 0 );\n\t\t\tthis.context.moveTo( 0, 0 );\n\t\t\tthis.context.lineTo( iconSize - 4, iconSize / 2 );\n\t\t\tthis.context.lineTo( 0, iconSize );\n\t\t\tthis.context.fillStyle = '#fff';\n\t\t\tthis.context.fill();\n\t\t}\n\n\t\tthis.context.restore();\n\n\t}\n\n\ton( type, listener ) {\n\t\tthis.canvas.addEventListener( type, listener, false );\n\t}\n\n\toff( type, listener ) {\n\t\tthis.canvas.removeEventListener( type, listener, false );\n\t}\n\n\tdestroy() {\n\n\t\tthis.playing = false;\n\n\t\tif( this.canvas.parentNode ) {\n\t\t\tthis.container.removeChild( this.canvas );\n\t\t}\n\n\t}\n\n}","/**\n * The default reveal.js config object.\n */\nexport default {\n\n\t// The \"normal\" size of the presentation, aspect ratio will be preserved\n\t// when the presentation is scaled to fit different resolutions\n\twidth: 960,\n\theight: 700,\n\n\t// Factor of the display size that should remain empty around the content\n\tmargin: 0.04,\n\n\t// Bounds for smallest/largest possible scale to apply to content\n\tminScale: 0.2,\n\tmaxScale: 2.0,\n\n\t// Display presentation control arrows\n\tcontrols: true,\n\n\t// Help the user learn the controls by providing hints, for example by\n\t// bouncing the down arrow when they first encounter a vertical slide\n\tcontrolsTutorial: true,\n\n\t// Determines where controls appear, \"edges\" or \"bottom-right\"\n\tcontrolsLayout: 'bottom-right',\n\n\t// Visibility rule for backwards navigation arrows; \"faded\", \"hidden\"\n\t// or \"visible\"\n\tcontrolsBackArrows: 'faded',\n\n\t// Display a presentation progress bar\n\tprogress: true,\n\n\t// Display the page number of the current slide\n\t// - true: Show slide number\n\t// - false: Hide slide number\n\t//\n\t// Can optionally be set as a string that specifies the number formatting:\n\t// - \"h.v\":\t Horizontal . vertical slide number (default)\n\t// - \"h/v\":\t Horizontal / vertical slide number\n\t// - \"c\":\t Flattened slide number\n\t// - \"c/t\":\t Flattened slide number / total slides\n\t//\n\t// Alternatively, you can provide a function that returns the slide\n\t// number for the current slide. The function should take in a slide\n\t// object and return an array with one string [slideNumber] or\n\t// three strings [n1,delimiter,n2]. See #formatSlideNumber().\n\tslideNumber: false,\n\n\t// Can be used to limit the contexts in which the slide number appears\n\t// - \"all\": Always show the slide number\n\t// - \"print\": Only when printing to PDF\n\t// - \"speaker\": Only in the speaker view\n\tshowSlideNumber: 'all',\n\n\t// Use 1 based indexing for # links to match slide number (default is zero\n\t// based)\n\thashOneBasedIndex: false,\n\n\t// Add the current slide number to the URL hash so that reloading the\n\t// page/copying the URL will return you to the same slide\n\thash: false,\n\n\t// Flags if we should monitor the hash and change slides accordingly\n\trespondToHashChanges: true,\n\n\t// Enable support for jump-to-slide navigation shortcuts\n\tjumpToSlide: true,\n\n\t// Push each slide change to the browser history. Implies `hash: true`\n\thistory: false,\n\n\t// Enable keyboard shortcuts for navigation\n\tkeyboard: true,\n\n\t// Optional function that blocks keyboard events when retuning false\n\t//\n\t// If you set this to 'focused', we will only capture keyboard events\n\t// for embedded decks when they are in focus\n\tkeyboardCondition: null,\n\n\t// Disables the default reveal.js slide layout (scaling and centering)\n\t// so that you can use custom CSS layout\n\tdisableLayout: false,\n\n\t// Enable the slide overview mode\n\toverview: true,\n\n\t// Vertical centering of slides\n\tcenter: true,\n\n\t// Enables touch navigation on devices with touch input\n\ttouch: true,\n\n\t// Loop the presentation\n\tloop: false,\n\n\t// Change the presentation direction to be RTL\n\trtl: false,\n\n\t// Changes the behavior of our navigation directions.\n\t//\n\t// \"default\"\n\t// Left/right arrow keys step between horizontal slides, up/down\n\t// arrow keys step between vertical slides. Space key steps through\n\t// all slides (both horizontal and vertical).\n\t//\n\t// \"linear\"\n\t// Removes the up/down arrows. Left/right arrows step through all\n\t// slides (both horizontal and vertical).\n\t//\n\t// \"grid\"\n\t// When this is enabled, stepping left/right from a vertical stack\n\t// to an adjacent vertical stack will land you at the same vertical\n\t// index.\n\t//\n\t// Consider a deck with six slides ordered in two vertical stacks:\n\t// 1.1 2.1\n\t// 1.2 2.2\n\t// 1.3 2.3\n\t//\n\t// If you're on slide 1.3 and navigate right, you will normally move\n\t// from 1.3 -> 2.1. If \"grid\" is used, the same navigation takes you\n\t// from 1.3 -> 2.3.\n\tnavigationMode: 'default',\n\n\t// Randomizes the order of slides each time the presentation loads\n\tshuffle: false,\n\n\t// Turns fragments on and off globally\n\tfragments: true,\n\n\t// Flags whether to include the current fragment in the URL,\n\t// so that reloading brings you to the same fragment position\n\tfragmentInURL: true,\n\n\t// Flags if the presentation is running in an embedded mode,\n\t// i.e. contained within a limited portion of the screen\n\tembedded: false,\n\n\t// Flags if we should show a help overlay when the question-mark\n\t// key is pressed\n\thelp: true,\n\n\t// Flags if it should be possible to pause the presentation (blackout)\n\tpause: true,\n\n\t// Flags if speaker notes should be visible to all viewers\n\tshowNotes: false,\n\n\t// Flags if slides with data-visibility=\"hidden\" should be kep visible\n\tshowHiddenSlides: false,\n\n\t// Global override for autoplaying embedded media (video/audio/iframe)\n\t// - null: Media will only autoplay if data-autoplay is present\n\t// - true: All media will autoplay, regardless of individual setting\n\t// - false: No media will autoplay, regardless of individual setting\n\tautoPlayMedia: null,\n\n\t// Global override for preloading lazy-loaded iframes\n\t// - null: Iframes with data-src AND data-preload will be loaded when within\n\t// the viewDistance, iframes with only data-src will be loaded when visible\n\t// - true: All iframes with data-src will be loaded when within the viewDistance\n\t// - false: All iframes with data-src will be loaded only when visible\n\tpreloadIframes: null,\n\n\t// Can be used to globally disable auto-animation\n\tautoAnimate: true,\n\n\t// Optionally provide a custom element matcher that will be\n\t// used to dictate which elements we can animate between.\n\tautoAnimateMatcher: null,\n\n\t// Default settings for our auto-animate transitions, can be\n\t// overridden per-slide or per-element via data arguments\n\tautoAnimateEasing: 'ease',\n\tautoAnimateDuration: 1.0,\n\tautoAnimateUnmatched: true,\n\n\t// CSS properties that can be auto-animated. Position & scale\n\t// is matched separately so there's no need to include styles\n\t// like top/right/bottom/left, width/height or margin.\n\tautoAnimateStyles: [\n\t\t'opacity',\n\t\t'color',\n\t\t'background-color',\n\t\t'padding',\n\t\t'font-size',\n\t\t'line-height',\n\t\t'letter-spacing',\n\t\t'border-width',\n\t\t'border-color',\n\t\t'border-radius',\n\t\t'outline',\n\t\t'outline-offset'\n\t],\n\n\t// Controls automatic progression to the next slide\n\t// - 0: Auto-sliding only happens if the data-autoslide HTML attribute\n\t// is present on the current slide or fragment\n\t// - 1+: All slides will progress automatically at the given interval\n\t// - false: No auto-sliding, even if data-autoslide is present\n\tautoSlide: 0,\n\n\t// Stop auto-sliding after user input\n\tautoSlideStoppable: true,\n\n\t// Use this method for navigation when auto-sliding (defaults to navigateNext)\n\tautoSlideMethod: null,\n\n\t// Specify the average time in seconds that you think you will spend\n\t// presenting each slide. This is used to show a pacing timer in the\n\t// speaker view\n\tdefaultTiming: null,\n\n\t// Enable slide navigation via mouse wheel\n\tmouseWheel: false,\n\n\t// Opens links in an iframe preview overlay\n\t// Add `data-preview-link` and `data-preview-link=\"false\"` to customise each link\n\t// individually\n\tpreviewLinks: false,\n\n\t// Exposes the reveal.js API through window.postMessage\n\tpostMessage: true,\n\n\t// Dispatches all reveal.js events to the parent window through postMessage\n\tpostMessageEvents: false,\n\n\t// Focuses body when page changes visibility to ensure keyboard shortcuts work\n\tfocusBodyOnPageVisibilityChange: true,\n\n\t// Transition style\n\ttransition: 'slide', // none/fade/slide/convex/concave/zoom\n\n\t// Transition speed\n\ttransitionSpeed: 'default', // default/fast/slow\n\n\t// Transition style for full page slide backgrounds\n\tbackgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom\n\n\t// Parallax background image\n\tparallaxBackgroundImage: '', // CSS syntax, e.g. \"a.jpg\"\n\n\t// Parallax background size\n\tparallaxBackgroundSize: '', // CSS syntax, e.g. \"3000px 2000px\"\n\n\t// Parallax background repeat\n\tparallaxBackgroundRepeat: '', // repeat/repeat-x/repeat-y/no-repeat/initial/inherit\n\n\t// Parallax background position\n\tparallaxBackgroundPosition: '', // CSS syntax, e.g. \"top left\"\n\n\t// Amount of pixels to move the parallax background per slide step\n\tparallaxBackgroundHorizontal: null,\n\tparallaxBackgroundVertical: null,\n\n\t// Can be used to initialize reveal.js in one of the following views:\n\t// - print: Render the presentation so that it can be printed to PDF\n\t// - reader: Show the presentation as a tall scrollable page with scroll\n\t// triggered animations\n\tview: null,\n\n\t// Adjusts the height of each slide in reader mode\n\t// - full: Each slide is as tall as the viewport\n\t// - compact: Slides are as small as possible, allowing multiple slides\n\t// to be visible in parallel on tall devices\n\treaderLayout: 'full',\n\n\t// Control how scroll snapping works in reader mode.\n\t// - false: \tNo snapping, scrolling is continuous\n\t// - proximity: Snap when close to a slide\n\t// - mandatory: Always snap to the closest slide\n\t//\n\t// Only applies to presentations in reader mode.\n\treaderScrollSnap: 'proximity',\n\n\t// Responsively activate the reader mode when we reach the specified\n\t// width (in pixels)\n\treaderActivationWidth: null,\n\n\t// The maximum number of pages a single slide can expand onto when printing\n\t// to PDF, unlimited by default\n\tpdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,\n\n\t// Prints each fragment on a separate slide\n\tpdfSeparateFragments: true,\n\n\t// Offset used to reduce the height of content within exported PDF pages.\n\t// This exists to account for environment differences based on how you\n\t// print to PDF. CLI printing options, like phantomjs and wkpdf, can end\n\t// on precisely the total height of the document whereas in-browser\n\t// printing has to end one pixel before.\n\tpdfPageHeightOffset: -1,\n\n\t// Number of slides away from the current that are visible\n\tviewDistance: 3,\n\n\t// Number of slides away from the current that are visible on mobile\n\t// devices. It is advisable to set this to a lower number than\n\t// viewDistance in order to save resources.\n\tmobileViewDistance: 2,\n\n\t// The display mode that will be used to show slides\n\tdisplay: 'block',\n\n\t// Hide cursor if inactive\n\thideInactiveCursor: true,\n\n\t// Time before the cursor is hidden (in ms)\n\thideCursorTime: 5000,\n\n\t// Should we automatically sort and set indices for fragments\n\t// at each sync? (See Reveal.sync)\n\tsortFragmentsOnSync: true,\n\n\t// Script dependencies to load\n\tdependencies: [],\n\n\t// Plugin objects to register and use for this presentation\n\tplugins: []\n\n}","import SlideContent from './controllers/slidecontent.js'\nimport SlideNumber from './controllers/slidenumber.js'\nimport JumpToSlide from './controllers/jumptoslide.js'\nimport Backgrounds from './controllers/backgrounds.js'\nimport AutoAnimate from './controllers/autoanimate.js'\nimport Fragments from './controllers/fragments.js'\nimport Overview from './controllers/overview.js'\nimport Keyboard from './controllers/keyboard.js'\nimport Location from './controllers/location.js'\nimport Controls from './controllers/controls.js'\nimport Progress from './controllers/progress.js'\nimport Pointer from './controllers/pointer.js'\nimport Plugins from './controllers/plugins.js'\nimport Reader from './controllers/reader.js'\nimport Print from './controllers/print.js'\nimport Touch from './controllers/touch.js'\nimport Focus from './controllers/focus.js'\nimport Notes from './controllers/notes.js'\nimport Playback from './components/playback.js'\nimport defaultConfig from './config.js'\nimport * as Util from './utils/util.js'\nimport * as Device from './utils/device.js'\nimport {\n\tSLIDES_SELECTOR,\n\tHORIZONTAL_SLIDES_SELECTOR,\n\tVERTICAL_SLIDES_SELECTOR,\n\tPOST_MESSAGE_METHOD_BLACKLIST\n} from './utils/constants.js'\n\n// The reveal.js version\nexport const VERSION = '4.6.0';\n\n/**\n * reveal.js\n * https://revealjs.com\n * MIT licensed\n *\n * Copyright (C) 2011-2022 Hakim El Hattab, https://hakim.se\n */\nexport default function( revealElement, options ) {\n\n\t// Support initialization with no args, one arg\n\t// [options] or two args [revealElement, options]\n\tif( arguments.length < 2 ) {\n\t\toptions = arguments[0];\n\t\trevealElement = document.querySelector( '.reveal' );\n\t}\n\n\tconst Reveal = {};\n\n\t// Configuration defaults, can be overridden at initialization time\n\tlet config = {},\n\n\t\t// Flags if reveal.js is loaded (has dispatched the 'ready' event)\n\t\tready = false,\n\n\t\t// The horizontal and vertical index of the currently active slide\n\t\tindexh,\n\t\tindexv,\n\n\t\t// The previous and current slide HTML elements\n\t\tpreviousSlide,\n\t\tcurrentSlide,\n\n\t\t// Remember which directions that the user has navigated towards\n\t\tnavigationHistory = {\n\t\t\thasNavigatedHorizontally: false,\n\t\t\thasNavigatedVertically: false\n\t\t},\n\n\t\t// Slides may have a data-state attribute which we pick up and apply\n\t\t// as a class to the body. This list contains the combined state of\n\t\t// all current slides.\n\t\tstate = [],\n\n\t\t// The current scale of the presentation (see width/height config)\n\t\tscale = 1,\n\n\t\t// CSS transform that is currently applied to the slides container,\n\t\t// split into two groups\n\t\tslidesTransform = { layout: '', overview: '' },\n\n\t\t// Cached references to DOM elements\n\t\tdom = {},\n\n\t\t// Flags if the interaction event listeners are bound\n\t\teventsAreBound = false,\n\n\t\t// The current slide transition state; idle or running\n\t\ttransition = 'idle',\n\n\t\t// The current auto-slide duration\n\t\tautoSlide = 0,\n\n\t\t// Auto slide properties\n\t\tautoSlidePlayer,\n\t\tautoSlideTimeout = 0,\n\t\tautoSlideStartTime = -1,\n\t\tautoSlidePaused = false,\n\n\t\t// Controllers for different aspects of our presentation. They're\n\t\t// all given direct references to this Reveal instance since there\n\t\t// may be multiple presentations running in parallel.\n\t\tslideContent = new SlideContent( Reveal ),\n\t\tslideNumber = new SlideNumber( Reveal ),\n\t\tjumpToSlide = new JumpToSlide( Reveal ),\n\t\tautoAnimate = new AutoAnimate( Reveal ),\n\t\tbackgrounds = new Backgrounds( Reveal ),\n\t\tfragments = new Fragments( Reveal ),\n\t\toverview = new Overview( Reveal ),\n\t\tkeyboard = new Keyboard( Reveal ),\n\t\tlocation = new Location( Reveal ),\n\t\tcontrols = new Controls( Reveal ),\n\t\tprogress = new Progress( Reveal ),\n\t\tpointer = new Pointer( Reveal ),\n\t\tplugins = new Plugins( Reveal ),\n\t\treader = new Reader( Reveal ),\n\t\tprint = new Print( Reveal ),\n\t\tfocus = new Focus( Reveal ),\n\t\ttouch = new Touch( Reveal ),\n\t\tnotes = new Notes( Reveal );\n\n\t/**\n\t * Starts up the presentation.\n\t */\n\tfunction initialize( initOptions ) {\n\n\t\tif( !revealElement ) throw 'Unable to find presentation root (<div class=\"reveal\">).';\n\n\t\t// Cache references to key DOM elements\n\t\tdom.wrapper = revealElement;\n\t\tdom.slides = revealElement.querySelector( '.slides' );\n\n\t\tif( !dom.slides ) throw 'Unable to find slides container (<div class=\"slides\">).';\n\n\t\t// Compose our config object in order of increasing precedence:\n\t\t// 1. Default reveal.js options\n\t\t// 2. Options provided via Reveal.configure() prior to\n\t\t// initialization\n\t\t// 3. Options passed to the Reveal constructor\n\t\t// 4. Options passed to Reveal.initialize\n\t\t// 5. Query params\n\t\tconfig = { ...defaultConfig, ...config, ...options, ...initOptions, ...Util.getQueryHash() };\n\n\t\t// Legacy support for the ?print-pdf query\n\t\tif( /print-pdf/gi.test( window.location.search ) ) {\n\t\t\tconfig.view = 'print';\n\t\t}\n\n\t\tsetViewport();\n\n\t\t// Force a layout when the whole page, incl fonts, has loaded\n\t\twindow.addEventListener( 'load', layout, false );\n\n\t\t// Register plugins and load dependencies, then move on to #start()\n\t\tplugins.load( config.plugins, config.dependencies ).then( start );\n\n\t\treturn new Promise( resolve => Reveal.on( 'ready', resolve ) );\n\n\t}\n\n\t/**\n\t * Encase the presentation in a reveal.js viewport. The\n\t * extent of the viewport differs based on configuration.\n\t */\n\tfunction setViewport() {\n\n\t\t// Embedded decks use the reveal element as their viewport\n\t\tif( config.embedded === true ) {\n\t\t\tdom.viewport = Util.closest( revealElement, '.reveal-viewport' ) || revealElement;\n\t\t}\n\t\t// Full-page decks use the body as their viewport\n\t\telse {\n\t\t\tdom.viewport = document.body;\n\t\t\tdocument.documentElement.classList.add( 'reveal-full-page' );\n\t\t}\n\n\t\tdom.viewport.classList.add( 'reveal-viewport' );\n\n\t}\n\n\t/**\n\t * Starts up reveal.js by binding input events and navigating\n\t * to the current URL deeplink if there is one.\n\t */\n\tfunction start() {\n\n\t\tready = true;\n\n\t\t// Remove slides hidden with data-visibility\n\t\tremoveHiddenSlides();\n\n\t\t// Make sure we've got all the DOM elements we need\n\t\tsetupDOM();\n\n\t\t// Listen to messages posted to this window\n\t\tsetupPostMessage();\n\n\t\t// Prevent the slides from being scrolled out of view\n\t\tsetupScrollPrevention();\n\n\t\t// Adds bindings for fullscreen mode\n\t\tsetupFullscreen();\n\n\t\t// Resets all vertical slides so that only the first is visible\n\t\tresetVerticalSlides();\n\n\t\t// Updates the presentation to match the current configuration values\n\t\tconfigure();\n\n\t\t// Read the initial hash\n\t\tlocation.readURL();\n\n\t\t// Create slide backgrounds\n\t\tbackgrounds.update( true );\n\n\t\t// Notify listeners that the presentation is ready but use a 1ms\n\t\t// timeout to ensure it's not fired synchronously after #initialize()\n\t\tsetTimeout( () => {\n\t\t\t// Enable transitions now that we're loaded\n\t\t\tdom.slides.classList.remove( 'no-transition' );\n\n\t\t\tdom.wrapper.classList.add( 'ready' );\n\n\t\t\tdispatchEvent({\n\t\t\t\ttype: 'ready',\n\t\t\t\tdata: {\n\t\t\t\t\tindexh,\n\t\t\t\t\tindexv,\n\t\t\t\t\tcurrentSlide\n\t\t\t\t}\n\t\t\t});\n\t\t}, 1 );\n\n\t\tconst activatePrintView = config.view === 'print';\n\t\tconst activateReaderView = config.view === 'reader';\n\n\t\t// Special setup and config is required when initializing a deck\n\t\t// to be read or printed linearly\n\t\tif( activatePrintView || activateReaderView ) {\n\n\t\t\tif( activatePrintView ) {\n\t\t\t\tremoveEventListeners();\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttouch.unbind();\n\t\t\t}\n\n\t\t\t// Avoid content flickering during layout\n\t\t\tdom.viewport.classList.add( 'loading-scroll-mode' );\n\n\t\t\tif( activatePrintView ) {\n\t\t\t\t// The document needs to have loaded for the PDF layout\n\t\t\t\t// measurements to be accurate\n\t\t\t\tif( document.readyState === 'complete' ) {\n\t\t\t\t\tprint.activate();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\twindow.addEventListener( 'load', () => print.activate() );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\treader.activate();\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Removes all slides with data-visibility=\"hidden\". This\n\t * is done right before the rest of the presentation is\n\t * initialized.\n\t *\n\t * If you want to show all hidden slides, initialize\n\t * reveal.js with showHiddenSlides set to true.\n\t */\n\tfunction removeHiddenSlides() {\n\n\t\tif( !config.showHiddenSlides ) {\n\t\t\tUtil.queryAll( dom.wrapper, 'section[data-visibility=\"hidden\"]' ).forEach( slide => {\n\t\t\t\tslide.parentNode.removeChild( slide );\n\t\t\t} );\n\t\t}\n\n\t}\n\n\t/**\n\t * Finds and stores references to DOM elements which are\n\t * required by the presentation. If a required element is\n\t * not found, it is created.\n\t */\n\tfunction setupDOM() {\n\n\t\t// Prevent transitions while we're loading\n\t\tdom.slides.classList.add( 'no-transition' );\n\n\t\tif( Device.isMobile ) {\n\t\t\tdom.wrapper.classList.add( 'no-hover' );\n\t\t}\n\t\telse {\n\t\t\tdom.wrapper.classList.remove( 'no-hover' );\n\t\t}\n\n\t\tbackgrounds.render();\n\t\tslideNumber.render();\n\t\tjumpToSlide.render();\n\t\tcontrols.render();\n\t\tprogress.render();\n\t\tnotes.render();\n\n\t\t// Overlay graphic which is displayed during the paused mode\n\t\tdom.pauseOverlay = Util.createSingletonNode( dom.wrapper, 'div', 'pause-overlay', config.controls ? '<button class=\"resume-button\">Resume presentation</button>' : null );\n\n\t\tdom.statusElement = createStatusElement();\n\n\t\tdom.wrapper.setAttribute( 'role', 'application' );\n\t}\n\n\t/**\n\t * Creates a hidden div with role aria-live to announce the\n\t * current slide content. Hide the div off-screen to make it\n\t * available only to Assistive Technologies.\n\t *\n\t * @return {HTMLElement}\n\t */\n\tfunction createStatusElement() {\n\n\t\tlet statusElement = dom.wrapper.querySelector( '.aria-status' );\n\t\tif( !statusElement ) {\n\t\t\tstatusElement = document.createElement( 'div' );\n\t\t\tstatusElement.style.position = 'absolute';\n\t\t\tstatusElement.style.height = '1px';\n\t\t\tstatusElement.style.width = '1px';\n\t\t\tstatusElement.style.overflow = 'hidden';\n\t\t\tstatusElement.style.clip = 'rect( 1px, 1px, 1px, 1px )';\n\t\t\tstatusElement.classList.add( 'aria-status' );\n\t\t\tstatusElement.setAttribute( 'aria-live', 'polite' );\n\t\t\tstatusElement.setAttribute( 'aria-atomic','true' );\n\t\t\tdom.wrapper.appendChild( statusElement );\n\t\t}\n\t\treturn statusElement;\n\n\t}\n\n\t/**\n\t * Announces the given text to screen readers.\n\t */\n\tfunction announceStatus( value ) {\n\n\t\tdom.statusElement.textContent = value;\n\n\t}\n\n\t/**\n\t * Converts the given HTML element into a string of text\n\t * that can be announced to a screen reader. Hidden\n\t * elements are excluded.\n\t */\n\tfunction getStatusText( node ) {\n\n\t\tlet text = '';\n\n\t\t// Text node\n\t\tif( node.nodeType === 3 ) {\n\t\t\ttext += node.textContent;\n\t\t}\n\t\t// Element node\n\t\telse if( node.nodeType === 1 ) {\n\n\t\t\tlet isAriaHidden = node.getAttribute( 'aria-hidden' );\n\t\t\tlet isDisplayHidden = window.getComputedStyle( node )['display'] === 'none';\n\t\t\tif( isAriaHidden !== 'true' && !isDisplayHidden ) {\n\n\t\t\t\tArray.from( node.childNodes ).forEach( child => {\n\t\t\t\t\ttext += getStatusText( child );\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t}\n\n\t\ttext = text.trim();\n\n\t\treturn text === '' ? '' : text + ' ';\n\n\t}\n\n\t/**\n\t * This is an unfortunate necessity. Some actions – such as\n\t * an input field being focused in an iframe or using the\n\t * keyboard to expand text selection beyond the bounds of\n\t * a slide – can trigger our content to be pushed out of view.\n\t * This scrolling can not be prevented by hiding overflow in\n\t * CSS (we already do) so we have to resort to repeatedly\n\t * checking if the slides have been offset :(\n\t */\n\tfunction setupScrollPrevention() {\n\n\t\tsetInterval( () => {\n\t\t\tif( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {\n\t\t\t\tdom.wrapper.scrollTop = 0;\n\t\t\t\tdom.wrapper.scrollLeft = 0;\n\t\t\t}\n\t\t}, 1000 );\n\n\t}\n\n\t/**\n\t * After entering fullscreen we need to force a layout to\n\t * get our presentations to scale correctly. This behavior\n\t * is inconsistent across browsers but a force layout seems\n\t * to normalize it.\n\t */\n\tfunction setupFullscreen() {\n\n\t\tdocument.addEventListener( 'fullscreenchange', onFullscreenChange );\n\t\tdocument.addEventListener( 'webkitfullscreenchange', onFullscreenChange );\n\n\t}\n\n\t/**\n\t * Registers a listener to postMessage events, this makes it\n\t * possible to call all reveal.js API methods from another\n\t * window. For example:\n\t *\n\t * revealWindow.postMessage( JSON.stringify({\n\t * method: 'slide',\n\t * args: [ 2 ]\n\t * }), '*' );\n\t */\n\tfunction setupPostMessage() {\n\n\t\tif( config.postMessage ) {\n\t\t\twindow.addEventListener( 'message', onPostMessage, false );\n\t\t}\n\n\t}\n\n\t/**\n\t * Applies the configuration settings from the config\n\t * object. May be called multiple times.\n\t *\n\t * @param {object} options\n\t */\n\tfunction configure( options ) {\n\n\t\tconst oldConfig = { ...config }\n\n\t\t// New config options may be passed when this method\n\t\t// is invoked through the API after initialization\n\t\tif( typeof options === 'object' ) Util.extend( config, options );\n\n\t\t// Abort if reveal.js hasn't finished loading, config\n\t\t// changes will be applied automatically once ready\n\t\tif( Reveal.isReady() === false ) return;\n\n\t\tconst numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length;\n\n\t\t// The transition is added as a class on the .reveal element\n\t\tdom.wrapper.classList.remove( oldConfig.transition );\n\t\tdom.wrapper.classList.add( config.transition );\n\n\t\tdom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );\n\t\tdom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );\n\n\t\t// Expose our configured slide dimensions as custom props\n\t\tdom.viewport.style.setProperty( '--slide-width', config.width + 'px' );\n\t\tdom.viewport.style.setProperty( '--slide-height', config.height + 'px' );\n\n\t\tif( config.shuffle ) {\n\t\t\tshuffle();\n\t\t}\n\n\t\tUtil.toggleClass( dom.wrapper, 'embedded', config.embedded );\n\t\tUtil.toggleClass( dom.wrapper, 'rtl', config.rtl );\n\t\tUtil.toggleClass( dom.wrapper, 'center', config.center );\n\n\t\t// Exit the paused mode if it was configured off\n\t\tif( config.pause === false ) {\n\t\t\tresume();\n\t\t}\n\n\t\t// Iframe link previews\n\t\tif( config.previewLinks ) {\n\t\t\tenablePreviewLinks();\n\t\t\tdisablePreviewLinks( '[data-preview-link=false]' );\n\t\t}\n\t\telse {\n\t\t\tdisablePreviewLinks();\n\t\t\tenablePreviewLinks( '[data-preview-link]:not([data-preview-link=false])' );\n\t\t}\n\n\t\t// Reset all changes made by auto-animations\n\t\tautoAnimate.reset();\n\n\t\t// Remove existing auto-slide controls\n\t\tif( autoSlidePlayer ) {\n\t\t\tautoSlidePlayer.destroy();\n\t\t\tautoSlidePlayer = null;\n\t\t}\n\n\t\t// Generate auto-slide controls if needed\n\t\tif( numberOfSlides > 1 && config.autoSlide && config.autoSlideStoppable ) {\n\t\t\tautoSlidePlayer = new Playback( dom.wrapper, () => {\n\t\t\t\treturn Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 );\n\t\t\t} );\n\n\t\t\tautoSlidePlayer.on( 'click', onAutoSlidePlayerClick );\n\t\t\tautoSlidePaused = false;\n\t\t}\n\n\t\t// Add the navigation mode to the DOM so we can adjust styling\n\t\tif( config.navigationMode !== 'default' ) {\n\t\t\tdom.wrapper.setAttribute( 'data-navigation-mode', config.navigationMode );\n\t\t}\n\t\telse {\n\t\t\tdom.wrapper.removeAttribute( 'data-navigation-mode' );\n\t\t}\n\n\t\tnotes.configure( config, oldConfig );\n\t\tfocus.configure( config, oldConfig );\n\t\tpointer.configure( config, oldConfig );\n\t\tcontrols.configure( config, oldConfig );\n\t\tprogress.configure( config, oldConfig );\n\t\tkeyboard.configure( config, oldConfig );\n\t\tfragments.configure( config, oldConfig );\n\t\tslideNumber.configure( config, oldConfig );\n\n\t\tsync();\n\n\t}\n\n\t/**\n\t * Binds all event listeners.\n\t */\n\tfunction addEventListeners() {\n\n\t\teventsAreBound = true;\n\n\t\twindow.addEventListener( 'resize', onWindowResize, false );\n\n\t\tif( config.touch ) touch.bind();\n\t\tif( config.keyboard ) keyboard.bind();\n\t\tif( config.progress ) progress.bind();\n\t\tif( config.respondToHashChanges ) location.bind();\n\t\tcontrols.bind();\n\t\tfocus.bind();\n\n\t\tdom.slides.addEventListener( 'click', onSlidesClicked, false );\n\t\tdom.slides.addEventListener( 'transitionend', onTransitionEnd, false );\n\t\tdom.pauseOverlay.addEventListener( 'click', resume, false );\n\n\t\tif( config.focusBodyOnPageVisibilityChange ) {\n\t\t\tdocument.addEventListener( 'visibilitychange', onPageVisibilityChange, false );\n\t\t}\n\n\t}\n\n\t/**\n\t * Unbinds all event listeners.\n\t */\n\tfunction removeEventListeners() {\n\n\t\teventsAreBound = false;\n\n\t\ttouch.unbind();\n\t\tfocus.unbind();\n\t\tkeyboard.unbind();\n\t\tcontrols.unbind();\n\t\tprogress.unbind();\n\t\tlocation.unbind();\n\n\t\twindow.removeEventListener( 'resize', onWindowResize, false );\n\n\t\tdom.slides.removeEventListener( 'click', onSlidesClicked, false );\n\t\tdom.slides.removeEventListener( 'transitionend', onTransitionEnd, false );\n\t\tdom.pauseOverlay.removeEventListener( 'click', resume, false );\n\n\t}\n\n\t/**\n\t * Uninitializes reveal.js by undoing changes made to the\n\t * DOM and removing all event listeners.\n\t */\n\tfunction destroy() {\n\n\t\tremoveEventListeners();\n\t\tcancelAutoSlide();\n\t\tdisablePreviewLinks();\n\n\t\t// Destroy controllers\n\t\tnotes.destroy();\n\t\tfocus.destroy();\n\t\tplugins.destroy();\n\t\tpointer.destroy();\n\t\tcontrols.destroy();\n\t\tprogress.destroy();\n\t\tbackgrounds.destroy();\n\t\tslideNumber.destroy();\n\t\tjumpToSlide.destroy();\n\n\t\t// Remove event listeners\n\t\tdocument.removeEventListener( 'fullscreenchange', onFullscreenChange );\n\t\tdocument.removeEventListener( 'webkitfullscreenchange', onFullscreenChange );\n\t\tdocument.removeEventListener( 'visibilitychange', onPageVisibilityChange, false );\n\t\twindow.removeEventListener( 'message', onPostMessage, false );\n\t\twindow.removeEventListener( 'load', layout, false );\n\n\t\t// Undo DOM changes\n\t\tif( dom.pauseOverlay ) dom.pauseOverlay.remove();\n\t\tif( dom.statusElement ) dom.statusElement.remove();\n\n\t\tdocument.documentElement.classList.remove( 'reveal-full-page' );\n\n\t\tdom.wrapper.classList.remove( 'ready', 'center', 'has-horizontal-slides', 'has-vertical-slides' );\n\t\tdom.wrapper.removeAttribute( 'data-transition-speed' );\n\t\tdom.wrapper.removeAttribute( 'data-background-transition' );\n\n\t\tdom.viewport.classList.remove( 'reveal-viewport' );\n\t\tdom.viewport.style.removeProperty( '--slide-width' );\n\t\tdom.viewport.style.removeProperty( '--slide-height' );\n\n\t\tdom.slides.style.removeProperty( 'width' );\n\t\tdom.slides.style.removeProperty( 'height' );\n\t\tdom.slides.style.removeProperty( 'zoom' );\n\t\tdom.slides.style.removeProperty( 'left' );\n\t\tdom.slides.style.removeProperty( 'top' );\n\t\tdom.slides.style.removeProperty( 'bottom' );\n\t\tdom.slides.style.removeProperty( 'right' );\n\t\tdom.slides.style.removeProperty( 'transform' );\n\n\t\tArray.from( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( slide => {\n\t\t\tslide.style.removeProperty( 'display' );\n\t\t\tslide.style.removeProperty( 'top' );\n\t\t\tslide.removeAttribute( 'hidden' );\n\t\t\tslide.removeAttribute( 'aria-hidden' );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Adds a listener to one of our custom reveal.js events,\n\t * like slidechanged.\n\t */\n\tfunction on( type, listener, useCapture ) {\n\n\t\trevealElement.addEventListener( type, listener, useCapture );\n\n\t}\n\n\t/**\n\t * Unsubscribes from a reveal.js event.\n\t */\n\tfunction off( type, listener, useCapture ) {\n\n\t\trevealElement.removeEventListener( type, listener, useCapture );\n\n\t}\n\n\t/**\n\t * Applies CSS transforms to the slides container. The container\n\t * is transformed from two separate sources: layout and the overview\n\t * mode.\n\t *\n\t * @param {object} transforms\n\t */\n\tfunction transformSlides( transforms ) {\n\n\t\t// Pick up new transforms from arguments\n\t\tif( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout;\n\t\tif( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview;\n\n\t\t// Apply the transforms to the slides container\n\t\tif( slidesTransform.layout ) {\n\t\t\tUtil.transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview );\n\t\t}\n\t\telse {\n\t\t\tUtil.transformElement( dom.slides, slidesTransform.overview );\n\t\t}\n\n\t}\n\n\t/**\n\t * Dispatches an event of the specified type from the\n\t * reveal DOM element.\n\t */\n\tfunction dispatchEvent({ target=dom.wrapper, type, data, bubbles=true }) {\n\n\t\tlet event = document.createEvent( 'HTMLEvents', 1, 2 );\n\t\tevent.initEvent( type, bubbles, true );\n\t\tUtil.extend( event, data );\n\t\ttarget.dispatchEvent( event );\n\n\t\tif( target === dom.wrapper ) {\n\t\t\t// If we're in an iframe, post each reveal.js event to the\n\t\t\t// parent window. Used by the notes plugin\n\t\t\tdispatchPostMessage( type );\n\t\t}\n\n\t\treturn event;\n\n\t}\n\n\t/**\n\t * Dispatches a slidechanged event.\n\t *\n\t * @param {string} origin Used to identify multiplex clients\n\t */\n\tfunction dispatchSlideChanged( origin ) {\n\n\t\tdispatchEvent({\n\t\t\ttype: 'slidechanged',\n\t\t\tdata: {\n\t\t\t\tindexh,\n\t\t\t\tindexv,\n\t\t\t\tpreviousSlide,\n\t\t\t\tcurrentSlide,\n\t\t\t\torigin\n\t\t\t}\n\t\t});\n\n\t}\n\n\t/**\n\t * Dispatched a postMessage of the given type from our window.\n\t */\n\tfunction dispatchPostMessage( type, data ) {\n\n\t\tif( config.postMessageEvents && window.parent !== window.self ) {\n\t\t\tlet message = {\n\t\t\t\tnamespace: 'reveal',\n\t\t\t\teventName: type,\n\t\t\t\tstate: getState()\n\t\t\t};\n\n\t\t\tUtil.extend( message, data );\n\n\t\t\twindow.parent.postMessage( JSON.stringify( message ), '*' );\n\t\t}\n\n\t}\n\n\t/**\n\t * Bind preview frame links.\n\t *\n\t * @param {string} [selector=a] - selector for anchors\n\t */\n\tfunction enablePreviewLinks( selector = 'a' ) {\n\n\t\tArray.from( dom.wrapper.querySelectorAll( selector ) ).forEach( element => {\n\t\t\tif( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {\n\t\t\t\telement.addEventListener( 'click', onPreviewLinkClicked, false );\n\t\t\t}\n\t\t} );\n\n\t}\n\n\t/**\n\t * Unbind preview frame links.\n\t */\n\tfunction disablePreviewLinks( selector = 'a' ) {\n\n\t\tArray.from( dom.wrapper.querySelectorAll( selector ) ).forEach( element => {\n\t\t\tif( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {\n\t\t\t\telement.removeEventListener( 'click', onPreviewLinkClicked, false );\n\t\t\t}\n\t\t} );\n\n\t}\n\n\t/**\n\t * Opens a preview window for the target URL.\n\t *\n\t * @param {string} url - url for preview iframe src\n\t */\n\tfunction showPreview( url ) {\n\n\t\tcloseOverlay();\n\n\t\tdom.overlay = document.createElement( 'div' );\n\t\tdom.overlay.classList.add( 'overlay' );\n\t\tdom.overlay.classList.add( 'overlay-preview' );\n\t\tdom.wrapper.appendChild( dom.overlay );\n\n\t\tdom.overlay.innerHTML =\n\t\t\t`<header>\n\t\t\t\t<a class=\"close\" href=\"#\"><span class=\"icon\"></span></a>\n\t\t\t\t<a class=\"external\" href=\"${url}\" target=\"_blank\"><span class=\"icon\"></span></a>\n\t\t\t</header>\n\t\t\t<div class=\"spinner\"></div>\n\t\t\t<div class=\"viewport\">\n\t\t\t\t<iframe src=\"${url}\"></iframe>\n\t\t\t\t<small class=\"viewport-inner\">\n\t\t\t\t\t<span class=\"x-frame-error\">Unable to load iframe. This is likely due to the site's policy (x-frame-options).</span>\n\t\t\t\t</small>\n\t\t\t</div>`;\n\n\t\tdom.overlay.querySelector( 'iframe' ).addEventListener( 'load', event => {\n\t\t\tdom.overlay.classList.add( 'loaded' );\n\t\t}, false );\n\n\t\tdom.overlay.querySelector( '.close' ).addEventListener( 'click', event => {\n\t\t\tcloseOverlay();\n\t\t\tevent.preventDefault();\n\t\t}, false );\n\n\t\tdom.overlay.querySelector( '.external' ).addEventListener( 'click', event => {\n\t\t\tcloseOverlay();\n\t\t}, false );\n\n\t}\n\n\t/**\n\t * Open or close help overlay window.\n\t *\n\t * @param {Boolean} [override] Flag which overrides the\n\t * toggle logic and forcibly sets the desired state. True means\n\t * help is open, false means it's closed.\n\t */\n\tfunction toggleHelp( override ){\n\n\t\tif( typeof override === 'boolean' ) {\n\t\t\toverride ? showHelp() : closeOverlay();\n\t\t}\n\t\telse {\n\t\t\tif( dom.overlay ) {\n\t\t\t\tcloseOverlay();\n\t\t\t}\n\t\t\telse {\n\t\t\t\tshowHelp();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Opens an overlay window with help material.\n\t */\n\tfunction showHelp() {\n\n\t\tif( config.help ) {\n\n\t\t\tcloseOverlay();\n\n\t\t\tdom.overlay = document.createElement( 'div' );\n\t\t\tdom.overlay.classList.add( 'overlay' );\n\t\t\tdom.overlay.classList.add( 'overlay-help' );\n\t\t\tdom.wrapper.appendChild( dom.overlay );\n\n\t\t\tlet html = '<p class=\"title\">Keyboard Shortcuts</p><br/>';\n\n\t\t\tlet shortcuts = keyboard.getShortcuts(),\n\t\t\t\tbindings = keyboard.getBindings();\n\n\t\t\thtml += '<table><th>KEY</th><th>ACTION</th>';\n\t\t\tfor( let key in shortcuts ) {\n\t\t\t\thtml += `<tr><td>${key}</td><td>${shortcuts[ key ]}</td></tr>`;\n\t\t\t}\n\n\t\t\t// Add custom key bindings that have associated descriptions\n\t\t\tfor( let binding in bindings ) {\n\t\t\t\tif( bindings[binding].key && bindings[binding].description ) {\n\t\t\t\t\thtml += `<tr><td>${bindings[binding].key}</td><td>${bindings[binding].description}</td></tr>`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\thtml += '</table>';\n\n\t\t\tdom.overlay.innerHTML = `\n\t\t\t\t<header>\n\t\t\t\t\t<a class=\"close\" href=\"#\"><span class=\"icon\"></span></a>\n\t\t\t\t</header>\n\t\t\t\t<div class=\"viewport\">\n\t\t\t\t\t<div class=\"viewport-inner\">${html}</div>\n\t\t\t\t</div>\n\t\t\t`;\n\n\t\t\tdom.overlay.querySelector( '.close' ).addEventListener( 'click', event => {\n\t\t\t\tcloseOverlay();\n\t\t\t\tevent.preventDefault();\n\t\t\t}, false );\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Closes any currently open overlay.\n\t */\n\tfunction closeOverlay() {\n\n\t\tif( dom.overlay ) {\n\t\t\tdom.overlay.parentNode.removeChild( dom.overlay );\n\t\t\tdom.overlay = null;\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t/**\n\t * Applies JavaScript-controlled layout rules to the\n\t * presentation.\n\t */\n\tfunction layout() {\n\n\t\tif( dom.wrapper && !print.isActive() ) {\n\n\t\t\tif( !config.disableLayout ) {\n\n\t\t\t\t// On some mobile devices '100vh' is taller than the visible\n\t\t\t\t// viewport which leads to part of the presentation being\n\t\t\t\t// cut off. To work around this we define our own '--vh' custom\n\t\t\t\t// property where 100x adds up to the correct height.\n\t\t\t\t//\n\t\t\t\t// https://css-tricks.com/the-trick-to-viewport-units-on-mobile/\n\t\t\t\tif( Device.isMobile && !config.embedded ) {\n\t\t\t\t\tdocument.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' );\n\t\t\t\t}\n\n\t\t\t\tconst size = reader.isActive() ?\n\t\t\t\t\t\t\t getComputedSlideSize( dom.viewport.offsetWidth, dom.viewport.offsetHeight ) :\n\t\t\t\t\t\t\t getComputedSlideSize();\n\n\t\t\t\tconst oldScale = scale;\n\n\t\t\t\t// Layout the contents of the slides\n\t\t\t\tlayoutSlideContents( config.width, config.height );\n\n\t\t\t\tdom.slides.style.width = size.width + 'px';\n\t\t\t\tdom.slides.style.height = size.height + 'px';\n\n\t\t\t\t// Determine scale of content to fit within available space\n\t\t\t\tscale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height );\n\n\t\t\t\t// Respect max/min scale settings\n\t\t\t\tscale = Math.max( scale, config.minScale );\n\t\t\t\tscale = Math.min( scale, config.maxScale );\n\n\t\t\t\t// Don't apply any scaling styles if scale is 1 or we're\n\t\t\t\t// in reader mode\n\t\t\t\tif( scale === 1 || reader.isActive() ) {\n\t\t\t\t\tdom.slides.style.zoom = '';\n\t\t\t\t\tdom.slides.style.left = '';\n\t\t\t\t\tdom.slides.style.top = '';\n\t\t\t\t\tdom.slides.style.bottom = '';\n\t\t\t\t\tdom.slides.style.right = '';\n\t\t\t\t\ttransformSlides( { layout: '' } );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tdom.slides.style.zoom = '';\n\t\t\t\t\tdom.slides.style.left = '50%';\n\t\t\t\t\tdom.slides.style.top = '50%';\n\t\t\t\t\tdom.slides.style.bottom = 'auto';\n\t\t\t\t\tdom.slides.style.right = 'auto';\n\t\t\t\t\ttransformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );\n\t\t\t\t}\n\n\t\t\t\t// Select all slides, vertical and horizontal\n\t\t\t\tconst slides = Array.from( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) );\n\n\t\t\t\tfor( let i = 0, len = slides.length; i < len; i++ ) {\n\t\t\t\t\tconst slide = slides[ i ];\n\n\t\t\t\t\t// Don't bother updating invisible slides\n\t\t\t\t\tif( slide.style.display === 'none' ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif( ( config.center || slide.classList.contains( 'center' ) ) ) {\n\t\t\t\t\t\t// Vertical stacks are not centred since their section\n\t\t\t\t\t\t// children will be\n\t\t\t\t\t\tif( slide.classList.contains( 'stack' ) ) {\n\t\t\t\t\t\t\tslide.style.top = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tslide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px';\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tslide.style.top = '';\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif( oldScale !== scale ) {\n\t\t\t\t\tdispatchEvent({\n\t\t\t\t\t\ttype: 'resize',\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\toldScale,\n\t\t\t\t\t\t\tscale,\n\t\t\t\t\t\t\tsize\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Responsively turn on the reader mode if there is an activation\n\t\t\t\t// width configured. Ignore if we're configured to always be in\n\t\t\t\t// reader mode.\n\t\t\t\tif( typeof config.readerActivationWidth === 'number' && config.view !== 'reader' ) {\n\t\t\t\t\tif( size.presentationWidth < config.readerActivationWidth ) {\n\t\t\t\t\t\tif( !reader.isActive() ) reader.activate();\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif( reader.isActive() ) reader.deactivate();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdom.viewport.style.setProperty( '--slide-scale', scale );\n\n\t\t\treader.layout();\n\n\t\t\tprogress.update();\n\t\t\tbackgrounds.updateParallax();\n\n\t\t\tif( overview.isActive() ) {\n\t\t\t\toverview.update();\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Applies layout logic to the contents of all slides in\n\t * the presentation.\n\t *\n\t * @param {string|number} width\n\t * @param {string|number} height\n\t */\n\tfunction layoutSlideContents( width, height ) {\n\t\t// Handle sizing of elements with the 'r-stretch' class\n\t\tUtil.queryAll( dom.slides, 'section > .stretch, section > .r-stretch' ).forEach( element => {\n\n\t\t\t// Determine how much vertical space we can use\n\t\t\tlet remainingHeight = Util.getRemainingHeight( element, height );\n\n\t\t\t// Consider the aspect ratio of media elements\n\t\t\tif( /(img|video)/gi.test( element.nodeName ) ) {\n\t\t\t\tconst nw = element.naturalWidth || element.videoWidth,\n\t\t\t\t\t nh = element.naturalHeight || element.videoHeight;\n\n\t\t\t\tconst es = Math.min( width / nw, remainingHeight / nh );\n\n\t\t\t\telement.style.width = ( nw * es ) + 'px';\n\t\t\t\telement.style.height = ( nh * es ) + 'px';\n\n\t\t\t}\n\t\t\telse {\n\t\t\t\telement.style.width = width + 'px';\n\t\t\t\telement.style.height = remainingHeight + 'px';\n\t\t\t}\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Calculates the computed pixel size of our slides. These\n\t * values are based on the width and height configuration\n\t * options.\n\t *\n\t * @param {number} [presentationWidth=dom.wrapper.offsetWidth]\n\t * @param {number} [presentationHeight=dom.wrapper.offsetHeight]\n\t */\n\tfunction getComputedSlideSize( presentationWidth, presentationHeight ) {\n\n\t\tlet width = config.width;\n\t\tlet height = config.height;\n\n\t\tif( config.disableLayout ) {\n\t\t\twidth = dom.slides.offsetWidth;\n\t\t\theight = dom.slides.offsetHeight;\n\t\t}\n\n\t\tconst size = {\n\t\t\t// Slide size\n\t\t\twidth: width,\n\t\t\theight: height,\n\n\t\t\t// Presentation size\n\t\t\tpresentationWidth: presentationWidth || dom.wrapper.offsetWidth,\n\t\t\tpresentationHeight: presentationHeight || dom.wrapper.offsetHeight\n\t\t};\n\n\t\t// Reduce available space by margin\n\t\tsize.presentationWidth -= ( size.presentationWidth * config.margin );\n\t\tsize.presentationHeight -= ( size.presentationHeight * config.margin );\n\n\t\t// Slide width may be a percentage of available width\n\t\tif( typeof size.width === 'string' && /%$/.test( size.width ) ) {\n\t\t\tsize.width = parseInt( size.width, 10 ) / 100 * size.presentationWidth;\n\t\t}\n\n\t\t// Slide height may be a percentage of available height\n\t\tif( typeof size.height === 'string' && /%$/.test( size.height ) ) {\n\t\t\tsize.height = parseInt( size.height, 10 ) / 100 * size.presentationHeight;\n\t\t}\n\n\t\treturn size;\n\n\t}\n\n\t/**\n\t * Stores the vertical index of a stack so that the same\n\t * vertical slide can be selected when navigating to and\n\t * from the stack.\n\t *\n\t * @param {HTMLElement} stack The vertical stack element\n\t * @param {string|number} [v=0] Index to memorize\n\t */\n\tfunction setPreviousVerticalIndex( stack, v ) {\n\n\t\tif( typeof stack === 'object' && typeof stack.setAttribute === 'function' ) {\n\t\t\tstack.setAttribute( 'data-previous-indexv', v || 0 );\n\t\t}\n\n\t}\n\n\t/**\n\t * Retrieves the vertical index which was stored using\n\t * #setPreviousVerticalIndex() or 0 if no previous index\n\t * exists.\n\t *\n\t * @param {HTMLElement} stack The vertical stack element\n\t */\n\tfunction getPreviousVerticalIndex( stack ) {\n\n\t\tif( typeof stack === 'object' && typeof stack.setAttribute === 'function' && stack.classList.contains( 'stack' ) ) {\n\t\t\t// Prefer manually defined start-indexv\n\t\t\tconst attributeName = stack.hasAttribute( 'data-start-indexv' ) ? 'data-start-indexv' : 'data-previous-indexv';\n\n\t\t\treturn parseInt( stack.getAttribute( attributeName ) || 0, 10 );\n\t\t}\n\n\t\treturn 0;\n\n\t}\n\n\t/**\n\t * Checks if the current or specified slide is vertical\n\t * (nested within another slide).\n\t *\n\t * @param {HTMLElement} [slide=currentSlide] The slide to check\n\t * orientation of\n\t * @return {Boolean}\n\t */\n\tfunction isVerticalSlide( slide = currentSlide ) {\n\n\t\treturn slide && slide.parentNode && !!slide.parentNode.nodeName.match( /section/i );\n\n\t}\n\n\t/**\n\t * Returns true if we're on the last slide in the current\n\t * vertical stack.\n\t */\n\tfunction isLastVerticalSlide() {\n\n\t\tif( currentSlide && isVerticalSlide( currentSlide ) ) {\n\t\t\t// Does this slide have a next sibling?\n\t\t\tif( currentSlide.nextElementSibling ) return false;\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t/**\n\t * Returns true if we're currently on the first slide in\n\t * the presentation.\n\t */\n\tfunction isFirstSlide() {\n\n\t\treturn indexh === 0 && indexv === 0;\n\n\t}\n\n\t/**\n\t * Returns true if we're currently on the last slide in\n\t * the presenation. If the last slide is a stack, we only\n\t * consider this the last slide if it's at the end of the\n\t * stack.\n\t */\n\tfunction isLastSlide() {\n\n\t\tif( currentSlide ) {\n\t\t\t// Does this slide have a next sibling?\n\t\t\tif( currentSlide.nextElementSibling ) return false;\n\n\t\t\t// If it's vertical, does its parent have a next sibling?\n\t\t\tif( isVerticalSlide( currentSlide ) && currentSlide.parentNode.nextElementSibling ) return false;\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\t/**\n\t * Enters the paused mode which fades everything on screen to\n\t * black.\n\t */\n\tfunction pause() {\n\n\t\tif( config.pause ) {\n\t\t\tconst wasPaused = dom.wrapper.classList.contains( 'paused' );\n\n\t\t\tcancelAutoSlide();\n\t\t\tdom.wrapper.classList.add( 'paused' );\n\n\t\t\tif( wasPaused === false ) {\n\t\t\t\tdispatchEvent({ type: 'paused' });\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Exits from the paused mode.\n\t */\n\tfunction resume() {\n\n\t\tconst wasPaused = dom.wrapper.classList.contains( 'paused' );\n\t\tdom.wrapper.classList.remove( 'paused' );\n\n\t\tcueAutoSlide();\n\n\t\tif( wasPaused ) {\n\t\t\tdispatchEvent({ type: 'resumed' });\n\t\t}\n\n\t}\n\n\t/**\n\t * Toggles the paused mode on and off.\n\t */\n\tfunction togglePause( override ) {\n\n\t\tif( typeof override === 'boolean' ) {\n\t\t\toverride ? pause() : resume();\n\t\t}\n\t\telse {\n\t\t\tisPaused() ? resume() : pause();\n\t\t}\n\n\t}\n\n\t/**\n\t * Checks if we are currently in the paused mode.\n\t *\n\t * @return {Boolean}\n\t */\n\tfunction isPaused() {\n\n\t\treturn dom.wrapper.classList.contains( 'paused' );\n\n\t}\n\n\t/**\n\t * Toggles visibility of the jump-to-slide UI.\n\t */\n\tfunction toggleJumpToSlide( override ) {\n\n\t\tif( typeof override === 'boolean' ) {\n\t\t\toverride ? jumpToSlide.show() : jumpToSlide.hide();\n\t\t}\n\t\telse {\n\t\t\tjumpToSlide.isVisible() ? jumpToSlide.hide() : jumpToSlide.show();\n\t\t}\n\n\t}\n\n\t/**\n\t * Toggles the auto slide mode on and off.\n\t *\n\t * @param {Boolean} [override] Flag which sets the desired state.\n\t * True means autoplay starts, false means it stops.\n\t */\n\n\tfunction toggleAutoSlide( override ) {\n\n\t\tif( typeof override === 'boolean' ) {\n\t\t\toverride ? resumeAutoSlide() : pauseAutoSlide();\n\t\t}\n\n\t\telse {\n\t\t\tautoSlidePaused ? resumeAutoSlide() : pauseAutoSlide();\n\t\t}\n\n\t}\n\n\t/**\n\t * Checks if the auto slide mode is currently on.\n\t *\n\t * @return {Boolean}\n\t */\n\tfunction isAutoSliding() {\n\n\t\treturn !!( autoSlide && !autoSlidePaused );\n\n\t}\n\n\t/**\n\t * Steps from the current point in the presentation to the\n\t * slide which matches the specified horizontal and vertical\n\t * indices.\n\t *\n\t * @param {number} [h=indexh] Horizontal index of the target slide\n\t * @param {number} [v=indexv] Vertical index of the target slide\n\t * @param {number} [f] Index of a fragment within the\n\t * target slide to activate\n\t * @param {number} [origin] Origin for use in multimaster environments\n\t */\n\tfunction slide( h, v, f, origin ) {\n\n\t\t// Dispatch an event before the slide\n\t\tconst slidechange = dispatchEvent({\n\t\t\ttype: 'beforeslidechange',\n\t\t\tdata: {\n\t\t\t\tindexh: h === undefined ? indexh : h,\n\t\t\t\tindexv: v === undefined ? indexv : v,\n\t\t\t\torigin\n\t\t\t}\n\t\t});\n\n\t\t// Abort if this slide change was prevented by an event listener\n\t\tif( slidechange.defaultPrevented ) return;\n\n\t\t// Remember where we were at before\n\t\tpreviousSlide = currentSlide;\n\n\t\t// Query all horizontal slides in the deck\n\t\tconst horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );\n\n\t\t// If we're in reader mode we scroll the target slide into view\n\t\t// instead of running our standard slide transition\n\t\tif( reader.isActive() ) {\n\t\t\tconst scrollToSlide = dom.wrapper.querySelectorAll( SLIDES_SELECTOR )[ h ];\n\t\t\tif( scrollToSlide ) reader.scrollToSlide( scrollToSlide );\n\t\t\treturn;\n\t\t}\n\n\t\t// Abort if there are no slides\n\t\tif( horizontalSlides.length === 0 ) return;\n\n\t\t// If no vertical index is specified and the upcoming slide is a\n\t\t// stack, resume at its previous vertical index\n\t\tif( v === undefined && !overview.isActive() ) {\n\t\t\tv = getPreviousVerticalIndex( horizontalSlides[ h ] );\n\t\t}\n\n\t\t// If we were on a vertical stack, remember what vertical index\n\t\t// it was on so we can resume at the same position when returning\n\t\tif( previousSlide && previousSlide.parentNode && previousSlide.parentNode.classList.contains( 'stack' ) ) {\n\t\t\tsetPreviousVerticalIndex( previousSlide.parentNode, indexv );\n\t\t}\n\n\t\t// Remember the state before this slide\n\t\tconst stateBefore = state.concat();\n\n\t\t// Reset the state array\n\t\tstate.length = 0;\n\n\t\tlet indexhBefore = indexh || 0,\n\t\t\tindexvBefore = indexv || 0;\n\n\t\t// Activate and transition to the new slide\n\t\tindexh = updateSlides( HORIZONTAL_SLIDES_SELECTOR, h === undefined ? indexh : h );\n\t\tindexv = updateSlides( VERTICAL_SLIDES_SELECTOR, v === undefined ? indexv : v );\n\n\t\t// Dispatch an event if the slide changed\n\t\tlet slideChanged = ( indexh !== indexhBefore || indexv !== indexvBefore );\n\n\t\t// Ensure that the previous slide is never the same as the current\n\t\tif( !slideChanged ) previousSlide = null;\n\n\t\t// Find the current horizontal slide and any possible vertical slides\n\t\t// within it\n\t\tlet currentHorizontalSlide = horizontalSlides[ indexh ],\n\t\t\tcurrentVerticalSlides = currentHorizontalSlide.querySelectorAll( 'section' );\n\n\t\t// Store references to the previous and current slides\n\t\tcurrentSlide = currentVerticalSlides[ indexv ] || currentHorizontalSlide;\n\n\t\tlet autoAnimateTransition = false;\n\n\t\t// Detect if we're moving between two auto-animated slides\n\t\tif( slideChanged && previousSlide && currentSlide && !overview.isActive() ) {\n\t\t\ttransition = 'running';\n\n\t\t\tautoAnimateTransition = shoulAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexvBefore );\n\n\t\t\t// If this is an auto-animated transition, we disable the\n\t\t\t// regular slide transition\n\t\t\t//\n\t\t\t// Note 20-03-2020:\n\t\t\t// This needs to happen before we update slide visibility,\n\t\t\t// otherwise transitions will still run in Safari.\n\t\t\tif( autoAnimateTransition ) {\n\t\t\t\tdom.slides.classList.add( 'disable-slide-transitions' )\n\t\t\t}\n\t\t}\n\n\t\t// Update the visibility of slides now that the indices have changed\n\t\tupdateSlidesVisibility();\n\n\t\tlayout();\n\n\t\t// Update the overview if it's currently active\n\t\tif( overview.isActive() ) {\n\t\t\toverview.update();\n\t\t}\n\n\t\t// Show fragment, if specified\n\t\tif( typeof f !== 'undefined' ) {\n\t\t\tfragments.goto( f );\n\t\t}\n\n\t\t// Solves an edge case where the previous slide maintains the\n\t\t// 'present' class when navigating between adjacent vertical\n\t\t// stacks\n\t\tif( previousSlide && previousSlide !== currentSlide ) {\n\t\t\tpreviousSlide.classList.remove( 'present' );\n\t\t\tpreviousSlide.setAttribute( 'aria-hidden', 'true' );\n\n\t\t\t// Reset all slides upon navigate to home\n\t\t\tif( isFirstSlide() ) {\n\t\t\t\t// Launch async task\n\t\t\t\tsetTimeout( () => {\n\t\t\t\t\tgetVerticalStacks().forEach( slide => {\n\t\t\t\t\t\tsetPreviousVerticalIndex( slide, 0 );\n\t\t\t\t\t} );\n\t\t\t\t}, 0 );\n\t\t\t}\n\t\t}\n\n\t\t// Apply the new state\n\t\tstateLoop: for( let i = 0, len = state.length; i < len; i++ ) {\n\t\t\t// Check if this state existed on the previous slide. If it\n\t\t\t// did, we will avoid adding it repeatedly\n\t\t\tfor( let j = 0; j < stateBefore.length; j++ ) {\n\t\t\t\tif( stateBefore[j] === state[i] ) {\n\t\t\t\t\tstateBefore.splice( j, 1 );\n\t\t\t\t\tcontinue stateLoop;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdom.viewport.classList.add( state[i] );\n\n\t\t\t// Dispatch custom event matching the state's name\n\t\t\tdispatchEvent({ type: state[i] });\n\t\t}\n\n\t\t// Clean up the remains of the previous state\n\t\twhile( stateBefore.length ) {\n\t\t\tdom.viewport.classList.remove( stateBefore.pop() );\n\t\t}\n\n\t\tif( slideChanged ) {\n\t\t\tdispatchSlideChanged( origin );\n\t\t}\n\n\t\t// Handle embedded content\n\t\tif( slideChanged || !previousSlide ) {\n\t\t\tslideContent.stopEmbeddedContent( previousSlide );\n\t\t\tslideContent.startEmbeddedContent( currentSlide );\n\t\t}\n\n\t\t// Announce the current slide contents to screen readers\n\t\t// Use animation frame to prevent getComputedStyle in getStatusText\n\t\t// from triggering layout mid-frame\n\t\trequestAnimationFrame( () => {\n\t\t\tannounceStatus( getStatusText( currentSlide ) );\n\t\t});\n\n\t\tprogress.update();\n\t\tcontrols.update();\n\t\tnotes.update();\n\t\tbackgrounds.update();\n\t\tbackgrounds.updateParallax();\n\t\tslideNumber.update();\n\t\tfragments.update();\n\n\t\t// Update the URL hash\n\t\tlocation.writeURL();\n\n\t\tcueAutoSlide();\n\n\t\t// Auto-animation\n\t\tif( autoAnimateTransition ) {\n\n\t\t\tsetTimeout( () => {\n\t\t\t\tdom.slides.classList.remove( 'disable-slide-transitions' );\n\t\t\t}, 0 );\n\n\t\t\tif( config.autoAnimate ) {\n\t\t\t\t// Run the auto-animation between our slides\n\t\t\t\tautoAnimate.run( previousSlide, currentSlide );\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Checks whether or not an auto-animation should take place between\n\t * the two given slides.\n\t *\n\t * @param {HTMLElement} fromSlide\n\t * @param {HTMLElement} toSlide\n\t * @param {number} indexhBefore\n\t * @param {number} indexvBefore\n\t *\n\t * @returns {boolean}\n\t */\n\tfunction shoulAutoAnimateBetween( fromSlide, toSlide, indexhBefore, indexvBefore ) {\n\n\t\treturn \tfromSlide.hasAttribute( 'data-auto-animate' ) && toSlide.hasAttribute( 'data-auto-animate' ) &&\n\t\t\t\tfromSlide.getAttribute( 'data-auto-animate-id' ) === toSlide.getAttribute( 'data-auto-animate-id' ) &&\n\t\t\t\t!( ( indexh > indexhBefore || indexv > indexvBefore ) ? toSlide : fromSlide ).hasAttribute( 'data-auto-animate-restart' );\n\n\t}\n\n\t/**\n\t * Called anytime current page in reader mode changes. The current\n\t * page is the page that occupies the most space in the viewport.\n\t *\n\t * @param {number} pageIndex\n\t * @param {HTMLElement} pageElement\n\t */\n\tfunction setCurrentReaderPage( pageIndex, pageElement ) {\n\n\t\tlet indexhBefore = indexh || 0;\n\n\t\tindexh = pageIndex;\n\t\tindexv = 0;\n\n\t\tpreviousSlide = currentSlide;\n\t\tcurrentSlide = pageElement.querySelector( 'section' );\n\n\t\tif( currentSlide && previousSlide ) {\n\t\t\tif( config.autoAnimate && shoulAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexv ) ) {\n\t\t\t\t// Run the auto-animation between our slides\n\t\t\t\t// autoAnimate.run( previousSlide, currentSlide );\n\t\t\t}\n\t\t}\n\n\t\tdispatchSlideChanged();\n\n\t}\n\n\t/**\n\t * Syncs the presentation with the current DOM. Useful\n\t * when new slides or control elements are added or when\n\t * the configuration has changed.\n\t */\n\tfunction sync() {\n\n\t\t// Subscribe to input\n\t\tremoveEventListeners();\n\t\taddEventListeners();\n\n\t\t// Force a layout to make sure the current config is accounted for\n\t\tlayout();\n\n\t\t// Reflect the current autoSlide value\n\t\tautoSlide = config.autoSlide;\n\n\t\t// Start auto-sliding if it's enabled\n\t\tcueAutoSlide();\n\n\t\t// Re-create all slide backgrounds\n\t\tbackgrounds.create();\n\n\t\t// Write the current hash to the URL\n\t\tlocation.writeURL();\n\n\t\tif( config.sortFragmentsOnSync === true ) {\n\t\t\tfragments.sortAll();\n\t\t}\n\n\t\tcontrols.update();\n\t\tprogress.update();\n\n\t\tupdateSlidesVisibility();\n\n\t\tnotes.update();\n\t\tnotes.updateVisibility();\n\t\tbackgrounds.update( true );\n\t\tslideNumber.update();\n\t\tslideContent.formatEmbeddedContent();\n\n\t\t// Start or stop embedded content depending on global config\n\t\tif( config.autoPlayMedia === false ) {\n\t\t\tslideContent.stopEmbeddedContent( currentSlide, { unloadIframes: false } );\n\t\t}\n\t\telse {\n\t\t\tslideContent.startEmbeddedContent( currentSlide );\n\t\t}\n\n\t\tif( overview.isActive() ) {\n\t\t\toverview.layout();\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates reveal.js to keep in sync with new slide attributes. For\n\t * example, if you add a new `data-background-image` you can call\n\t * this to have reveal.js render the new background image.\n\t *\n\t * Similar to #sync() but more efficient when you only need to\n\t * refresh a specific slide.\n\t *\n\t * @param {HTMLElement} slide\n\t */\n\tfunction syncSlide( slide = currentSlide ) {\n\n\t\tbackgrounds.sync( slide );\n\t\tfragments.sync( slide );\n\n\t\tslideContent.load( slide );\n\n\t\tbackgrounds.update();\n\t\tnotes.update();\n\n\t}\n\n\t/**\n\t * Resets all vertical slides so that only the first\n\t * is visible.\n\t */\n\tfunction resetVerticalSlides() {\n\n\t\tgetHorizontalSlides().forEach( horizontalSlide => {\n\n\t\t\tUtil.queryAll( horizontalSlide, 'section' ).forEach( ( verticalSlide, y ) => {\n\n\t\t\t\tif( y > 0 ) {\n\t\t\t\t\tverticalSlide.classList.remove( 'present' );\n\t\t\t\t\tverticalSlide.classList.remove( 'past' );\n\t\t\t\t\tverticalSlide.classList.add( 'future' );\n\t\t\t\t\tverticalSlide.setAttribute( 'aria-hidden', 'true' );\n\t\t\t\t}\n\n\t\t\t} );\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Randomly shuffles all slides in the deck.\n\t */\n\tfunction shuffle( slides = getHorizontalSlides() ) {\n\n\t\tslides.forEach( ( slide, i ) => {\n\n\t\t\t// Insert the slide next to a randomly picked sibling slide\n\t\t\t// slide. This may cause the slide to insert before itself,\n\t\t\t// but that's not an issue.\n\t\t\tlet beforeSlide = slides[ Math.floor( Math.random() * slides.length ) ];\n\t\t\tif( beforeSlide.parentNode === slide.parentNode ) {\n\t\t\t\tslide.parentNode.insertBefore( slide, beforeSlide );\n\t\t\t}\n\n\t\t\t// Randomize the order of vertical slides (if there are any)\n\t\t\tlet verticalSlides = slide.querySelectorAll( 'section' );\n\t\t\tif( verticalSlides.length ) {\n\t\t\t\tshuffle( verticalSlides );\n\t\t\t}\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Updates one dimension of slides by showing the slide\n\t * with the specified index.\n\t *\n\t * @param {string} selector A CSS selector that will fetch\n\t * the group of slides we are working with\n\t * @param {number} index The index of the slide that should be\n\t * shown\n\t *\n\t * @return {number} The index of the slide that is now shown,\n\t * might differ from the passed in index if it was out of\n\t * bounds.\n\t */\n\tfunction updateSlides( selector, index ) {\n\n\t\t// Select all slides and convert the NodeList result to\n\t\t// an array\n\t\tlet slides = Util.queryAll( dom.wrapper, selector ),\n\t\t\tslidesLength = slides.length;\n\n\t\tlet printMode = reader.isActive() || print.isActive();\n\t\tlet loopedForwards = false;\n\t\tlet loopedBackwards = false;\n\n\t\tif( slidesLength ) {\n\n\t\t\t// Should the index loop?\n\t\t\tif( config.loop ) {\n\t\t\t\tif( index >= slidesLength ) loopedForwards = true;\n\n\t\t\t\tindex %= slidesLength;\n\n\t\t\t\tif( index < 0 ) {\n\t\t\t\t\tindex = slidesLength + index;\n\t\t\t\t\tloopedBackwards = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Enforce max and minimum index bounds\n\t\t\tindex = Math.max( Math.min( index, slidesLength - 1 ), 0 );\n\n\t\t\tfor( let i = 0; i < slidesLength; i++ ) {\n\t\t\t\tlet element = slides[i];\n\n\t\t\t\tlet reverse = config.rtl && !isVerticalSlide( element );\n\n\t\t\t\t// Avoid .remove() with multiple args for IE11 support\n\t\t\t\telement.classList.remove( 'past' );\n\t\t\t\telement.classList.remove( 'present' );\n\t\t\t\telement.classList.remove( 'future' );\n\n\t\t\t\t// http://www.w3.org/html/wg/drafts/html/master/editing.html#the-hidden-attribute\n\t\t\t\telement.setAttribute( 'hidden', '' );\n\t\t\t\telement.setAttribute( 'aria-hidden', 'true' );\n\n\t\t\t\t// If this element contains vertical slides\n\t\t\t\tif( element.querySelector( 'section' ) ) {\n\t\t\t\t\telement.classList.add( 'stack' );\n\t\t\t\t}\n\n\t\t\t\t// If we're printing static slides, all slides are \"present\"\n\t\t\t\tif( printMode ) {\n\t\t\t\t\telement.classList.add( 'present' );\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif( i < index ) {\n\t\t\t\t\t// Any element previous to index is given the 'past' class\n\t\t\t\t\telement.classList.add( reverse ? 'future' : 'past' );\n\n\t\t\t\t\tif( config.fragments ) {\n\t\t\t\t\t\t// Show all fragments in prior slides\n\t\t\t\t\t\tshowFragmentsIn( element );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if( i > index ) {\n\t\t\t\t\t// Any element subsequent to index is given the 'future' class\n\t\t\t\t\telement.classList.add( reverse ? 'past' : 'future' );\n\n\t\t\t\t\tif( config.fragments ) {\n\t\t\t\t\t\t// Hide all fragments in future slides\n\t\t\t\t\t\thideFragmentsIn( element );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Update the visibility of fragments when a presentation loops\n\t\t\t\t// in either direction\n\t\t\t\telse if( i === index && config.fragments ) {\n\t\t\t\t\tif( loopedForwards ) {\n\t\t\t\t\t\thideFragmentsIn( element );\n\t\t\t\t\t}\n\t\t\t\t\telse if( loopedBackwards ) {\n\t\t\t\t\t\tshowFragmentsIn( element );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet slide = slides[index];\n\t\t\tlet wasPresent = slide.classList.contains( 'present' );\n\n\t\t\t// Mark the current slide as present\n\t\t\tslide.classList.add( 'present' );\n\t\t\tslide.removeAttribute( 'hidden' );\n\t\t\tslide.removeAttribute( 'aria-hidden' );\n\n\t\t\tif( !wasPresent ) {\n\t\t\t\t// Dispatch an event indicating the slide is now visible\n\t\t\t\tdispatchEvent({\n\t\t\t\t\ttarget: slide,\n\t\t\t\t\ttype: 'visible',\n\t\t\t\t\tbubbles: false\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// If this slide has a state associated with it, add it\n\t\t\t// onto the current state of the deck\n\t\t\tlet slideState = slide.getAttribute( 'data-state' );\n\t\t\tif( slideState ) {\n\t\t\t\tstate = state.concat( slideState.split( ' ' ) );\n\t\t\t}\n\n\t\t}\n\t\telse {\n\t\t\t// Since there are no slides we can't be anywhere beyond the\n\t\t\t// zeroth index\n\t\t\tindex = 0;\n\t\t}\n\n\t\treturn index;\n\n\t}\n\n\t/**\n\t * Shows all fragment elements within the given contaienr.\n\t */\n\tfunction showFragmentsIn( container ) {\n\n\t\tUtil.queryAll( container, '.fragment' ).forEach( fragment => {\n\t\t\tfragment.classList.add( 'visible' );\n\t\t\tfragment.classList.remove( 'current-fragment' );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Hides all fragment elements within the given contaienr.\n\t */\n\tfunction hideFragmentsIn( container ) {\n\n\t\tUtil.queryAll( container, '.fragment.visible' ).forEach( fragment => {\n\t\t\tfragment.classList.remove( 'visible', 'current-fragment' );\n\t\t} );\n\n\t}\n\n\t/**\n\t * Optimization method; hide all slides that are far away\n\t * from the present slide.\n\t */\n\tfunction updateSlidesVisibility() {\n\n\t\t// Select all slides and convert the NodeList result to\n\t\t// an array\n\t\tlet horizontalSlides = getHorizontalSlides(),\n\t\t\thorizontalSlidesLength = horizontalSlides.length,\n\t\t\tdistanceX,\n\t\t\tdistanceY;\n\n\t\tif( horizontalSlidesLength && typeof indexh !== 'undefined' ) {\n\n\t\t\t// The number of steps away from the present slide that will\n\t\t\t// be visible\n\t\t\tlet viewDistance = overview.isActive() ? 10 : config.viewDistance;\n\n\t\t\t// Shorten the view distance on devices that typically have\n\t\t\t// less resources\n\t\t\tif( Device.isMobile ) {\n\t\t\t\tviewDistance = overview.isActive() ? 6 : config.mobileViewDistance;\n\t\t\t}\n\n\t\t\t// All slides need to be visible when exporting to PDF\n\t\t\tif( print.isActive() ) {\n\t\t\t\tviewDistance = Number.MAX_VALUE;\n\t\t\t}\n\n\t\t\tfor( let x = 0; x < horizontalSlidesLength; x++ ) {\n\t\t\t\tlet horizontalSlide = horizontalSlides[x];\n\n\t\t\t\tlet verticalSlides = Util.queryAll( horizontalSlide, 'section' ),\n\t\t\t\t\tverticalSlidesLength = verticalSlides.length;\n\n\t\t\t\t// Determine how far away this slide is from the present\n\t\t\t\tdistanceX = Math.abs( ( indexh || 0 ) - x ) || 0;\n\n\t\t\t\t// If the presentation is looped, distance should measure\n\t\t\t\t// 1 between the first and last slides\n\t\t\t\tif( config.loop ) {\n\t\t\t\t\tdistanceX = Math.abs( ( ( indexh || 0 ) - x ) % ( horizontalSlidesLength - viewDistance ) ) || 0;\n\t\t\t\t}\n\n\t\t\t\t// Show the horizontal slide if it's within the view distance\n\t\t\t\tif( distanceX < viewDistance ) {\n\t\t\t\t\tslideContent.load( horizontalSlide );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tslideContent.unload( horizontalSlide );\n\t\t\t\t}\n\n\t\t\t\tif( verticalSlidesLength ) {\n\n\t\t\t\t\tlet oy = getPreviousVerticalIndex( horizontalSlide );\n\n\t\t\t\t\tfor( let y = 0; y < verticalSlidesLength; y++ ) {\n\t\t\t\t\t\tlet verticalSlide = verticalSlides[y];\n\n\t\t\t\t\t\tdistanceY = x === ( indexh || 0 ) ? Math.abs( ( indexv || 0 ) - y ) : Math.abs( y - oy );\n\n\t\t\t\t\t\tif( distanceX + distanceY < viewDistance ) {\n\t\t\t\t\t\t\tslideContent.load( verticalSlide );\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tslideContent.unload( verticalSlide );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Flag if there are ANY vertical slides, anywhere in the deck\n\t\t\tif( hasVerticalSlides() ) {\n\t\t\t\tdom.wrapper.classList.add( 'has-vertical-slides' );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdom.wrapper.classList.remove( 'has-vertical-slides' );\n\t\t\t}\n\n\t\t\t// Flag if there are ANY horizontal slides, anywhere in the deck\n\t\t\tif( hasHorizontalSlides() ) {\n\t\t\t\tdom.wrapper.classList.add( 'has-horizontal-slides' );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdom.wrapper.classList.remove( 'has-horizontal-slides' );\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Determine what available routes there are for navigation.\n\t *\n\t * @return {{left: boolean, right: boolean, up: boolean, down: boolean}}\n\t */\n\tfunction availableRoutes({ includeFragments = false } = {}) {\n\n\t\tlet horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),\n\t\t\tverticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR );\n\n\t\tlet routes = {\n\t\t\tleft: indexh > 0,\n\t\t\tright: indexh < horizontalSlides.length - 1,\n\t\t\tup: indexv > 0,\n\t\t\tdown: indexv < verticalSlides.length - 1\n\t\t};\n\n\t\t// Looped presentations can always be navigated as long as\n\t\t// there are slides available\n\t\tif( config.loop ) {\n\t\t\tif( horizontalSlides.length > 1 ) {\n\t\t\t\troutes.left = true;\n\t\t\t\troutes.right = true;\n\t\t\t}\n\n\t\t\tif( verticalSlides.length > 1 ) {\n\t\t\t\troutes.up = true;\n\t\t\t\troutes.down = true;\n\t\t\t}\n\t\t}\n\n\t\tif ( horizontalSlides.length > 1 && config.navigationMode === 'linear' ) {\n\t\t\troutes.right = routes.right || routes.down;\n\t\t\troutes.left = routes.left || routes.up;\n\t\t}\n\n\t\t// If includeFragments is set, a route will be considered\n\t\t// available if either a slid OR fragment is available in\n\t\t// the given direction\n\t\tif( includeFragments === true ) {\n\t\t\tlet fragmentRoutes = fragments.availableRoutes();\n\t\t\troutes.left = routes.left || fragmentRoutes.prev;\n\t\t\troutes.up = routes.up || fragmentRoutes.prev;\n\t\t\troutes.down = routes.down || fragmentRoutes.next;\n\t\t\troutes.right = routes.right || fragmentRoutes.next;\n\t\t}\n\n\t\t// Reverse horizontal controls for rtl\n\t\tif( config.rtl ) {\n\t\t\tlet left = routes.left;\n\t\t\troutes.left = routes.right;\n\t\t\troutes.right = left;\n\t\t}\n\n\t\treturn routes;\n\n\t}\n\n\t/**\n\t * Returns the number of past slides. This can be used as a global\n\t * flattened index for slides.\n\t *\n\t * @param {HTMLElement} [slide=currentSlide] The slide we're counting before\n\t *\n\t * @return {number} Past slide count\n\t */\n\tfunction getSlidePastCount( slide = currentSlide ) {\n\n\t\tlet horizontalSlides = getHorizontalSlides();\n\n\t\t// The number of past slides\n\t\tlet pastCount = 0;\n\n\t\t// Step through all slides and count the past ones\n\t\tmainLoop: for( let i = 0; i < horizontalSlides.length; i++ ) {\n\n\t\t\tlet horizontalSlide = horizontalSlides[i];\n\t\t\tlet verticalSlides = horizontalSlide.querySelectorAll( 'section' );\n\n\t\t\tfor( let j = 0; j < verticalSlides.length; j++ ) {\n\n\t\t\t\t// Stop as soon as we arrive at the present\n\t\t\t\tif( verticalSlides[j] === slide ) {\n\t\t\t\t\tbreak mainLoop;\n\t\t\t\t}\n\n\t\t\t\t// Don't count slides with the \"uncounted\" class\n\t\t\t\tif( verticalSlides[j].dataset.visibility !== 'uncounted' ) {\n\t\t\t\t\tpastCount++;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// Stop as soon as we arrive at the present\n\t\t\tif( horizontalSlide === slide ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Don't count the wrapping section for vertical slides and\n\t\t\t// slides marked as uncounted\n\t\t\tif( horizontalSlide.classList.contains( 'stack' ) === false && horizontalSlide.dataset.visibility !== 'uncounted' ) {\n\t\t\t\tpastCount++;\n\t\t\t}\n\n\t\t}\n\n\t\treturn pastCount;\n\n\t}\n\n\t/**\n\t * Returns a value ranging from 0-1 that represents\n\t * how far into the presentation we have navigated.\n\t *\n\t * @return {number}\n\t */\n\tfunction getProgress() {\n\n\t\t// The number of past and total slides\n\t\tlet totalCount = getTotalSlides();\n\t\tlet pastCount = getSlidePastCount();\n\n\t\tif( currentSlide ) {\n\n\t\t\tlet allFragments = currentSlide.querySelectorAll( '.fragment' );\n\n\t\t\t// If there are fragments in the current slide those should be\n\t\t\t// accounted for in the progress.\n\t\t\tif( allFragments.length > 0 ) {\n\t\t\t\tlet visibleFragments = currentSlide.querySelectorAll( '.fragment.visible' );\n\n\t\t\t\t// This value represents how big a portion of the slide progress\n\t\t\t\t// that is made up by its fragments (0-1)\n\t\t\t\tlet fragmentWeight = 0.9;\n\n\t\t\t\t// Add fragment progress to the past slide count\n\t\t\t\tpastCount += ( visibleFragments.length / allFragments.length ) * fragmentWeight;\n\t\t\t}\n\n\t\t}\n\n\t\treturn Math.min( pastCount / ( totalCount - 1 ), 1 );\n\n\t}\n\n\t/**\n\t * Retrieves the h/v location and fragment of the current,\n\t * or specified, slide.\n\t *\n\t * @param {HTMLElement} [slide] If specified, the returned\n\t * index will be for this slide rather than the currently\n\t * active one\n\t *\n\t * @return {{h: number, v: number, f: number}}\n\t */\n\tfunction getIndices( slide ) {\n\n\t\t// By default, return the current indices\n\t\tlet h = indexh,\n\t\t\tv = indexv,\n\t\t\tf;\n\n\t\t// If a slide is specified, return the indices of that slide\n\t\tif( slide ) {\n\t\t\tlet isVertical = isVerticalSlide( slide );\n\t\t\tlet slideh = isVertical ? slide.parentNode : slide;\n\n\t\t\t// Select all horizontal slides\n\t\t\tlet horizontalSlides = getHorizontalSlides();\n\n\t\t\t// Now that we know which the horizontal slide is, get its index\n\t\t\th = Math.max( horizontalSlides.indexOf( slideh ), 0 );\n\n\t\t\t// Assume we're not vertical\n\t\t\tv = undefined;\n\n\t\t\t// If this is a vertical slide, grab the vertical index\n\t\t\tif( isVertical ) {\n\t\t\t\tv = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );\n\t\t\t}\n\t\t}\n\n\t\tif( !slide && currentSlide ) {\n\t\t\tlet hasFragments = currentSlide.querySelectorAll( '.fragment' ).length > 0;\n\t\t\tif( hasFragments ) {\n\t\t\t\tlet currentFragment = currentSlide.querySelector( '.current-fragment' );\n\t\t\t\tif( currentFragment && currentFragment.hasAttribute( 'data-fragment-index' ) ) {\n\t\t\t\t\tf = parseInt( currentFragment.getAttribute( 'data-fragment-index' ), 10 );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tf = currentSlide.querySelectorAll( '.fragment.visible' ).length - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { h, v, f };\n\n\t}\n\n\t/**\n\t * Retrieves all slides in this presentation.\n\t */\n\tfunction getSlides() {\n\n\t\treturn Util.queryAll( dom.wrapper, SLIDES_SELECTOR + ':not(.stack):not([data-visibility=\"uncounted\"])' );\n\n\t}\n\n\t/**\n\t * Returns a list of all horizontal slides in the deck. Each\n\t * vertical stack is included as one horizontal slide in the\n\t * resulting array.\n\t */\n\tfunction getHorizontalSlides() {\n\n\t\treturn Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR );\n\n\t}\n\n\t/**\n\t * Returns all vertical slides that exist within this deck.\n\t */\n\tfunction getVerticalSlides() {\n\n\t\treturn Util.queryAll( dom.wrapper, '.slides>section>section' );\n\n\t}\n\n\t/**\n\t * Returns all vertical stacks (each stack can contain multiple slides).\n\t */\n\tfunction getVerticalStacks() {\n\n\t\treturn Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR + '.stack');\n\n\t}\n\n\t/**\n\t * Returns true if there are at least two horizontal slides.\n\t */\n\tfunction hasHorizontalSlides() {\n\n\t\treturn getHorizontalSlides().length > 1;\n\t}\n\n\t/**\n\t * Returns true if there are at least two vertical slides.\n\t */\n\tfunction hasVerticalSlides() {\n\n\t\treturn getVerticalSlides().length > 1;\n\n\t}\n\n\t/**\n\t * Returns an array of objects where each object represents the\n\t * attributes on its respective slide.\n\t */\n\tfunction getSlidesAttributes() {\n\n\t\treturn getSlides().map( slide => {\n\n\t\t\tlet attributes = {};\n\t\t\tfor( let i = 0; i < slide.attributes.length; i++ ) {\n\t\t\t\tlet attribute = slide.attributes[ i ];\n\t\t\t\tattributes[ attribute.name ] = attribute.value;\n\t\t\t}\n\t\t\treturn attributes;\n\n\t\t} );\n\n\t}\n\n\t/**\n\t * Retrieves the total number of slides in this presentation.\n\t *\n\t * @return {number}\n\t */\n\tfunction getTotalSlides() {\n\n\t\treturn getSlides().length;\n\n\t}\n\n\t/**\n\t * Returns the slide element matching the specified index.\n\t *\n\t * @return {HTMLElement}\n\t */\n\tfunction getSlide( x, y ) {\n\n\t\tlet horizontalSlide = getHorizontalSlides()[ x ];\n\t\tlet verticalSlides = horizontalSlide && horizontalSlide.querySelectorAll( 'section' );\n\n\t\tif( verticalSlides && verticalSlides.length && typeof y === 'number' ) {\n\t\t\treturn verticalSlides ? verticalSlides[ y ] : undefined;\n\t\t}\n\n\t\treturn horizontalSlide;\n\n\t}\n\n\t/**\n\t * Returns the background element for the given slide.\n\t * All slides, even the ones with no background properties\n\t * defined, have a background element so as long as the\n\t * index is valid an element will be returned.\n\t *\n\t * @param {mixed} x Horizontal background index OR a slide\n\t * HTML element\n\t * @param {number} y Vertical background index\n\t * @return {(HTMLElement[]|*)}\n\t */\n\tfunction getSlideBackground( x, y ) {\n\n\t\tlet slide = typeof x === 'number' ? getSlide( x, y ) : x;\n\t\tif( slide ) {\n\t\t\treturn slide.slideBackgroundElement;\n\t\t}\n\n\t\treturn undefined;\n\n\t}\n\n\t/**\n\t * Retrieves the current state of the presentation as\n\t * an object. This state can then be restored at any\n\t * time.\n\t *\n\t * @return {{indexh: number, indexv: number, indexf: number, paused: boolean, overview: boolean}}\n\t */\n\tfunction getState() {\n\n\t\tlet indices = getIndices();\n\n\t\treturn {\n\t\t\tindexh: indices.h,\n\t\t\tindexv: indices.v,\n\t\t\tindexf: indices.f,\n\t\t\tpaused: isPaused(),\n\t\t\toverview: overview.isActive()\n\t\t};\n\n\t}\n\n\t/**\n\t * Restores the presentation to the given state.\n\t *\n\t * @param {object} state As generated by getState()\n\t * @see {@link getState} generates the parameter `state`\n\t */\n\tfunction setState( state ) {\n\n\t\tif( typeof state === 'object' ) {\n\t\t\tslide( Util.deserialize( state.indexh ), Util.deserialize( state.indexv ), Util.deserialize( state.indexf ) );\n\n\t\t\tlet pausedFlag = Util.deserialize( state.paused ),\n\t\t\t\toverviewFlag = Util.deserialize( state.overview );\n\n\t\t\tif( typeof pausedFlag === 'boolean' && pausedFlag !== isPaused() ) {\n\t\t\t\ttogglePause( pausedFlag );\n\t\t\t}\n\n\t\t\tif( typeof overviewFlag === 'boolean' && overviewFlag !== overview.isActive() ) {\n\t\t\t\toverview.toggle( overviewFlag );\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Cues a new automated slide if enabled in the config.\n\t */\n\tfunction cueAutoSlide() {\n\n\t\tcancelAutoSlide();\n\n\t\tif( currentSlide && config.autoSlide !== false ) {\n\n\t\t\tlet fragment = currentSlide.querySelector( '.current-fragment[data-autoslide]' );\n\n\t\t\tlet fragmentAutoSlide = fragment ? fragment.getAttribute( 'data-autoslide' ) : null;\n\t\t\tlet parentAutoSlide = currentSlide.parentNode ? currentSlide.parentNode.getAttribute( 'data-autoslide' ) : null;\n\t\t\tlet slideAutoSlide = currentSlide.getAttribute( 'data-autoslide' );\n\n\t\t\t// Pick value in the following priority order:\n\t\t\t// 1. Current fragment's data-autoslide\n\t\t\t// 2. Current slide's data-autoslide\n\t\t\t// 3. Parent slide's data-autoslide\n\t\t\t// 4. Global autoSlide setting\n\t\t\tif( fragmentAutoSlide ) {\n\t\t\t\tautoSlide = parseInt( fragmentAutoSlide, 10 );\n\t\t\t}\n\t\t\telse if( slideAutoSlide ) {\n\t\t\t\tautoSlide = parseInt( slideAutoSlide, 10 );\n\t\t\t}\n\t\t\telse if( parentAutoSlide ) {\n\t\t\t\tautoSlide = parseInt( parentAutoSlide, 10 );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tautoSlide = config.autoSlide;\n\n\t\t\t\t// If there are media elements with data-autoplay,\n\t\t\t\t// automatically set the autoSlide duration to the\n\t\t\t\t// length of that media. Not applicable if the slide\n\t\t\t\t// is divided up into fragments.\n\t\t\t\t// playbackRate is accounted for in the duration.\n\t\t\t\tif( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {\n\t\t\t\t\tUtil.queryAll( currentSlide, 'video, audio' ).forEach( el => {\n\t\t\t\t\t\tif( el.hasAttribute( 'data-autoplay' ) ) {\n\t\t\t\t\t\t\tif( autoSlide && (el.duration * 1000 / el.playbackRate ) > autoSlide ) {\n\t\t\t\t\t\t\t\tautoSlide = ( el.duration * 1000 / el.playbackRate ) + 1000;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Cue the next auto-slide if:\n\t\t\t// - There is an autoSlide value\n\t\t\t// - Auto-sliding isn't paused by the user\n\t\t\t// - The presentation isn't paused\n\t\t\t// - The overview isn't active\n\t\t\t// - The presentation isn't over\n\t\t\tif( autoSlide && !autoSlidePaused && !isPaused() && !overview.isActive() && ( !isLastSlide() || fragments.availableRoutes().next || config.loop === true ) ) {\n\t\t\t\tautoSlideTimeout = setTimeout( () => {\n\t\t\t\t\tif( typeof config.autoSlideMethod === 'function' ) {\n\t\t\t\t\t\tconfig.autoSlideMethod()\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tnavigateNext();\n\t\t\t\t\t}\n\t\t\t\t\tcueAutoSlide();\n\t\t\t\t}, autoSlide );\n\t\t\t\tautoSlideStartTime = Date.now();\n\t\t\t}\n\n\t\t\tif( autoSlidePlayer ) {\n\t\t\t\tautoSlidePlayer.setPlaying( autoSlideTimeout !== -1 );\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t/**\n\t * Cancels any ongoing request to auto-slide.\n\t */\n\tfunction cancelAutoSlide() {\n\n\t\tclearTimeout( autoSlideTimeout );\n\t\tautoSlideTimeout = -1;\n\n\t}\n\n\tfunction pauseAutoSlide() {\n\n\t\tif( autoSlide && !autoSlidePaused ) {\n\t\t\tautoSlidePaused = true;\n\t\t\tdispatchEvent({ type: 'autoslidepaused' });\n\t\t\tclearTimeout( autoSlideTimeout );\n\n\t\t\tif( autoSlidePlayer ) {\n\t\t\t\tautoSlidePlayer.setPlaying( false );\n\t\t\t}\n\t\t}\n\n\t}\n\n\tfunction resumeAutoSlide() {\n\n\t\tif( autoSlide && autoSlidePaused ) {\n\t\t\tautoSlidePaused = false;\n\t\t\tdispatchEvent({ type: 'autoslideresumed' });\n\t\t\tcueAutoSlide();\n\t\t}\n\n\t}\n\n\tfunction navigateLeft({skipFragments=false}={}) {\n\n\t\tnavigationHistory.hasNavigatedHorizontally = true;\n\n\t\t// Reverse for RTL\n\t\tif( config.rtl ) {\n\t\t\tif( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().left ) {\n\t\t\t\tslide( indexh + 1, config.navigationMode === 'grid' ? indexv : undefined );\n\t\t\t}\n\t\t}\n\t\t// Normal navigation\n\t\telse if( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().left ) {\n\t\t\tslide( indexh - 1, config.navigationMode === 'grid' ? indexv : undefined );\n\t\t}\n\n\t}\n\n\tfunction navigateRight({skipFragments=false}={}) {\n\n\t\tnavigationHistory.hasNavigatedHorizontally = true;\n\n\t\t// Reverse for RTL\n\t\tif( config.rtl ) {\n\t\t\tif( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().right ) {\n\t\t\t\tslide( indexh - 1, config.navigationMode === 'grid' ? indexv : undefined );\n\t\t\t}\n\t\t}\n\t\t// Normal navigation\n\t\telse if( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().right ) {\n\t\t\tslide( indexh + 1, config.navigationMode === 'grid' ? indexv : undefined );\n\t\t}\n\n\t}\n\n\tfunction navigateUp({skipFragments=false}={}) {\n\n\t\t// Prioritize hiding fragments\n\t\tif( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().up ) {\n\t\t\tslide( indexh, indexv - 1 );\n\t\t}\n\n\t}\n\n\tfunction navigateDown({skipFragments=false}={}) {\n\n\t\tnavigationHistory.hasNavigatedVertically = true;\n\n\t\t// Prioritize revealing fragments\n\t\tif( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().down ) {\n\t\t\tslide( indexh, indexv + 1 );\n\t\t}\n\n\t}\n\n\t/**\n\t * Navigates backwards, prioritized in the following order:\n\t * 1) Previous fragment\n\t * 2) Previous vertical slide\n\t * 3) Previous horizontal slide\n\t */\n\tfunction navigatePrev({skipFragments=false}={}) {\n\n\t\t// Prioritize revealing fragments\n\t\tif( skipFragments || fragments.prev() === false ) {\n\t\t\tif( availableRoutes().up ) {\n\t\t\t\tnavigateUp({skipFragments});\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Fetch the previous horizontal slide, if there is one\n\t\t\t\tlet previousSlide;\n\n\t\t\t\tif( config.rtl ) {\n\t\t\t\t\tpreviousSlide = Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR + '.future' ).pop();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpreviousSlide = Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR + '.past' ).pop();\n\t\t\t\t}\n\n\t\t\t\t// When going backwards and arriving on a stack we start\n\t\t\t\t// at the bottom of the stack\n\t\t\t\tif( previousSlide && previousSlide.classList.contains( 'stack' ) ) {\n\t\t\t\t\tlet v = ( previousSlide.querySelectorAll( 'section' ).length - 1 ) || undefined;\n\t\t\t\t\tlet h = indexh - 1;\n\t\t\t\t\tslide( h, v );\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnavigateLeft({skipFragments});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * The reverse of #navigatePrev().\n\t */\n\tfunction navigateNext({skipFragments=false}={}) {\n\n\t\tnavigationHistory.hasNavigatedHorizontally = true;\n\t\tnavigationHistory.hasNavigatedVertically = true;\n\n\t\t// Prioritize revealing fragments\n\t\tif( skipFragments || fragments.next() === false ) {\n\n\t\t\tlet routes = availableRoutes();\n\n\t\t\t// When looping is enabled `routes.down` is always available\n\t\t\t// so we need a separate check for when we've reached the\n\t\t\t// end of a stack and should move horizontally\n\t\t\tif( routes.down && routes.right && config.loop && isLastVerticalSlide() ) {\n\t\t\t\troutes.down = false;\n\t\t\t}\n\n\t\t\tif( routes.down ) {\n\t\t\t\tnavigateDown({skipFragments});\n\t\t\t}\n\t\t\telse if( config.rtl ) {\n\t\t\t\tnavigateLeft({skipFragments});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnavigateRight({skipFragments});\n\t\t\t}\n\t\t}\n\n\t}\n\n\n\t// --------------------------------------------------------------------//\n\t// ----------------------------- EVENTS -------------------------------//\n\t// --------------------------------------------------------------------//\n\n\t/**\n\t * Called by all event handlers that are based on user\n\t * input.\n\t *\n\t * @param {object} [event]\n\t */\n\tfunction onUserInput( event ) {\n\n\t\tif( config.autoSlideStoppable ) {\n\t\t\tpauseAutoSlide();\n\t\t}\n\n\t}\n\n\t/**\n\t* Listener for post message events posted to this window.\n\t*/\n\tfunction onPostMessage( event ) {\n\n\t\tlet data = event.data;\n\n\t\t// Make sure we're dealing with JSON\n\t\tif( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) {\n\t\t\tdata = JSON.parse( data );\n\n\t\t\t// Check if the requested method can be found\n\t\t\tif( data.method && typeof Reveal[data.method] === 'function' ) {\n\n\t\t\t\tif( POST_MESSAGE_METHOD_BLACKLIST.test( data.method ) === false ) {\n\n\t\t\t\t\tconst result = Reveal[data.method].apply( Reveal, data.args );\n\n\t\t\t\t\t// Dispatch a postMessage event with the returned value from\n\t\t\t\t\t// our method invocation for getter functions\n\t\t\t\t\tdispatchPostMessage( 'callback', { method: data.method, result: result } );\n\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconsole.warn( 'reveal.js: \"'+ data.method +'\" is is blacklisted from the postMessage API' );\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Event listener for transition end on the current slide.\n\t *\n\t * @param {object} [event]\n\t */\n\tfunction onTransitionEnd( event ) {\n\n\t\tif( transition === 'running' && /section/gi.test( event.target.nodeName ) ) {\n\t\t\ttransition = 'idle';\n\t\t\tdispatchEvent({\n\t\t\t\ttype: 'slidetransitionend',\n\t\t\t\tdata: { indexh, indexv, previousSlide, currentSlide }\n\t\t\t});\n\t\t}\n\n\t}\n\n\t/**\n\t * A global listener for all click events inside of the\n\t * .slides container.\n\t *\n\t * @param {object} [event]\n\t */\n\tfunction onSlidesClicked( event ) {\n\n\t\tconst anchor = Util.closest( event.target, 'a[href^=\"#\"]' );\n\n\t\t// If a hash link is clicked, we find the target slide\n\t\t// and navigate to it. We previously relied on 'hashchange'\n\t\t// for links like these but that prevented media with\n\t\t// audio tracks from playing in mobile browsers since it\n\t\t// wasn't considered a direct interaction with the document.\n\t\tif( anchor ) {\n\t\t\tconst hash = anchor.getAttribute( 'href' );\n\t\t\tconst indices = location.getIndicesFromHash( hash );\n\n\t\t\tif( indices ) {\n\t\t\t\tReveal.slide( indices.h, indices.v, indices.f );\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Handler for the window level 'resize' event.\n\t *\n\t * @param {object} [event]\n\t */\n\tfunction onWindowResize( event ) {\n\n\t\tlayout();\n\n\t}\n\n\t/**\n\t * Handle for the window level 'visibilitychange' event.\n\t *\n\t * @param {object} [event]\n\t */\n\tfunction onPageVisibilityChange( event ) {\n\n\t\t// If, after clicking a link or similar and we're coming back,\n\t\t// focus the document.body to ensure we can use keyboard shortcuts\n\t\tif( document.hidden === false && document.activeElement !== document.body ) {\n\t\t\t// Not all elements support .blur() - SVGs among them.\n\t\t\tif( typeof document.activeElement.blur === 'function' ) {\n\t\t\t\tdocument.activeElement.blur();\n\t\t\t}\n\t\t\tdocument.body.focus();\n\t\t}\n\n\t}\n\n\t/**\n\t * Handler for the document level 'fullscreenchange' event.\n\t *\n\t * @param {object} [event]\n\t */\n\tfunction onFullscreenChange( event ) {\n\n\t\tlet element = document.fullscreenElement || document.webkitFullscreenElement;\n\t\tif( element === dom.wrapper ) {\n\t\t\tevent.stopImmediatePropagation();\n\n\t\t\t// Timeout to avoid layout shift in Safari\n\t\t\tsetTimeout( () => {\n\t\t\t\tReveal.layout();\n\t\t\t\tReveal.focus.focus(); // focus.focus :'(\n\t\t\t}, 1 );\n\t\t}\n\n\t}\n\n\t/**\n\t * Handles clicks on links that are set to preview in the\n\t * iframe overlay.\n\t *\n\t * @param {object} event\n\t */\n\tfunction onPreviewLinkClicked( event ) {\n\n\t\tif( event.currentTarget && event.currentTarget.hasAttribute( 'href' ) ) {\n\t\t\tlet url = event.currentTarget.getAttribute( 'href' );\n\t\t\tif( url ) {\n\t\t\t\tshowPreview( url );\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Handles click on the auto-sliding controls element.\n\t *\n\t * @param {object} [event]\n\t */\n\tfunction onAutoSlidePlayerClick( event ) {\n\n\t\t// Replay\n\t\tif( isLastSlide() && config.loop === false ) {\n\t\t\tslide( 0, 0 );\n\t\t\tresumeAutoSlide();\n\t\t}\n\t\t// Resume\n\t\telse if( autoSlidePaused ) {\n\t\t\tresumeAutoSlide();\n\t\t}\n\t\t// Pause\n\t\telse {\n\t\t\tpauseAutoSlide();\n\t\t}\n\n\t}\n\n\n\t// --------------------------------------------------------------------//\n\t// ------------------------------- API --------------------------------//\n\t// --------------------------------------------------------------------//\n\n\t// The public reveal.js API\n\tconst API = {\n\t\tVERSION,\n\n\t\tinitialize,\n\t\tconfigure,\n\t\tdestroy,\n\n\t\tsync,\n\t\tsyncSlide,\n\t\tsyncFragments: fragments.sync.bind( fragments ),\n\n\t\t// Navigation methods\n\t\tslide,\n\t\tleft: navigateLeft,\n\t\tright: navigateRight,\n\t\tup: navigateUp,\n\t\tdown: navigateDown,\n\t\tprev: navigatePrev,\n\t\tnext: navigateNext,\n\n\t\t// Navigation aliases\n\t\tnavigateLeft, navigateRight, navigateUp, navigateDown, navigatePrev, navigateNext,\n\n\t\t// Fragment methods\n\t\tnavigateFragment: fragments.goto.bind( fragments ),\n\t\tprevFragment: fragments.prev.bind( fragments ),\n\t\tnextFragment: fragments.next.bind( fragments ),\n\n\t\t// Event binding\n\t\ton,\n\t\toff,\n\n\t\t// Legacy event binding methods left in for backwards compatibility\n\t\taddEventListener: on,\n\t\tremoveEventListener: off,\n\n\t\t// Forces an update in slide layout\n\t\tlayout,\n\n\t\t// Randomizes the order of slides\n\t\tshuffle,\n\n\t\t// Returns an object with the available routes as booleans (left/right/top/bottom)\n\t\tavailableRoutes,\n\n\t\t// Returns an object with the available fragments as booleans (prev/next)\n\t\tavailableFragments: fragments.availableRoutes.bind( fragments ),\n\n\t\t// Toggles a help overlay with keyboard shortcuts\n\t\ttoggleHelp,\n\n\t\t// Toggles the overview mode on/off\n\t\ttoggleOverview: overview.toggle.bind( overview ),\n\n\t\t// Toggles the reader mode on/off\n\t\ttoggleReaderMode: reader.toggle.bind( reader ),\n\n\t\t// Toggles the \"black screen\" mode on/off\n\t\ttogglePause,\n\n\t\t// Toggles the auto slide mode on/off\n\t\ttoggleAutoSlide,\n\n\t\t// Toggles visibility of the jump-to-slide UI\n\t\ttoggleJumpToSlide,\n\n\t\t// Slide navigation checks\n\t\tisFirstSlide,\n\t\tisLastSlide,\n\t\tisLastVerticalSlide,\n\t\tisVerticalSlide,\n\n\t\t// State checks\n\t\tisPaused,\n\t\tisAutoSliding,\n\t\tisSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),\n\t\tisOverview: overview.isActive.bind( overview ),\n\t\tisFocused: focus.isFocused.bind( focus ),\n\n\t\tisReaderMode: reader.isActive.bind( reader ),\n\t\tisPrinting: print.isActive.bind( print ),\n\n\t\t// Checks if reveal.js has been loaded and is ready for use\n\t\tisReady: () => ready,\n\n\t\t// Slide preloading\n\t\tloadSlide: slideContent.load.bind( slideContent ),\n\t\tunloadSlide: slideContent.unload.bind( slideContent ),\n\n\t\t// Media playback\n\t\tstartEmbeddedContent: () => slideContent.startEmbeddedContent( currentSlide ),\n\t\tstopEmbeddedContent: () => slideContent.stopEmbeddedContent( currentSlide, { unloadIframes: false } ),\n\n\t\t// Preview management\n\t\tshowPreview,\n\t\thidePreview: closeOverlay,\n\n\t\t// Adds or removes all internal event listeners\n\t\taddEventListeners,\n\t\tremoveEventListeners,\n\t\tdispatchEvent,\n\n\t\t// Facility for persisting and restoring the presentation state\n\t\tgetState,\n\t\tsetState,\n\n\t\t// Presentation progress on range of 0-1\n\t\tgetProgress,\n\n\t\t// Returns the indices of the current, or specified, slide\n\t\tgetIndices,\n\n\t\t// Returns an Array of key:value maps of the attributes of each\n\t\t// slide in the deck\n\t\tgetSlidesAttributes,\n\n\t\t// Returns the number of slides that we have passed\n\t\tgetSlidePastCount,\n\n\t\t// Returns the total number of slides\n\t\tgetTotalSlides,\n\n\t\t// Returns the slide element at the specified index\n\t\tgetSlide,\n\n\t\t// Returns the previous slide element, may be null\n\t\tgetPreviousSlide: () => previousSlide,\n\n\t\t// Returns the current slide element\n\t\tgetCurrentSlide: () => currentSlide,\n\n\t\t// Returns the slide background element at the specified index\n\t\tgetSlideBackground,\n\n\t\t// Returns the speaker notes string for a slide, or null\n\t\tgetSlideNotes: notes.getSlideNotes.bind( notes ),\n\n\t\t// Returns an Array of all slides\n\t\tgetSlides,\n\n\t\t// Returns an array with all horizontal/vertical slides in the deck\n\t\tgetHorizontalSlides,\n\t\tgetVerticalSlides,\n\n\t\t// Checks if the presentation contains two or more horizontal\n\t\t// and vertical slides\n\t\thasHorizontalSlides,\n\t\thasVerticalSlides,\n\n\t\t// Checks if the deck has navigated on either axis at least once\n\t\thasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally,\n\t\thasNavigatedVertically: () => navigationHistory.hasNavigatedVertically,\n\n\t\t// Adds/removes a custom key binding\n\t\taddKeyBinding: keyboard.addKeyBinding.bind( keyboard ),\n\t\tremoveKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),\n\n\t\t// Programmatically triggers a keyboard event\n\t\ttriggerKey: keyboard.triggerKey.bind( keyboard ),\n\n\t\t// Registers a new shortcut to include in the help overlay\n\t\tregisterKeyboardShortcut: keyboard.registerKeyboardShortcut.bind( keyboard ),\n\n\t\tgetComputedSlideSize,\n\t\tsetCurrentReaderPage,\n\n\t\t// Returns the current scale of the presentation content\n\t\tgetScale: () => scale,\n\n\t\t// Returns the current configuration object\n\t\tgetConfig: () => config,\n\n\t\t// Helper method, retrieves query string as a key:value map\n\t\tgetQueryHash: Util.getQueryHash,\n\n\t\t// Returns the path to the current slide as represented in the URL\n\t\tgetSlidePath: location.getHash.bind( location ),\n\n\t\t// Returns reveal.js DOM elements\n\t\tgetRevealElement: () => revealElement,\n\t\tgetSlidesElement: () => dom.slides,\n\t\tgetViewportElement: () => dom.viewport,\n\t\tgetBackgroundsElement: () => backgrounds.element,\n\n\t\t// API for registering and retrieving plugins\n\t\tregisterPlugin: plugins.registerPlugin.bind( plugins ),\n\t\thasPlugin: plugins.hasPlugin.bind( plugins ),\n\t\tgetPlugin: plugins.getPlugin.bind( plugins ),\n\t\tgetPlugins: plugins.getRegisteredPlugins.bind( plugins )\n\n\t};\n\n\t// Our internal API which controllers have access to\n\tUtil.extend( Reveal, {\n\t\t...API,\n\n\t\t// Methods for announcing content to screen readers\n\t\tannounceStatus,\n\t\tgetStatusText,\n\n\t\t// Controllers\n\t\tfocus,\n\t\treader,\n\t\tprogress,\n\t\tcontrols,\n\t\tlocation,\n\t\toverview,\n\t\tfragments,\n\t\tslideContent,\n\t\tslideNumber,\n\n\t\tonUserInput,\n\t\tcloseOverlay,\n\t\tupdateSlidesVisibility,\n\t\tlayoutSlideContents,\n\t\ttransformSlides,\n\t\tcueAutoSlide,\n\t\tcancelAutoSlide\n\t} );\n\n\treturn API;\n\n};\n","import Deck, { VERSION } from './reveal.js'\n\n/**\n * Expose the Reveal class to the window. To create a\n * new instance:\n * let deck = new Reveal( document.querySelector( '.reveal' ), {\n * controls: false\n * } );\n * deck.initialize().then(() => {\n * // reveal.js is ready\n * });\n */\nlet Reveal = Deck;\n\n\n/**\n * The below is a thin shell that mimics the pre 4.0\n * reveal.js API and ensures backwards compatibility.\n * This API only allows for one Reveal instance per\n * page, whereas the new API above lets you run many\n * presentations on the same page.\n *\n * Reveal.initialize( { controls: false } ).then(() => {\n * // reveal.js is ready\n * });\n */\n\nlet enqueuedAPICalls = [];\n\nReveal.initialize = options => {\n\n\t// Create our singleton reveal.js instance\n\tObject.assign( Reveal, new Deck( document.querySelector( '.reveal' ), options ) );\n\n\t// Invoke any enqueued API calls\n\tenqueuedAPICalls.map( method => method( Reveal ) );\n\n\treturn Reveal.initialize();\n\n}\n\n/**\n * The pre 4.0 API let you add event listener before\n * initializing. We maintain the same behavior by\n * queuing up premature API calls and invoking all\n * of them when Reveal.initialize is called.\n */\n[ 'configure', 'on', 'off', 'addEventListener', 'removeEventListener', 'registerPlugin' ].forEach( method => {\n\tReveal[method] = ( ...args ) => {\n\t\tenqueuedAPICalls.push( deck => deck[method].call( null, ...args ) );\n\t}\n} );\n\nReveal.isReady = () => false;\n\nReveal.VERSION = VERSION;\n\nexport default Reveal;"],"names":["extend","a","b","i","queryAll","el","selector","Array","from","querySelectorAll","toggleClass","className","value","classList","add","remove","deserialize","match","parseFloat","transformElement","element","transform","style","matches","target","matchesMethod","matchesSelector","msMatchesSelector","call","closest","parentNode","createSingletonNode","container","tagname","classname","innerHTML","nodes","length","testNode","node","document","createElement","appendChild","createStyleSheet","tag","type","styleSheet","cssText","createTextNode","head","getQueryHash","query","location","search","replace","split","shift","pop","unescape","getRemainingHeight","height","newHeight","oldHeight","offsetHeight","removeProperty","fileExtensionToMimeMap","UA","navigator","userAgent","isMobile","test","platform","maxTouchPoints","isAndroid","Object","defineProperty","fitty_module","_extends","assign","arguments","source","key","prototype","hasOwnProperty","w","toArray","nl","slice","DrawState","fitties","redrawFrame","requestRedraw","cancelAnimationFrame","requestAnimationFrame","redraw","filter","f","dirty","active","redrawAll","forEach","styleComputed","computeStyle","shouldPreStyle","applyStyle","fittiesToRedraw","shouldRedraw","calculateStyles","markAsClean","dispatchFitEvent","availableWidth","clientWidth","currentWidth","scrollWidth","previousFontSize","currentFontSize","Math","min","max","minSize","maxSize","whiteSpace","multiLine","getComputedStyle","getPropertyValue","display","preStyle","preStyleTestCompleted","fontSize","dispatchEvent","CustomEvent","detail","oldValue","newValue","scaleFactor","fit","destroy","_","observeMutations","observer","disconnect","originalStyle","subscribe","unsubscribe","MutationObserver","observe","defaultOptions","subtree","childList","characterData","resizeDebounce","onWindowResized","clearTimeout","setTimeout","fitty","observeWindowDelay","events","set","enabled","method","e","observeWindow","fitAll","fittyCreate","elements","options","fittyOptions","publicFitties","map","newbie","push","init","unfreeze","freeze","undefined","window","SlideContent","constructor","Reveal","startEmbeddedIframe","this","bind","shouldPreload","isReaderMode","preload","getConfig","preloadIframes","hasAttribute","load","slide","tagName","setAttribute","getAttribute","removeAttribute","media","sources","background","slideBackgroundElement","backgroundContent","slideBackgroundContentElement","backgroundIframe","backgroundImage","backgroundVideo","backgroundVideoLoop","backgroundVideoMuted","trim","url","encodeURI","c","charCodeAt","toString","toUpperCase","encodeRFC3986URI","decodeURI","join","isSpeakerNotes","video","muted","filename","getMimeTypeFromFile","excludeIframes","iframe","width","maxHeight","maxWidth","backgroundIframeElement","querySelector","layout","scopeElement","unload","getSlideBackground","formatEmbeddedContent","_appendParamToIframeSource","sourceAttribute","sourceURL","param","getSlidesElement","src","indexOf","startEmbeddedContent","autoplay","autoPlayMedia","play","readyState","startEmbeddedMedia","promise","catch","controls","addEventListener","removeEventListener","event","isAttachedToDOM","isVisible","currentTime","contentWindow","postMessage","stopEmbeddedContent","unloadIframes","pause","SlideNumber","render","getRevealElement","configure","config","oldConfig","slideNumberDisplay","slideNumber","isPrinting","showSlideNumber","update","getSlideNumber","getCurrentSlide","format","getHorizontalSlides","horizontalOffset","dataset","visibility","getSlidePastCount","getTotalSlides","indices","getIndices","h","sep","isVerticalSlide","v","getHash","formatNumber","delimiter","isNaN","JumpToSlide","onInput","onBlur","onKeyDown","jumpInput","placeholder","show","indicesOnShow","focus","hide","jumpTimeout","jump","getIndicesFromHash","oneBasedIndex","jumpAfter","delay","regex","RegExp","getSlides","find","innerText","cancel","confirm","keyCode","stopImmediatePropagation","colorToRgb","color","hex3","r","parseInt","charAt","g","hex6","rgb","rgba","Backgrounds","create","slideh","backgroundStack","createBackground","slidev","parallaxBackgroundImage","backgroundSize","parallaxBackgroundSize","backgroundRepeat","parallaxBackgroundRepeat","backgroundPosition","parallaxBackgroundPosition","contentElement","sync","data","backgroundColor","backgroundGradient","backgroundTransition","backgroundOpacity","dataPreload","opacity","contrastColor","computedBackgroundStyle","includeAll","currentSlide","currentBackground","horizontalPast","rtl","horizontalFuture","childNodes","backgroundh","backgroundv","previousBackground","slideContent","currentBackgroundContent","backgroundImageURL","previousBackgroundHash","currentBackgroundHash","classToBubble","contains","updateParallax","backgroundWidth","backgroundHeight","horizontalSlides","verticalSlides","getVerticalSlides","horizontalOffsetMultiplier","slideWidth","offsetWidth","horizontalSlideCount","parallaxBackgroundHorizontal","verticalOffsetMultiplier","verticalOffset","slideHeight","verticalSlideCount","parallaxBackgroundVertical","SLIDES_SELECTOR","HORIZONTAL_SLIDES_SELECTOR","VERTICAL_SLIDES_SELECTOR","POST_MESSAGE_METHOD_BLACKLIST","FRAGMENT_STYLE_REGEX","autoAnimateCounter","AutoAnimate","run","fromSlide","toSlide","reset","allSlides","toSlideIndex","fromSlideIndex","autoAnimateStyleSheet","animationOptions","getAutoAnimateOptions","autoAnimate","slideDirection","fromSlideIsHidden","css","getAutoAnimatableElements","autoAnimateElements","to","autoAnimateUnmatched","defaultUnmatchedDuration","duration","defaultUnmatchedDelay","getUnmatchedAutoAnimateElements","unmatchedElement","unmatchedOptions","id","autoAnimateTarget","fontWeight","sheet","removeChild","elementOptions","easing","fromProps","getAutoAnimatableProperties","toProps","styles","translate","scale","presentationScale","getScale","delta","x","y","scaleX","scaleY","round","propertyName","toValue","fromValue","explicitValue","toStyleProperties","keys","inheritedOptions","autoAnimateEasing","autoAnimateDuration","autoAnimatedParent","autoAnimateDelay","direction","properties","bounds","measure","center","getBoundingClientRect","offsetLeft","offsetTop","computedStyles","autoAnimateStyles","property","pairs","autoAnimateMatcher","getAutoAnimatePairs","reserved","pair","index","textNodes","findAutoAnimateMatches","nodeName","textContent","getLocalBoundingBox","fromScope","toScope","serializer","fromMatches","toMatches","fromElement","primaryIndex","secondaryIndex","rootElement","children","reduce","result","containsAnimatedElements","concat","Fragments","fragments","disable","enable","availableRoutes","hiddenFragments","prev","next","sort","grouped","ordered","unordered","sorted","fragment","group","sortAll","horizontalSlide","verticalSlide","changedFragments","shown","hidden","maxIndex","currentFragment","wasVisible","announceStatus","getStatusText","bubbles","goto","offset","lastVisibleFragment","progress","fragmentInURL","writeURL","Overview","onSlideClicked","activate","overview","isActive","cancelAutoSlide","getBackgroundsElement","margin","slideSize","getComputedSlideSize","overviewSlideWidth","overviewSlideHeight","updateSlidesVisibility","hslide","vslide","hbackground","vbackground","vmin","innerWidth","innerHeight","transformSlides","deactivate","cueAutoSlide","toggle","override","preventDefault","Keyboard","shortcuts","bindings","onDocumentKeyDown","onDocumentKeyPress","navigationMode","unbind","addKeyBinding","binding","callback","description","removeKeyBinding","triggerKey","registerKeyboardShortcut","getShortcuts","getBindings","shiftKey","charCode","toggleHelp","keyboardCondition","isFocused","autoSlideWasPaused","isAutoSliding","onUserInput","activeElementIsCE","activeElement","isContentEditable","activeElementIsInput","activeElementIsNotes","unusedModifier","altKey","ctrlKey","metaKey","resumeKeyCodes","keyboard","isPaused","useLinearMode","hasHorizontalSlides","hasVerticalSlides","triggered","apply","action","skipFragments","left","right","up","Number","MAX_VALUE","down","togglePause","requestMethod","documentElement","requestFullscreen","webkitRequestFullscreen","webkitRequestFullScreen","mozRequestFullScreen","msRequestFullscreen","enterFullscreen","embedded","getViewportElement","autoSlideStoppable","toggleAutoSlide","jumpToSlide","toggleJumpToSlide","closeOverlay","Location","writeURLTimeout","replaceStateTimestamp","onWindowHashChange","hash","name","bits","hashIndexBase","hashOneBasedIndex","getElementById","decodeURIComponent","error","readURL","currentIndices","newIndices","history","debouncedReplaceState","pathname","replaceState","Date","now","replaceStateTimeout","MAX_REPLACE_STATE_FREQUENCY","s","encodeURIComponent","Controls","onNavigateLeftClicked","onNavigateRightClicked","onNavigateUpClicked","onNavigateDownClicked","onNavigatePrevClicked","onNavigateNextClicked","revealElement","controlsLeft","controlsRight","controlsUp","controlsDown","controlsPrev","controlsNext","controlsRightArrow","controlsLeftArrow","controlsDownArrow","controlsLayout","controlsBackArrows","pointerEvents","eventName","routes","fragmentsRoutes","controlsTutorial","hasNavigatedVertically","hasNavigatedHorizontally","Progress","onProgressClicked","bar","getProgress","getMaxWidth","slides","slidesTotal","slideIndex","floor","clientX","targetIndices","Pointer","lastMouseWheelStep","cursorHidden","cursorInactiveTimeout","onDocumentCursorActive","onDocumentMouseScroll","mouseWheel","hideInactiveCursor","showCursor","cursor","hideCursor","hideCursorTime","wheelDelta","loadScript","script","async","defer","onload","onreadystatechange","onerror","err","Error","insertBefore","lastChild","Plugins","reveal","state","registeredPlugins","asyncDependencies","plugins","dependencies","registerPlugin","Promise","resolve","scripts","scriptsToLoad","condition","scriptLoadedCallback","initPlugins","then","console","warn","pluginValues","values","pluginsToInitialize","loadAsync","initNextPlugin","afterPlugInitialized","plugin","hasPlugin","getPlugin","getRegisteredPlugins","Reader","activatedCallbacks","onScroll","slideHTMLBeforeActivation","viewportElement","presentationBackground","viewportStyles","pageElements","pageContainer","page","stickyContainer","contentContainer","stack","readerLayout","viewportHeight","compactHeight","pageHeight","scrollTriggerHeight","setProperty","scrollSnapType","readerScrollSnap","pages","pageElement","stickyElement","slideElement","backgroundElement","top","scrollTriggers","fragmentGroups","segmentSize","range","fragmentIndex","scrollPadding","scrollSnapAlign","totalHeight","bottom","position","scrollToSlide","scrollIntoView","scrollTop","activePage","closestPage","distance","abs","Infinity","pageIndex","isWithinPreloadRange","isPartiallyVisible","preloaded","setCurrentReaderPage","scrollProgress","trigger","Print","injectPageNumbers","pageWidth","body","layoutSlideContents","slideScrollHeights","scrollHeight","contentHeight","numberOfPages","ceil","pdfMaxPagesPerSlide","pdfPageHeightOffset","showNotes","notes","getSlideNotes","notesSpacing","notesLayout","notesElement","numberElement","pdfSeparateFragments","previousFragmentStep","clonedPage","cloneNode","fragmentNumber","view","Touch","touchStartX","touchStartY","touchStartCount","touchCaptured","onPointerDown","onPointerMove","onPointerUp","onTouchStart","onTouchMove","onTouchEnd","msPointerEnabled","isSwipePrevented","touches","clientY","currentX","currentY","includeFragments","deltaX","deltaY","pointerType","MSPOINTER_TYPE_TOUCH","STATE_FOCUS","STATE_BLUR","Focus","onRevealPointerDown","onDocumentPointerDown","blur","Notes","updateVisibility","hasNotes","isSpeakerNotesWindow","notesElements","Playback","progressCheck","diameter","diameter2","thickness","playing","progressOffset","canvas","context","getContext","setPlaying","wasPlaying","animate","progressBefore","radius","iconSize","endAngle","PI","startAngle","save","clearRect","beginPath","arc","fillStyle","fill","lineWidth","strokeStyle","stroke","fillRect","moveTo","lineTo","restore","on","listener","off","minScale","maxScale","respondToHashChanges","disableLayout","touch","loop","shuffle","help","showHiddenSlides","autoSlide","autoSlideMethod","defaultTiming","previewLinks","postMessageEvents","focusBodyOnPageVisibilityChange","transition","transitionSpeed","readerActivationWidth","POSITIVE_INFINITY","viewDistance","mobileViewDistance","sortFragmentsOnSync","VERSION","indexh","indexv","previousSlide","autoSlidePlayer","ready","navigationHistory","slidesTransform","dom","autoSlideTimeout","autoSlideStartTime","autoSlidePaused","backgrounds","pointer","reader","print","initialize","initOptions","wrapper","defaultConfig","Util","setViewport","start","viewport","removeHiddenSlides","setupDOM","setupPostMessage","setupScrollPrevention","setupFullscreen","resetVerticalSlides","activatePrintView","activateReaderView","removeEventListeners","Device","pauseOverlay","statusElement","createStatusElement","overflow","clip","text","nodeType","isAriaHidden","isDisplayHidden","child","setInterval","scrollLeft","onFullscreenChange","onPostMessage","isReady","numberOfSlides","resume","enablePreviewLinks","disablePreviewLinks","onAutoSlidePlayerClick","addEventListeners","onWindowResize","onSlidesClicked","onTransitionEnd","onPageVisibilityChange","useCapture","transforms","createEvent","initEvent","dispatchPostMessage","dispatchSlideChanged","origin","parent","self","message","namespace","getState","JSON","stringify","onPreviewLinkClicked","showPreview","overlay","showHelp","html","size","oldScale","presentationWidth","presentationHeight","zoom","len","remainingHeight","nw","naturalWidth","videoWidth","nh","naturalHeight","videoHeight","es","setPreviousVerticalIndex","getPreviousVerticalIndex","attributeName","isLastVerticalSlide","nextElementSibling","isFirstSlide","isLastSlide","wasPaused","resumeAutoSlide","pauseAutoSlide","defaultPrevented","stateBefore","indexhBefore","indexvBefore","updateSlides","slideChanged","currentHorizontalSlide","currentVerticalSlides","autoAnimateTransition","shoulAutoAnimateBetween","getVerticalStacks","stateLoop","j","splice","syncSlide","beforeSlide","random","slidesLength","printMode","loopedForwards","loopedBackwards","reverse","showFragmentsIn","hideFragmentsIn","wasPresent","slideState","distanceX","distanceY","horizontalSlidesLength","verticalSlidesLength","oy","fragmentRoutes","pastCount","mainLoop","totalCount","allFragments","fragmentWeight","isVertical","getSlidesAttributes","attributes","attribute","getSlide","indexf","paused","setState","pausedFlag","overviewFlag","fragmentAutoSlide","parentAutoSlide","slideAutoSlide","playbackRate","navigateNext","navigateLeft","navigateRight","navigateUp","navigateDown","navigatePrev","parse","args","anchor","fullscreenElement","webkitFullscreenElement","currentTarget","API","syncFragments","navigateFragment","prevFragment","nextFragment","availableFragments","toggleOverview","toggleReaderMode","isOverview","loadSlide","unloadSlide","hidePreview","getPreviousSlide","getSlidePath","getPlugins","Deck","enqueuedAPICalls","deck"],"mappings":"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"} |