diff --git a/dist/reveal.min.js b/dist/reveal.min.js index 5903c51..8091d9d 100644 --- a/dist/reveal.min.js +++ b/dist/reveal.min.js @@ -5,4 +5,4 @@ * * Copyright (C) 2020 Hakim El Hattab, https://hakim.se */ -!function(e){var t={};function a(r){if(t[r])return t[r].exports;var n=t[r]={i:r,l:!1,exports:{}};return e[r].call(n.exports,n,n.exports,a),n.l=!0,n.exports}a.m=e,a.c=t,a.d=function(e,t,r){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(a.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)a.d(r,n,function(t){return e[t]}.bind(null,n));return r},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="",a(a.s=0)}([function(e,t,a){"use strict";a.r(t);const r=(e,t)=>{const a=document.createElement("script");a.type="text/javascript",a.async=!1,a.defer=!1,a.src=e,"function"==typeof t&&(a.onload=a.onreadystatechange=e=>{("load"===e.type||/loaded|complete/.test(a.readyState))&&(a.onload=a.onreadystatechange=a.onerror=null,t())},a.onerror=e=>{a.onload=a.onreadystatechange=a.onerror=null,t(new Error("Failed loading script: "+a.src+"\n"+e))});const r=document.querySelector("head");r.insertBefore(a,r.lastChild)};class n{constructor(){this.state="pending",this.registeredPlugins={},this.asyncDependencies=[]}load(e){return this.state="loading",new Promise(t=>{let a=[],n=0;e.forEach(e=>{e.condition&&!e.condition()||(e.async?this.asyncDependencies.push(e):a.push(e))}),a.length?(n=a.length,a.forEach(e=>{r(e.src,()=>{"function"==typeof e.callback&&e.callback(),0==--n&&this.initPlugins().then(t)})})):this.initPlugins().then(t)})}initPlugins(){return new Promise(e=>{let t=Object.keys(this.registeredPlugins).length;if(0===t)this.loadAsync().then(e);else{let a=()=>{0==--t&&this.loadAsync().then(e)};for(let e in this.registeredPlugins){let t=this.registeredPlugins[e];if("function"==typeof t.init){let e=t.init();e&&"function"==typeof e.then?e.then(a):a()}else a()}}})}loadAsync(){return this.state="loaded",this.asyncDependencies.length&&this.asyncDependencies.forEach(e=>{r(e.src,e.callback)}),Promise.resolve()}registerPlugin(e,t){void 0===this.registeredPlugins[e]?(this.registeredPlugins[e]=t,"loaded"===this.state&&"function"==typeof t.init&&t.init()):console.warn('reveal.js: "'+e+'" plugin has already been registered')}hasPlugin(e){return!!this.registeredPlugins[e]}getPlugin(e){return this.registeredPlugins[e]}getRegisteredPlugins(){return this.registeredPlugins}}class i{constructor(e,t){this.diameter=100,this.diameter2=this.diameter/2,this.thickness=6,this.playing=!1,this.progress=0,this.progressOffset=1,this.container=e,this.progressCheck=t,this.canvas=document.createElement("canvas"),this.canvas.className="playback",this.canvas.width=this.diameter,this.canvas.height=this.diameter,this.canvas.style.width=this.diameter2+"px",this.canvas.style.height=this.diameter2+"px",this.context=this.canvas.getContext("2d"),this.container.appendChild(this.canvas),this.render()}setPlaying(e){const t=this.playing;this.playing=e,!t&&this.playing?this.animate():this.render()}animate(){const e=this.progress;this.progress=this.progressCheck(),e>.8&&this.progress<.2&&(this.progressOffset=this.progress),this.render(),this.playing&&requestAnimationFrame(this.animate.bind(this))}render(){let e=this.playing?this.progress:0,t=this.diameter2-this.thickness,a=this.diameter2,r=this.diameter2;this.progressOffset+=.1*(1-this.progressOffset);const n=-Math.PI/2+e*(2*Math.PI),i=-Math.PI/2+this.progressOffset*(2*Math.PI);this.context.save(),this.context.clearRect(0,0,this.diameter,this.diameter),this.context.beginPath(),this.context.arc(a,r,t+4,0,2*Math.PI,!1),this.context.fillStyle="rgba( 0, 0, 0, 0.4 )",this.context.fill(),this.context.beginPath(),this.context.arc(a,r,t,0,2*Math.PI,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="rgba( 255, 255, 255, 0.2 )",this.context.stroke(),this.playing&&(this.context.beginPath(),this.context.arc(a,r,t,i,n,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="#fff",this.context.stroke()),this.context.translate(a-14,r-14),this.playing?(this.context.fillStyle="#fff",this.context.fillRect(0,0,10,28),this.context.fillRect(18,0,10,28)):(this.context.beginPath(),this.context.translate(4,0),this.context.moveTo(0,0),this.context.lineTo(24,14),this.context.lineTo(0,28),this.context.fillStyle="#fff",this.context.fill()),this.context.restore()}on(e,t){this.canvas.addEventListener(e,t,!1)}off(e,t){this.canvas.removeEventListener(e,t,!1)}destroy(){this.playing=!1,this.canvas.parentNode&&this.container.removeChild(this.canvas)}}var o={width:960,height:700,margin:.04,minScale:.2,maxScale:2,controls:!0,controlsTutorial:!0,controlsLayout:"bottom-right",controlsBackArrows:"faded",progress:!0,slideNumber:!1,showSlideNumber:"all",hashOneBasedIndex:!1,hash:!1,history:!1,keyboard:!0,keyboardCondition:null,overview:!0,disableLayout:!1,center:!0,touch:!0,loop:!1,rtl:!1,navigationMode:"default",shuffle:!1,fragments:!0,fragmentInURL:!1,embedded:!1,help:!0,pause:!0,showNotes:!1,autoPlayMedia:null,preloadIframes:null,autoAnimate:!0,autoAnimateMatcher:null,autoAnimateEasing:"ease",autoAnimateDuration:1,autoAnimateUnmatched:!0,autoAnimateStyles:["opacity","color","background-color","padding","font-size","line-height","letter-spacing","border-width","border-color","border-radius","outline","outline-offset"],autoSlide:0,autoSlideStoppable:!0,autoSlideMethod:null,defaultTiming:null,mouseWheel:!1,previewLinks:!1,postMessage:!0,postMessageEvents:!1,focusBodyOnPageVisibilityChange:!0,transition:"slide",transitionSpeed:"default",backgroundTransition:"fade",parallaxBackgroundImage:"",parallaxBackgroundSize:"",parallaxBackgroundRepeat:"",parallaxBackgroundPosition:"",parallaxBackgroundHorizontal:null,parallaxBackgroundVertical:null,pdfMaxPagesPerSlide:Number.POSITIVE_INFINITY,pdfSeparateFragments:!0,pdfPageHeightOffset:-1,viewDistance:3,mobileViewDistance:2,display:"block",hideInactiveCursor:!0,hideCursorTime:5e3,dependencies:[]};const s=/registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener/,l=(e,t)=>{for(let a in t)e[a]=t[a];return e},d=e=>Array.prototype.slice.call(e),c=e=>{if("string"==typeof e){if("null"===e)return null;if("true"===e)return!0;if("false"===e)return!1;if(e.match(/^-?[\d\.]+$/))return parseFloat(e)}return e},u=(e,t)=>{e.style.transform=t},p=(e,t)=>{let a=e.parentNode;for(;a;){let e=a.matches||a.matchesSelector||a.msMatchesSelector;if(e&&e.call(a,t))return a;a=a.parentNode}return null},h=e=>{let t=document.createElement("style");t.type="text/css",t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document.createTextNode(e)),document.getElementsByTagName("head")[0].appendChild(t)},g=e=>{let t=e.match(/^#([0-9a-f]{3})$/i);if(t&&t[1])return t=t[1],{r:17*parseInt(t.charAt(0),16),g:17*parseInt(t.charAt(1),16),b:17*parseInt(t.charAt(2),16)};let a=e.match(/^#([0-9a-f]{6})$/i);if(a&&a[1])return a=a[1],{r:parseInt(a.substr(0,2),16),g:parseInt(a.substr(2,2),16),b:parseInt(a.substr(4,2),16)};let r=e.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);if(r)return{r:parseInt(r[1],10),g:parseInt(r[2],10),b:parseInt(r[3],10)};let n=e.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i);return n?{r:parseInt(n[1],10),g:parseInt(n[2],10),b:parseInt(n[3],10),a:parseFloat(n[4])}:null};var f=function(e,t){let a;const r=navigator.userAgent;let f,m,v,y,b,w,A,k,E,S,L=!1,x=!1,M=null,N=null,q=!1,P=!1,I=[],T=1,C={layout:"",overview:""},R={},D=new n,O={},z=0,B=0,H=!1,j=0,$=!1,W=0,F=0,U=0,V=-1,X=!1,Y={startX:0,startY:0,startCount:0,captured:!1,threshold:40},K={},_={};function J(){L=!0,function(){R.slides.classList.add("no-transition"),A?R.wrapper.classList.add("no-hover"):R.wrapper.classList.remove("no-hover");/iphone/gi.test(r)?R.wrapper.classList.add("ua-iphone"):R.wrapper.classList.remove("ua-iphone");R.background=G(R.wrapper,"div","backgrounds",null),R.progress=G(R.wrapper,"div","progress",""),R.progressbar=R.progress.querySelector("span"),R.controls=G(R.wrapper,"aside","controls",`\n\t\t\t\n\t\t\t\n\t\t\t`),R.slideNumber=G(R.wrapper,"div","slide-number",""),R.speakerNotes=G(R.wrapper,"div","speaker-notes",null),R.speakerNotes.setAttribute("data-prevent-swipe",""),R.speakerNotes.setAttribute("tabindex","0"),R.pauseOverlay=G(R.wrapper,"div","pause-overlay",f.controls?'':null),R.wrapper.setAttribute("role","application"),R.controlsLeft=d(R.wrapper.querySelectorAll(".navigate-left")),R.controlsRight=d(R.wrapper.querySelectorAll(".navigate-right")),R.controlsUp=d(R.wrapper.querySelectorAll(".navigate-up")),R.controlsDown=d(R.wrapper.querySelectorAll(".navigate-down")),R.controlsPrev=d(R.wrapper.querySelectorAll(".navigate-prev")),R.controlsNext=d(R.wrapper.querySelectorAll(".navigate-next")),R.controlsRightArrow=R.controls.querySelector(".navigate-right"),R.controlsLeftArrow=R.controls.querySelector(".navigate-left"),R.controlsDownArrow=R.controls.querySelector(".navigate-down"),R.statusDiv=function(){let e=R.wrapper.querySelector(".aria-status");e||(e=document.createElement("div"),e.style.position="absolute",e.style.height="1px",e.style.width="1px",e.style.overflow="hidden",e.style.clip="rect( 1px, 1px, 1px, 1px )",e.classList.add("aria-status"),e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),R.wrapper.appendChild(e));return e}()}(),f.postMessage&&window.addEventListener("message",e=>{let t=e.data;if("string"==typeof t&&"{"===t.charAt(0)&&"}"===t.charAt(t.length-1)&&(t=JSON.parse(t),t.method&&"function"==typeof a[t.method]))if(!1===s.test(t.method)){const e=a[t.method].apply(a,t.args);le("callback",{method:t.method,result:e})}else console.warn('reveal.js: "'+t.method+'" is is blacklisted from the postMessage API')},!1),setInterval(()=>{0===R.wrapper.scrollTop&&0===R.wrapper.scrollLeft||(R.wrapper.scrollTop=0,R.wrapper.scrollLeft=0)},1e3),ft().forEach(e=>{d(e.querySelectorAll("section")).forEach((e,t)=>{t>0&&(e.classList.remove("present"),e.classList.remove("past"),e.classList.add("future"),e.setAttribute("aria-hidden","true"))})}),ae(),ut(),Ve(!0),setTimeout(()=>{R.slides.classList.remove("no-transition"),R.wrapper.classList.add("ready"),se("ready",{indexh:m,indexv:v,currentSlide:b})},1),oe()&&(ne(),"complete"===document.readyState?Z():window.addEventListener("load",Z))}function Q(e){let t="";if(3===e.nodeType)t+=e.textContent;else if(1===e.nodeType){let a=e.getAttribute("aria-hidden"),r="none"===window.getComputedStyle(e).display;"true"===a||r||d(e.childNodes).forEach(e=>{t+=Q(e)})}return t=t.trim(),""===t?"":t+" "}function Z(){let e=me(window.innerWidth,window.innerHeight),t=Math.floor(e.width*(1+f.margin)),a=Math.floor(e.height*(1+f.margin)),r=e.width,n=e.height;h("@page{size:"+t+"px "+a+"px; margin: 0px;}"),h(".reveal section>img, .reveal section>video, .reveal section>iframe{max-width: "+r+"px; max-height:"+n+"px}"),document.body.classList.add("print-pdf"),document.body.style.width=t+"px",document.body.style.height=a+"px",fe(r,n);let i=f.slideNumber&&/all|print/i.test(f.showSlideNumber);d(R.wrapper.querySelectorAll(".slides section")).forEach((function(e){e.setAttribute("data-slide-number",Fe(e))})),d(R.wrapper.querySelectorAll(".slides section")).forEach((function(e){if(!1===e.classList.contains("stack")){let o=(t-r)/2,s=(a-n)/2,l=e.scrollHeight,c=Math.max(Math.ceil(l/a),1);c=Math.min(c,f.pdfMaxPagesPerSlide),(1===c&&f.center||e.classList.contains("center"))&&(s=Math.max((a-l)/2,0));let u=document.createElement("div");if(u.className="pdf-page",u.style.height=(a+f.pdfPageHeightOffset)*c+"px",e.parentNode.insertBefore(u,e),u.appendChild(e),e.style.left=o+"px",e.style.top=s+"px",e.style.width=r+"px",e.slideBackgroundElement&&u.insertBefore(e.slideBackgroundElement,e),f.showNotes){let a=kt(e);if(a){let e=8,r="string"==typeof f.showNotes?f.showNotes:"inline",n=document.createElement("div");n.classList.add("speaker-notes"),n.classList.add("speaker-notes-pdf"),n.setAttribute("data-layout",r),n.innerHTML=a,"separate-page"===r?u.parentNode.insertBefore(n,u.nextSibling):(n.style.left=e+"px",n.style.bottom=e+"px",n.style.width=t-2*e+"px",u.appendChild(n))}}if(i){let t=document.createElement("div");t.classList.add("slide-number"),t.classList.add("slide-number-pdf"),t.innerHTML=e.getAttribute("data-slide-number"),u.appendChild(t)}if(f.pdfSeparateFragments){let e,t,a=St(u.querySelectorAll(".fragment"),!0);a.forEach((function(a){e&&e.forEach((function(e){e.classList.remove("current-fragment")})),a.forEach((function(e){e.classList.add("visible","current-fragment")}));let r=u.cloneNode(!0);u.parentNode.insertBefore(r,(t||u).nextSibling),e=a,t=r})),a.forEach((function(e){e.forEach((function(e){e.classList.remove("visible","current-fragment")}))}))}else d(u.querySelectorAll(".fragment:not(.fade-out)")).forEach((function(e){e.classList.add("visible")}))}})),se("pdf-ready")}function G(e,t,a,r=""){let n=e.querySelectorAll("."+a);for(let t=0;t{e.dataset.autoAnimate=""}),Ye(),E&&E.parentNode&&(E.parentNode.removeChild(E),E=null),S&&(S.destroy(),S=null),r>1&&f.autoSlide&&f.autoSlideStoppable&&(S=new i(R.wrapper,()=>Math.min(Math.max((Date.now()-V)/F,0),1)),S.on("click",da),X=!1),!1===f.fragments&&d(R.slides.querySelectorAll(".fragment")).forEach(e=>{e.classList.add("visible"),e.classList.remove("current-fragment")});let n="none";f.slideNumber&&!oe()&&("all"===f.showSlideNumber||"speaker"===f.showSlideNumber&&ct())&&(n="block"),R.slideNumber.style.display=n,"default"!==f.navigationMode?R.wrapper.setAttribute("data-navigation-mode",f.navigationMode):R.wrapper.removeAttribute("data-navigation-mode"),"linear"===f.navigationMode?(K["→ , ↓ , SPACE , N , L , J"]="Next slide",K["← , ↑ , P , H , K"]="Previous slide"):(K["N , SPACE"]="Next slide",K.P="Previous slide",K["← , H"]="Navigate left",K["→ , L"]="Navigate right",K["↑ , K"]="Navigate up",K["↓ , J"]="Navigate down"),K["Home , Shift ←"]="First slide",K["End , Shift →"]="Last slide",K["B , ."]="Pause",K.F="Fullscreen",K["ESC, O"]="Slide overview",De()}function re(){$=!0,window.addEventListener("hashchange",na,!1),window.addEventListener("resize",ia,!1),f.touch&&("onpointerdown"in window?(R.wrapper.addEventListener("pointerdown",Yt,!1),R.wrapper.addEventListener("pointermove",Kt,!1),R.wrapper.addEventListener("pointerup",_t,!1)):window.navigator.msPointerEnabled?(R.wrapper.addEventListener("MSPointerDown",Yt,!1),R.wrapper.addEventListener("MSPointerMove",Kt,!1),R.wrapper.addEventListener("MSPointerUp",_t,!1)):(R.wrapper.addEventListener("touchstart",Ut,!1),R.wrapper.addEventListener("touchmove",Vt,!1),R.wrapper.addEventListener("touchend",Xt,!1))),f.keyboard&&(document.addEventListener("keydown",Ft,!1),document.addEventListener("keypress",Wt,!1)),f.progress&&R.progress&&R.progress.addEventListener("click",Qt,!1),R.pauseOverlay.addEventListener("click",Pe,!1),f.focusBodyOnPageVisibilityChange&&document.addEventListener("visibilitychange",oa,!1);let e=["touchstart","click"];r.match(/android/gi)&&(e=["touchstart"]),e.forEach(e=>{R.controlsLeft.forEach(t=>t.addEventListener(e,Zt,!1)),R.controlsRight.forEach(t=>t.addEventListener(e,Gt,!1)),R.controlsUp.forEach(t=>t.addEventListener(e,ea,!1)),R.controlsDown.forEach(t=>t.addEventListener(e,ta,!1)),R.controlsPrev.forEach(t=>t.addEventListener(e,aa,!1)),R.controlsNext.forEach(t=>t.addEventListener(e,ra,!1))})}function ne(){$=!1,document.removeEventListener("keydown",Ft,!1),document.removeEventListener("keypress",Wt,!1),window.removeEventListener("hashchange",na,!1),window.removeEventListener("resize",ia,!1),R.wrapper.removeEventListener("pointerdown",Yt,!1),R.wrapper.removeEventListener("pointermove",Kt,!1),R.wrapper.removeEventListener("pointerup",_t,!1),R.wrapper.removeEventListener("MSPointerDown",Yt,!1),R.wrapper.removeEventListener("MSPointerMove",Kt,!1),R.wrapper.removeEventListener("MSPointerUp",_t,!1),R.wrapper.removeEventListener("touchstart",Ut,!1),R.wrapper.removeEventListener("touchmove",Vt,!1),R.wrapper.removeEventListener("touchend",Xt,!1),R.pauseOverlay.removeEventListener("click",Pe,!1),f.progress&&R.progress&&R.progress.removeEventListener("click",Qt,!1),["touchstart","click"].forEach(e=>{R.controlsLeft.forEach(t=>t.removeEventListener(e,Zt,!1)),R.controlsRight.forEach(t=>t.removeEventListener(e,Gt,!1)),R.controlsUp.forEach(t=>t.removeEventListener(e,ea,!1)),R.controlsDown.forEach(t=>t.removeEventListener(e,ta,!1)),R.controlsPrev.forEach(t=>t.removeEventListener(e,aa,!1)),R.controlsNext.forEach(t=>t.removeEventListener(e,ra,!1))})}function ie(e){"string"==typeof e.layout&&(C.layout=e.layout),"string"==typeof e.overview&&(C.overview=e.overview),C.layout?u(R.slides,C.layout+" "+C.overview):u(R.slides,C.overview)}function oe(){return/print-pdf/gi.test(window.location.search)}function se(e,t){let a=document.createEvent("HTMLEvents",1,2);a.initEvent(e,!0,!0),l(a,t),R.wrapper.dispatchEvent(a),le(e)}function le(e,t){if(f.postMessageEvents&&window.parent!==window.self){let a={namespace:"reveal",eventName:e,state:Et()};l(a,t),window.parent.postMessage(JSON.stringify(a),"*")}}function de(e="a"){d(R.wrapper.querySelectorAll(e)).forEach(e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.addEventListener("click",la,!1)})}function ce(e="a"){d(R.wrapper.querySelectorAll(e)).forEach(e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.removeEventListener("click",la,!1)})}function ue(e){"boolean"==typeof e?e?pe():he():R.overlay?he():pe()}function pe(){if(f.help){he(),R.overlay=document.createElement("div"),R.overlay.classList.add("overlay"),R.overlay.classList.add("overlay-help"),R.wrapper.appendChild(R.overlay);let e='

Keyboard Shortcuts


';e+="";for(let t in K)e+=``;for(let t in _)_[t].key&&_[t].description&&(e+=``);e+="
KEYACTION
${t}${K[t]}
${_[t].key}${_[t].description}
",R.overlay.innerHTML=`\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
${e}
\n\t\t\t\t
\n\t\t\t`,R.overlay.querySelector(".close").addEventListener("click",e=>{he(),e.preventDefault()},!1)}}function he(){R.overlay&&(R.overlay.parentNode.removeChild(R.overlay),R.overlay=null)}function ge(){if(R.wrapper&&!oe()){if(!f.disableLayout){A&&document.documentElement.style.setProperty("--vh",.01*window.innerHeight+"px");const e=me(),t=T;fe(f.width,f.height),R.slides.style.width=e.width+"px",R.slides.style.height=e.height+"px",T=Math.min(e.presentationWidth/e.width,e.presentationHeight/e.height),T=Math.max(T,f.minScale),T=Math.min(T,f.maxScale),1===T?(R.slides.style.zoom="",R.slides.style.left="",R.slides.style.top="",R.slides.style.bottom="",R.slides.style.right="",ie({layout:""})):T>1&&O.zoom&&window.devicePixelRatio<2?(R.slides.style.zoom=T,R.slides.style.left="",R.slides.style.top="",R.slides.style.bottom="",R.slides.style.right="",ie({layout:""})):(R.slides.style.zoom="",R.slides.style.left="50%",R.slides.style.top="50%",R.slides.style.bottom="auto",R.slides.style.right="auto",ie({layout:"translate(-50%, -50%) scale("+T+")"}));const a=d(R.wrapper.querySelectorAll(".slides section"));for(let t=0,r=a.length;t .stretch")).forEach(a=>{let r=function(e,t=0){if(e){let a,r=e.style.height;return e.style.height="0px",e.parentNode.style.height="auto",a=t-e.parentNode.offsetHeight,e.style.height=r+"px",e.parentNode.style.removeProperty("height"),a}return t}(a,t);if(/(img|video)/gi.test(a.nodeName)){const t=a.naturalWidth||a.videoWidth,n=a.naturalHeight||a.videoHeight,i=Math.min(e/t,r/n);a.style.width=t*i+"px",a.style.height=n*i+"px"}else a.style.width=e+"px",a.style.height=r+"px"})}function me(e,t){const a={width:f.width,height:f.height,presentationWidth:e||R.wrapper.offsetWidth,presentationHeight:t||R.wrapper.offsetHeight};return a.presentationWidth-=a.presentationWidth*f.margin,a.presentationHeight-=a.presentationHeight*f.margin,"string"==typeof a.width&&/%$/.test(a.width)&&(a.width=parseInt(a.width,10)/100*a.presentationWidth),"string"==typeof a.height&&/%$/.test(a.height)&&(a.height=parseInt(a.height,10)/100*a.presentationHeight),a}function ve(e,t){"object"==typeof e&&"function"==typeof e.setAttribute&&e.setAttribute("data-previous-indexv",t||0)}function ye(e){if("object"==typeof e&&"function"==typeof e.setAttribute&&e.classList.contains("stack")){const t=e.hasAttribute("data-start-indexv")?"data-start-indexv":"data-previous-indexv";return parseInt(e.getAttribute(t)||0,10)}return 0}function be(){if(f.overview&&!Se()){x=!0,R.wrapper.classList.add("overview"),Pt(),R.slides.appendChild(R.background),d(R.wrapper.querySelectorAll(".slides section")).forEach(e=>{e.classList.contains("stack")||e.addEventListener("click",sa,!0)});const e=70,t=me();M=t.width+e,N=t.height+e,f.rtl&&(M=-M),He(),we(),Ae(),ge(),se("overviewshown",{indexh:m,indexv:v,currentSlide:b})}}function we(){d(R.wrapper.querySelectorAll(".slides>section")).forEach((e,t)=>{e.setAttribute("data-index-h",t),u(e,"translate3d("+t*M+"px, 0, 0)"),e.classList.contains("stack")&&d(e.querySelectorAll("section")).forEach((e,a)=>{e.setAttribute("data-index-h",t),e.setAttribute("data-index-v",a),u(e,"translate3d(0, "+a*N+"px, 0)")})}),d(R.background.childNodes).forEach((e,t)=>{u(e,"translate3d("+t*M+"px, 0, 0)"),d(e.querySelectorAll(".slide-background")).forEach((e,t)=>{u(e,"translate3d(0, "+t*N+"px, 0)")})})}function Ae(){const e=Math.min(window.innerWidth,window.innerHeight);ie({overview:["scale("+Math.max(e/5,150)/e+")","translateX("+-m*M+"px)","translateY("+-v*N+"px)"].join(" ")})}function ke(){f.overview&&(x=!1,R.wrapper.classList.remove("overview"),R.wrapper.classList.add("overview-deactivating"),setTimeout(()=>{R.wrapper.classList.remove("overview-deactivating")},1),R.wrapper.appendChild(R.background),d(R.wrapper.querySelectorAll(".slides section")).forEach(e=>{u(e,""),e.removeEventListener("click",sa,!0)}),d(R.background.querySelectorAll(".slide-background")).forEach(e=>{u(e,"")}),ie({overview:""}),Re(m,v),ge(),qt(),se("overviewhidden",{indexh:m,indexv:v,currentSlide:b}))}function Ee(e){"boolean"==typeof e?e?be():ke():Se()?ke():be()}function Se(){return x}function Le(e){let t="/",a=e||b,r=a?a.getAttribute("id"):null;r&&(r=encodeURIComponent(r));let n=ht(e);if(f.fragmentInURL||(n.f=void 0),"string"==typeof r&&r.length&&void 0===n.f)t="/"+r;else{let e=f.hashOneBasedIndex?1:0;(n.h>0||n.v>0||void 0!==n.f)&&(t+=n.h+e),(n.v>0||void 0!==n.f)&&(t+="/"+(n.v+e)),void 0!==n.f&&(t+="/"+n.f)}return t}function xe(e=b){return e&&e.parentNode&&!!e.parentNode.nodeName.match(/section/i)}function Me(){H&&(H=!1,R.wrapper.style.cursor="")}function Ne(){!1===H&&(H=!0,R.wrapper.style.cursor="none")}function qe(){if(f.pause){const e=R.wrapper.classList.contains("paused");Pt(),R.wrapper.classList.add("paused"),!1===e&&se("paused")}}function Pe(){const e=R.wrapper.classList.contains("paused");R.wrapper.classList.remove("paused"),qt(),e&&se("resumed")}function Ie(e){"boolean"==typeof e?e?qe():Pe():Te()?Pe():qe()}function Te(){return R.wrapper.classList.contains("paused")}function Ce(e){"boolean"==typeof e?e?Tt():It():X?Tt():It()}function Re(e,t,r,n){y=b;const i=R.wrapper.querySelectorAll(".slides>section");if(0===i.length)return;void 0!==t||Se()||(t=ye(i[e])),y&&y.parentNode&&y.parentNode.classList.contains("stack")&&ve(y.parentNode,v);const o=I.concat();I.length=0;let s=m||0,l=v||0;m=Be(".slides>section",void 0===e?m:e),v=Be(".slides>section.present>section",void 0===t?v:t),He(),ge(),Se()&&Ae();let c=i[m],u=c.querySelectorAll("section");b=u[v]||c,void 0!==r&&xt(r);let p=m!==s||v!==l;p||(y=null),y&&y!==b&&(y.classList.remove("present"),y.setAttribute("aria-hidden","true"),a.isFirstSlide()&&setTimeout(()=>{d(R.wrapper.querySelectorAll(".slides>section.stack")).forEach(e=>{ve(e,0)})},0));e:for(let e=0,t=I.length;e{R.slides.classList.remove("disable-slide-transitions")},0),f.autoAnimate&&function(e,t){Ye(),E&&E.parentNode&&(E.parentNode.removeChild(E),E=null);if(e.hasAttribute("data-auto-animate")&&t.hasAttribute("data-auto-animate")){E=E||document.createElement("style"),E.type="text/css",document.head.appendChild(E);let r=Ke(t);e.dataset.autoAnimate="pending",t.dataset.autoAnimate="pending";let n=function(e,t){let a=("function"==typeof f.autoAnimateMatcher?f.autoAnimateMatcher:Je)(e,t),r=[];return a.filter((e,t)=>{if(-1===r.indexOf(e.to))return r.push(e.to),!0})}(e,t).map(e=>function(e,t,r,n,i){e.dataset.autoAnimateTarget="",t.dataset.autoAnimateTarget=i;let o=Ke(t,n);void 0!==r.delay&&(o.delay=r.delay);void 0!==r.duration&&(o.duration=r.duration);void 0!==r.easing&&(o.easing=r.easing);let s=_e("from",e,r),l=_e("to",t,r);if(!1!==r.translate||!1!==r.scale){let e=a.getScale(),t={x:(s.x-l.x)/e,y:(s.y-l.y)/e,scaleX:s.width/l.width,scaleY:s.height/l.height};t.x=Math.round(1e3*t.x)/1e3,t.y=Math.round(1e3*t.y)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3;let n=!1!==r.translate&&(0!==t.x||0!==t.y),i=!1!==r.scale&&(0!==t.scaleX||0!==t.scaleY);if(n||i){let e=[];n&&e.push(`translate(${t.x}px, ${t.y}px)`),i&&e.push(`scale(${t.scaleX}, ${t.scaleY})`),s.styles.transform=e.join(" "),s.styles["transform-origin"]="top left",l.styles.transform="none"}}for(let e in l.styles){const t=l.styles[e],a=s.styles[e];t===a?delete l.styles[e]:(!0===t.explicitValue&&(l.styles[e]=t.value),!0===a.explicitValue&&(s.styles[e]=a.value))}let d="",c=Object.keys(l.styles);if(c.length>0){s.styles.transition="none",l.styles.transition=`all ${o.duration}s ${o.easing} ${o.delay}s`,l.styles["transition-property"]=c.join(", "),l.styles["will-change"]=c.join(", ");let e=Object.keys(s.styles).map(e=>e+": "+s.styles[e]+" !important;").join(""),t=Object.keys(l.styles).map(e=>e+": "+l.styles[e]+" !important;").join("");d='[data-auto-animate-target="'+i+'"] {'+e+'}[data-auto-animate="running"] [data-auto-animate-target="'+i+'"] {'+t+"}"}return d}(e.from,e.to,e.options||{},r,W++));"false"!==t.dataset.autoAnimateUnmatched&&!0===f.autoAnimateUnmatched&&(function e(t){return[].slice.call(t.children).reduce((t,a)=>{const r=a.querySelector("[data-auto-animate-target]");return a.hasAttribute("data-auto-animate-target")||r||t.push(a),a.querySelector("[data-auto-animate-target]")&&(t=t.concat(e(a))),t},[])}(t).forEach(e=>{e.dataset.autoAnimateTarget="unmatched"}),n.push(`[data-auto-animate="running"] [data-auto-animate-target="unmatched"] { transition: opacity ${.8*r.duration}s ease ${.2*r.duration}s; }`)),E.innerHTML=n.join(""),requestAnimationFrame(()=>{E&&(getComputedStyle(E).fontWeight,t.dataset.autoAnimate="running")}),se("autoanimate",{fromSlide:e,toSlide:t,sheet:E})}}(y,b))}function De(){ne(),re(),ge(),F=f.autoSlide,qt(),oe(),R.background.innerHTML="",R.background.classList.add("no-transition"),d(R.wrapper.querySelectorAll(".slides>section")).forEach(e=>{let t=ee(e,R.background);d(e.querySelectorAll("section")).forEach(e=>{ee(e,t),t.classList.add("stack")})}),f.parallaxBackgroundImage?(R.background.style.backgroundImage='url("'+f.parallaxBackgroundImage+'")',R.background.style.backgroundSize=f.parallaxBackgroundSize,R.background.style.backgroundRepeat=f.parallaxBackgroundRepeat,R.background.style.backgroundPosition=f.parallaxBackgroundPosition,setTimeout(()=>{R.wrapper.classList.add("has-parallax-background")},1)):(R.background.style.backgroundImage="",R.wrapper.classList.remove("has-parallax-background")),pt(),ft().forEach(e=>{let t=d(e.querySelectorAll("section"));t.forEach((e,t)=>{St(e.querySelectorAll(".fragment"))}),0===t.length&&St(e.querySelectorAll(".fragment"))}),Ue(),$e(),We(),He(),Ve(!0),f.showNotes&&R.slides.querySelectorAll("[data-notes], aside.notes").length>0?R.wrapper.classList.add("show-notes"):R.wrapper.classList.remove("show-notes"),je(),function(){let e=(e,t,a)=>{d(R.slides.querySelectorAll("iframe["+e+'*="'+t+'"]')).forEach(t=>{let r=t.getAttribute(e);r&&-1===r.indexOf(a)&&t.setAttribute(e,r+(/\?/.test(r)?"&":"?")+a)})};e("src","youtube.com/embed/","enablejsapi=1"),e("data-src","youtube.com/embed/","enablejsapi=1"),e("src","player.vimeo.com/","api=1"),e("data-src","player.vimeo.com/","api=1")}(),!1===f.autoPlayMedia?st(b,{unloadIframes:!1}):nt(b),Se()&&we()}function Oe(e=b){return St(e.querySelectorAll(".fragment"))}function ze(){ft().forEach((e,t,a)=>{R.slides.insertBefore(e,a[Math.floor(Math.random()*a.length)])})}function Be(e,t){let a=d(R.wrapper.querySelectorAll(e)),r=a.length,n=oe();if(r){f.loop&&(t%=r)<0&&(t=r+t),t=Math.max(Math.min(t,r-1),0);for(let e=0;e{e.classList.add("visible"),e.classList.remove("current-fragment")})):e>t&&(r.classList.add(i?"past":"future"),f.fragments&&d(r.querySelectorAll(".fragment.visible")).forEach(e=>{e.classList.remove("visible","current-fragment")}))}a[t].classList.add("present"),a[t].removeAttribute("hidden"),a[t].removeAttribute("aria-hidden");let e=a[t].getAttribute("data-state");e&&(I=I.concat(e.split(" ")))}else t=0;return t}function He(){let e,t,a=ft(),r=a.length;if(r&&void 0!==m){let n=Se()?10:f.viewDistance;A&&(n=Se()?6:f.mobileViewDistance),oe()&&(n=Number.MAX_VALUE);for(let i=0;iNo notes on this slide.')}function $e(){f.progress&&R.progressbar&&(R.progressbar.style.width=dt()*R.wrapper.offsetWidth+"px")}function We(){f.slideNumber&&R.slideNumber&&(R.slideNumber.innerHTML=Fe())}function Fe(e=b){let t,a="h.v";if("function"==typeof f.slideNumber)t=f.slideNumber(e);else switch("string"==typeof f.slideNumber&&(a=f.slideNumber),/c/.test(a)||1!==R.wrapper.querySelectorAll(".slides>section").length||(a="c"),t=[],a){case"c":t.push(lt(e)+1);break;case"c/t":t.push(lt(e)+1,"/",bt());break;default:let r=ht(e);t.push(r.h+1);let n="h/v"===a?"/":".";xe(e)&&t.push(n,r.v+1)}let r="#"+Le(e);return function(e,t,a,r="#"+Le()){return"number"!=typeof a||isNaN(a)?`\n\t\t\t\t\t${e}\n\t\t\t\t\t`:`\n\t\t\t\t\t${e}\n\t\t\t\t\t${t}\n\t\t\t\t\t${a}\n\t\t\t\t\t`}(t[0],t[1],t[2],r)}function Ue(){let e=at(),t=rt();[...R.controlsLeft,...R.controlsRight,...R.controlsUp,...R.controlsDown,...R.controlsPrev,...R.controlsNext].forEach(e=>{e.classList.remove("enabled","fragmented"),e.setAttribute("disabled","disabled")}),e.left&&R.controlsLeft.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),e.right&&R.controlsRight.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),e.up&&R.controlsUp.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),e.down&&R.controlsDown.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),(e.left||e.up)&&R.controlsPrev.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),(e.right||e.down)&&R.controlsNext.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),b&&(t.prev&&R.controlsPrev.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),t.next&&R.controlsNext.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),xe(b)?(t.prev&&R.controlsUp.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),t.next&&R.controlsDown.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})):(t.prev&&R.controlsLeft.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),t.next&&R.controlsRight.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}))),f.controlsTutorial&&(!P&&e.down?R.controlsDownArrow.classList.add("highlight"):(R.controlsDownArrow.classList.remove("highlight"),f.rtl?!q&&e.left&&0===v?R.controlsLeftArrow.classList.add("highlight"):R.controlsLeftArrow.classList.remove("highlight"):!q&&e.right&&0===v?R.controlsRightArrow.classList.add("highlight"):R.controlsRightArrow.classList.remove("highlight")))}function Ve(e=!1){let t=null,a=f.rtl?"future":"past",r=f.rtl?"past":"future";if(d(R.background.childNodes).forEach((n,i)=>{n.classList.remove("past","present","future"),im?n.classList.add(r):(n.classList.add("present"),t=n),(e||i===m)&&d(n.querySelectorAll(".slide-background")).forEach((e,a)=>{e.classList.remove("past","present","future"),av?e.classList.add("future"):(e.classList.add("present"),i===m&&(t=e))})}),w&&st(w,{unloadIframes:!Ge(w)}),t){nt(t);let e=t.querySelector(".slide-background-content");if(e){let t=e.style.backgroundImage||"";/\.gif/i.test(t)&&(e.style.backgroundImage="",window.getComputedStyle(e).opacity,e.style.backgroundImage=t)}let a=w?w.getAttribute("data-background-hash"):null,r=t.getAttribute("data-background-hash");r&&r===a&&t!==w&&R.background.classList.add("no-transition"),w=t}b&&["has-light-background","has-dark-background"].forEach(e=>{b.classList.contains(e)?R.wrapper.classList.add(e):R.wrapper.classList.remove(e)}),setTimeout(()=>{R.background.classList.remove("no-transition")},1)}function Xe(){if(f.parallaxBackgroundImage){let e,t,a=ft(),r=mt(),n=R.background.style.backgroundSize.split(" ");1===n.length?e=t=parseInt(n[0],10):(e=parseInt(n[0],10),t=parseInt(n[1],10));let i,o,s=R.background.offsetWidth,l=a.length;i="number"==typeof f.parallaxBackgroundHorizontal?f.parallaxBackgroundHorizontal:l>1?(e-s)/(l-1):0,o=i*m*-1;let d,c,u=R.background.offsetHeight,p=r.length;d="number"==typeof f.parallaxBackgroundVertical?f.parallaxBackgroundVertical:(t-u)/(p-1),c=p>0?d*v:0,R.background.style.backgroundPosition=o+"px "+-c+"px"}}function Ye(){d(R.wrapper.querySelectorAll("[data-auto-animate-target]")).forEach(e=>{delete e.dataset.autoAnimateTarget})}function Ke(e,t){let a={easing:f.autoAnimateEasing,duration:f.autoAnimateDuration,delay:0};if(a=l(a,t),e.closest&&e.parentNode){let t=e.parentNode.closest("[data-auto-animate-target]");t&&(a=Ke(t,a))}return e.dataset.autoAnimateEasing&&(a.easing=e.dataset.autoAnimateEasing),e.dataset.autoAnimateDuration&&(a.duration=parseFloat(e.dataset.autoAnimateDuration)),e.dataset.autoAnimateDelay&&(a.delay=parseFloat(e.dataset.autoAnimateDelay)),a}function _e(e,t,a){let r={styles:[]};if(!1!==a.translate||!1!==a.scale){let e;e="function"==typeof a.measure?a.measure(t):t.getBoundingClientRect(),r.x=e.x,r.y=e.y,r.width=e.width,r.height=e.height}const n=getComputedStyle(t);return(a.styles||f.autoAnimateStyles).forEach(t=>{let a;"string"==typeof t&&(t={property:t}),a=void 0!==t.from&&"from"===e?{value:t.from,explicitValue:!0}:void 0!==t.to&&"to"===e?{value:t.to,explicitValue:!0}:n[t.property],""!==a&&(r.styles[t.property]=a)}),r}function Je(e,t){let a=[];const r="h1, h2, h3, h4, h5, h6, p, li";return Ze(a,e,t,"[data-id]",e=>e.nodeName+":::"+e.getAttribute("data-id")),Ze(a,e,t,r,e=>e.nodeName+":::"+e.innerText),Ze(a,e,t,"img, video, iframe",e=>e.nodeName+":::"+(e.getAttribute("src")||e.getAttribute("data-src"))),Ze(a,e,t,"pre",e=>e.nodeName+":::"+e.innerText),a.forEach(e=>{e.from.matches(r)?e.options={scale:!1}:e.from.matches("pre")&&(e.options={scale:!1,styles:["width","height"]},Ze(a,e.from,e.to,".hljs .hljs-ln-code",e=>e.textContent,{scale:!1,styles:[],measure:Qe}),Ze(a,e.from,e.to,".hljs .hljs-ln-line[data-line-number]",e=>e.getAttribute("data-line-number"),{scale:!1,styles:["width"],measure:Qe}))}),a}function Qe(e){const t=a.getScale();return{x:Math.round(e.offsetLeft*t*100)/100,y:Math.round(e.offsetTop*t*100)/100,width:Math.round(e.offsetWidth*t*100)/100,height:Math.round(e.offsetHeight*t*100)/100}}function Ze(e,t,a,r,n,i){let o={},s={};[].slice.call(t.querySelectorAll(r)).forEach((e,t)=>{const a=n(e);"string"==typeof a&&a.length&&(o[a]=o[a]||[],o[a].push(e))}),[].slice.call(a.querySelectorAll(r)).forEach((t,a)=>{const r=n(t);let l;if(s[r]=s[r]||[],s[r].push(t),o[r]){const e=s[r].length-1,t=o[r].length-1;o[r][e]?(l=o[r][e],o[r][e]=null):o[r][t]&&(l=o[r][t],o[r][t]=null)}l&&e.push({from:l,to:t,options:i})})}function Ge(e){let t=f.preloadIframes;return"boolean"!=typeof t&&(t=e.hasAttribute("data-preload")),t}function et(e,t={}){e.style.display=f.display,d(e.querySelectorAll("img[data-src], video[data-src], audio[data-src], iframe[data-src]")).forEach(e=>{("IFRAME"!==e.tagName||Ge(e))&&(e.setAttribute("src",e.getAttribute("data-src")),e.setAttribute("data-lazy-loaded",""),e.removeAttribute("data-src"))}),d(e.querySelectorAll("video, audio")).forEach(e=>{let t=0;d(e.querySelectorAll("source[data-src]")).forEach(e=>{e.setAttribute("src",e.getAttribute("data-src")),e.removeAttribute("data-src"),e.setAttribute("data-lazy-loaded",""),t+=1}),t>0&&e.load()});let a=e.slideBackgroundElement;if(a){a.style.display="block";let r=e.slideBackgroundContentElement,n=e.getAttribute("data-background-iframe");if(!1===a.hasAttribute("data-loaded")){a.setAttribute("data-loaded","true");let i=e.getAttribute("data-background-image"),o=e.getAttribute("data-background-video"),s=e.hasAttribute("data-background-video-loop"),l=e.hasAttribute("data-background-video-muted");if(i)r.style.backgroundImage="url("+encodeURI(i)+")";else if(o&&!ct()){let e=document.createElement("video");s&&e.setAttribute("loop",""),l&&(e.muted=!0),A&&(e.muted=!0,e.autoplay=!0,e.setAttribute("playsinline","")),o.split(",").forEach(t=>{e.innerHTML+=''}),r.appendChild(e)}else if(n&&!0!==t.excludeIframes){let e=document.createElement("iframe");e.setAttribute("allowfullscreen",""),e.setAttribute("mozallowfullscreen",""),e.setAttribute("webkitallowfullscreen",""),e.setAttribute("allow","autoplay"),e.setAttribute("data-src",n),e.style.width="100%",e.style.height="100%",e.style.maxHeight="100%",e.style.maxWidth="100%",r.appendChild(e)}}let i=r.querySelector("iframe[data-src]");i&&Ge(a)&&!/autoplay=(1|true|yes)/gi.test(n)&&i.getAttribute("src")!==n&&i.setAttribute("src",n)}}function tt(e){e.style.display="none";let t=At(e);t&&(t.style.display="none",d(t.querySelectorAll("iframe[src]")).forEach(e=>{e.removeAttribute("src")})),d(e.querySelectorAll("video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")}),d(e.querySelectorAll("video[data-lazy-loaded] source[src], audio source[src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")})}function at(){let e=R.wrapper.querySelectorAll(".slides>section"),t=R.wrapper.querySelectorAll(".slides>section.present>section"),a={left:m>0,right:m0,down:v1&&(a.left=!0,a.right=!0),t.length>1&&(a.up=!0,a.down=!0)),f.rtl){let e=a.left;a.left=a.right,a.right=e}return a}function rt(){if(b&&f.fragments){let e=b.querySelectorAll(".fragment"),t=b.querySelectorAll(".fragment:not(.visible)");return{prev:e.length-t.length>0,next:!!t.length}}return{prev:!1,next:!1}}function nt(e){e&&!ct()&&(d(e.querySelectorAll('img[src$=".gif"]')).forEach(e=>{e.setAttribute("src",e.getAttribute("src"))}),d(e.querySelectorAll("video, audio")).forEach(e=>{if(p(e,".fragment")&&!p(e,".fragment.visible"))return;let t=f.autoPlayMedia;if("boolean"!=typeof t&&(t=e.hasAttribute("data-autoplay")||!!p(e,".slide-background")),t&&"function"==typeof e.play)if(e.readyState>1)it({target:e});else if(A){let t=e.play();t&&"function"==typeof t.catch&&!1===e.controls&&t.catch(()=>{e.controls=!0,e.addEventListener("play",()=>{e.controls=!1})})}else e.removeEventListener("loadeddata",it),e.addEventListener("loadeddata",it)}),d(e.querySelectorAll("iframe[src]")).forEach(e=>{p(e,".fragment")&&!p(e,".fragment.visible")||ot({target:e})}),d(e.querySelectorAll("iframe[data-src]")).forEach(e=>{p(e,".fragment")&&!p(e,".fragment.visible")||e.getAttribute("src")!==e.getAttribute("data-src")&&(e.removeEventListener("load",ot),e.addEventListener("load",ot),e.setAttribute("src",e.getAttribute("data-src")))}))}function it(e){let t=!!p(e.target,"html"),a=!!p(e.target,".present");t&&a&&(e.target.currentTime=0,e.target.play()),e.target.removeEventListener("loadeddata",it)}function ot(e){let t=e.target;if(t&&t.contentWindow){let a=!!p(e.target,"html"),r=!!p(e.target,".present");if(a&&r){let e=f.autoPlayMedia;"boolean"!=typeof e&&(e=t.hasAttribute("data-autoplay")||!!p(t,".slide-background")),/youtube\.com\/embed\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}',"*"):/player\.vimeo\.com\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"method":"play"}',"*"):t.contentWindow.postMessage("slide:start","*")}}}function st(e,t={}){t=l({unloadIframes:!0},t),e&&e.parentNode&&(d(e.querySelectorAll("video, audio")).forEach(e=>{e.hasAttribute("data-ignore")||"function"!=typeof e.pause||(e.setAttribute("data-paused-by-reveal",""),e.pause())}),d(e.querySelectorAll("iframe")).forEach(e=>{e.contentWindow&&e.contentWindow.postMessage("slide:stop","*"),e.removeEventListener("load",ot)}),d(e.querySelectorAll('iframe[src*="youtube.com/embed/"]')).forEach(e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}',"*")}),d(e.querySelectorAll('iframe[src*="player.vimeo.com/"]')).forEach(e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"method":"pause"}',"*")}),!0===t.unloadIframes&&d(e.querySelectorAll("iframe[data-src]")).forEach(e=>{e.setAttribute("src","about:blank"),e.removeAttribute("src")}))}function lt(e=b){let t=ft(),a=0;e:for(let r=0;r0){let a=.9;t+=b.querySelectorAll(".fragment.visible").length/e.length*a}}return Math.min(t/(e-1),1)}function ct(){return!!window.location.search.match(/receiver/gi)}function ut(){let e=window.location.hash,t=e.slice(2).split("/"),r=e.replace(/#|\//gi,"");if(!/^[0-9]*$/.test(t[0])&&r.length){let e;try{e=document.getElementById(decodeURIComponent(r))}catch(e){}let t=!!b&&b.getAttribute("id")===r;if(e){if(!t){let t=a.getIndices(e);Re(t.h,t.v)}}else Re(m||0,v||0)}else{let e,a=f.hashOneBasedIndex?1:0,r=parseInt(t[0],10)-a||0,n=parseInt(t[1],10)-a||0;f.fragmentInURL&&(e=parseInt(t[2],10),isNaN(e)&&(e=void 0)),r===m&&n===v&&void 0===e||Re(r,n,e)}}function pt(e){clearTimeout(B),"number"==typeof e?B=setTimeout(pt,e):b&&(f.history||!window.history?window.location.hash=Le():f.hash?window.history.replaceState(null,null,"#"+Le()):window.history.replaceState(null,null,window.location.pathname+window.location.search))}function ht(e){let t,a=m,r=v;if(e){let t=xe(e),n=t?e.parentNode:e,i=d(R.wrapper.querySelectorAll(".slides>section"));a=Math.max(i.indexOf(n),0),r=void 0,t&&(r=Math.max(d(e.parentNode.querySelectorAll("section")).indexOf(e),0))}if(!e&&b){if(b.querySelectorAll(".fragment").length>0){let e=b.querySelector(".current-fragment");t=e&&e.hasAttribute("data-fragment-index")?parseInt(e.getAttribute("data-fragment-index"),10):b.querySelectorAll(".fragment.visible").length-1}}return{h:a,v:r,f:t}}function gt(){return d(R.wrapper.querySelectorAll('.slides section:not(.stack):not([data-visibility="uncounted"])'))}function ft(){return d(R.wrapper.querySelectorAll(".slides>section"))}function mt(){return d(R.wrapper.querySelectorAll(".slides>section>section"))}function vt(){return ft().length>1}function yt(){return mt().length>1}function bt(){return gt().length}function wt(e,t){let a=ft()[e],r=a&&a.querySelectorAll("section");return r&&r.length&&"number"==typeof t?r?r[t]:void 0:a}function At(e,t){let a="number"==typeof e?wt(e,t):e;if(a)return a.slideBackgroundElement}function kt(e=b){if(e.hasAttribute("data-notes"))return e.getAttribute("data-notes");let t=e.querySelector("aside.notes");return t?t.innerHTML:null}function Et(){let e=ht();return{indexh:e.h,indexv:e.v,indexf:e.f,paused:Te(),overview:Se()}}function St(e,t=!1){e=d(e);let a=[],r=[],n=[];e.forEach(e=>{if(e.hasAttribute("data-fragment-index")){let t=parseInt(e.getAttribute("data-fragment-index"),10);a[t]||(a[t]=[]),a[t].push(e)}else r.push([e])}),a=a.concat(r);let i=0;return a.forEach(e=>{e.forEach(e=>{n.push(e),e.setAttribute("data-fragment-index",i)}),i++}),!0===t?a:n}function Lt(e,t){let a={shown:[],hidden:[]};if(b&&f.fragments&&(t=t||St(b.querySelectorAll(".fragment"))).length){let r=0;if("number"!=typeof e){let t=St(b.querySelectorAll(".fragment.visible")).pop();t&&(e=parseInt(t.getAttribute("data-fragment-index")||0,10))}d(t).forEach((t,n)=>{t.hasAttribute("data-fragment-index")&&(n=parseInt(t.getAttribute("data-fragment-index"),10)),r=Math.max(r,n),n<=e?(t.classList.contains("visible")||a.shown.push(t),t.classList.add("visible"),t.classList.remove("current-fragment"),R.statusDiv.textContent=Q(t),n===e&&(t.classList.add("current-fragment"),nt(t))):(t.classList.contains("visible")&&a.hidden.push(t),t.classList.remove("visible"),t.classList.remove("current-fragment"))}),e="number"==typeof e?e:-1,e=Math.max(Math.min(e,r),-1),b.setAttribute("data-fragment",e)}return a}function xt(e,t=0){if(b&&f.fragments){let a=St(b.querySelectorAll(".fragment"));if(a.length){if("number"!=typeof e){let t=St(b.querySelectorAll(".fragment.visible")).pop();e=t?parseInt(t.getAttribute("data-fragment-index")||0,10):-1}let r=Lt(e+=t,a);return r.hidden.length&&se("fragmenthidden",{fragment:r.hidden[0],fragments:r.hidden}),r.shown.length&&se("fragmentshown",{fragment:r.shown[0],fragments:r.shown}),Ue(),$e(),f.fragmentInURL&&pt(),!(!r.shown.length&&!r.hidden.length)}}return!1}function Mt(){return xt(null,1)}function Nt(){return xt(null,-1)}function qt(){if(Pt(),b&&!1!==f.autoSlide){let e=b.querySelector(".current-fragment");e||(e=b.querySelector(".fragment"));let t=e?e.getAttribute("data-autoslide"):null,r=b.parentNode?b.parentNode.getAttribute("data-autoslide"):null,n=b.getAttribute("data-autoslide");F=t?parseInt(t,10):n?parseInt(n,10):r?parseInt(r,10):f.autoSlide,0===b.querySelectorAll(".fragment").length&&d(b.querySelectorAll("video, audio")).forEach(e=>{e.hasAttribute("data-autoplay")&&F&&1e3*e.duration/e.playbackRate>F&&(F=1e3*e.duration/e.playbackRate+1e3)}),!F||X||Te()||Se()||a.isLastSlide()&&!rt().next&&!0!==f.loop||(U=setTimeout(()=>{"function"==typeof f.autoSlideMethod?f.autoSlideMethod():Bt(),qt()},F),V=Date.now()),S&&S.setPlaying(-1!==U)}}function Pt(){clearTimeout(U),U=-1}function It(){F&&!X&&(X=!0,se("autoslidepaused"),clearTimeout(U),S&&S.setPlaying(!1))}function Tt(){F&&X&&(X=!1,se("autoslideresumed"),qt())}function Ct(){q=!0,f.rtl?(Se()||!1===Mt())&&at().left&&Re(m+1,"grid"===f.navigationMode?v:void 0):(Se()||!1===Nt())&&at().left&&Re(m-1,"grid"===f.navigationMode?v:void 0)}function Rt(){q=!0,f.rtl?(Se()||!1===Nt())&&at().right&&Re(m-1,"grid"===f.navigationMode?v:void 0):(Se()||!1===Mt())&&at().right&&Re(m+1,"grid"===f.navigationMode?v:void 0)}function Dt(){(Se()||!1===Nt())&&at().up&&Re(m,v-1)}function Ot(){P=!0,(Se()||!1===Mt())&&at().down&&Re(m,v+1)}function zt(){if(!1===Nt())if(at().up)Dt();else{let e;if(e=f.rtl?d(R.wrapper.querySelectorAll(".slides>section.future")).pop():d(R.wrapper.querySelectorAll(".slides>section.past")).pop(),e){let t=e.querySelectorAll("section").length-1||void 0;Re(m-1,t)}}}function Bt(){if(q=!0,P=!0,!1===Mt()){let e=at();e.down&&e.right&&f.loop&&a.isLastVerticalSlide(b)&&(e.down=!1),e.down?Ot():f.rtl?Ct():Rt()}}function Ht(e){for(;e&&"function"==typeof e.hasAttribute;){if(e.hasAttribute("data-prevent-swipe"))return!0;e=e.parentNode}return!1}function jt(e){f.autoSlideStoppable&&It()}function $t(e){Me(),clearTimeout(j),j=setTimeout(Ne,f.hideCursorTime)}function Wt(e){e.shiftKey&&63===e.charCode&&ue()}function Ft(e){if("function"==typeof f.keyboardCondition&&!1===f.keyboardCondition(e))return!0;let t=e.keyCode,r=X;jt();let n=document.activeElement&&"inherit"!==document.activeElement.contentEditable,i=document.activeElement&&document.activeElement.tagName&&/input|textarea/i.test(document.activeElement.tagName),o=document.activeElement&&document.activeElement.className&&/speaker-notes/i.test(document.activeElement.className),s=e.shiftKey&&32===e.keyCode,l=e.shiftKey&&37===t,d=e.shiftKey&&39===t,c=!s&&!l&&!d&&(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey);if(n||i||o||c)return;let u,p=[66,86,190,191];if("object"==typeof f.keyboard)for(u in f.keyboard)"togglePause"===f.keyboard[u]&&p.push(parseInt(u,10));if(Te()&&-1===p.indexOf(t))return!1;let h="linear"===f.navigationMode||!vt()||!yt(),g=!1;if("object"==typeof f.keyboard)for(u in f.keyboard)if(parseInt(u,10)===t){let t=f.keyboard[u];"function"==typeof t?t.apply(null,[e]):"string"==typeof t&&"function"==typeof a[t]&&a[t].call(),g=!0}if(!1===g)for(u in _)if(parseInt(u,10)===t){let t=_[u].callback;"function"==typeof t?t.apply(null,[e]):"string"==typeof t&&"function"==typeof a[t]&&a[t].call(),g=!0}!1===g&&(g=!0,80===t||33===t?zt():78===t||34===t?Bt():72===t||37===t?l?Re(0):!Se()&&h?zt():Ct():76===t||39===t?d?Re(Number.MAX_VALUE):!Se()&&h?Bt():Rt():75===t||38===t?!Se()&&h?zt():Dt():74===t||40===t?!Se()&&h?Bt():Ot():36===t?Re(0):35===t?Re(Number.MAX_VALUE):32===t?(Se()&&ke(),e.shiftKey?zt():Bt()):58===t||59===t||66===t||86===t||190===t||191===t?Ie():70===t?(()=>{let e=document.documentElement,t=e.requestFullscreen||e.webkitRequestFullscreen||e.webkitRequestFullScreen||e.mozRequestFullScreen||e.msRequestFullscreen;t&&t.apply(e)})():65===t?f.autoSlideStoppable&&Ce(r):g=!1),g?e.preventDefault&&e.preventDefault():27!==t&&79!==t||(R.overlay?he():Ee(),e.preventDefault&&e.preventDefault()),qt()}function Ut(e){if(Ht(e.target))return!0;Y.startX=e.touches[0].clientX,Y.startY=e.touches[0].clientY,Y.startCount=e.touches.length}function Vt(e){if(Ht(e.target))return!0;if(Y.captured)r.match(/android/gi)&&e.preventDefault();else{jt();let t=e.touches[0].clientX,a=e.touches[0].clientY;if(1===e.touches.length&&2!==Y.startCount){let r=t-Y.startX,n=a-Y.startY;r>Y.threshold&&Math.abs(r)>Math.abs(n)?(Y.captured=!0,"linear"===f.navigationMode?f.rtl?Bt():zt():Ct()):r<-Y.threshold&&Math.abs(r)>Math.abs(n)?(Y.captured=!0,"linear"===f.navigationMode?f.rtl?zt():Bt():Rt()):n>Y.threshold?(Y.captured=!0,"linear"===f.navigationMode?zt():Dt()):n<-Y.threshold&&(Y.captured=!0,"linear"===f.navigationMode?Bt():Ot()),f.embedded?(Y.captured||xe(b))&&e.preventDefault():e.preventDefault()}}}function Xt(e){Y.captured=!1}function Yt(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],Ut(e))}function Kt(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],Vt(e))}function _t(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],Xt())}function Jt(e){if(Date.now()-z>600){z=Date.now();let t=e.detail||-e.wheelDelta;t>0?Bt():t<0&&zt()}}function Qt(e){jt(),e.preventDefault();let t=ft().length,a=Math.floor(e.clientX/R.wrapper.offsetWidth*t);f.rtl&&(a=t-a),Re(a)}function Zt(e){e.preventDefault(),jt(),"linear"===f.navigationMode?zt():Ct()}function Gt(e){e.preventDefault(),jt(),"linear"===f.navigationMode?Bt():Rt()}function ea(e){e.preventDefault(),jt(),Dt()}function ta(e){e.preventDefault(),jt(),Ot()}function aa(e){e.preventDefault(),jt(),zt()}function ra(e){e.preventDefault(),jt(),Bt()}function na(e){ut()}function ia(e){ge()}function oa(e){!1===document.hidden&&document.activeElement!==document.body&&("function"==typeof document.activeElement.blur&&document.activeElement.blur(),document.body.focus())}function sa(e){if($&&Se()){e.preventDefault();let t=e.target;for(;t&&!t.nodeName.match(/section/gi);)t=t.parentNode;if(t&&!t.classList.contains("disabled")&&(ke(),t.nodeName.match(/section/gi))){Re(parseInt(t.getAttribute("data-index-h"),10),parseInt(t.getAttribute("data-index-v"),10))}}}function la(e){if(e.currentTarget&&e.currentTarget.hasAttribute("href")){let t=e.currentTarget.getAttribute("href");t&&(!function(e){he(),R.overlay=document.createElement("div"),R.overlay.classList.add("overlay"),R.overlay.classList.add("overlay-preview"),R.wrapper.appendChild(R.overlay),R.overlay.innerHTML=`
\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\tUnable to load iframe. This is likely due to the site's policy (x-frame-options).\n\t\t\t\t\n\t\t\t
`,R.overlay.querySelector("iframe").addEventListener("load",e=>{R.overlay.classList.add("loaded")},!1),R.overlay.querySelector(".close").addEventListener("click",e=>{he(),e.preventDefault()},!1),R.overlay.querySelector(".external").addEventListener("click",e=>{he()},!1)}(t),e.preventDefault())}}function da(e){a.isLastSlide()&&!1===f.loop?(Re(0,0),Tt()):X?Tt():It()}return a={VERSION:"4.0.0-dev",initialize:function(){if(e)return function(){A=/(iphone|ipod|ipad|android)/gi.test(r)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1,k=/chrome/i.test(r)&&!/edge/i.test(r);let e=document.createElement("div");O.zoom="zoom"in e.style&&!A&&(k||/Version\/[\d\.]+.*Safari/.test(r))}(),R.wrapper=e,R.slides=e.querySelector(".slides"),window.addEventListener("load",ge,!1),f={...o,...t,...a.getQueryHash()},D.load(f.dependencies).then(J),a;console.warn("reveal.js can not initialize without a valid .reveal element.")},configure:ae,sync:De,syncSlide:function(e=b){te(e),Oe(e),et(e),Ve(),je()},syncFragments:Oe,slide:Re,left:Ct,right:Rt,up:Dt,down:Ot,prev:zt,next:Bt,navigateTo:Re,navigateLeft:Ct,navigateRight:Rt,navigateUp:Dt,navigateDown:Ot,navigatePrev:zt,navigateNext:Bt,navigateFragment:xt,prevFragment:Nt,nextFragment:Mt,layout:ge,shuffle:ze,availableRoutes:at,availableFragments:rt,toggleHelp:ue,toggleOverview:Ee,togglePause:Ie,toggleAutoSlide:Ce,isOverview:Se,isPaused:Te,isAutoSliding:function(){return!(!F||X)},isSpeakerNotes:ct,loadSlide:et,unloadSlide:tt,addEventListeners:re,removeEventListeners:ne,getState:Et,setState:function(e){if("object"==typeof e){Re(c(e.indexh),c(e.indexv),c(e.indexf));let t=c(e.paused),a=c(e.overview);"boolean"==typeof t&&t!==Te()&&Ie(t),"boolean"==typeof a&&a!==Se()&&Ee(a)}},getSlidePastCount:lt,getProgress:dt,getIndices:ht,getSlides:gt,getSlidesAttributes:function(){return gt().map(e=>{let t={};for(let a=0;aD.registerPlugin(...e),hasPlugin:(...e)=>D.hasPlugin(...e),getPlugin:(...e)=>D.getPlugin(...e),getPlugins:()=>D.getRegisteredPlugins(),getComputedSlideSize:me,getPreviousSlide:()=>y,getCurrentSlide:()=>b,getScale:()=>T,getConfig:()=>f,getQueryHash:()=>{let e={};location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi,t=>{e[t.split("=").shift()]=t.split("=").pop()});for(let t in e){let a=e[t];e[t]=c(unescape(a))}return void 0!==e.dependencies&&delete e.dependencies,e},getRevealElement:()=>R.wrapper||document.querySelector(".reveal"),isFirstSlide:()=>0===m&&0===v,isLastSlide:()=>!!b&&(!b.nextElementSibling&&(!xe(b)||!b.parentNode.nextElementSibling)),isLastVerticalSlide:()=>!(!b||!xe(b))&&!b.nextElementSibling,isReady:()=>L,addEventListener:(e,t,r)=>{a.getRevealElement().addEventListener(e,t,r)},removeEventListener:(e,t,r)=>{a.getRevealElement().removeEventListener(e,t,r)},triggerKey:e=>Ft({keyCode:e}),registerKeyboardShortcut:(e,t)=>K[e]=t},a};window.Reveal=f,window.Reveal.initialize=e=>(window.Reveal=new f(document.querySelector(".reveal"),e),window.Reveal.initialize(),new Promise(e=>window.Reveal.addEventListener("ready",e)))}]); \ No newline at end of file +!function(e){var t={};function a(i){if(t[i])return t[i].exports;var r=t[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,a),r.l=!0,r.exports}a.m=e,a.c=t,a.d=function(e,t,i){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(a.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)a.d(i,r,function(t){return e[t]}.bind(null,r));return i},a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="",a(a.s=0)}([function(e,t,a){"use strict";a.r(t);const i=/registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener/,r=(e,t)=>{for(let a in t)e[a]=t[a];return e},n=e=>Array.prototype.slice.call(e),s=e=>{if("string"==typeof e){if("null"===e)return null;if("true"===e)return!0;if("false"===e)return!1;if(e.match(/^-?[\d\.]+$/))return parseFloat(e)}return e},o=(e,t)=>{e.style.transform=t},l=(e,t)=>{let a=e.parentNode;for(;a;){let e=a.matches||a.matchesSelector||a.msMatchesSelector;if(e&&e.call(a,t))return a;a=a.parentNode}return null},d=e=>{let t=document.createElement("style");return t.type="text/css",e&&e.length>0&&(t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document.createTextNode(e))),document.head.appendChild(t),t},c=navigator.userAgent,u=document.createElement("div"),h=/(iphone|ipod|ipad|android)/gi.test(c)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1,p=/chrome/i.test(c)&&!/edge/i.test(c),g=/android/gi.test(c),f="zoom"in u.style&&!h&&(p||/Version\/[\d\.]+.*Safari/.test(c));class m{constructor(e){this.Reveal=e}shouldPreload(e){let t=this.Reveal.getConfig().preloadIframes;return"boolean"!=typeof t&&(t=e.hasAttribute("data-preload")),t}load(e,t={}){e.style.display=this.Reveal.getConfig().display,n(e.querySelectorAll("img[data-src], video[data-src], audio[data-src], iframe[data-src]")).forEach(e=>{("IFRAME"!==e.tagName||this.shouldPreload(e))&&(e.setAttribute("src",e.getAttribute("data-src")),e.setAttribute("data-lazy-loaded",""),e.removeAttribute("data-src"))}),n(e.querySelectorAll("video, audio")).forEach(e=>{let t=0;n(e.querySelectorAll("source[data-src]")).forEach(e=>{e.setAttribute("src",e.getAttribute("data-src")),e.removeAttribute("data-src"),e.setAttribute("data-lazy-loaded",""),t+=1}),t>0&&e.load()});let a=e.slideBackgroundElement;if(a){a.style.display="block";let i=e.slideBackgroundContentElement,r=e.getAttribute("data-background-iframe");if(!1===a.hasAttribute("data-loaded")){a.setAttribute("data-loaded","true");let n=e.getAttribute("data-background-image"),s=e.getAttribute("data-background-video"),o=e.hasAttribute("data-background-video-loop"),l=e.hasAttribute("data-background-video-muted");if(n)i.style.backgroundImage="url("+encodeURI(n)+")";else if(s&&!this.Reveal.isSpeakerNotes()){let e=document.createElement("video");o&&e.setAttribute("loop",""),l&&(e.muted=!0),h&&(e.muted=!0,e.autoplay=!0,e.setAttribute("playsinline","")),s.split(",").forEach(t=>{e.innerHTML+=''}),i.appendChild(e)}else if(r&&!0!==t.excludeIframes){let e=document.createElement("iframe");e.setAttribute("allowfullscreen",""),e.setAttribute("mozallowfullscreen",""),e.setAttribute("webkitallowfullscreen",""),e.setAttribute("allow","autoplay"),e.setAttribute("data-src",r),e.style.width="100%",e.style.height="100%",e.style.maxHeight="100%",e.style.maxWidth="100%",i.appendChild(e)}}let n=i.querySelector("iframe[data-src]");n&&this.shouldPreload(a)&&!/autoplay=(1|true|yes)/gi.test(r)&&n.getAttribute("src")!==r&&n.setAttribute("src",r)}}unload(e){e.style.display="none";let t=this.Reveal.getSlideBackground(e);t&&(t.style.display="none",n(t.querySelectorAll("iframe[src]")).forEach(e=>{e.removeAttribute("src")})),n(e.querySelectorAll("video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")}),n(e.querySelectorAll("video[data-lazy-loaded] source[src], audio source[src]")).forEach(e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")})}formatEmbeddedContent(){let e=(e,t,a)=>{n(this.Reveal.getSlidesElement().querySelectorAll("iframe["+e+'*="'+t+'"]')).forEach(t=>{let i=t.getAttribute(e);i&&-1===i.indexOf(a)&&t.setAttribute(e,i+(/\?/.test(i)?"&":"?")+a)})};e("src","youtube.com/embed/","enablejsapi=1"),e("data-src","youtube.com/embed/","enablejsapi=1"),e("src","player.vimeo.com/","api=1"),e("data-src","player.vimeo.com/","api=1")}startEmbeddedContent(e){e&&!this.Reveal.isSpeakerNotes()&&(n(e.querySelectorAll('img[src$=".gif"]')).forEach(e=>{e.setAttribute("src",e.getAttribute("src"))}),n(e.querySelectorAll("video, audio")).forEach(e=>{if(l(e,".fragment")&&!l(e,".fragment.visible"))return;let t=this.Reveal.getConfig().autoPlayMedia;if("boolean"!=typeof t&&(t=e.hasAttribute("data-autoplay")||!!l(e,".slide-background")),t&&"function"==typeof e.play)if(e.readyState>1)this.startEmbeddedMedia({target:e});else if(h){let t=e.play();t&&"function"==typeof t.catch&&!1===e.controls&&t.catch(()=>{e.controls=!0,e.addEventListener("play",()=>{e.controls=!1})})}else e.removeEventListener("loadeddata",this.startEmbeddedMedia),e.addEventListener("loadeddata",this.startEmbeddedMedia)}),n(e.querySelectorAll("iframe[src]")).forEach(e=>{l(e,".fragment")&&!l(e,".fragment.visible")||this.startEmbeddedIframe({target:e})}),n(e.querySelectorAll("iframe[data-src]")).forEach(e=>{l(e,".fragment")&&!l(e,".fragment.visible")||e.getAttribute("src")!==e.getAttribute("data-src")&&(e.removeEventListener("load",this.startEmbeddedIframe),e.addEventListener("load",this.startEmbeddedIframe),e.setAttribute("src",e.getAttribute("data-src")))}))}startEmbeddedMedia(e){let t=!!l(e.target,"html"),a=!!l(e.target,".present");t&&a&&(e.target.currentTime=0,e.target.play()),e.target.removeEventListener("loadeddata",this.startEmbeddedMedia)}startEmbeddedIframe(e){let t=e.target;if(t&&t.contentWindow){let a=!!l(e.target,"html"),i=!!l(e.target,".present");if(a&&i){let e=this.Reveal.getConfig().autoPlayMedia;"boolean"!=typeof e&&(e=t.hasAttribute("data-autoplay")||!!l(t,".slide-background")),/youtube\.com\/embed\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}',"*"):/player\.vimeo\.com\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"method":"play"}',"*"):t.contentWindow.postMessage("slide:start","*")}}}stopEmbeddedContent(e,t={}){t=r({unloadIframes:!0},t),e&&e.parentNode&&(n(e.querySelectorAll("video, audio")).forEach(e=>{e.hasAttribute("data-ignore")||"function"!=typeof e.pause||(e.setAttribute("data-paused-by-reveal",""),e.pause())}),n(e.querySelectorAll("iframe")).forEach(e=>{e.contentWindow&&e.contentWindow.postMessage("slide:stop","*"),e.removeEventListener("load",this.startEmbeddedIframe)}),n(e.querySelectorAll('iframe[src*="youtube.com/embed/"]')).forEach(e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}',"*")}),n(e.querySelectorAll('iframe[src*="player.vimeo.com/"]')).forEach(e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"method":"pause"}',"*")}),!0===t.unloadIframes&&n(e.querySelectorAll("iframe[data-src]")).forEach(e=>{e.setAttribute("src","about:blank"),e.removeAttribute("src")}))}}class v{constructor(e){this.Reveal=e,this.autoAnimateCounter=0}run(e,t){if(this.reset(),e.hasAttribute("data-auto-animate")&&t.hasAttribute("data-auto-animate")){this.autoAnimateStyleSheet=this.autoAnimateStyleSheet||d();let a=this.getAutoAnimateOptions(t);e.dataset.autoAnimate="pending",t.dataset.autoAnimate="pending";let i=this.getAutoAnimatableElements(e,t).map(e=>this.getAutoAnimateCSS(e.from,e.to,e.options||{},a,this.autoAnimateCounter++));"false"!==t.dataset.autoAnimateUnmatched&&!0===this.Reveal.getConfig().autoAnimateUnmatched&&(this.getUnmatchedAutoAnimateElements(t).forEach(e=>{e.dataset.autoAnimateTarget="unmatched"}),i.push(`[data-auto-animate="running"] [data-auto-animate-target="unmatched"] { transition: opacity ${.8*a.duration}s ease ${.2*a.duration}s; }`)),this.autoAnimateStyleSheet.innerHTML=i.join(""),requestAnimationFrame(()=>{this.autoAnimateStyleSheet&&(getComputedStyle(this.autoAnimateStyleSheet).fontWeight,t.dataset.autoAnimate="running")}),this.Reveal.dispatchEvent("autoanimate",{fromSlide:e,toSlide:t,sheet:this.autoAnimateStyleSheet})}}reset(){n(this.Reveal.getRevealElement().querySelectorAll('[data-auto-animate]:not([data-auto-animate=""])')).forEach(e=>{e.dataset.autoAnimate=""}),n(this.Reveal.getRevealElement().querySelectorAll("[data-auto-animate-target]")).forEach(e=>{delete e.dataset.autoAnimateTarget}),this.autoAnimateStyleSheet&&this.autoAnimateStyleSheet.parentNode&&(this.autoAnimateStyleSheet.parentNode.removeChild(this.autoAnimateStyleSheet),this.autoAnimateStyleSheet=null)}getAutoAnimateCSS(e,t,a,i,r){e.dataset.autoAnimateTarget="",t.dataset.autoAnimateTarget=r;let n=this.getAutoAnimateOptions(t,i);void 0!==a.delay&&(n.delay=a.delay),void 0!==a.duration&&(n.duration=a.duration),void 0!==a.easing&&(n.easing=a.easing);let s=this.getAutoAnimatableProperties("from",e,a),o=this.getAutoAnimatableProperties("to",t,a);if(!1!==a.translate||!1!==a.scale){let e=this.Reveal.getScale(),t={x:(s.x-o.x)/e,y:(s.y-o.y)/e,scaleX:s.width/o.width,scaleY:s.height/o.height};t.x=Math.round(1e3*t.x)/1e3,t.y=Math.round(1e3*t.y)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3;let i=!1!==a.translate&&(0!==t.x||0!==t.y),r=!1!==a.scale&&(0!==t.scaleX||0!==t.scaleY);if(i||r){let e=[];i&&e.push(`translate(${t.x}px, ${t.y}px)`),r&&e.push(`scale(${t.scaleX}, ${t.scaleY})`),s.styles.transform=e.join(" "),s.styles["transform-origin"]="top left",o.styles.transform="none"}}for(let e in o.styles){const t=o.styles[e],a=s.styles[e];t===a?delete o.styles[e]:(!0===t.explicitValue&&(o.styles[e]=t.value),!0===a.explicitValue&&(s.styles[e]=a.value))}let l="",d=Object.keys(o.styles);if(d.length>0){s.styles.transition="none",o.styles.transition=`all ${n.duration}s ${n.easing} ${n.delay}s`,o.styles["transition-property"]=d.join(", "),o.styles["will-change"]=d.join(", "),l='[data-auto-animate-target="'+r+'"] {'+Object.keys(s.styles).map(e=>e+": "+s.styles[e]+" !important;").join("")+'}[data-auto-animate="running"] [data-auto-animate-target="'+r+'"] {'+Object.keys(o.styles).map(e=>e+": "+o.styles[e]+" !important;").join("")+"}"}return l}getAutoAnimateOptions(e,t){let a={easing:this.Reveal.getConfig().autoAnimateEasing,duration:this.Reveal.getConfig().autoAnimateDuration,delay:0};if(a=r(a,t),e.closest&&e.parentNode){let t=e.parentNode.closest("[data-auto-animate-target]");t&&(a=this.getAutoAnimateOptions(t,a))}return e.dataset.autoAnimateEasing&&(a.easing=e.dataset.autoAnimateEasing),e.dataset.autoAnimateDuration&&(a.duration=parseFloat(e.dataset.autoAnimateDuration)),e.dataset.autoAnimateDelay&&(a.delay=parseFloat(e.dataset.autoAnimateDelay)),a}getAutoAnimatableProperties(e,t,a){let i={styles:[]};if(!1!==a.translate||!1!==a.scale){let e;e="function"==typeof a.measure?a.measure(t):t.getBoundingClientRect(),i.x=e.x,i.y=e.y,i.width=e.width,i.height=e.height}const r=getComputedStyle(t);return(a.styles||this.Reveal.getConfig().autoAnimateStyles).forEach(t=>{let a;"string"==typeof t&&(t={property:t}),a=void 0!==t.from&&"from"===e?{value:t.from,explicitValue:!0}:void 0!==t.to&&"to"===e?{value:t.to,explicitValue:!0}:r[t.property],""!==a&&(i.styles[t.property]=a)}),i}getAutoAnimatableElements(e,t){let a=("function"==typeof this.Reveal.getConfig().autoAnimateMatcher?this.Reveal.getConfig().autoAnimateMatcher:this.getAutoAnimatePairs).call(this,e,t),i=[];return a.filter((e,t)=>{if(-1===i.indexOf(e.to))return i.push(e.to),!0})}getAutoAnimatePairs(e,t){let a=[];const i="h1, h2, h3, h4, h5, h6, p, li";return this.findAutoAnimateMatches(a,e,t,"[data-id]",e=>e.nodeName+":::"+e.getAttribute("data-id")),this.findAutoAnimateMatches(a,e,t,i,e=>e.nodeName+":::"+e.innerText),this.findAutoAnimateMatches(a,e,t,"img, video, iframe",e=>e.nodeName+":::"+(e.getAttribute("src")||e.getAttribute("data-src"))),this.findAutoAnimateMatches(a,e,t,"pre",e=>e.nodeName+":::"+e.innerText),a.forEach(e=>{e.from.matches(i)?e.options={scale:!1}:e.from.matches("pre")&&(e.options={scale:!1,styles:["width","height"]},this.findAutoAnimateMatches(a,e.from,e.to,".hljs .hljs-ln-code",e=>e.textContent,{scale:!1,styles:[],measure:this.getLocalBoundingBox.bind(this)}),this.findAutoAnimateMatches(a,e.from,e.to,".hljs .hljs-ln-line[data-line-number]",e=>e.getAttribute("data-line-number"),{scale:!1,styles:["width"],measure:this.getLocalBoundingBox.bind(this)}))},this),a}getLocalBoundingBox(e){const t=this.Reveal.getScale();return{x:Math.round(e.offsetLeft*t*100)/100,y:Math.round(e.offsetTop*t*100)/100,width:Math.round(e.offsetWidth*t*100)/100,height:Math.round(e.offsetHeight*t*100)/100}}findAutoAnimateMatches(e,t,a,i,r,n){let s={},o={};[].slice.call(t.querySelectorAll(i)).forEach((e,t)=>{const a=r(e);"string"==typeof a&&a.length&&(s[a]=s[a]||[],s[a].push(e))}),[].slice.call(a.querySelectorAll(i)).forEach((t,a)=>{const i=r(t);let l;if(o[i]=o[i]||[],o[i].push(t),s[i]){const e=o[i].length-1,t=s[i].length-1;s[i][e]?(l=s[i][e],s[i][e]=null):s[i][t]&&(l=s[i][t],s[i][t]=null)}l&&e.push({from:l,to:t,options:n})})}getUnmatchedAutoAnimateElements(e){return[].slice.call(e.children).reduce((e,t)=>{const a=t.querySelector("[data-auto-animate-target]");return t.hasAttribute("data-auto-animate-target")||a||e.push(t),t.querySelector("[data-auto-animate-target]")&&(e=e.concat(this.getUnmatchedAutoAnimateElements(t))),e},[])}}class b{constructor(e){this.Reveal=e}showAll(){n(this.Reveal.getSlidesElement().querySelectorAll(".fragment")).forEach(e=>{e.classList.add("visible"),e.classList.remove("current-fragment")})}availableRoutes(){let e=this.Reveal.getCurrentSlide();if(e&&this.Reveal.getConfig().fragments){let t=e.querySelectorAll(".fragment"),a=e.querySelectorAll(".fragment:not(.visible)");return{prev:t.length-a.length>0,next:!!a.length}}return{prev:!1,next:!1}}sort(e,t=!1){e=n(e);let a=[],i=[],r=[];e.forEach(e=>{if(e.hasAttribute("data-fragment-index")){let t=parseInt(e.getAttribute("data-fragment-index"),10);a[t]||(a[t]=[]),a[t].push(e)}else i.push([e])}),a=a.concat(i);let s=0;return a.forEach(e=>{e.forEach(e=>{r.push(e),e.setAttribute("data-fragment-index",s)}),s++}),!0===t?a:r}sortAll(){this.Reveal.getHorizontalSlides().forEach(e=>{let t=n(e.querySelectorAll("section"));t.forEach((e,t)=>{this.sort(e.querySelectorAll(".fragment"))},this),0===t.length&&this.sort(e.querySelectorAll(".fragment"))})}update(e,t){let a={shown:[],hidden:[]},i=this.Reveal.getCurrentSlide();if(i&&this.Reveal.getConfig().fragments&&(t=t||this.sort(i.querySelectorAll(".fragment"))).length){let r=0;if("number"!=typeof e){let t=this.sort(i.querySelectorAll(".fragment.visible")).pop();t&&(e=parseInt(t.getAttribute("data-fragment-index")||0,10))}n(t).forEach((t,i)=>{t.hasAttribute("data-fragment-index")&&(i=parseInt(t.getAttribute("data-fragment-index"),10)),r=Math.max(r,i),i<=e?(t.classList.contains("visible")||a.shown.push(t),t.classList.add("visible"),t.classList.remove("current-fragment"),this.Reveal.announceStatus(this.Reveal.getStatusText(t)),i===e&&(t.classList.add("current-fragment"),this.Reveal.slideContent.startEmbeddedContent(t))):(t.classList.contains("visible")&&a.hidden.push(t),t.classList.remove("visible"),t.classList.remove("current-fragment"))}),e="number"==typeof e?e:-1,e=Math.max(Math.min(e,r),-1),i.setAttribute("data-fragment",e)}return a}goto(e,t=0){let a=this.Reveal.getCurrentSlide();if(a&&this.Reveal.getConfig().fragments){let i=this.sort(a.querySelectorAll(".fragment"));if(i.length){if("number"!=typeof e){let t=this.sort(a.querySelectorAll(".fragment.visible")).pop();e=t?parseInt(t.getAttribute("data-fragment-index")||0,10):-1}e+=t;let r=this.update(e,i);return r.hidden.length&&this.Reveal.dispatchEvent("fragmenthidden",{fragment:r.hidden[0],fragments:r.hidden}),r.shown.length&&this.Reveal.dispatchEvent("fragmentshown",{fragment:r.shown[0],fragments:r.shown}),this.Reveal.updateControls(),this.Reveal.updateProgress(),this.Reveal.getConfig().fragmentInURL&&this.Reveal.writeURL(),!(!r.shown.length&&!r.hidden.length)}}return!1}next(){return this.goto(null,1)}prev(){return this.goto(null,-1)}}class y{constructor(e){this.Reveal=e,this.active=!1,this.onSlideClicked=this.onSlideClicked.bind(this)}activate(){if(this.Reveal.getConfig().overview&&!this.isActive()){this.active=!0,this.Reveal.getRevealElement().classList.add("overview"),this.Reveal.cancelAutoSlide(),this.Reveal.getSlidesElement().appendChild(this.Reveal.getBackgroundsElement()),n(this.Reveal.getRevealElement().querySelectorAll(".slides section")).forEach(e=>{e.classList.contains("stack")||e.addEventListener("click",this.onSlideClicked,!0)});const e=70,t=this.Reveal.getComputedSlideSize();this.overviewSlideWidth=t.width+e,this.overviewSlideHeight=t.height+e,this.Reveal.getConfig().rtl&&(this.overviewSlideWidth=-this.overviewSlideWidth),this.Reveal.updateSlidesVisibility(),this.layout(),this.update(),this.Reveal.layout();const a=this.Reveal.getIndices();this.Reveal.dispatchEvent("overviewshown",{indexh:a.h,indexv:a.v,currentSlide:this.Reveal.getCurrentSlide()})}}layout(){this.Reveal.getHorizontalSlides().forEach((e,t)=>{e.setAttribute("data-index-h",t),o(e,"translate3d("+t*this.overviewSlideWidth+"px, 0, 0)"),e.classList.contains("stack")&&n(e.querySelectorAll("section")).forEach((e,a)=>{e.setAttribute("data-index-h",t),e.setAttribute("data-index-v",a),o(e,"translate3d(0, "+a*this.overviewSlideHeight+"px, 0)")})}),n(this.Reveal.getBackgroundsElement().childNodes).forEach((e,t)=>{o(e,"translate3d("+t*this.overviewSlideWidth+"px, 0, 0)"),n(e.querySelectorAll(".slide-background")).forEach((e,t)=>{o(e,"translate3d(0, "+t*this.overviewSlideHeight+"px, 0)")})})}update(){const e=Math.min(window.innerWidth,window.innerHeight),t=Math.max(e/5,150)/e,a=this.Reveal.getIndices();this.Reveal.transformSlides({overview:["scale("+t+")","translateX("+-a.h*this.overviewSlideWidth+"px)","translateY("+-a.v*this.overviewSlideHeight+"px)"].join(" ")})}deactivate(){if(this.Reveal.getConfig().overview){this.active=!1,this.Reveal.getRevealElement().classList.remove("overview"),this.Reveal.getRevealElement().classList.add("overview-deactivating"),setTimeout(()=>{this.Reveal.getRevealElement().classList.remove("overview-deactivating")},1),this.Reveal.getRevealElement().appendChild(this.Reveal.getBackgroundsElement()),n(this.Reveal.getRevealElement().querySelectorAll(".slides section")).forEach(e=>{o(e,""),e.removeEventListener("click",this.onSlideClicked,!0)}),n(this.Reveal.getBackgroundsElement().querySelectorAll(".slide-background")).forEach(e=>{o(e,"")}),this.Reveal.transformSlides({overview:""});const e=this.Reveal.getIndices();this.Reveal.slide(e.h,e.v),this.Reveal.layout(),this.Reveal.cueAutoSlide(),this.Reveal.dispatchEvent("overviewhidden",{indexh:e.h,indexv:e.v,currentSlide:this.Reveal.getCurrentSlide()})}}toggle(e){"boolean"==typeof e?e?this.activate():this.deactivate():this.isActive()?this.deactivate():this.activate()}isActive(){return this.active}onSlideClicked(e){if(this.isActive()){e.preventDefault();let t=e.target;for(;t&&!t.nodeName.match(/section/gi);)t=t.parentNode;if(t&&!t.classList.contains("disabled")&&(this.deactivate(),t.nodeName.match(/section/gi))){let e=parseInt(t.getAttribute("data-index-h"),10),a=parseInt(t.getAttribute("data-index-v"),10);this.Reveal.slide(e,a)}}}}const A=(e,t)=>{const a=document.createElement("script");a.type="text/javascript",a.async=!1,a.defer=!1,a.src=e,"function"==typeof t&&(a.onload=a.onreadystatechange=e=>{("load"===e.type||/loaded|complete/.test(a.readyState))&&(a.onload=a.onreadystatechange=a.onerror=null,t())},a.onerror=e=>{a.onload=a.onreadystatechange=a.onerror=null,t(new Error("Failed loading script: "+a.src+"\n"+e))});const i=document.querySelector("head");i.insertBefore(a,i.lastChild)};class w{constructor(){this.state="idle",this.registeredPlugins={},this.asyncDependencies=[]}load(e){return this.state="loading",new Promise(t=>{let a=[],i=0;e.forEach(e=>{e.condition&&!e.condition()||(e.async?this.asyncDependencies.push(e):a.push(e))}),a.length?(i=a.length,a.forEach(e=>{A(e.src,()=>{"function"==typeof e.callback&&e.callback(),0==--i&&this.initPlugins().then(t)})})):this.initPlugins().then(t)})}initPlugins(){return new Promise(e=>{let t=Object.keys(this.registeredPlugins).length;if(0===t)this.loadAsync().then(e);else{let a=()=>{0==--t&&this.loadAsync().then(e)};for(let e in this.registeredPlugins){let t=this.registeredPlugins[e];if("function"==typeof t.init){let e=t.init();e&&"function"==typeof e.then?e.then(a):a()}else a()}}})}loadAsync(){return this.state="loaded",this.asyncDependencies.length&&this.asyncDependencies.forEach(e=>{A(e.src,e.callback)}),Promise.resolve()}registerPlugin(e,t){void 0===this.registeredPlugins[e]?(this.registeredPlugins[e]=t,"loaded"===this.state&&"function"==typeof t.init&&t.init()):console.warn('reveal.js: "'+e+'" plugin has already been registered')}hasPlugin(e){return!!this.registeredPlugins[e]}getPlugin(e){return this.registeredPlugins[e]}getRegisteredPlugins(){return this.registeredPlugins}}class S{constructor(e,t){this.diameter=100,this.diameter2=this.diameter/2,this.thickness=6,this.playing=!1,this.progress=0,this.progressOffset=1,this.container=e,this.progressCheck=t,this.canvas=document.createElement("canvas"),this.canvas.className="playback",this.canvas.width=this.diameter,this.canvas.height=this.diameter,this.canvas.style.width=this.diameter2+"px",this.canvas.style.height=this.diameter2+"px",this.context=this.canvas.getContext("2d"),this.container.appendChild(this.canvas),this.render()}setPlaying(e){const t=this.playing;this.playing=e,!t&&this.playing?this.animate():this.render()}animate(){const e=this.progress;this.progress=this.progressCheck(),e>.8&&this.progress<.2&&(this.progressOffset=this.progress),this.render(),this.playing&&requestAnimationFrame(this.animate.bind(this))}render(){let e=this.playing?this.progress:0,t=this.diameter2-this.thickness,a=this.diameter2,i=this.diameter2;this.progressOffset+=.1*(1-this.progressOffset);const r=-Math.PI/2+e*(2*Math.PI),n=-Math.PI/2+this.progressOffset*(2*Math.PI);this.context.save(),this.context.clearRect(0,0,this.diameter,this.diameter),this.context.beginPath(),this.context.arc(a,i,t+4,0,2*Math.PI,!1),this.context.fillStyle="rgba( 0, 0, 0, 0.4 )",this.context.fill(),this.context.beginPath(),this.context.arc(a,i,t,0,2*Math.PI,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="rgba( 255, 255, 255, 0.2 )",this.context.stroke(),this.playing&&(this.context.beginPath(),this.context.arc(a,i,t,n,r,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="#fff",this.context.stroke()),this.context.translate(a-14,i-14),this.playing?(this.context.fillStyle="#fff",this.context.fillRect(0,0,10,28),this.context.fillRect(18,0,10,28)):(this.context.beginPath(),this.context.translate(4,0),this.context.moveTo(0,0),this.context.lineTo(24,14),this.context.lineTo(0,28),this.context.fillStyle="#fff",this.context.fill()),this.context.restore()}on(e,t){this.canvas.addEventListener(e,t,!1)}off(e,t){this.canvas.removeEventListener(e,t,!1)}destroy(){this.playing=!1,this.canvas.parentNode&&this.container.removeChild(this.canvas)}}var E={width:960,height:700,margin:.04,minScale:.2,maxScale:2,controls:!0,controlsTutorial:!0,controlsLayout:"bottom-right",controlsBackArrows:"faded",progress:!0,slideNumber:!1,showSlideNumber:"all",hashOneBasedIndex:!1,hash:!1,history:!1,keyboard:!0,keyboardCondition:null,overview:!0,disableLayout:!1,center:!0,touch:!0,loop:!1,rtl:!1,navigationMode:"default",shuffle:!1,fragments:!0,fragmentInURL:!1,embedded:!1,help:!0,pause:!0,showNotes:!1,autoPlayMedia:null,preloadIframes:null,autoAnimate:!0,autoAnimateMatcher:null,autoAnimateEasing:"ease",autoAnimateDuration:1,autoAnimateUnmatched:!0,autoAnimateStyles:["opacity","color","background-color","padding","font-size","line-height","letter-spacing","border-width","border-color","border-radius","outline","outline-offset"],autoSlide:0,autoSlideStoppable:!0,autoSlideMethod:null,defaultTiming:null,mouseWheel:!1,previewLinks:!1,postMessage:!0,postMessageEvents:!1,focusBodyOnPageVisibilityChange:!0,transition:"slide",transitionSpeed:"default",backgroundTransition:"fade",parallaxBackgroundImage:"",parallaxBackgroundSize:"",parallaxBackgroundRepeat:"",parallaxBackgroundPosition:"",parallaxBackgroundHorizontal:null,parallaxBackgroundVertical:null,pdfMaxPagesPerSlide:Number.POSITIVE_INFINITY,pdfSeparateFragments:!0,pdfPageHeightOffset:-1,viewDistance:3,mobileViewDistance:2,display:"block",hideInactiveCursor:!0,hideCursorTime:5e3,dependencies:[]};const k=e=>{let t=e.match(/^#([0-9a-f]{3})$/i);if(t&&t[1])return t=t[1],{r:17*parseInt(t.charAt(0),16),g:17*parseInt(t.charAt(1),16),b:17*parseInt(t.charAt(2),16)};let a=e.match(/^#([0-9a-f]{6})$/i);if(a&&a[1])return a=a[1],{r:parseInt(a.substr(0,2),16),g:parseInt(a.substr(2,2),16),b:parseInt(a.substr(4,2),16)};let i=e.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);if(i)return{r:parseInt(i[1],10),g:parseInt(i[2],10),b:parseInt(i[3],10)};let r=e.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i);return r?{r:parseInt(r[1],10),g:parseInt(r[2],10),b:parseInt(r[3],10),a:parseFloat(r[4])}:null};var L=function(e,t){const a={};let l,c,u,p,A,L,x,R=!1,M=!1,C=!1,N=[],P=1,q={layout:"",overview:""},I={},T=new w,B=new m(a),O=new v(a),H=new b(a),D=new y(a),z=0,W=0,j=!1,$=0,U=!1,V=0,F=0,X=-1,Y=!1,K={startX:0,startY:0,startCount:0,captured:!1,threshold:40},_={},J={};function Q(){R=!0,function(){I.slides.classList.add("no-transition"),h?I.wrapper.classList.add("no-hover"):I.wrapper.classList.remove("no-hover");I.background=te(I.wrapper,"div","backgrounds",null),I.progress=te(I.wrapper,"div","progress",""),I.progressbar=I.progress.querySelector("span"),I.controls=te(I.wrapper,"aside","controls",`\n\t\t\t\n\t\t\t\n\t\t\t`),I.slideNumber=te(I.wrapper,"div","slide-number",""),I.speakerNotes=te(I.wrapper,"div","speaker-notes",null),I.speakerNotes.setAttribute("data-prevent-swipe",""),I.speakerNotes.setAttribute("tabindex","0"),I.pauseOverlay=te(I.wrapper,"div","pause-overlay",l.controls?'':null),I.wrapper.setAttribute("role","application"),I.controlsLeft=n(I.wrapper.querySelectorAll(".navigate-left")),I.controlsRight=n(I.wrapper.querySelectorAll(".navigate-right")),I.controlsUp=n(I.wrapper.querySelectorAll(".navigate-up")),I.controlsDown=n(I.wrapper.querySelectorAll(".navigate-down")),I.controlsPrev=n(I.wrapper.querySelectorAll(".navigate-prev")),I.controlsNext=n(I.wrapper.querySelectorAll(".navigate-next")),I.controlsRightArrow=I.controls.querySelector(".navigate-right"),I.controlsLeftArrow=I.controls.querySelector(".navigate-left"),I.controlsDownArrow=I.controls.querySelector(".navigate-down"),I.statusElement=function(){let e=I.wrapper.querySelector(".aria-status");e||(e=document.createElement("div"),e.style.position="absolute",e.style.height="1px",e.style.width="1px",e.style.overflow="hidden",e.style.clip="rect( 1px, 1px, 1px, 1px )",e.classList.add("aria-status"),e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),I.wrapper.appendChild(e));return e}()}(),l.postMessage&&window.addEventListener("message",e=>{let t=e.data;if("string"==typeof t&&"{"===t.charAt(0)&&"}"===t.charAt(t.length-1)&&(t=JSON.parse(t),t.method&&"function"==typeof a[t.method]))if(!1===i.test(t.method)){const e=a[t.method].apply(a,t.args);ce("callback",{method:t.method,result:e})}else console.warn('reveal.js: "'+t.method+'" is is blacklisted from the postMessage API')},!1),setInterval(()=>{0===I.wrapper.scrollTop&&0===I.wrapper.scrollLeft||(I.wrapper.scrollTop=0,I.wrapper.scrollLeft=0)},1e3),et().forEach(e=>{n(e.querySelectorAll("section")).forEach((e,t)=>{t>0&&(e.classList.remove("present"),e.classList.remove("past"),e.classList.add("future"),e.setAttribute("aria-hidden","true"))})}),re(),Je(),Ve(!0),setTimeout(()=>{I.slides.classList.remove("no-transition"),I.wrapper.classList.add("ready"),de("ready",{indexh:c,indexv:u,currentSlide:A})},1),le()&&(se(),"complete"===document.readyState?ee():window.addEventListener("load",ee))}function Z(e){I.statusElement.textContent=e}function G(e){let t="";if(3===e.nodeType)t+=e.textContent;else if(1===e.nodeType){let a=e.getAttribute("aria-hidden"),i="none"===window.getComputedStyle(e).display;"true"===a||i||n(e.childNodes).forEach(e=>{t+=G(e)})}return t=t.trim(),""===t?"":t+" "}function ee(){let e=be(window.innerWidth,window.innerHeight),t=Math.floor(e.width*(1+l.margin)),a=Math.floor(e.height*(1+l.margin)),i=e.width,r=e.height;d("@page{size:"+t+"px "+a+"px; margin: 0px;}"),d(".reveal section>img, .reveal section>video, .reveal section>iframe{max-width: "+i+"px; max-height:"+r+"px}"),document.body.classList.add("print-pdf"),document.body.style.width=t+"px",document.body.style.height=a+"px",ve(i,r);let s=l.slideNumber&&/all|print/i.test(l.showSlideNumber);n(I.wrapper.querySelectorAll(".slides section")).forEach((function(e){e.setAttribute("data-slide-number",$e(e))})),n(I.wrapper.querySelectorAll(".slides section")).forEach((function(e){if(!1===e.classList.contains("stack")){let o=(t-i)/2,d=(a-r)/2,c=e.scrollHeight,u=Math.max(Math.ceil(c/a),1);u=Math.min(u,l.pdfMaxPagesPerSlide),(1===u&&l.center||e.classList.contains("center"))&&(d=Math.max((a-c)/2,0));let h=document.createElement("div");if(h.className="pdf-page",h.style.height=(a+l.pdfPageHeightOffset)*u+"px",e.parentNode.insertBefore(h,e),h.appendChild(e),e.style.left=o+"px",e.style.top=d+"px",e.style.width=i+"px",e.slideBackgroundElement&&h.insertBefore(e.slideBackgroundElement,e),l.showNotes){let a=st(e);if(a){let e=8,i="string"==typeof l.showNotes?l.showNotes:"inline",r=document.createElement("div");r.classList.add("speaker-notes"),r.classList.add("speaker-notes-pdf"),r.setAttribute("data-layout",i),r.innerHTML=a,"separate-page"===i?h.parentNode.insertBefore(r,h.nextSibling):(r.style.left=e+"px",r.style.bottom=e+"px",r.style.width=t-2*e+"px",h.appendChild(r))}}if(s){let t=document.createElement("div");t.classList.add("slide-number"),t.classList.add("slide-number-pdf"),t.innerHTML=e.getAttribute("data-slide-number"),h.appendChild(t)}if(l.pdfSeparateFragments){let e,t,a=H.sort(h.querySelectorAll(".fragment"),!0);a.forEach((function(a){e&&e.forEach((function(e){e.classList.remove("current-fragment")})),a.forEach((function(e){e.classList.add("visible","current-fragment")}));let i=h.cloneNode(!0);h.parentNode.insertBefore(i,(t||h).nextSibling),e=a,t=i})),a.forEach((function(e){e.forEach((function(e){e.classList.remove("visible","current-fragment")}))}))}else n(h.querySelectorAll(".fragment:not(.fade-out)")).forEach((function(e){e.classList.add("visible")}))}})),de("pdf-ready")}function te(e,t,a,i=""){let r=e.querySelectorAll("."+a);for(let t=0;t1&&l.autoSlide&&l.autoSlideStoppable&&(x=new S(I.wrapper,()=>Math.min(Math.max((Date.now()-X)/V,0),1)),x.on("click",jt),Y=!1),!1===l.fragments&&H.showAll();let n="none";l.slideNumber&&!le()&&("all"===l.showSlideNumber||"speaker"===l.showSlideNumber&&_e())&&(n="block"),I.slideNumber.style.display=n,"default"!==l.navigationMode?I.wrapper.setAttribute("data-navigation-mode",l.navigationMode):I.wrapper.removeAttribute("data-navigation-mode"),"linear"===l.navigationMode?(_["→ , ↓ , SPACE , N , L , J"]="Next slide",_["← , ↑ , P , H , K"]="Previous slide"):(_["N , SPACE"]="Next slide",_.P="Previous slide",_["← , H"]="Navigate left",_["→ , L"]="Navigate right",_["↑ , K"]="Navigate up",_["↓ , J"]="Navigate down"),_["Home , Shift ←"]="First slide",_["End , Shift →"]="Last slide",_["B , ."]="Pause",_.F="Fullscreen",_["ESC, O"]="Slide overview",Te()}function ne(){U=!0,window.addEventListener("hashchange",Ht,!1),window.addEventListener("resize",Dt,!1),l.touch&&("onpointerdown"in window?(I.wrapper.addEventListener("pointerdown",xt,!1),I.wrapper.addEventListener("pointermove",Rt,!1),I.wrapper.addEventListener("pointerup",Mt,!1)):window.navigator.msPointerEnabled?(I.wrapper.addEventListener("MSPointerDown",xt,!1),I.wrapper.addEventListener("MSPointerMove",Rt,!1),I.wrapper.addEventListener("MSPointerUp",Mt,!1)):(I.wrapper.addEventListener("touchstart",Et,!1),I.wrapper.addEventListener("touchmove",kt,!1),I.wrapper.addEventListener("touchend",Lt,!1))),l.keyboard&&(document.addEventListener("keydown",St,!1),document.addEventListener("keypress",wt,!1)),l.progress&&I.progress&&I.progress.addEventListener("click",Nt,!1),I.pauseOverlay.addEventListener("click",Ce,!1),l.focusBodyOnPageVisibilityChange&&document.addEventListener("visibilitychange",zt,!1);let e=["touchstart","click"];g&&(e=["touchstart"]),e.forEach(e=>{I.controlsLeft.forEach(t=>t.addEventListener(e,Pt,!1)),I.controlsRight.forEach(t=>t.addEventListener(e,qt,!1)),I.controlsUp.forEach(t=>t.addEventListener(e,It,!1)),I.controlsDown.forEach(t=>t.addEventListener(e,Tt,!1)),I.controlsPrev.forEach(t=>t.addEventListener(e,Bt,!1)),I.controlsNext.forEach(t=>t.addEventListener(e,Ot,!1))})}function se(){U=!1,document.removeEventListener("keydown",St,!1),document.removeEventListener("keypress",wt,!1),window.removeEventListener("hashchange",Ht,!1),window.removeEventListener("resize",Dt,!1),I.wrapper.removeEventListener("pointerdown",xt,!1),I.wrapper.removeEventListener("pointermove",Rt,!1),I.wrapper.removeEventListener("pointerup",Mt,!1),I.wrapper.removeEventListener("MSPointerDown",xt,!1),I.wrapper.removeEventListener("MSPointerMove",Rt,!1),I.wrapper.removeEventListener("MSPointerUp",Mt,!1),I.wrapper.removeEventListener("touchstart",Et,!1),I.wrapper.removeEventListener("touchmove",kt,!1),I.wrapper.removeEventListener("touchend",Lt,!1),I.pauseOverlay.removeEventListener("click",Ce,!1),l.progress&&I.progress&&I.progress.removeEventListener("click",Nt,!1),["touchstart","click"].forEach(e=>{I.controlsLeft.forEach(t=>t.removeEventListener(e,Pt,!1)),I.controlsRight.forEach(t=>t.removeEventListener(e,qt,!1)),I.controlsUp.forEach(t=>t.removeEventListener(e,It,!1)),I.controlsDown.forEach(t=>t.removeEventListener(e,Tt,!1)),I.controlsPrev.forEach(t=>t.removeEventListener(e,Bt,!1)),I.controlsNext.forEach(t=>t.removeEventListener(e,Ot,!1))})}function oe(e){"string"==typeof e.layout&&(q.layout=e.layout),"string"==typeof e.overview&&(q.overview=e.overview),q.layout?o(I.slides,q.layout+" "+q.overview):o(I.slides,q.overview)}function le(){return/print-pdf/gi.test(window.location.search)}function de(e,t){let a=document.createEvent("HTMLEvents",1,2);a.initEvent(e,!0,!0),r(a,t),I.wrapper.dispatchEvent(a),ce(e)}function ce(e,t){if(l.postMessageEvents&&window.parent!==window.self){let a={namespace:"reveal",eventName:e,state:ot()};r(a,t),window.parent.postMessage(JSON.stringify(a),"*")}}function ue(e="a"){n(I.wrapper.querySelectorAll(e)).forEach(e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.addEventListener("click",Wt,!1)})}function he(e="a"){n(I.wrapper.querySelectorAll(e)).forEach(e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.removeEventListener("click",Wt,!1)})}function pe(e){"boolean"==typeof e?e?ge():fe():I.overlay?fe():ge()}function ge(){if(l.help){fe(),I.overlay=document.createElement("div"),I.overlay.classList.add("overlay"),I.overlay.classList.add("overlay-help"),I.wrapper.appendChild(I.overlay);let e='

Keyboard Shortcuts


';e+="";for(let t in _)e+=``;for(let t in J)J[t].key&&J[t].description&&(e+=``);e+="
KEYACTION
${t}${_[t]}
${J[t].key}${J[t].description}
",I.overlay.innerHTML=`\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
${e}
\n\t\t\t\t
\n\t\t\t`,I.overlay.querySelector(".close").addEventListener("click",e=>{fe(),e.preventDefault()},!1)}}function fe(){I.overlay&&(I.overlay.parentNode.removeChild(I.overlay),I.overlay=null)}function me(){if(I.wrapper&&!le()){if(!l.disableLayout){h&&document.documentElement.style.setProperty("--vh",.01*window.innerHeight+"px");const e=be(),t=P;ve(l.width,l.height),I.slides.style.width=e.width+"px",I.slides.style.height=e.height+"px",P=Math.min(e.presentationWidth/e.width,e.presentationHeight/e.height),P=Math.max(P,l.minScale),P=Math.min(P,l.maxScale),1===P?(I.slides.style.zoom="",I.slides.style.left="",I.slides.style.top="",I.slides.style.bottom="",I.slides.style.right="",oe({layout:""})):P>1&&f&&window.devicePixelRatio<2?(I.slides.style.zoom=P,I.slides.style.left="",I.slides.style.top="",I.slides.style.bottom="",I.slides.style.right="",oe({layout:""})):(I.slides.style.zoom="",I.slides.style.left="50%",I.slides.style.top="50%",I.slides.style.bottom="auto",I.slides.style.right="auto",oe({layout:"translate(-50%, -50%) scale("+P+")"}));const a=n(I.wrapper.querySelectorAll(".slides section"));for(let t=0,i=a.length;t .stretch")).forEach(a=>{let i=function(e,t=0){if(e){let a,i=e.style.height;return e.style.height="0px",e.parentNode.style.height="auto",a=t-e.parentNode.offsetHeight,e.style.height=i+"px",e.parentNode.style.removeProperty("height"),a}return t}(a,t);if(/(img|video)/gi.test(a.nodeName)){const t=a.naturalWidth||a.videoWidth,r=a.naturalHeight||a.videoHeight,n=Math.min(e/t,i/r);a.style.width=t*n+"px",a.style.height=r*n+"px"}else a.style.width=e+"px",a.style.height=i+"px"})}function be(e,t){const a={width:l.width,height:l.height,presentationWidth:e||I.wrapper.offsetWidth,presentationHeight:t||I.wrapper.offsetHeight};return a.presentationWidth-=a.presentationWidth*l.margin,a.presentationHeight-=a.presentationHeight*l.margin,"string"==typeof a.width&&/%$/.test(a.width)&&(a.width=parseInt(a.width,10)/100*a.presentationWidth),"string"==typeof a.height&&/%$/.test(a.height)&&(a.height=parseInt(a.height,10)/100*a.presentationHeight),a}function ye(e,t){"object"==typeof e&&"function"==typeof e.setAttribute&&e.setAttribute("data-previous-indexv",t||0)}function Ae(e){if("object"==typeof e&&"function"==typeof e.setAttribute&&e.classList.contains("stack")){const t=e.hasAttribute("data-start-indexv")?"data-start-indexv":"data-previous-indexv";return parseInt(e.getAttribute(t)||0,10)}return 0}function we(e){let t="/",a=e||A,i=a?a.getAttribute("id"):null;i&&(i=encodeURIComponent(i));let r=Ze(e);if(l.fragmentInURL||(r.f=void 0),"string"==typeof i&&i.length&&void 0===r.f)t="/"+i;else{let e=l.hashOneBasedIndex?1:0;(r.h>0||r.v>0||void 0!==r.f)&&(t+=r.h+e),(r.v>0||void 0!==r.f)&&(t+="/"+(r.v+e)),void 0!==r.f&&(t+="/"+r.f)}return t}function Se(e=A){return e&&e.parentNode&&!!e.parentNode.nodeName.match(/section/i)}function Ee(){return!(!A||!Se(A))&&!A.nextElementSibling}function ke(){return 0===c&&0===u}function Le(){return!!A&&(!A.nextElementSibling&&(!Se(A)||!A.parentNode.nextElementSibling))}function xe(){j&&(j=!1,I.wrapper.style.cursor="")}function Re(){!1===j&&(j=!0,I.wrapper.style.cursor="none")}function Me(){if(l.pause){const e=I.wrapper.classList.contains("paused");dt(),I.wrapper.classList.add("paused"),!1===e&&de("paused")}}function Ce(){const e=I.wrapper.classList.contains("paused");I.wrapper.classList.remove("paused"),lt(),e&&de("resumed")}function Ne(e){"boolean"==typeof e?e?Me():Ce():Pe()?Ce():Me()}function Pe(){return I.wrapper.classList.contains("paused")}function qe(e){"boolean"==typeof e?e?ut():ct():Y?ut():ct()}function Ie(e,t,a,i){p=A;const r=I.wrapper.querySelectorAll(".slides>section");if(0===r.length)return;void 0!==t||D.isActive()||(t=Ae(r[e])),p&&p.parentNode&&p.parentNode.classList.contains("stack")&&ye(p.parentNode,u);const s=N.concat();N.length=0;let o=c||0,d=u||0;c=He(".slides>section",void 0===e?c:e),u=He(".slides>section.present>section",void 0===t?u:t),De(),me(),D.isActive()&&D.update();let h=r[c],g=h.querySelectorAll("section");A=g[u]||h,void 0!==a&&H.goto(a);let f=c!==o||u!==d;f||(p=null),p&&p!==A&&(p.classList.remove("present"),p.setAttribute("aria-hidden","true"),ke()&&setTimeout(()=>{n(I.wrapper.querySelectorAll(".slides>section.stack")).forEach(e=>{ye(e,0)})},0));e:for(let e=0,t=N.length;e{I.slides.classList.remove("disable-slide-transitions")},0),l.autoAnimate&&O.run(p,A))}function Te(){se(),ne(),me(),V=l.autoSlide,lt(),le(),I.background.innerHTML="",I.background.classList.add("no-transition"),n(I.wrapper.querySelectorAll(".slides>section")).forEach(e=>{let t=ae(e,I.background);n(e.querySelectorAll("section")).forEach(e=>{ae(e,t),t.classList.add("stack")})}),l.parallaxBackgroundImage?(I.background.style.backgroundImage='url("'+l.parallaxBackgroundImage+'")',I.background.style.backgroundSize=l.parallaxBackgroundSize,I.background.style.backgroundRepeat=l.parallaxBackgroundRepeat,I.background.style.backgroundPosition=l.parallaxBackgroundPosition,setTimeout(()=>{I.wrapper.classList.add("has-parallax-background")},1)):(I.background.style.backgroundImage="",I.wrapper.classList.remove("has-parallax-background")),Qe(),H.sortAll(),Ue(),We(),je(),De(),Ve(!0),l.showNotes&&I.slides.querySelectorAll("[data-notes], aside.notes").length>0?I.wrapper.classList.add("show-notes"):I.wrapper.classList.remove("show-notes"),ze(),B.formatEmbeddedContent(),!1===l.autoPlayMedia?B.stopEmbeddedContent(A,{unloadIframes:!1}):B.startEmbeddedContent(A),D.isActive()&&D.layout()}function Be(e=A){return l.sort(e.querySelectorAll(".fragment"))}function Oe(){et().forEach((e,t,a)=>{I.slides.insertBefore(e,a[Math.floor(Math.random()*a.length)])})}function He(e,t){let a=n(I.wrapper.querySelectorAll(e)),i=a.length,r=le();if(i){l.loop&&(t%=i)<0&&(t=i+t),t=Math.max(Math.min(t,i-1),0);for(let e=0;e{e.classList.add("visible"),e.classList.remove("current-fragment")})):e>t&&(i.classList.add(s?"past":"future"),l.fragments&&n(i.querySelectorAll(".fragment.visible")).forEach(e=>{e.classList.remove("visible","current-fragment")}))}a[t].classList.add("present"),a[t].removeAttribute("hidden"),a[t].removeAttribute("aria-hidden");let e=a[t].getAttribute("data-state");e&&(N=N.concat(e.split(" ")))}else t=0;return t}function De(){let e,t,a=et(),i=a.length;if(i&&void 0!==c){let r=D.isActive()?10:l.viewDistance;h&&(r=D.isActive()?6:l.mobileViewDistance),le()&&(r=Number.MAX_VALUE);for(let s=0;sNo notes on this slide.')}function We(){l.progress&&I.progressbar&&(I.progressbar.style.width=Ke()*I.wrapper.offsetWidth+"px")}function je(){l.slideNumber&&I.slideNumber&&(I.slideNumber.innerHTML=$e())}function $e(e=A){let t,a="h.v";if("function"==typeof l.slideNumber)t=l.slideNumber(e);else switch("string"==typeof l.slideNumber&&(a=l.slideNumber),/c/.test(a)||1!==I.wrapper.querySelectorAll(".slides>section").length||(a="c"),t=[],a){case"c":t.push(Ye(e)+1);break;case"c/t":t.push(Ye(e)+1,"/",rt());break;default:let i=Ze(e);t.push(i.h+1);let r="h/v"===a?"/":".";Se(e)&&t.push(r,i.v+1)}let i="#"+we(e);return function(e,t,a,i="#"+we()){return"number"!=typeof a||isNaN(a)?`\n\t\t\t\t\t${e}\n\t\t\t\t\t`:`\n\t\t\t\t\t${e}\n\t\t\t\t\t${t}\n\t\t\t\t\t${a}\n\t\t\t\t\t`}(t[0],t[1],t[2],i)}function Ue(){let e=Xe(),t=H.availableRoutes();[...I.controlsLeft,...I.controlsRight,...I.controlsUp,...I.controlsDown,...I.controlsPrev,...I.controlsNext].forEach(e=>{e.classList.remove("enabled","fragmented"),e.setAttribute("disabled","disabled")}),e.left&&I.controlsLeft.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),e.right&&I.controlsRight.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),e.up&&I.controlsUp.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),e.down&&I.controlsDown.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),(e.left||e.up)&&I.controlsPrev.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),(e.right||e.down)&&I.controlsNext.forEach(e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}),A&&(t.prev&&I.controlsPrev.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),t.next&&I.controlsNext.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),Se(A)?(t.prev&&I.controlsUp.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),t.next&&I.controlsDown.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})):(t.prev&&I.controlsLeft.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}),t.next&&I.controlsRight.forEach(e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}))),l.controlsTutorial&&(!C&&e.down?I.controlsDownArrow.classList.add("highlight"):(I.controlsDownArrow.classList.remove("highlight"),l.rtl?!M&&e.left&&0===u?I.controlsLeftArrow.classList.add("highlight"):I.controlsLeftArrow.classList.remove("highlight"):!M&&e.right&&0===u?I.controlsRightArrow.classList.add("highlight"):I.controlsRightArrow.classList.remove("highlight")))}function Ve(e=!1){let t=null,a=l.rtl?"future":"past",i=l.rtl?"past":"future";if(n(I.background.childNodes).forEach((r,s)=>{r.classList.remove("past","present","future"),sc?r.classList.add(i):(r.classList.add("present"),t=r),(e||s===c)&&n(r.querySelectorAll(".slide-background")).forEach((e,a)=>{e.classList.remove("past","present","future"),au?e.classList.add("future"):(e.classList.add("present"),s===c&&(t=e))})}),L&&B.stopEmbeddedContent(L,{unloadIframes:!B.shouldPreload(L)}),t){B.startEmbeddedContent(t);let e=t.querySelector(".slide-background-content");if(e){let t=e.style.backgroundImage||"";/\.gif/i.test(t)&&(e.style.backgroundImage="",window.getComputedStyle(e).opacity,e.style.backgroundImage=t)}let a=L?L.getAttribute("data-background-hash"):null,i=t.getAttribute("data-background-hash");i&&i===a&&t!==L&&I.background.classList.add("no-transition"),L=t}A&&["has-light-background","has-dark-background"].forEach(e=>{A.classList.contains(e)?I.wrapper.classList.add(e):I.wrapper.classList.remove(e)}),setTimeout(()=>{I.background.classList.remove("no-transition")},1)}function Fe(){if(l.parallaxBackgroundImage){let e,t,a=et(),i=tt(),r=I.background.style.backgroundSize.split(" ");1===r.length?e=t=parseInt(r[0],10):(e=parseInt(r[0],10),t=parseInt(r[1],10));let n,s,o=I.background.offsetWidth,d=a.length;n="number"==typeof l.parallaxBackgroundHorizontal?l.parallaxBackgroundHorizontal:d>1?(e-o)/(d-1):0,s=n*c*-1;let h,p,g=I.background.offsetHeight,f=i.length;h="number"==typeof l.parallaxBackgroundVertical?l.parallaxBackgroundVertical:(t-g)/(f-1),p=f>0?h*u:0,I.background.style.backgroundPosition=s+"px "+-p+"px"}}function Xe(){let e=I.wrapper.querySelectorAll(".slides>section"),t=I.wrapper.querySelectorAll(".slides>section.present>section"),a={left:c>0,right:c0,down:u1&&(a.left=!0,a.right=!0),t.length>1&&(a.up=!0,a.down=!0)),l.rtl){let e=a.left;a.left=a.right,a.right=e}return a}function Ye(e=A){let t=et(),a=0;e:for(let i=0;i0){let a=.9;t+=A.querySelectorAll(".fragment.visible").length/e.length*a}}return Math.min(t/(e-1),1)}function _e(){return!!window.location.search.match(/receiver/gi)}function Je(){let e=window.location.hash,t=e.slice(2).split("/"),i=e.replace(/#|\//gi,"");if(!/^[0-9]*$/.test(t[0])&&i.length){let e;try{e=document.getElementById(decodeURIComponent(i))}catch(e){}let t=!!A&&A.getAttribute("id")===i;if(e){if(!t){let t=a.getIndices(e);Ie(t.h,t.v)}}else Ie(c||0,u||0)}else{let e,a=l.hashOneBasedIndex?1:0,i=parseInt(t[0],10)-a||0,r=parseInt(t[1],10)-a||0;l.fragmentInURL&&(e=parseInt(t[2],10),isNaN(e)&&(e=void 0)),i===c&&r===u&&void 0===e||Ie(i,r,e)}}function Qe(e){clearTimeout(W),"number"==typeof e?W=setTimeout(Qe,e):A&&(l.history||!window.history?window.location.hash=we():l.hash?window.history.replaceState(null,null,"#"+we()):window.history.replaceState(null,null,window.location.pathname+window.location.search))}function Ze(e){let t,a=c,i=u;if(e){let t=Se(e),r=t?e.parentNode:e,s=n(I.wrapper.querySelectorAll(".slides>section"));a=Math.max(s.indexOf(r),0),i=void 0,t&&(i=Math.max(n(e.parentNode.querySelectorAll("section")).indexOf(e),0))}if(!e&&A){if(A.querySelectorAll(".fragment").length>0){let e=A.querySelector(".current-fragment");t=e&&e.hasAttribute("data-fragment-index")?parseInt(e.getAttribute("data-fragment-index"),10):A.querySelectorAll(".fragment.visible").length-1}}return{h:a,v:i,f:t}}function Ge(){return n(I.wrapper.querySelectorAll('.slides section:not(.stack):not([data-visibility="uncounted"])'))}function et(){return n(I.wrapper.querySelectorAll(".slides>section"))}function tt(){return n(I.wrapper.querySelectorAll(".slides>section>section"))}function at(){return et().length>1}function it(){return tt().length>1}function rt(){return Ge().length}function nt(e,t){let a=et()[e],i=a&&a.querySelectorAll("section");return i&&i.length&&"number"==typeof t?i?i[t]:void 0:a}function st(e=A){if(e.hasAttribute("data-notes"))return e.getAttribute("data-notes");let t=e.querySelector("aside.notes");return t?t.innerHTML:null}function ot(){let e=Ze();return{indexh:e.h,indexv:e.v,indexf:e.f,paused:Pe(),overview:D.isActive()}}function lt(){if(dt(),A&&!1!==l.autoSlide){let e=A.querySelector(".current-fragment");e||(e=A.querySelector(".fragment"));let t=e?e.getAttribute("data-autoslide"):null,a=A.parentNode?A.parentNode.getAttribute("data-autoslide"):null,i=A.getAttribute("data-autoslide");V=t?parseInt(t,10):i?parseInt(i,10):a?parseInt(a,10):l.autoSlide,0===A.querySelectorAll(".fragment").length&&n(A.querySelectorAll("video, audio")).forEach(e=>{e.hasAttribute("data-autoplay")&&V&&1e3*e.duration/e.playbackRate>V&&(V=1e3*e.duration/e.playbackRate+1e3)}),!V||Y||Pe()||D.isActive()||Le()&&!H.availableRoutes().next&&!0!==l.loop||(F=setTimeout(()=>{"function"==typeof l.autoSlideMethod?l.autoSlideMethod():vt(),lt()},V),X=Date.now()),x&&x.setPlaying(-1!==F)}}function dt(){clearTimeout(F),F=-1}function ct(){V&&!Y&&(Y=!0,de("autoslidepaused"),clearTimeout(F),x&&x.setPlaying(!1))}function ut(){V&&Y&&(Y=!1,de("autoslideresumed"),lt())}function ht(){M=!0,l.rtl?(D.isActive()||!1===H.next())&&Xe().left&&Ie(c+1,"grid"===l.navigationMode?u:void 0):(D.isActive()||!1===H.prev())&&Xe().left&&Ie(c-1,"grid"===l.navigationMode?u:void 0)}function pt(){M=!0,l.rtl?(D.isActive()||!1===H.prev())&&Xe().right&&Ie(c-1,"grid"===l.navigationMode?u:void 0):(D.isActive()||!1===H.next())&&Xe().right&&Ie(c+1,"grid"===l.navigationMode?u:void 0)}function gt(){(D.isActive()||!1===H.prev())&&Xe().up&&Ie(c,u-1)}function ft(){C=!0,(D.isActive()||!1===H.next())&&Xe().down&&Ie(c,u+1)}function mt(){if(!1===H.prev())if(Xe().up)gt();else{let e;if(e=l.rtl?n(I.wrapper.querySelectorAll(".slides>section.future")).pop():n(I.wrapper.querySelectorAll(".slides>section.past")).pop(),e){let t=e.querySelectorAll("section").length-1||void 0;Ie(c-1,t)}}}function vt(){if(M=!0,C=!0,!1===H.next()){let e=Xe();e.down&&e.right&&l.loop&&Ee()&&(e.down=!1),e.down?ft():l.rtl?ht():pt()}}function bt(e){for(;e&&"function"==typeof e.hasAttribute;){if(e.hasAttribute("data-prevent-swipe"))return!0;e=e.parentNode}return!1}function yt(e){l.autoSlideStoppable&&ct()}function At(e){xe(),clearTimeout($),$=setTimeout(Re,l.hideCursorTime)}function wt(e){e.shiftKey&&63===e.charCode&&pe()}function St(e){if("function"==typeof l.keyboardCondition&&!1===l.keyboardCondition(e))return!0;let t=e.keyCode,i=Y;yt();let r=document.activeElement&&"inherit"!==document.activeElement.contentEditable,n=document.activeElement&&document.activeElement.tagName&&/input|textarea/i.test(document.activeElement.tagName),s=document.activeElement&&document.activeElement.className&&/speaker-notes/i.test(document.activeElement.className),o=e.shiftKey&&32===e.keyCode,d=e.shiftKey&&37===t,c=e.shiftKey&&39===t,u=!o&&!d&&!c&&(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey);if(r||n||s||u)return;let h,p=[66,86,190,191];if("object"==typeof l.keyboard)for(h in l.keyboard)"togglePause"===l.keyboard[h]&&p.push(parseInt(h,10));if(Pe()&&-1===p.indexOf(t))return!1;let g="linear"===l.navigationMode||!at()||!it(),f=!1;if("object"==typeof l.keyboard)for(h in l.keyboard)if(parseInt(h,10)===t){let t=l.keyboard[h];"function"==typeof t?t.apply(null,[e]):"string"==typeof t&&"function"==typeof a[t]&&a[t].call(),f=!0}if(!1===f)for(h in J)if(parseInt(h,10)===t){let t=J[h].callback;"function"==typeof t?t.apply(null,[e]):"string"==typeof t&&"function"==typeof a[t]&&a[t].call(),f=!0}!1===f&&(f=!0,80===t||33===t?mt():78===t||34===t?vt():72===t||37===t?d?Ie(0):!D.isActive()&&g?mt():ht():76===t||39===t?c?Ie(Number.MAX_VALUE):!D.isActive()&&g?vt():pt():75===t||38===t?!D.isActive()&&g?mt():gt():74===t||40===t?!D.isActive()&&g?vt():ft():36===t?Ie(0):35===t?Ie(Number.MAX_VALUE):32===t?(D.isActive()&&D.deactivate(),e.shiftKey?mt():vt()):58===t||59===t||66===t||86===t||190===t||191===t?Ne():70===t?(()=>{let e=document.documentElement,t=e.requestFullscreen||e.webkitRequestFullscreen||e.webkitRequestFullScreen||e.mozRequestFullScreen||e.msRequestFullscreen;t&&t.apply(e)})():65===t?l.autoSlideStoppable&&qe(i):f=!1),f?e.preventDefault&&e.preventDefault():27!==t&&79!==t||(I.overlay?fe():D.toggle(),e.preventDefault&&e.preventDefault()),lt()}function Et(e){if(bt(e.target))return!0;K.startX=e.touches[0].clientX,K.startY=e.touches[0].clientY,K.startCount=e.touches.length}function kt(e){if(bt(e.target))return!0;if(K.captured)g&&e.preventDefault();else{yt();let t=e.touches[0].clientX,a=e.touches[0].clientY;if(1===e.touches.length&&2!==K.startCount){let i=t-K.startX,r=a-K.startY;i>K.threshold&&Math.abs(i)>Math.abs(r)?(K.captured=!0,"linear"===l.navigationMode?l.rtl?vt():mt():ht()):i<-K.threshold&&Math.abs(i)>Math.abs(r)?(K.captured=!0,"linear"===l.navigationMode?l.rtl?mt():vt():pt()):r>K.threshold?(K.captured=!0,"linear"===l.navigationMode?mt():gt()):r<-K.threshold&&(K.captured=!0,"linear"===l.navigationMode?vt():ft()),l.embedded?(K.captured||Se(A))&&e.preventDefault():e.preventDefault()}}}function Lt(e){K.captured=!1}function xt(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],Et(e))}function Rt(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],kt(e))}function Mt(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],Lt())}function Ct(e){if(Date.now()-z>600){z=Date.now();let t=e.detail||-e.wheelDelta;t>0?vt():t<0&&mt()}}function Nt(e){yt(),e.preventDefault();let t=et().length,a=Math.floor(e.clientX/I.wrapper.offsetWidth*t);l.rtl&&(a=t-a),Ie(a)}function Pt(e){e.preventDefault(),yt(),"linear"===l.navigationMode?mt():ht()}function qt(e){e.preventDefault(),yt(),"linear"===l.navigationMode?vt():pt()}function It(e){e.preventDefault(),yt(),gt()}function Tt(e){e.preventDefault(),yt(),ft()}function Bt(e){e.preventDefault(),yt(),mt()}function Ot(e){e.preventDefault(),yt(),vt()}function Ht(e){Je()}function Dt(e){me()}function zt(e){!1===document.hidden&&document.activeElement!==document.body&&("function"==typeof document.activeElement.blur&&document.activeElement.blur(),document.body.focus())}function Wt(e){if(e.currentTarget&&e.currentTarget.hasAttribute("href")){let t=e.currentTarget.getAttribute("href");t&&(!function(e){fe(),I.overlay=document.createElement("div"),I.overlay.classList.add("overlay"),I.overlay.classList.add("overlay-preview"),I.wrapper.appendChild(I.overlay),I.overlay.innerHTML=`
\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\tUnable to load iframe. This is likely due to the site's policy (x-frame-options).\n\t\t\t\t\n\t\t\t
`,I.overlay.querySelector("iframe").addEventListener("load",e=>{I.overlay.classList.add("loaded")},!1),I.overlay.querySelector(".close").addEventListener("click",e=>{fe(),e.preventDefault()},!1),I.overlay.querySelector(".external").addEventListener("click",e=>{fe()},!1)}(t),e.preventDefault())}}function jt(e){Le()&&!1===l.loop?(Ie(0,0),ut()):Y?ut():ct()}return r(a,{VERSION:"4.0.0-dev",initialize:function(){if(e)return I.wrapper=e,I.slides=e.querySelector(".slides"),window.addEventListener("load",me,!1),l={...E,...t,...a.getQueryHash()},T.load(l.dependencies).then(Q),a;console.warn("reveal.js can not initialize without a valid .reveal element.")},configure:re,sync:Te,syncSlide:function(e=A){ie(e),Be(e),B.load(e),Ve(),ze()},syncFragments:Be,slide:Ie,left:ht,right:pt,up:gt,down:ft,prev:mt,next:vt,navigateTo:Ie,navigateLeft:ht,navigateRight:pt,navigateUp:gt,navigateDown:ft,navigatePrev:mt,navigateNext:vt,navigateFragment:()=>H.goto.bind(H),prevFragment:()=>H.prev.bind(H),nextFragment:()=>H.next.bind(H),layout:me,shuffle:Oe,availableRoutes:Xe,availableFragments:H.availableRoutes.bind(H),toggleHelp:pe,toggleOverview:D.toggle.bind(D),togglePause:Ne,toggleAutoSlide:qe,isFirstSlide:ke,isLastSlide:Le,isLastVerticalSlide:Ee,isOverview:()=>D.isActive.bind(D),isPaused:Pe,isAutoSliding:function(){return!(!V||Y)},isSpeakerNotes:_e,loadSlide:()=>B.load.bind(B),unloadSlide:()=>B.unload.bind(B),addEventListeners:ne,removeEventListeners:se,dispatchEvent:de,getState:ot,setState:function(e){if("object"==typeof e){Ie(s(e.indexh),s(e.indexv),s(e.indexf));let t=s(e.paused),a=s(e.overview);"boolean"==typeof t&&t!==Pe()&&Ne(t),"boolean"==typeof a&&a!==D.isActive()&&D.toggle(a)}},getSlidePastCount:Ye,getProgress:Ke,getIndices:Ze,getSlides:Ge,getSlidesAttributes:function(){return Ge().map(e=>{let t={};for(let a=0;aSt({keyCode:e}),registerKeyboardShortcut:(e,t)=>_[e]=t,addEventListener:(e,t,i)=>{a.getRevealElement().addEventListener(e,t,i)},removeEventListener:(e,t,i)=>{a.getRevealElement().removeEventListener(e,t,i)},registerPlugin:()=>T.registerPlugin.bind(T),hasPlugin:()=>T.hasPlugin.bind(T),getPlugin:()=>T.getPlugin.bind(T),getPlugins:()=>T.getRegisteredPlugins.bind(T),getComputedSlideSize:be,getPreviousSlide:()=>p,getCurrentSlide:()=>A,getScale:()=>P,getConfig:()=>l,getQueryHash:()=>{let e={};location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi,t=>{e[t.split("=").shift()]=t.split("=").pop()});for(let t in e){let a=e[t];e[t]=s(unescape(a))}return void 0!==e.dependencies&&delete e.dependencies,e},getRevealElement:()=>I.wrapper||document.querySelector(".reveal"),getSlidesElement:()=>I.slides,getBackgroundsElement:()=>I.background,isReady:()=>R,announceStatus:Z,getStatusText:G,slideContent:B,updateControls:Ue,updateProgress:We,updateSlidesVisibility:De,writeURL:Qe,transformSlides:oe,cueAutoSlide:lt,cancelAutoSlide:dt})};window.Reveal=L,window.Reveal.initialize=e=>(window.Reveal=new L(document.querySelector(".reveal"),e),window.Reveal.initialize(),new Promise(e=>window.Reveal.addEventListener("ready",e)))}]); \ No newline at end of file diff --git a/js/controllers/autoanimate.js b/js/controllers/autoanimate.js new file mode 100644 index 0000000..9204524 --- /dev/null +++ b/js/controllers/autoanimate.js @@ -0,0 +1,548 @@ +import { extend, toArray, createStyleSheet } from '../utils/util.js' + +/** + * Automatically animates matching elements across + * slides with the [data-auto-animate] attribute. + */ +export default class AutoAnimate { + + constructor( Reveal ) { + + this.Reveal = Reveal; + + // Counter used to generate unique IDs for auto-animated elements + this.autoAnimateCounter = 0; + + } + + /** + * Runs an auto-animation between the given slides. + * + * @param {HTMLElement} fromSlide + * @param {HTMLElement} toSlide + */ + run( fromSlide, toSlide ) { + + // Clean up after prior animations + this.reset(); + + // Ensure that both slides are auto-animate targets + if( fromSlide.hasAttribute( 'data-auto-animate' ) && toSlide.hasAttribute( 'data-auto-animate' ) ) { + + // Create a new auto-animate sheet + this.autoAnimateStyleSheet = this.autoAnimateStyleSheet || createStyleSheet(); + + let animationOptions = this.getAutoAnimateOptions( toSlide ); + + // Set our starting state + fromSlide.dataset.autoAnimate = 'pending'; + toSlide.dataset.autoAnimate = 'pending'; + + // Inject our auto-animate styles for this transition + let css = this.getAutoAnimatableElements( fromSlide, toSlide ).map( elements => { + return this.getAutoAnimateCSS( elements.from, elements.to, elements.options || {}, animationOptions, this.autoAnimateCounter++ ); + } ); + + // Animate unmatched elements, if enabled + if( toSlide.dataset.autoAnimateUnmatched !== 'false' && this.Reveal.getConfig().autoAnimateUnmatched === true ) { + this.getUnmatchedAutoAnimateElements( toSlide ).forEach( unmatchedElement => { + unmatchedElement.dataset.autoAnimateTarget = 'unmatched'; + } ); + + css.push( `[data-auto-animate="running"] [data-auto-animate-target="unmatched"] { transition: opacity ${animationOptions.duration*0.8}s ease ${animationOptions.duration*0.2}s; }` ); + } + + // Setting the whole chunk of CSS at once is the most + // efficient way to do this. Using sheet.insertRule + // is multiple factors slower. + this.autoAnimateStyleSheet.innerHTML = css.join( '' ); + + // Start the animation next cycle + requestAnimationFrame( () => { + if( this.autoAnimateStyleSheet ) { + // This forces our newly injected styles to be applied in Firefox + getComputedStyle( this.autoAnimateStyleSheet ).fontWeight; + + toSlide.dataset.autoAnimate = 'running'; + } + } ); + + this.Reveal.dispatchEvent( 'autoanimate', { fromSlide: fromSlide, toSlide: toSlide, sheet: this.autoAnimateStyleSheet } ); + + } + + } + + /** + * Rolls back all changes that we've made to the DOM so + * that as part of animating. + */ + reset() { + + // Reset slides + toArray( this.Reveal.getRevealElement().querySelectorAll( '[data-auto-animate]:not([data-auto-animate=""])' ) ).forEach( element => { + element.dataset.autoAnimate = ''; + } ); + + // Reset elements + toArray( this.Reveal.getRevealElement().querySelectorAll( '[data-auto-animate-target]' ) ).forEach( element => { + delete element.dataset.autoAnimateTarget; + } ); + + // Remove the animation sheet + if( this.autoAnimateStyleSheet && this.autoAnimateStyleSheet.parentNode ) { + this.autoAnimateStyleSheet.parentNode.removeChild( this.autoAnimateStyleSheet ); + this.autoAnimateStyleSheet = null; + } + + } + + /** + * Auto-animates the properties of an element from their original + * values to their new state. + * + * @param {HTMLElement} from + * @param {HTMLElement} to + * @param {Object} elementOptions Options for this element pair + * @param {Object} animationOptions Options set at the slide level + * @param {String} id Unique ID that we can use to identify this + * auto-animate element in the DOM + */ + getAutoAnimateCSS( from, to, elementOptions, animationOptions, id ) { + + // 'from' elements are given a data-auto-animate-target with no value, + // 'to' elements are are given a data-auto-animate-target with an ID + from.dataset.autoAnimateTarget = ''; + to.dataset.autoAnimateTarget = id; + + // Each element may override any of the auto-animate options + // like transition easing, duration and delay via data-attributes + let options = this.getAutoAnimateOptions( to, animationOptions ); + + // If we're using a custom element matcher the element options + // may contain additional transition overrides + if( typeof elementOptions.delay !== 'undefined' ) options.delay = elementOptions.delay; + if( typeof elementOptions.duration !== 'undefined' ) options.duration = elementOptions.duration; + if( typeof elementOptions.easing !== 'undefined' ) options.easing = elementOptions.easing; + + let fromProps = this.getAutoAnimatableProperties( 'from', from, elementOptions ), + toProps = this.getAutoAnimatableProperties( 'to', to, elementOptions ); + + // If translation and/or scaling are enabled, css transform + // the 'to' element so that it matches the position and size + // of the 'from' element + if( elementOptions.translate !== false || elementOptions.scale !== false ) { + + let presentationScale = this.Reveal.getScale(); + + let delta = { + x: ( fromProps.x - toProps.x ) / presentationScale, + y: ( fromProps.y - toProps.y ) / presentationScale, + scaleX: fromProps.width / toProps.width, + scaleY: fromProps.height / toProps.height + }; + + // Limit decimal points to avoid 0.0001px blur and stutter + delta.x = Math.round( delta.x * 1000 ) / 1000; + delta.y = Math.round( delta.y * 1000 ) / 1000; + delta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000; + delta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000; + + let translate = elementOptions.translate !== false && ( delta.x !== 0 || delta.y !== 0 ), + scale = elementOptions.scale !== false && ( delta.scaleX !== 0 || delta.scaleY !== 0 ); + + // No need to transform if nothing's changed + if( translate || scale ) { + + let transform = []; + + if( translate ) transform.push( `translate(${delta.x}px, ${delta.y}px)` ); + if( scale ) transform.push( `scale(${delta.scaleX}, ${delta.scaleY})` ); + + fromProps.styles['transform'] = transform.join( ' ' ); + fromProps.styles['transform-origin'] = 'top left'; + + toProps.styles['transform'] = 'none'; + + } + + } + + // Delete all unchanged 'to' styles + for( let propertyName in toProps.styles ) { + const toValue = toProps.styles[propertyName]; + const fromValue = fromProps.styles[propertyName]; + + if( toValue === fromValue ) { + delete toProps.styles[propertyName]; + } + else { + // If these property values were set via a custom matcher providing + // an explicit 'from' and/or 'to' value, we always inject those values. + if( toValue.explicitValue === true ) { + toProps.styles[propertyName] = toValue.value; + } + + if( fromValue.explicitValue === true ) { + fromProps.styles[propertyName] = fromValue.value; + } + } + } + + let css = ''; + + let toStyleProperties = Object.keys( toProps.styles ); + + // Only create animate this element IF at least one style + // property has changed + if( toStyleProperties.length > 0 ) { + + // Instantly move to the 'from' state + fromProps.styles['transition'] = 'none'; + + // Animate towards the 'to' state + toProps.styles['transition'] = `all ${options.duration}s ${options.easing} ${options.delay}s`; + toProps.styles['transition-property'] = toStyleProperties.join( ', ' ); + toProps.styles['will-change'] = toStyleProperties.join( ', ' ); + + // Build up our custom CSS. We need to override inline styles + // so we need to make our styles vErY IMPORTANT!1!! + let fromCSS = Object.keys( fromProps.styles ).map( propertyName => { + return propertyName + ': ' + fromProps.styles[propertyName] + ' !important;'; + } ).join( '' ); + + let toCSS = Object.keys( toProps.styles ).map( propertyName => { + return propertyName + ': ' + toProps.styles[propertyName] + ' !important;'; + } ).join( '' ); + + css = '[data-auto-animate-target="'+ id +'"] {'+ fromCSS +'}' + + '[data-auto-animate="running"] [data-auto-animate-target="'+ id +'"] {'+ toCSS +'}'; + + } + + return css; + + } + + /** + * Returns the auto-animate options for the given element. + * + * @param {HTMLElement} element Element to pick up options + * from, either a slide or an animation target + * @param {Object} [inheritedOptions] Optional set of existing + * options + */ + getAutoAnimateOptions( element, inheritedOptions ) { + + let options = { + easing: this.Reveal.getConfig().autoAnimateEasing, + duration: this.Reveal.getConfig().autoAnimateDuration, + delay: 0 + }; + + options = extend( options, inheritedOptions ); + + // Inherit options from parent elements + if( element.closest && element.parentNode ) { + let autoAnimatedParent = element.parentNode.closest( '[data-auto-animate-target]' ); + if( autoAnimatedParent ) { + options = this.getAutoAnimateOptions( autoAnimatedParent, options ); + } + } + + if( element.dataset.autoAnimateEasing ) { + options.easing = element.dataset.autoAnimateEasing; + } + + if( element.dataset.autoAnimateDuration ) { + options.duration = parseFloat( element.dataset.autoAnimateDuration ); + } + + if( element.dataset.autoAnimateDelay ) { + options.delay = parseFloat( element.dataset.autoAnimateDelay ); + } + + return options; + + } + + /** + * Returns an object containing all of the properties + * that can be auto-animated for the given element and + * their current computed values. + * + * @param {String} direction 'from' or 'to' + */ + getAutoAnimatableProperties( direction, element, elementOptions ) { + + let properties = { styles: [] }; + + // Position and size + if( elementOptions.translate !== false || elementOptions.scale !== false ) { + let bounds; + + // Custom auto-animate may optionally return a custom tailored + // measurement function + if( typeof elementOptions.measure === 'function' ) { + bounds = elementOptions.measure( element ); + } + else { + bounds = element.getBoundingClientRect(); + } + + properties.x = bounds.x; + properties.y = bounds.y; + properties.width = bounds.width; + properties.height = bounds.height; + } + + const computedStyles = getComputedStyle( element ); + + // CSS styles + ( elementOptions.styles || this.Reveal.getConfig().autoAnimateStyles ).forEach( style => { + let value; + + // `style` is either the property name directly, or an object + // definition of a style property + if( typeof style === 'string' ) style = { property: style }; + + if( typeof style.from !== 'undefined' && direction === 'from' ) { + value = { value: style.from, explicitValue: true }; + } + else if( typeof style.to !== 'undefined' && direction === 'to' ) { + value = { value: style.to, explicitValue: true }; + } + else { + value = computedStyles[style.property]; + } + + if( value !== '' ) { + properties.styles[style.property] = value; + } + } ); + + return properties; + + } + + /** + * Get a list of all element pairs that we can animate + * between the given slides. + * + * @param {HTMLElement} fromSlide + * @param {HTMLElement} toSlide + * + * @return {Array} Each value is an array where [0] is + * the element we're animating from and [1] is the + * element we're animating to + */ + getAutoAnimatableElements( fromSlide, toSlide ) { + + let matcher = typeof this.Reveal.getConfig().autoAnimateMatcher === 'function' ? this.Reveal.getConfig().autoAnimateMatcher : this.getAutoAnimatePairs; + + let pairs = matcher.call( this, fromSlide, toSlide ); + + let reserved = []; + + // Remove duplicate pairs + return pairs.filter( ( pair, index ) => { + if( reserved.indexOf( pair.to ) === -1 ) { + reserved.push( pair.to ); + return true; + } + } ); + + } + + /** + * Identifies matching elements between slides. + * + * You can specify a custom matcher function by using + * the `autoAnimateMatcher` config option. + */ + getAutoAnimatePairs( fromSlide, toSlide ) { + + let pairs = []; + + const codeNodes = 'pre'; + const textNodes = 'h1, h2, h3, h4, h5, h6, p, li'; + const mediaNodes = 'img, video, iframe'; + + // Eplicit matches via data-id + this.findAutoAnimateMatches( pairs, fromSlide, toSlide, '[data-id]', node => { + return node.nodeName + ':::' + node.getAttribute( 'data-id' ); + } ); + + // Text + this.findAutoAnimateMatches( pairs, fromSlide, toSlide, textNodes, node => { + return node.nodeName + ':::' + node.innerText; + } ); + + // Media + this.findAutoAnimateMatches( pairs, fromSlide, toSlide, mediaNodes, node => { + return node.nodeName + ':::' + ( node.getAttribute( 'src' ) || node.getAttribute( 'data-src' ) ); + } ); + + // Code + this.findAutoAnimateMatches( pairs, fromSlide, toSlide, codeNodes, node => { + return node.nodeName + ':::' + node.innerText; + } ); + + pairs.forEach( pair => { + + // Disable scale transformations on text nodes, we transiition + // each individual text property instead + if( pair.from.matches( textNodes ) ) { + pair.options = { scale: false }; + } + // Animate individual lines of code + else if( pair.from.matches( codeNodes ) ) { + + // Transition the code block's width and height instead of scaling + // to prevent its content from being squished + pair.options = { scale: false, styles: [ 'width', 'height' ] }; + + // Lines of code + this.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-code', node => { + return node.textContent; + }, { + scale: false, + styles: [], + measure: this.getLocalBoundingBox.bind( this ) + } ); + + // Line numbers + this.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-line[data-line-number]', node => { + return node.getAttribute( 'data-line-number' ); + }, { + scale: false, + styles: [ 'width' ], + measure: this.getLocalBoundingBox.bind( this ) + } ); + + } + + }, this ); + + return pairs; + + } + + /** + * Helper method which returns a bounding box based on + * the given elements offset coordinates. + * + * @param {HTMLElement} element + * @return {Object} x, y, width, height + */ + getLocalBoundingBox( element ) { + + const presentationScale = this.Reveal.getScale(); + + return { + x: Math.round( ( element.offsetLeft * presentationScale ) * 100 ) / 100, + y: Math.round( ( element.offsetTop * presentationScale ) * 100 ) / 100, + width: Math.round( ( element.offsetWidth * presentationScale ) * 100 ) / 100, + height: Math.round( ( element.offsetHeight * presentationScale ) * 100 ) / 100 + }; + + } + + /** + * Finds matching elements between two slides. + * + * @param {Array} pairs List of pairs to push matches to + * @param {HTMLElement} fromScope Scope within the from element exists + * @param {HTMLElement} toScope Scope within the to element exists + * @param {String} selector CSS selector of the element to match + * @param {Function} serializer A function that accepts an element and returns + * a stringified ID based on its contents + * @param {Object} animationOptions Optional config options for this pair + */ + findAutoAnimateMatches( pairs, fromScope, toScope, selector, serializer, animationOptions ) { + + let fromMatches = {}; + let toMatches = {}; + + [].slice.call( fromScope.querySelectorAll( selector ) ).forEach( ( element, i ) => { + const key = serializer( element ); + if( typeof key === 'string' && key.length ) { + fromMatches[key] = fromMatches[key] || []; + fromMatches[key].push( element ); + } + } ); + + [].slice.call( toScope.querySelectorAll( selector ) ).forEach( ( element, i ) => { + const key = serializer( element ); + toMatches[key] = toMatches[key] || []; + toMatches[key].push( element ); + + let fromElement; + + // Retrieve the 'from' element + if( fromMatches[key] ) { + const pimaryIndex = toMatches[key].length - 1; + const secondaryIndex = fromMatches[key].length - 1; + + // If there are multiple identical from elements, retrieve + // the one at the same index as our to-element. + if( fromMatches[key][ pimaryIndex ] ) { + fromElement = fromMatches[key][ pimaryIndex ]; + fromMatches[key][ pimaryIndex ] = null; + } + // If there are no matching from-elements at the same index, + // use the last one. + else if( fromMatches[key][ secondaryIndex ] ) { + fromElement = fromMatches[key][ secondaryIndex ]; + fromMatches[key][ secondaryIndex ] = null; + } + } + + // If we've got a matching pair, push it to the list of pairs + if( fromElement ) { + pairs.push({ + from: fromElement, + to: element, + options: animationOptions + }); + } + } ); + + } + + /** + * Returns a all elements within the given scope that should + * be considered unmatched in an auto-animate transition. If + * fading of unmatched elements is turned on, these elements + * will fade when going between auto-animate slides. + * + * Note that parents of auto-animate targets are NOT considerd + * unmatched since fading them would break the auto-animation. + * + * @param {HTMLElement} rootElement + * @return {Array} + */ + getUnmatchedAutoAnimateElements( rootElement ) { + + return [].slice.call( rootElement.children ).reduce( ( result, element ) => { + + const containsAnimatedElements = element.querySelector( '[data-auto-animate-target]' ); + + // The element is unmatched if + // - It is not an auto-animate target + // - It does not contain any auto-animate targets + if( !element.hasAttribute( 'data-auto-animate-target' ) && !containsAnimatedElements ) { + result.push( element ); + } + + if( element.querySelector( '[data-auto-animate-target]' ) ) { + result = result.concat( this.getUnmatchedAutoAnimateElements( element ) ); + } + + return result; + + }, [] ); + + } + +} \ No newline at end of file diff --git a/js/controllers/fragments.js b/js/controllers/fragments.js new file mode 100644 index 0000000..008e5de --- /dev/null +++ b/js/controllers/fragments.js @@ -0,0 +1,304 @@ +import { extend, toArray } from '../utils/util.js' + +/** + * Handles sorting and navigation of slide fragments. + * Fragments are elements within a slide that are + * revealed/animated incrementally. + */ +export default class Fragments { + + constructor( Reveal ) { + + this.Reveal = Reveal; + + } + + /** + * Shows all fragments in the presentation. Used when + * fragments are disabled presentation-wide. + */ + showAll() { + + toArray( this.Reveal.getSlidesElement().querySelectorAll( '.fragment' ) ).forEach( element => { + element.classList.add( 'visible' ); + element.classList.remove( 'current-fragment' ); + } ); + + } + + /** + * Returns an object describing the available fragment + * directions. + * + * @return {{prev: boolean, next: boolean}} + */ + availableRoutes() { + + let currentSlide = this.Reveal.getCurrentSlide(); + if( currentSlide && this.Reveal.getConfig().fragments ) { + let fragments = currentSlide.querySelectorAll( '.fragment' ); + let hiddenFragments = currentSlide.querySelectorAll( '.fragment:not(.visible)' ); + + return { + prev: fragments.length - hiddenFragments.length > 0, + next: !!hiddenFragments.length + }; + } + else { + return { prev: false, next: false }; + } + + } + + /** + * Return a sorted fragments list, ordered by an increasing + * "data-fragment-index" attribute. + * + * Fragments will be revealed in the order that they are returned by + * this function, so you can use the index attributes to control the + * order of fragment appearance. + * + * To maintain a sensible default fragment order, fragments are presumed + * to be passed in document order. This function adds a "fragment-index" + * attribute to each node if such an attribute is not already present, + * and sets that attribute to an integer value which is the position of + * the fragment within the fragments list. + * + * @param {object[]|*} fragments + * @param {boolean} grouped If true the returned array will contain + * nested arrays for all fragments with the same index + * @return {object[]} sorted Sorted array of fragments + */ + sort( fragments, grouped = false ) { + + fragments = toArray( fragments ); + + let ordered = [], + unordered = [], + sorted = []; + + // Group ordered and unordered elements + fragments.forEach( fragment => { + if( fragment.hasAttribute( 'data-fragment-index' ) ) { + let index = parseInt( fragment.getAttribute( 'data-fragment-index' ), 10 ); + + if( !ordered[index] ) { + ordered[index] = []; + } + + ordered[index].push( fragment ); + } + else { + unordered.push( [ fragment ] ); + } + } ); + + // Append fragments without explicit indices in their + // DOM order + ordered = ordered.concat( unordered ); + + // Manually count the index up per group to ensure there + // are no gaps + let index = 0; + + // Push all fragments in their sorted order to an array, + // this flattens the groups + ordered.forEach( group => { + group.forEach( fragment => { + sorted.push( fragment ); + fragment.setAttribute( 'data-fragment-index', index ); + } ); + + index ++; + } ); + + return grouped === true ? ordered : sorted; + + } + + /** + * Sorts and formats all of fragments in the + * presentation. + */ + sortAll() { + + this.Reveal.getHorizontalSlides().forEach( horizontalSlide => { + + let verticalSlides = toArray( horizontalSlide.querySelectorAll( 'section' ) ); + verticalSlides.forEach( ( verticalSlide, y ) => { + + this.sort( verticalSlide.querySelectorAll( '.fragment' ) ); + + }, this ); + + if( verticalSlides.length === 0 ) this.sort( horizontalSlide.querySelectorAll( '.fragment' ) ); + + } ); + + } + + /** + * Refreshes the fragments on the current slide so that they + * have the appropriate classes (.visible + .current-fragment). + * + * @param {number} [index] The index of the current fragment + * @param {array} [fragments] Array containing all fragments + * in the current slide + * + * @return {{shown: array, hidden: array}} + */ + update( index, fragments ) { + + let changedFragments = { + shown: [], + hidden: [] + }; + + let currentSlide = this.Reveal.getCurrentSlide(); + if( currentSlide && this.Reveal.getConfig().fragments ) { + + fragments = fragments || this.sort( currentSlide.querySelectorAll( '.fragment' ) ); + + if( fragments.length ) { + + let maxIndex = 0; + + if( typeof index !== 'number' ) { + let currentFragment = this.sort( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop(); + if( currentFragment ) { + index = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 ); + } + } + + toArray( fragments ).forEach( ( el, i ) => { + + if( el.hasAttribute( 'data-fragment-index' ) ) { + i = parseInt( el.getAttribute( 'data-fragment-index' ), 10 ); + } + + maxIndex = Math.max( maxIndex, i ); + + // Visible fragments + if( i <= index ) { + if( !el.classList.contains( 'visible' ) ) changedFragments.shown.push( el ); + el.classList.add( 'visible' ); + el.classList.remove( 'current-fragment' ); + + // Announce the fragments one by one to the Screen Reader + this.Reveal.announceStatus( this.Reveal.getStatusText( el ) ); + + if( i === index ) { + el.classList.add( 'current-fragment' ); + this.Reveal.slideContent.startEmbeddedContent( el ); + } + } + // Hidden fragments + else { + if( el.classList.contains( 'visible' ) ) changedFragments.hidden.push( el ); + el.classList.remove( 'visible' ); + el.classList.remove( 'current-fragment' ); + } + + } ); + + // Write the current fragment index to the slide
. + // This can be used by end users to apply styles based on + // the current fragment index. + index = typeof index === 'number' ? index : -1; + index = Math.max( Math.min( index, maxIndex ), -1 ); + currentSlide.setAttribute( 'data-fragment', index ); + + } + + } + + return changedFragments; + + } + + /** + * Navigate to the specified slide fragment. + * + * @param {?number} index The index of the fragment that + * should be shown, -1 means all are invisible + * @param {number} offset Integer offset to apply to the + * fragment index + * + * @return {boolean} true if a change was made in any + * fragments visibility as part of this call + */ + goto( index, offset = 0 ) { + + let currentSlide = this.Reveal.getCurrentSlide(); + if( currentSlide && this.Reveal.getConfig().fragments ) { + + let fragments = this.sort( currentSlide.querySelectorAll( '.fragment' ) ); + if( fragments.length ) { + + // If no index is specified, find the current + if( typeof index !== 'number' ) { + let lastVisibleFragment = this.sort( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop(); + + if( lastVisibleFragment ) { + index = parseInt( lastVisibleFragment.getAttribute( 'data-fragment-index' ) || 0, 10 ); + } + else { + index = -1; + } + } + + // Apply the offset if there is one + index += offset; + + let changedFragments = this.update( index, fragments ); + + if( changedFragments.hidden.length ) { + this.Reveal.dispatchEvent( 'fragmenthidden', { fragment: changedFragments.hidden[0], fragments: changedFragments.hidden } ); + } + + if( changedFragments.shown.length ) { + this.Reveal.dispatchEvent( 'fragmentshown', { fragment: changedFragments.shown[0], fragments: changedFragments.shown } ); + } + + this.Reveal.updateControls(); + this.Reveal.updateProgress(); + + if( this.Reveal.getConfig().fragmentInURL ) { + this.Reveal.writeURL(); + } + + return !!( changedFragments.shown.length || changedFragments.hidden.length ); + + } + + } + + return false; + + } + + /** + * Navigate to the next slide fragment. + * + * @return {boolean} true if there was a next fragment, + * false otherwise + */ + next() { + + return this.goto( null, 1 ); + + } + + /** + * Navigate to the previous slide fragment. + * + * @return {boolean} true if there was a previous fragment, + * false otherwise + */ + prev() { + + return this.goto( null, -1 ); + + } + +} \ No newline at end of file diff --git a/js/controllers/overview.js b/js/controllers/overview.js new file mode 100644 index 0000000..08a2404 --- /dev/null +++ b/js/controllers/overview.js @@ -0,0 +1,249 @@ +import { SLIDES_SELECTOR } from '../utils/constants.js' +import { extend, toArray, transformElement } from '../utils/util.js' + +/** + * Handles all logic related to the overview mode + * (birds-eye view of all slides). + */ +export default class Overview { + + constructor( Reveal ) { + + this.Reveal = Reveal; + + this.active = false; + + this.onSlideClicked = this.onSlideClicked.bind( this ); + + } + + /** + * Displays the overview of slides (quick nav) by scaling + * down and arranging all slide elements. + */ + activate() { + + // Only proceed if enabled in config + if( this.Reveal.getConfig().overview && !this.isActive() ) { + + this.active = true; + + this.Reveal.getRevealElement().classList.add( 'overview' ); + + // Don't auto-slide while in overview mode + this.Reveal.cancelAutoSlide(); + + // Move the backgrounds element into the slide container to + // that the same scaling is applied + this.Reveal.getSlidesElement().appendChild( this.Reveal.getBackgroundsElement() ); + + // Clicking on an overview slide navigates to it + toArray( this.Reveal.getRevealElement().querySelectorAll( SLIDES_SELECTOR ) ).forEach( slide => { + if( !slide.classList.contains( 'stack' ) ) { + slide.addEventListener( 'click', this.onSlideClicked, true ); + } + } ); + + // Calculate slide sizes + const margin = 70; + const slideSize = this.Reveal.getComputedSlideSize(); + this.overviewSlideWidth = slideSize.width + margin; + this.overviewSlideHeight = slideSize.height + margin; + + // Reverse in RTL mode + if( this.Reveal.getConfig().rtl ) { + this.overviewSlideWidth = -this.overviewSlideWidth; + } + + this.Reveal.updateSlidesVisibility(); + + this.layout(); + this.update(); + + this.Reveal.layout(); + + const indices = this.Reveal.getIndices(); + + // Notify observers of the overview showing + this.Reveal.dispatchEvent( 'overviewshown', { + 'indexh': indices.h, + 'indexv': indices.v, + 'currentSlide': this.Reveal.getCurrentSlide() + } ); + + } + + } + + /** + * Uses CSS transforms to position all slides in a grid for + * display inside of the overview mode. + */ + layout() { + + // Layout slides + this.Reveal.getHorizontalSlides().forEach( ( hslide, h ) => { + hslide.setAttribute( 'data-index-h', h ); + transformElement( hslide, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' ); + + if( hslide.classList.contains( 'stack' ) ) { + + toArray( hslide.querySelectorAll( 'section' ) ).forEach( ( vslide, v ) => { + vslide.setAttribute( 'data-index-h', h ); + vslide.setAttribute( 'data-index-v', v ); + + transformElement( vslide, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' ); + } ); + + } + } ); + + // Layout slide backgrounds + toArray( this.Reveal.getBackgroundsElement().childNodes ).forEach( ( hbackground, h ) => { + transformElement( hbackground, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' ); + + toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( ( vbackground, v ) => { + transformElement( vbackground, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' ); + } ); + } ); + + } + + /** + * Moves the overview viewport to the current slides. + * Called each time the current slide changes. + */ + update() { + + const vmin = Math.min( window.innerWidth, window.innerHeight ); + const scale = Math.max( vmin / 5, 150 ) / vmin; + const indices = this.Reveal.getIndices(); + + this.Reveal.transformSlides( { + overview: [ + 'scale('+ scale +')', + 'translateX('+ ( -indices.h * this.overviewSlideWidth ) +'px)', + 'translateY('+ ( -indices.v * this.overviewSlideHeight ) +'px)' + ].join( ' ' ) + } ); + + } + + /** + * Exits the slide overview and enters the currently + * active slide. + */ + deactivate() { + + // Only proceed if enabled in config + if( this.Reveal.getConfig().overview ) { + + this.active = false; + + this.Reveal.getRevealElement().classList.remove( 'overview' ); + + // Temporarily add a class so that transitions can do different things + // depending on whether they are exiting/entering overview, or just + // moving from slide to slide + this.Reveal.getRevealElement().classList.add( 'overview-deactivating' ); + + setTimeout( () => { + this.Reveal.getRevealElement().classList.remove( 'overview-deactivating' ); + }, 1 ); + + // Move the background element back out + this.Reveal.getRevealElement().appendChild( this.Reveal.getBackgroundsElement() ); + + // Clean up changes made to slides + toArray( this.Reveal.getRevealElement().querySelectorAll( SLIDES_SELECTOR ) ).forEach( slide => { + transformElement( slide, '' ); + + slide.removeEventListener( 'click', this.onSlideClicked, true ); + } ); + + // Clean up changes made to backgrounds + toArray( this.Reveal.getBackgroundsElement().querySelectorAll( '.slide-background' ) ).forEach( background => { + transformElement( background, '' ); + } ); + + this.Reveal.transformSlides( { overview: '' } ); + + const indices = this.Reveal.getIndices(); + + this.Reveal.slide( indices.h, indices.v ); + this.Reveal.layout(); + this.Reveal.cueAutoSlide(); + + // Notify observers of the overview hiding + this.Reveal.dispatchEvent( 'overviewhidden', { + 'indexh': indices.h, + 'indexv': indices.v, + 'currentSlide': this.Reveal.getCurrentSlide() + } ); + + } + } + + /** + * Toggles the slide overview mode on and off. + * + * @param {Boolean} [override] Flag which overrides the + * toggle logic and forcibly sets the desired state. True means + * overview is open, false means it's closed. + */ + toggle( override ) { + + if( typeof override === 'boolean' ) { + override ? this.activate() : this.deactivate(); + } + else { + this.isActive() ? this.deactivate() : this.activate(); + } + + } + + /** + * Checks if the overview is currently active. + * + * @return {Boolean} true if the overview is active, + * false otherwise + */ + isActive() { + + return this.active; + + } + + /** + * Invoked when a slide is and we're in the overview. + * + * @param {object} event + */ + onSlideClicked( event ) { + + if( this.isActive() ) { + event.preventDefault(); + + let element = event.target; + + while( element && !element.nodeName.match( /section/gi ) ) { + element = element.parentNode; + } + + if( element && !element.classList.contains( 'disabled' ) ) { + + this.deactivate(); + + if( element.nodeName.match( /section/gi ) ) { + let h = parseInt( element.getAttribute( 'data-index-h' ), 10 ), + v = parseInt( element.getAttribute( 'data-index-v' ), 10 ); + + this.Reveal.slide( h, v ); + } + + } + } + + } + +} \ No newline at end of file diff --git a/js/controllers/plugins.js b/js/controllers/plugins.js index 94077f7..00b0c5e 100644 --- a/js/controllers/plugins.js +++ b/js/controllers/plugins.js @@ -7,8 +7,8 @@ export default class Plugins { constructor() { - // Flags our current state (pending -> loading -> loaded) - this.state = 'pending'; + // Flags our current state (idle -> loading -> loaded) + this.state = 'idle'; // An id:instance map of currently registed plugins this.registeredPlugins = {}; diff --git a/js/controllers/slidecontent.js b/js/controllers/slidecontent.js new file mode 100644 index 0000000..f85be49 --- /dev/null +++ b/js/controllers/slidecontent.js @@ -0,0 +1,433 @@ +import { HORIZONTAL_SLIDES_SELECTOR, VERTICAL_SLIDES_SELECTOR } from '../utils/constants.js' +import { extend, toArray, closestParent } from '../utils/util.js' +import { isMobile } from '../utils/device.js' + +/** + * Handles loading, unloading and playback of slide + * content such as images, videos and iframes. + */ +export default class SlideContent { + + constructor( Reveal ) { + + this.Reveal = Reveal; + + } + + /** + * Should the given element be preloaded? + * Decides based on local element attributes and global config. + * + * @param {HTMLElement} element + */ + shouldPreload( element ) { + + // Prefer an explicit global preload setting + let preload = this.Reveal.getConfig().preloadIframes; + + // If no global setting is available, fall back on the element's + // own preload setting + if( typeof preload !== 'boolean' ) { + preload = element.hasAttribute( 'data-preload' ); + } + + return preload; + } + + /** + * Called when the given slide is within the configured view + * distance. Shows the slide element and loads any content + * that is set to load lazily (data-src). + * + * @param {HTMLElement} slide Slide to show + */ + load( slide, options = {} ) { + + // Show the slide element + slide.style.display = this.Reveal.getConfig().display; + + // Media elements with data-src attributes + toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ) ).forEach( element => { + if( element.tagName !== 'IFRAME' || this.shouldPreload( element ) ) { + element.setAttribute( 'src', element.getAttribute( 'data-src' ) ); + element.setAttribute( 'data-lazy-loaded', '' ); + element.removeAttribute( 'data-src' ); + } + } ); + + // Media elements with children + toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( media => { + let sources = 0; + + toArray( media.querySelectorAll( 'source[data-src]' ) ).forEach( source => { + source.setAttribute( 'src', source.getAttribute( 'data-src' ) ); + source.removeAttribute( 'data-src' ); + source.setAttribute( 'data-lazy-loaded', '' ); + sources += 1; + } ); + + // If we rewrote sources for this video/audio element, we need + // to manually tell it to load from its new origin + if( sources > 0 ) { + media.load(); + } + } ); + + + // Show the corresponding background element + let background = slide.slideBackgroundElement; + if( background ) { + background.style.display = 'block'; + + let backgroundContent = slide.slideBackgroundContentElement; + let backgroundIframe = slide.getAttribute( 'data-background-iframe' ); + + // If the background contains media, load it + if( background.hasAttribute( 'data-loaded' ) === false ) { + background.setAttribute( 'data-loaded', 'true' ); + + let backgroundImage = slide.getAttribute( 'data-background-image' ), + backgroundVideo = slide.getAttribute( 'data-background-video' ), + backgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ), + backgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' ); + + // Images + if( backgroundImage ) { + backgroundContent.style.backgroundImage = 'url('+ encodeURI( backgroundImage ) +')'; + } + // Videos + else if ( backgroundVideo && !this.Reveal.isSpeakerNotes() ) { + let video = document.createElement( 'video' ); + + if( backgroundVideoLoop ) { + video.setAttribute( 'loop', '' ); + } + + if( backgroundVideoMuted ) { + video.muted = true; + } + + // Inline video playback works (at least in Mobile Safari) as + // long as the video is muted and the `playsinline` attribute is + // present + if( isMobile ) { + video.muted = true; + video.autoplay = true; + video.setAttribute( 'playsinline', '' ); + } + + // Support comma separated lists of video sources + backgroundVideo.split( ',' ).forEach( source => { + video.innerHTML += ''; + } ); + + backgroundContent.appendChild( video ); + } + // Iframes + else if( backgroundIframe && options.excludeIframes !== true ) { + let iframe = document.createElement( 'iframe' ); + iframe.setAttribute( 'allowfullscreen', '' ); + iframe.setAttribute( 'mozallowfullscreen', '' ); + iframe.setAttribute( 'webkitallowfullscreen', '' ); + iframe.setAttribute( 'allow', 'autoplay' ); + + iframe.setAttribute( 'data-src', backgroundIframe ); + + iframe.style.width = '100%'; + iframe.style.height = '100%'; + iframe.style.maxHeight = '100%'; + iframe.style.maxWidth = '100%'; + + backgroundContent.appendChild( iframe ); + } + } + + // Start loading preloadable iframes + let backgroundIframeElement = backgroundContent.querySelector( 'iframe[data-src]' ); + if( backgroundIframeElement ) { + + // Check if this iframe is eligible to be preloaded + if( this.shouldPreload( background ) && !/autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) { + if( backgroundIframeElement.getAttribute( 'src' ) !== backgroundIframe ) { + backgroundIframeElement.setAttribute( 'src', backgroundIframe ); + } + } + + } + + } + + } + + /** + * Unloads and hides the given slide. This is called when the + * slide is moved outside of the configured view distance. + * + * @param {HTMLElement} slide + */ + unload( slide ) { + + // Hide the slide element + slide.style.display = 'none'; + + // Hide the corresponding background element + let background = this.Reveal.getSlideBackground( slide ); + if( background ) { + background.style.display = 'none'; + + // Unload any background iframes + toArray( background.querySelectorAll( 'iframe[src]' ) ).forEach( element => { + element.removeAttribute( 'src' ); + } ); + } + + // Reset lazy-loaded media elements with src attributes + toArray( slide.querySelectorAll( 'video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]' ) ).forEach( element => { + element.setAttribute( 'data-src', element.getAttribute( 'src' ) ); + element.removeAttribute( 'src' ); + } ); + + // Reset lazy-loaded media elements with children + toArray( slide.querySelectorAll( 'video[data-lazy-loaded] source[src], audio source[src]' ) ).forEach( source => { + source.setAttribute( 'data-src', source.getAttribute( 'src' ) ); + source.removeAttribute( 'src' ); + } ); + + } + + /** + * Enforces origin-specific format rules for embedded media. + */ + formatEmbeddedContent() { + + let _appendParamToIframeSource = ( sourceAttribute, sourceURL, param ) => { + toArray( this.Reveal.getSlidesElement().querySelectorAll( 'iframe['+ sourceAttribute +'*="'+ sourceURL +'"]' ) ).forEach( el => { + let src = el.getAttribute( sourceAttribute ); + if( src && src.indexOf( param ) === -1 ) { + el.setAttribute( sourceAttribute, src + ( !/\?/.test( src ) ? '?' : '&' ) + param ); + } + }); + }; + + // YouTube frames must include "?enablejsapi=1" + _appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' ); + _appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' ); + + // Vimeo frames must include "?api=1" + _appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' ); + _appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' ); + + } + + /** + * Start playback of any embedded content inside of + * the given element. + * + * @param {HTMLElement} element + */ + startEmbeddedContent( element ) { + + if( element && !this.Reveal.isSpeakerNotes() ) { + + // Restart GIFs + toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( el => { + // Setting the same unchanged source like this was confirmed + // to work in Chrome, FF & Safari + el.setAttribute( 'src', el.getAttribute( 'src' ) ); + } ); + + // HTML5 media elements + toArray( element.querySelectorAll( 'video, audio' ) ).forEach( el => { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + + // Prefer an explicit global autoplay setting + let autoplay = this.Reveal.getConfig().autoPlayMedia; + + // If no global setting is available, fall back on the element's + // own autoplay setting + if( typeof autoplay !== 'boolean' ) { + autoplay = el.hasAttribute( 'data-autoplay' ) || !!closestParent( el, '.slide-background' ); + } + + if( autoplay && typeof el.play === 'function' ) { + + // If the media is ready, start playback + if( el.readyState > 1 ) { + this.startEmbeddedMedia( { target: el } ); + } + // Mobile devices never fire a loaded event so instead + // of waiting, we initiate playback + else if( isMobile ) { + let promise = el.play(); + + // If autoplay does not work, ensure that the controls are visible so + // that the viewer can start the media on their own + if( promise && typeof promise.catch === 'function' && el.controls === false ) { + promise.catch( () => { + el.controls = true; + + // Once the video does start playing, hide the controls again + el.addEventListener( 'play', () => { + el.controls = false; + } ); + } ); + } + } + // If the media isn't loaded, wait before playing + else { + el.removeEventListener( 'loadeddata', this.startEmbeddedMedia ); // remove first to avoid dupes + el.addEventListener( 'loadeddata', this.startEmbeddedMedia ); + } + + } + } ); + + // Normal iframes + toArray( element.querySelectorAll( 'iframe[src]' ) ).forEach( el => { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + + this.startEmbeddedIframe( { target: el } ); + } ); + + // Lazy loading iframes + toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( el => { + if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { + return; + } + + if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) { + el.removeEventListener( 'load', this.startEmbeddedIframe ); // remove first to avoid dupes + el.addEventListener( 'load', this.startEmbeddedIframe ); + el.setAttribute( 'src', el.getAttribute( 'data-src' ) ); + } + } ); + + } + + } + + /** + * Starts playing an embedded video/audio element after + * it has finished loading. + * + * @param {object} event + */ + startEmbeddedMedia( event ) { + + let isAttachedToDOM = !!closestParent( event.target, 'html' ), + isVisible = !!closestParent( event.target, '.present' ); + + if( isAttachedToDOM && isVisible ) { + event.target.currentTime = 0; + event.target.play(); + } + + event.target.removeEventListener( 'loadeddata', this.startEmbeddedMedia ); + + } + + /** + * "Starts" the content of an embedded iframe using the + * postMessage API. + * + * @param {object} event + */ + startEmbeddedIframe( event ) { + + let iframe = event.target; + + if( iframe && iframe.contentWindow ) { + + let isAttachedToDOM = !!closestParent( event.target, 'html' ), + isVisible = !!closestParent( event.target, '.present' ); + + if( isAttachedToDOM && isVisible ) { + + // Prefer an explicit global autoplay setting + let autoplay = this.Reveal.getConfig().autoPlayMedia; + + // If no global setting is available, fall back on the element's + // own autoplay setting + if( typeof autoplay !== 'boolean' ) { + autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' ); + } + + // YouTube postMessage API + if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) { + iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' ); + } + // Vimeo postMessage API + else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) { + iframe.contentWindow.postMessage( '{"method":"play"}', '*' ); + } + // Generic postMessage API + else { + iframe.contentWindow.postMessage( 'slide:start', '*' ); + } + + } + + } + + } + + /** + * Stop playback of any embedded content inside of + * the targeted slide. + * + * @param {HTMLElement} element + */ + stopEmbeddedContent( element, options = {} ) { + + options = extend( { + // Defaults + unloadIframes: true + }, options ); + + if( element && element.parentNode ) { + // HTML5 media elements + toArray( element.querySelectorAll( 'video, audio' ) ).forEach( el => { + if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) { + el.setAttribute('data-paused-by-reveal', ''); + el.pause(); + } + } ); + + // Generic postMessage API for non-lazy loaded iframes + toArray( element.querySelectorAll( 'iframe' ) ).forEach( el => { + if( el.contentWindow ) el.contentWindow.postMessage( 'slide:stop', '*' ); + el.removeEventListener( 'load', this.startEmbeddedIframe ); + }); + + // YouTube postMessage API + toArray( element.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( el => { + if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) { + el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' ); + } + }); + + // Vimeo postMessage API + toArray( element.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( el => { + if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) { + el.contentWindow.postMessage( '{"method":"pause"}', '*' ); + } + }); + + if( options.unloadIframes === true ) { + // Unload lazy-loaded iframes + toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( el => { + // Only removing the src doesn't actually unload the frame + // in all browsers (Firefox) so we set it to blank first + el.setAttribute( 'src', 'about:blank' ); + el.removeAttribute( 'src' ); + } ); + } + } + + } + +} \ No newline at end of file diff --git a/js/reveal.js b/js/reveal.js index a48377b..717a0d6 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -1,3 +1,7 @@ +import SlideContent from './controllers/slidecontent.js' +import AutoAnimate from './controllers/autoanimate.js' +import Fragments from './controllers/fragments.js' +import Overview from './controllers/overview.js' import Plugins from './controllers/plugins.js' import Playback from './components/playback.js' import defaultConfig from './config.js' @@ -13,10 +17,11 @@ import { distanceBetween, deserialize, transformElement, - injectStyleSheet, + createStyleSheet, closestParent, enterFullscreen } from './utils/util.js' +import { isMobile, isChrome, isAndroid, supportsZoom } from './utils/device.js' import { colorToRgb, colorBrightness } from './utils/color.js' /** @@ -24,30 +29,21 @@ import { colorToRgb, colorBrightness } from './utils/color.js' * http://revealjs.com * MIT licensed * - * Copyright (C) 2020 Hakim El Hattab, http://hakim.se + * Copyright (C) 2020 Hakim El Hattab, https://hakim.se */ export default function( revealElement, options ) { - let Reveal; + const Reveal = {}; // The reveal.js version const VERSION = '4.0.0-dev'; - const UA = navigator.userAgent; - // Configuration defaults, can be overridden at initialization time let config, // Flags if reveal.js is loaded (has dispatched the 'ready' event) ready = false, - // Flags if the overview mode is currently active - overview = false, - - // Holds the dimensions of our overview slides, including margins - overviewSlideWidth = null, - overviewSlideHeight = null, - // The horizontal and vertical index of the currently active slide indexh, indexv, @@ -77,21 +73,23 @@ export default function( revealElement, options ) { // Cached references to DOM elements dom = {}, - // An instance of the Plugins controller + // Controller for plugin loading plugins = new Plugins(), + // Controls loading and playback of slide content + slideContent = new SlideContent( Reveal ), + + // Controls auto-animations between slides + autoAnimate = new AutoAnimate( Reveal ), + + // Controls navigation between slide fragments + fragments = new Fragments( Reveal ), + + overview = new Overview( Reveal ), + // List of asynchronously loaded reveal.js dependencies asyncDependencies = [], - // Features supported by the browser, see #checkCapabilities() - features = {}, - - // Client is a mobile device, see #checkCapabilities() - isMobileDevice, - - // Client is a desktop Chrome, see #checkCapabilities() - isChrome, - // Throttles mouse wheel navigation lastMouseWheelStep = 0, @@ -107,12 +105,6 @@ export default function( revealElement, options ) { // Flags if the interaction event listeners are bound eventsAreBound = false, - //